Помогите с растровым декодером - PullRequest
4 голосов
/ 11 апреля 2011

Я работал над растровым декодером, но мой алгоритм обработки пиксельных данных не совсем верный:

    public IntPtr ReadPixels(Stream fs, int offset, int width, int height, int bpp)
    {
        IntPtr bBits;

        int pixelCount = bpp * width * height;
        int Row = 0;
        decimal value = ((bpp*width)/32)/4;
        int RowSize = (int)Math.Ceiling(value);
        int ArraySize = RowSize * Math.Abs(height);
        int Col = 0;
        Byte[] BMPData = new Byte[ArraySize];

        BinaryReader r = new BinaryReader(fs);
        r.BaseStream.Seek(offset, SeekOrigin.Begin);

        while (Row < height)
        {
            Byte ReadByte;

            if (!(Col >= RowSize))
            {                       
                ReadByte = r.ReadByte();
                BMPData[(Row * RowSize) + Col] = ReadByte;
                Col += 1;                    
            }

            if (Col >= RowSize)
            {
                Col = 0;
                Row += 1;
            }
        }

        bBits = System.Runtime.InteropServices.Marshal.AllocHGlobal(BMPData.Length);
        System.Runtime.InteropServices.Marshal.Copy(BMPData, 0, bBits, BMPData.Length);

        return bBits;
}

Я могу обрабатывать только монохромные растровые изображения, а в некоторых частях растровое изображение обрабатывается нормально. Ни один из них не сжимается, а отображается вверх ногами и переворачивается. Я действительно мог бы помочь с этим.

Ответы [ 3 ]

3 голосов
/ 11 апреля 2011

Вы игнорируете шаг.

Строки изображения могут быть дополнены влево дополнительными байтами, чтобы разделить их размер на число, такое как (1 = без заполнения, 2, 4, 8 = по умолчанию длямного изображений, 16, ...).

Кроме того, изображения могут представлять собой прямоугольную область в большом изображении, что делает «отступ» между строками в меньшем изображении еще большим (поскольку шаг является большим изображениемшаг).- В этом случае у изображения также может быть смещение для его начальной точки в буфере.

Лучшая практика:

// Overload this method 3 time for different bit per SUB-pixel values (8, 16, or 32)
// = (byte, int, float)
// SUB-pixel != pixel (= 1 3 or 4 sub-pixels (grey or RGB or BGR or BGRA or RGBA or ARGB or ABGR)
unsafe
{
    byte[] buffer = image.Buffer;
    int stride = image.buffer.Length / image.PixelHeight;
    // or int stride = image.LineSize; (or something like that)

    fixed (float* regionStart = (float*)(void*)buffer) // or byte* or int* depending on datatype
    {
        for (int y = 0; y < height; y++) // height in pixels
        {
            // float* and float or byte* and byte or int* and int
            float* currentPos
                = regionStart + offset / SizeOf(float) + stride / SizeOf(float) * y;

            for (int x = 0; x < width; x++) // width in pixels
            {
                for (int chan = 0; chan < channel; chan++) // 1, 3 or 4 channels
                {
                    // DO NOT USE DECIMAL - you want accurate image values
                    // with best performance - primative types
                    // not a .NET complex type used for nice looking values for users e.g. 12.34
                    // instead use actual sub pixel type (float/int/byte) or double instead!
                    var currentValue = value;

                    currentPos++;
                }
            }
        }
    }
}
3 голосов
/ 11 апреля 2011
    decimal value = ((bpp*width)/32)/4;
    int RowSize = (int)Math.Ceiling(value);

Это не правильно. Ваша переменная RowSize фактически называется "шагом". Вы вычисляете это так:

    int bytes = (width * bitsPerPixel + 7) / 8;
    int stride = 4 * ((bytes + 3) / 4);
0 голосов
/ 11 апреля 2011

Я нахожу что-то, чего не понимаю:

decimal value = ((bpp*width)/32)/4;
int RowSize = (int)Math.Ceiling(value);

RowSize, по моему мнению, должно быть (bpp*width) / 8 + (bpp%8==0?0:1)

...