C# konwerowanie tablicy byte do Bitmap

0

Cześć piszę aplikację, która otwiera obrazy raw do bitmapy. Poniższy kod działa w następujący sposób: wczytuje w pliku raw wszystkie bity i wczytuje je do tablicy, a z tablicy bity te zapisywane są do bitmapy:

        private void readbutton_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                dialog.Filter = "raw file (*.raw) | *.raw";
                dialog.FilterIndex = 1;

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    byte[] _rawBytes = File.ReadAllBytes(dialog.FileName);

                    using (var ms = new MemoryStream(_rawBytes))
                    {
                        Bitmap image = new Bitmap(ms);
                    }
                }
            }
        }

Po uruchomieniu otrzymuję następujący błąd:
screenshot-20200614223747.png
Czy istnieje jakiś sposób na zapisanie tablicy bitowej do bitmapy?

0

A czemu nie po porostu Bitmap image = new Bitmap(dialog.FileName)?

0

ArgumentException dla Bitmap(Stream) (czyli w Twoim przypadku) wywala się w gdy:

stream does not contain image data or is null.
-or-
stream contains a PNG image file with a single dimension greater than 65,535 pixels.

Zerknij sobie do dokumentacji i sprawdź też w swoim kodzie, co dokładnie próbuje wejść w streamie do konstruktora bitmapy dla image.

0
LowSkiller napisał(a):

ArgumentException dla Bitmap(Stream) (czyli w Twoim przypadku) wywala się w gdy:

stream does not contain image data or is null.
-or-
stream contains a PNG image file with a single dimension greater than 65,535 pixels.

Zerknij sobie do dokumentacji i sprawdź też w swoim kodzie, co dokładnie próbuje wejść w streamie do konstruktora bitmapy dla image.

Przejrzałem dokumentację i spróbowałem użyć image:

        private void readbutton_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                dialog.Filter = "raw file (*.raw) | *.raw";
                dialog.FilterIndex = 1;

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    Bitmap raw = new Bitmap(Image.FromFile(dialog.FileName), new Size(640, 500));
                }
            }
        }

Uzyskałem wyjątek:
screenshot-20200615093015.png

Czy może być tak, że Bitmap nie radzi sobie z obrazkami raw?

0

Co jest w tym pliku .raw? Co to za format?

1

Klasa Bitmap nie obsługuje wszystkich możliwych formatów, tylko niektóre: https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/types-of-bitmaps. Aby obsługiwać własne formaty (cokolwiek to jest za RAW) to musisz to zrobić ręcznie.

0

A może by tak dokumentację przeczytać?

A bitmap consists of the pixel data for a graphics image and its attributes. There are many standard formats for saving a bitmap to a file. GDI+ supports the following file formats: BMP, GIF, EXIF, JPG, PNG and TIFF.

0
Grzegorz Świdwa napisał(a):

Nie znam się ale poczytaj na przykład to:
https://social.msdn.microsoft.com/Forums/en-US/f84cf487-fcef-4e32-aebe-e3c152464b8f/converting-raw-8bit-blackwhite-to-bmp?forum=csharpgeneral

lub to (chyba bardziej przypomina Twój problem)
https://stackoverflow.com/questions/52439389/create-8-bit-bitmap-from-array

A tutaj masz gotowiec, niestety 12bit RAW Data, ale nietrudno to przerobić na 8bit
https://stackoverflow.com/questions/6832948/c-sharp-converting-8-bit-or-16-bit-grayscale-raw-pixel-data

Przerobiłem gotowiec pod swoje potrzeby i kod teraz wygląda tak:

public class RAW2Image
    {
        /// <summary>
        /// Konwersja tablicy bitowej do bitmapy
        /// </summary>
        /// <param name="input">Tablica byte</param>
        /// <param name="width">szerokość</param>
        /// <param name="height">wysokość</param>
        /// <param name="bit">ilość bitów</param>
        /// <returns></returns>
        public static Bitmap Convert(byte[] input, int width, int height, int bit)
        {
            Bitmap bitmap = null;

            switch (bit)
            {
                case 8:
                    bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                    break;
                case 16:
                    bitmap = new Bitmap(width, height, PixelFormat.Format16bppGrayScale);
                    break;
                case 24:
                    bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                    break;
                case 32:
                    bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
                    break;
            }

            var rect = new Rectangle(0, 0, width, height);

            var lut = CreateLut(bit);

            var bitmap_data = bitmap.LockBits(rect, ImageLockMode.WriteOnly, bitmap.PixelFormat);

            ConvertCore(width, height, bit, input, bitmap_data, lut);

            bitmap.UnlockBits(bitmap_data);

            return bitmap;
        }

        private static uint[] CreateLut(int bits)
        {
            // Create a linear LUT to convert from grayscale to ARGB

            int max_input = 1 << bits;

            uint[] lut = new uint[max_input];

            for (int i = 0; i < max_input; i++)
            {
                // map input value to 8-bit range
                //
                byte intensity = (byte)((i * 0xFF) / max_input);

                // create ARGB output value A=255, R=G=B=intensity
                //
                lut[i] = (uint)(0xFF000000L | (intensity * 0x00010101L));
            }

            return lut;
        }

        private static unsafe void ConvertCore(int width, int height, int bits, byte[] input, BitmapData output, uint[] lut)
        {
            // Copy pixels from input to output, applying LUT

            ushort mask = (ushort)((1 << bits) - 1);

            int in_stride = output.Stride;
            int out_stride = width * 2;

            byte* out_data = (byte*)output.Scan0;

            fixed (byte* in_data = input)
            {
                for (int y = 0; y < height; y++)
                {
                    uint* out_row = (uint*)(out_data + (y * in_stride));

                    ushort* in_row = (ushort*)(in_data + (y * out_stride));

                    for (int x = 0; x < width; x++)
                    {
                        ushort in_pixel = (ushort)(in_row[x] & mask);

                        out_row[x] = lut[in_pixel];
                    }
                }
            }
        }
    }

Kod zwraca wyjątek:
screenshot-20200615173703.png
Co do tego Exception znalazłem takie rozwiązanie: https://stackoverflow.com/questions/13884503/bitmap-lockbits-error-parameter-is-not-valid-when-bitmap-is-a-certain-size
Jednak ono wyrzuciło znowu takie Exception
screenshot-20200615174340.png

1

Jeszcze nie jestem przy swoim kompie, żeby Ci pomóc, ale jest jedna rzecz, która mocno mnie razi i muszę o niej wspomnieć już teraz:
Visual Studio w języku polskim.
Weź pod uwagę, że jak będziesz miał wszystko po angielsku to z jednej strony poprawisz angielski, a z drugiej strony łatwiej Ci będzie szukać rozwiązań w internecie. Wystarczy, że będziesz kopiował sobie tekst z wyjątku i wklejał do przeglądarki (nie musisz go wtedy tłumaczyć i tracić przez to dokładny kontekst). Już nie mówiąc, że łatwiej jest klepać tutoriale z neta, bo większość jest po angielsku i wkurza zastanawianie się non-stop co kliknąć, bo mając swoje środowisko do pracy po polsku nie czaisz, które opcja jest która (jak zaczynałem z C# na studiach, to ten punkt mnie przekonał do przeskoczenia z PL na EN).
I zobaczysz wtedy, że po bardzo krótkim czasie tak się przestawisz, że będziesz się wykrzywiał patrząc na tłumaczenia z książek programistycznych przetłumaczonych na język polski. ;)

0

Czy szerokość i wysokość jest dokładnie taka sama jak w pliku RAW?

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