Искажается изображение

110
21 мая 2021, 09:20

Всем доброго времени суток. Подскажите пожалуйста, почему используя код приведенный ниже (Перерисовка изображений формата PCX в Png) некоторые изображения получаются нормальными, а некоторые искаженными?

public static Bitmap PCX_GetImageFromFile(string filename, string img_name)
    {
        BinaryReader binReader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read));
        int totalSize = (int)binReader.BaseStream.Length;
        // Create a new bitmap.
        byte Manufactorer = binReader.ReadByte();
        byte Version = binReader.ReadByte();
        byte Encoding = binReader.ReadByte();
        byte BPP = binReader.ReadByte();
        short xmin = binReader.ReadInt16();
        short ymin = binReader.ReadInt16();
        short xmax = binReader.ReadInt16();
        short ymax = binReader.ReadInt16();
        short hres = binReader.ReadInt16();
        short vres = binReader.ReadInt16();
        byte[] colormap = new byte[48];
        colormap = binReader.ReadBytes(48);
        byte reserved = binReader.ReadByte();
        byte NPlanes = binReader.ReadByte();
        short BPL = binReader.ReadInt16();
        short PaletteInfo = binReader.ReadInt16();
        byte[] Filter = new byte[58];
        Filter = binReader.ReadBytes(58);
        byte[] pal = new byte[256 * 3];
        binReader.BaseStream.Seek(-256 * 3 - 1, SeekOrigin.End);
        byte palExists = binReader.ReadByte();
        if (palExists == 12)
            pal = binReader.ReadBytes(256 * 3);
        binReader.BaseStream.Seek(128, SeekOrigin.Begin);
        short width = (short)(xmax - xmin + 1);
        short height = (short)(ymax - ymin + 1);
        int totalData = totalSize - 769 - 128;
        Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
        ColorPalette bpmPalette = bmp.Palette;
        for (int i = 0; i < bpmPalette.Entries.Length; i++)
            bpmPalette.Entries[i] = Color.FromArgb(pal[i * 3 + 0], pal[i * 3 + 1], pal[i * 3 + 2]);
        bmp.Palette = bpmPalette;
        // Lock the bitmap's bits.  
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        System.Drawing.Imaging.BitmapData bmpData =
            bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
            bmp.PixelFormat);
        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;
        // Declare an array to hold the bytes of the bitmap.
        int bytes = bmpData.Stride * bmp.Height;
        byte[] rgbValues = new byte[bytes];
        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

        int x = 0;
        int y = 0;
        byte count = 0;
        byte data = 0;
        try
        {
            while (totalData > 0)
            {
                count = 1;
                data = binReader.ReadByte();
                totalData--;
                if ((data & 192) == 192)
                {
                    count = (byte)(data & 63);
                    data = binReader.ReadByte();
                    totalData--;
                }
                for (int c = 0; c < count; c++)
                {
                    rgbValues[(y * width + x)] = data;
                    x++;
                    if (x > width - 1)
                    {
                        y++;
                        x = 0;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        // Copy the RGB values back to the bitmap
        System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
        // Unlock the bits.
        bmp.UnlockBits(bmpData);
        // Draw the modified image.
        // PictureBox for checking resulting image
        //pictureBox1.Image = bmp;
        Bitmap bmps = (Bitmap)bmp.Clone();
        binReader.Close();
        bmp.Dispose();
        bmps.Save(/*Directory.GetCurrentDirectory()*/ "source/" + img_name + ".png");
        return bmp;
    }

Фото:

Answer 1

Нашёл ошибку. В этом цикле

for (int c = 0; c < count; c++)
            {
                rgbValues[(y * width + x)] = data;
                x++;
                if (x > width - 1)
                {
                    y++;
                    x = 0;
                }
            }

была неверная строка: rgbValues[(y * width + x)] = data;

Исправил на : rgbValues[(y * bmpData.Stride + x * (BPP / 8))] = data; Теперь искажение пропало)

Если я всё правильно понял, то проблема была в игнорировании bmpData.Stride (Количество байтов в одной строке развертки изображения)

READ ALSO
Поменять Image.Source в WPF

Поменять Image.Source в WPF

Я делаю приложение с WPFВ форме есть кнопка для запуска exe файла, который меняет фотографию photo

108
Button ContextMenu Styling in wpf

Button ContextMenu Styling in wpf

Я пытаюсь присвоить стиль для ContextMenu, чтоб было похоже на интерфейс Дискорда

201
Не получается запретить доступ не авторизованным пользователям на страницу

Не получается запретить доступ не авторизованным пользователям на страницу

хочу запретить доступ не авторизованным пользователям на страницу indexphp и если пользователь пишет в адресной строке /index

113
Помогите сформировать массив на php

Помогите сформировать массив на php

Друзья, помогите сформировать массив

102