Generowanie obrazka

0

Witam.
Mam taki problem.
W aplikacji tworzonej pod WPF w C# chciałbym stworzyć obrazek bezpośrednio z kodu (rysując na nim jakieś linie) i zapisać go bezpośrednio do pliku na dysk.
Szukałem na sieci ale rozwiązania, które znalazłem zawsze wyświetlają stworzony obrazek w kontrolce wyświetlanej w oknie a ja nie chce tego nigdzie wyświetlać.
Korzystałem z dwóch rozwiązań:
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/how-to-use-a-drawing-as-an-image-source?view=netframeworkdesktop-4.8
oraz:
https://www.c-sharpcorner.com/UploadFile/mahakgupta/how-to-use-a-drawing-as-an-image-source-in-wpf/

W obydwu przypadkach zakładają mi się na dysku puste obrazki.
Tak jakby DrawImage nie wypełniał obrazka.

Czy ktoś mógłby mi pomóc w rozwiązaniu tego problemu?

Kod, którego używam:

private string CreateSignatureImage(int signatureId)
{
    try
    {
        Koncept.SSD.DAL.DAL.SSDSignature sign = DAL.SSD.Methods.GetSignature(signatureId);
        if (sign == null || sign.WindowHeight == null || sign.WindowWidth == null)
            return String.Empty;

        string result = GetFilePath(string.Format("signature{0}", signatureId));


        System.Windows.Controls.Image anImage = new System.Windows.Controls.Image();
        anImage.Height = sign.WindowHeight.Value;
        anImage.Width = sign.WindowWidth.Value;
        anImage.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;

        using (var bmp = new System.Drawing.Bitmap((int)sign.WindowWidth.Value, (int)sign.WindowHeight.Value))
        using (var gfx = System.Drawing.Graphics.FromImage(bmp))
        using (var pen = new System.Drawing.Pen(System.Drawing.Color.White))
        {
            // draw one thousand random white lines on a dark blue background
            gfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            gfx.Clear(System.Drawing.Color.Navy);

            var pt1 = new System.Drawing.Point(0, 0);
            var pt2 = new System.Drawing.Point((int)sign.WindowWidth.Value, (int)sign.WindowHeight.Value);
            gfx.DrawLine(pen, pt1, pt2);

            anImage.Source = BmpImageFromBmp(bmp);
        }
       
        //zapisujemy do pliku
        var encoder = new PngBitmapEncoder();
        SaveUsingEncoder(anImage, result, encoder);

        return result;
    }
    catch(Exception exp)
    {
        
    }

    return string.Empty;
}



private BitmapImage BmpImageFromBmp(System.Drawing.Bitmap bmp)
{
    using (var memory = new System.IO.MemoryStream())
    {
        bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
        memory.Position = 0;

        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.StreamSource = memory;
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.EndInit();
        bitmapImage.Freeze();

        return bitmapImage;
    }
}

private void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)
{
    RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.Width, (int)visual.Height, 96, 96, PixelFormats.Pbgra32);
    bitmap.Render(visual);
    BitmapFrame frame = BitmapFrame.Create(bitmap);
    encoder.Frames.Add(frame);

    using (var stream = File.Create(fileName))
    {
        encoder.Save(stream);
    }
}
1

Chyba powinno być:

using (var gfx = System.Drawing.Graphics.FromImage(anImage))

Ten gfx to jest obiekt grafiki obrazka, na którym chcesz malować.

Z drugiej strony, jak chcesz utworzyć bitmapę, namalować cos na niej i zapisać, to wykona wszystko na bmp = new System.Drawing.Bitmap i potem zapisz za pomocą bmp.Save(). Nie potrzeba żadnych obiektów związanych z WPF.

0

@andrzejlisek:

Ten tok myślenia

@WojtexProgramista:

Musisz nauczyć się ciąć problemy na podproblemy, i impelmentowac po analizie.
W kontekście tutejszym, powinieneś dostrzec że tworzenie pliku z obrazkiem, nie ma nic wspólnego z frameworkiem GUI.

Plik z obrazkiem to tylko plik z obrazkiem, nie ma nic do środowiska, nie jest specyficzny do Androida, Weba, WPF, Forms. Moze prowstać w programie command-line / servisie / demonie, które nie mają żadnych opcji ku jego prezentacji - a plik nadal ma sens.

0
andrzejlisek napisał(a):

Chyba powinno być:

using (var gfx = System.Drawing.Graphics.FromImage(anImage))

Ten gfx to jest obiekt grafiki obrazka, na którym chcesz malować.

Z drugiej strony, jak chcesz utworzyć bitmapę, namalować cos na niej i zapisać, to wykona wszystko na bmp = new System.Drawing.Bitmap i potem zapisz za pomocą bmp.Save(). Nie potrzeba żadnych obiektów związanych z WPF.

Dzięki za podpowiedź.
Rzeczywiście, trochę się zafiksowałem. A wystarczyło proste rysowanie na bitmap'ie:

System.Drawing.Bitmap anImage = new System.Drawing.Bitmap((int)sign.WindowWidth.Value, (int)sign.WindowHeight.Value);
               
                using (var gfx = System.Drawing.Graphics.FromImage(anImage))
                using (var pen = new System.Drawing.Pen(System.Drawing.Color.Black, 1))
                {
                    gfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;

                    var pt1 = new System.Drawing.Point(0, 0);
                    var pt2 = new System.Drawing.Point((int)sign.WindowWidth.Value, (int)sign.WindowHeight.Value);
                    gfx.DrawLine(pen, pt1, pt2);
                    
                    anImage.Save(result);
                }

I wszystko zadziałało.
Jeszcze raz dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1