Example #1
0
        private unsafe bool bFillColorTable(IntPtr hdc, IntPtr hpal, uint num3, ref BITMAPINFO_FLAT pbmi)
        {
            // bool flag = false;
            byte[] lppe = new byte[sizeof(PALETTEENTRY) * 0x100];
            fixed(byte *numRef = pbmi.bmiColors)
            {
                Contract.Assume(numRef != null);

                fixed(byte *numRef2 = lppe)
                {
                    Contract.Assume(numRef2 != null);

                    RGBQUAD *     rgbquadPtr      = (RGBQUAD *)numRef;
                    PALETTEENTRY *paletteentryPtr = (PALETTEENTRY *)numRef2;

                    int nEntries = ((int)1) << pbmi.bmiHeader_biBitCount;

                    if (nEntries <= 0x100)
                    {
                        // if (num3 != 0)
                        {
                            for (int i = 0; i < nEntries; i++)
                            {
                                rgbquadPtr[i].rgbRed      = paletteentryPtr[i].peRed;
                                rgbquadPtr[i].rgbGreen    = paletteentryPtr[i].peGreen;
                                rgbquadPtr[i].rgbBlue     = paletteentryPtr[i].peBlue;
                                rgbquadPtr[i].rgbReserved = 0;
                            }
                        }
                    }
                }
            }

            return(false);
        }
Example #2
0
        public static void ConvertPixelByPixel(IntPtr ipd, out int width, out int height)
        {
            // get the info about the HBITMAP inside the IPictureDisp
            DIBSECTION dibsection = new DIBSECTION();
            var        res        = GetObjectDIBSection(ipd, Marshal.SizeOf(dibsection), ref dibsection);

            width  = dibsection.dsBm.bmWidth;
            height = dibsection.dsBm.bmHeight;
            unsafe {
                //Check is that 32bit bitmap
                if (dibsection.dsBmih.biBitCount == 32)
                {
                    // get a pointer to the raw bits
                    RGBQUAD *pBits = (RGBQUAD *)(void *)dibsection.dsBm.bmBits;

                    // copy each pixel manually and premultiply the color values
                    for (int x = 0; x < dibsection.dsBmih.biWidth; x++)
                    {
                        for (int y = 0; y < dibsection.dsBmih.biHeight; y++)
                        {
                            int offset = y * dibsection.dsBmih.biWidth + x;
                            if (pBits[offset].rgbReserved > 0 && (pBits[offset].rgbBlue > pBits[offset].rgbReserved || pBits[offset].rgbGreen > pBits[offset].rgbReserved || pBits[offset].rgbRed > pBits[offset].rgbReserved))
                            {
                                pBits[offset].rgbBlue  = (byte)((((int)pBits[offset].rgbBlue * (int)pBits[offset].rgbReserved + 1) * 257) >> 16);
                                pBits[offset].rgbGreen = (byte)((((int)pBits[offset].rgbGreen * (int)pBits[offset].rgbReserved + 1) * 257) >> 16);
                                pBits[offset].rgbRed   = (byte)((((int)pBits[offset].rgbRed * (int)pBits[offset].rgbReserved + 1) * 257) >> 16);
                            }
                        }
                    }
                }
            }
        }
Example #3
0
        //-------------------------------------------------------------------
        // TransformImage_YUY2
        //
        // YUY2 to RGB-32
        //-------------------------------------------------------------------
        unsafe private static void TransformImage_YUY2(
            IntPtr pDest,
            int lDestStride,
            IntPtr pSrc,
            int lSrcStride,
            int dwWidthInPixels,
            int dwHeightInPixels)
        {
            YUYV *   pSrcPel  = (YUYV *)pSrc;
            RGBQUAD *pDestPel = (RGBQUAD *)pDest;

            lSrcStride  /= 4; // convert lSrcStride to YUYV
            lDestStride /= 4; // convert lDestStride to RGBQUAD

            for (int y = 0; y < dwHeightInPixels; y++)
            {
                for (int x = 0; x < dwWidthInPixels / 2; x++)
                {
                    pDestPel[x * 2]       = ConvertYCrCbToRGB(pSrcPel[x].Y, pSrcPel[x].V, pSrcPel[x].U);
                    pDestPel[(x * 2) + 1] = ConvertYCrCbToRGB(pSrcPel[x].Y2, pSrcPel[x].V, pSrcPel[x].U);
                }

                pSrcPel  += lSrcStride;
                pDestPel += lDestStride;
            }
        }
Example #4
0
        unsafe static private int ARGB32_To_RGB24(
            int dwWidthInPixels,
            int dwHeightInPixels,
            int dwDestStride,
            IntPtr ipSrc,
            IntPtr ipDest
            )
        {
            RGBQUAD *pSrc  = (RGBQUAD *)ipSrc;
            RGB24 *  pDest = (RGB24 *)ipDest;

            for (int y = 0; y < dwHeightInPixels; y++)
            {
                for (int x = 0; x < dwWidthInPixels; x++)
                {
                    pDest[x].rgbRed   = pSrc[x].R;
                    pDest[x].rgbGreen = pSrc[x].G;
                    pDest[x].rgbBlue  = pSrc[x].B;
                }

                pSrc  += dwWidthInPixels * 3;
                pDest += dwDestStride;
            }

            return(dwDestStride * dwHeightInPixels);
        }
        public static Bitmap ConvertPixelByPixel(IPictureDisp ipd)
        {
            // get the info about the HBITMAP inside the IPictureDisp
            DIBSECTION dibsection = new DIBSECTION();

            GetObjectDIBSection((IntPtr)ipd.Handle, Marshal.SizeOf(dibsection), ref dibsection);
            int width  = dibsection.dsBm.bmWidth;
            int height = dibsection.dsBm.bmHeight;

            // create the destination Bitmap object
            Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

            unsafe
            {
                // get a pointer to the raw bits
                RGBQUAD *pBits = (RGBQUAD *)(void *)dibsection.dsBm.bmBits;

                // copy each pixel manually
                for (int x = 0; x < dibsection.dsBmih.biWidth; x++)
                {
                    for (int y = 0; y < dibsection.dsBmih.biHeight; y++)
                    {
                        int offset = y * dibsection.dsBmih.biWidth + x;
                        if (pBits[offset].rgbReserved != 0)
                        {
                            bitmap.SetPixel(x, y, Color.FromArgb(pBits[offset].rgbReserved, pBits[offset].rgbRed, pBits[offset].rgbGreen, pBits[offset].rgbBlue));
                        }
                    }
                }
            }

            return(bitmap);
        }
        public static Bitmap ConvertWithAlphaBlend(IPictureDisp ipd)
        {
            // get the info about the HBITMAP inside the IPictureDisp
            DIBSECTION dibsection = new DIBSECTION();

            GetObjectDIBSection((IntPtr)ipd.Handle, Marshal.SizeOf(dibsection), ref dibsection);
            int width  = dibsection.dsBm.bmWidth;
            int height = dibsection.dsBm.bmHeight;

            // zero out the RGB values for all pixels with A == 0
            // (AlphaBlend expects them to all be zero)
            unsafe
            {
                RGBQUAD *pBits = (RGBQUAD *)(void *)dibsection.dsBm.bmBits;

                for (int x = 0; x < dibsection.dsBmih.biWidth; x++)
                {
                    for (int y = 0; y < dibsection.dsBmih.biHeight; y++)
                    {
                        int offset = y * dibsection.dsBmih.biWidth + x;
                        if (pBits[offset].rgbReserved == 0)
                        {
                            pBits[offset].rgbRed   = 0;
                            pBits[offset].rgbGreen = 0;
                            pBits[offset].rgbBlue  = 0;
                        }
                    }
                }
            }

            // create the destination Bitmap object
            Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

            // get the HDCs and select the HBITMAP
            Graphics graphics = Graphics.FromImage(bitmap);

            IntPtr hdcDest      = graphics.GetHdc();
            IntPtr hdcSrc       = CreateCompatibleDC(hdcDest);
            IntPtr hobjOriginal = SelectObject(hdcSrc, (IntPtr)ipd.Handle);

            // render the bitmap using AlphaBlend
            BLENDFUNCTION blendfunction = new BLENDFUNCTION(AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA);

            AlphaBlend(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, width, height, blendfunction);

            // clean up
            SelectObject(hdcSrc, hobjOriginal);
            DeleteDC(hdcSrc);
            graphics.ReleaseHdc(hdcDest);
            graphics.Dispose();

            return(bitmap);
        }
Example #7
0
        //-------------------------------------------------------------------
        // TransformImage_RGB24
        //
        // RGB-24 to RGB-32
        //-------------------------------------------------------------------
        unsafe private static void TransformImage_RGB24(IntPtr pDest, int lDestStride, IntPtr pSrc, int lSrcStride, int dwWidthInPixels, int dwHeightInPixels)
        {
            RGB24 *  source = (RGB24 *)pSrc;
            RGBQUAD *dest   = (RGBQUAD *)pDest;

            lSrcStride  /= 3;
            lDestStride /= 4;

            for (int y = 0; y < dwHeightInPixels; y++)
            {
                for (int x = 0; x < dwWidthInPixels; x++)
                {
                    dest[x].R = source[x].rgbRed;
                    dest[x].G = source[x].rgbGreen;
                    dest[x].B = source[x].rgbBlue;
                    dest[x].A = 0;
                }

                source += lSrcStride;
                dest   += lDestStride;
            }
        }
Example #8
0
        unsafe static private int ARGB32_To_YUY2(
            int dwWidthInPixels,
            int dwHeightInPixels,
            int dwDestStride,
            IntPtr ipSrc,
            IntPtr ipDest
            )
        {
            Debug.Assert(dwDestStride >= (dwWidthInPixels * 2));

            RGBQUAD *pSrcPixel  = (RGBQUAD *)ipSrc;
            YUYV *   pDestPixel = (YUYV *)ipDest;
            int      dwUseWidth = dwWidthInPixels / 2;

            // invert
            pSrcPixel += (dwHeightInPixels - 1) * dwWidthInPixels;

            for (int y = 0; y < dwHeightInPixels; y++)
            {
                for (int x = 0; x < dwUseWidth; x++)
                {
                    pDestPixel[x].Y = (byte)(((66 * pSrcPixel->R + 129 * pSrcPixel->G + 25 * pSrcPixel->B + 128) >> 8) + 16);
                    pDestPixel[x].U = (byte)(((-38 * pSrcPixel->R - 74 * pSrcPixel->G + 112 * pSrcPixel->B + 128) >> 8) + 128);

                    pSrcPixel++;

                    pDestPixel[x].Y2 = (byte)(((66 * pSrcPixel->R + 129 * pSrcPixel->G + 25 * pSrcPixel->B + 128) >> 8) + 16);
                    pDestPixel[x].V  = (byte)(((112 * pSrcPixel->R - 94 * pSrcPixel->G - 18 * pSrcPixel->B + 128) >> 8) + 128);

                    pSrcPixel++;
                }
                pDestPixel = &pDestPixel[dwDestStride / sizeof(YUYV)];

                // Invert
                pSrcPixel -= dwWidthInPixels * 2;
            }

            return((int)((byte *)pDestPixel - (byte *)ipDest));
        }
Example #9
0
        public unsafe void BlitMBMP(MBMP mbmp, RECTANGLE dest, GPT_UnkStruct1 *unkStruct)
        {
            RECTANGLE clip = default;

            if (unkStruct->Clip != null)
            {
                clip.Copy(in * unkStruct->Clip);
                if (!clip.CalculateIntersection(in dest))
                {
                    return;
                }
            }
            else
            {
                clip.Copy(in dest);
            }

            mbmp.GetRect(out var mbmpRect); // call 0x0043F7D0
            if (mbmpRect.Y1 < mbmpRect.Y2 && mbmpRect.X1 < mbmpRect.X2)
            {
                if (BitDepth == 8)
                {
                    if (dest.X1 - dest.X2 + mbmpRect.X2 != mbmpRect.X1 || dest.Y1 - dest.Y2 + mbmpRect.Y2 != mbmpRect.Y1)
                    {
                        // FIXME: The file dialog screens are black for some reason.
                        // 0042B451
                        PInvoke.Call(LibraryNames.GDI32, "SetTextColor", DC, new IntPtr(0x2FFFFFF));
                        PInvoke.Call(LibraryNames.GDI32, "SetBkColor", DC, new IntPtr(0x2000000));
                        mbmpRect.TopLeftOrigin();
                        if (FromPointer <GPT>(UnmanagedFunctionCall.StdCall((IntPtr)FunctionNames.AllocateGPT, new IntPtr(&mbmpRect), new IntPtr(1))) is GPT gptMaskMaybe)
                        {
                            UnmanagedFunctionCall.ThisCall((IntPtr)FunctionNames.MBMP_00425850, mbmp.NativeHandle.Address, gptMaskMaybe.PixelBuffer, (IntPtr)gptMaskMaybe.Stride, new IntPtr(mbmpRect.Height), new IntPtr(-mbmpRect.X1), new IntPtr(-mbmpRect.Y1), new IntPtr(&mbmpRect)); // call 0x00425850
                            UnmanagedFunctionCall.ThisCall((IntPtr)FunctionNames.GPT__0042A550, NativeHandle.Address, new IntPtr(&unkStruct->Clip));
                            PInvoke.Call(LibraryNames.GDI32, "StretchBlt", DC, new IntPtr(dest.X1), new IntPtr(dest.X2), new IntPtr(dest.Width), new IntPtr(dest.Height), gptMaskMaybe.DC, IntPtr.Zero, IntPtr.Zero, new IntPtr(mbmpRect.Width), new IntPtr(mbmpRect.Height), new IntPtr(0xEE0086));
                            gptMaskMaybe.VirtualCall(0x10); // Free?

                            if (FromPointer <GPT>(UnmanagedFunctionCall.StdCall((IntPtr)FunctionNames.AllocateGPT, new IntPtr(&mbmpRect), new IntPtr(8))) is GPT gptColor)
                            {
                                RECTANGLE fill = default;
                                mbmpRect.SizeLimit(ref fill);

                                PInvoke.Call(LibraryNames.USER32, "FillRect", gptColor.DC, new IntPtr(&fill), PInvoke.Call(LibraryNames.GDI32, "GetStockObject", IntPtr.Zero));
                                UnmanagedFunctionCall.StdCall((IntPtr)FunctionNames.GDIFlush);

                                mbmp.Blit(gptColor.PixelBuffer, gptColor.Stride, mbmpRect.Height, -mbmpRect.X1, -mbmpRect.Y1, &mbmpRect, null);

                                PInvoke.Call(LibraryNames.GDI32, "StretchBlt", DC, new IntPtr(dest.X1), new IntPtr(dest.Y1), new IntPtr(dest.Width), new IntPtr(dest.Height), gptColor.DC, IntPtr.Zero, IntPtr.Zero, new IntPtr(mbmpRect.Width), new IntPtr(mbmpRect.Height), new IntPtr(0x8800C6));
                                gptColor.VirtualCall(0x10); // Free?
                            }
                        }
                    }
                    else
                    {
                        // 0042B3F0

                        if (clip.CalculateIntersection(in Bounds))
                        {
                            if (FlushCounter >= APP.FlushCounter)
                            {
                                UnmanagedFunctionCall.StdCall((IntPtr)FunctionNames.GDIFlush);
                            }
                            int offsetX = dest.X1 - mbmpRect.X1;
                            int offsetY = dest.Y1 - mbmpRect.Y1;
                            mbmp.Blit(PixelBuffer, Stride, Bounds.Height, offsetX, offsetY, &clip, Region);
                            //var tex = mbmp.GetTexture(graphicsDevice);
                            //if (tex != null)
                            //{
                            //    var _dest = new Rectangle(offsetX, offsetY, mbmpRect.Width, mbmpRect.Height);
                            //    var _clip = new Rectangle(clip.X1, clip.Y1, clip.Width, clip.Height);
                            //    RenderTexture(tex, _dest, _clip);
                            //}
                        }
                    }
                }
                else if (BitDepth == 32)
                {
                    // TODO: Implement 32 bit GPT
                    if (clip.CalculateIntersection(in Bounds))
                    {
                        if (FlushCounter >= APP.FlushCounter)
                        {
                            UnmanagedFunctionCall.StdCall((IntPtr)FunctionNames.GDIFlush);
                        }
                        int offsetX = dest.X1 - mbmpRect.X1;
                        int offsetY = dest.Y1 - mbmpRect.Y1;
                        if (temp == null || temp.Length != Width * Height)
                            temp = new byte[Width * Height];
                        fixed(byte *b = temp)
                        {
                            mbmp.Blit(new IntPtr(b), 8, Bounds.Height, offsetX, offsetY, &clip, null);
                            RGBQUAD *p = (RGBQUAD *)PixelBuffer;

                            for (int y = clip.Y1; y < clip.Y2; y++)
                            {
                                for (int x = clip.X1; x < clip.X2; x++)
                                {
                                    int i = y * Width + x;
                                    *(p + i) = APP.Palette[b[i]];
                                }
                            }
                        }
                    }
                }
            }
        }
Example #10
0
 public unsafe static extern void CopyMemory(RGBQUAD *dest, byte *src, int cb);
Example #11
0
        public static Bitmap LoadImageFormFreeImage(string FileName)
        {
            Bitmap            Bmp = null;
            FREE_IMAGE_FORMAT fif = FREE_IMAGE_FORMAT.FIF_UNKNOWN;;

            if (FreeImage.IsAvailable() == true)
            {
                fif = FreeImage.GetFileType(FileName, 0);
                if (fif == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
                {
                    fif = FreeImage.GetFIFFromFilename(FileName);
                }

                if ((fif != FREE_IMAGE_FORMAT.FIF_UNKNOWN) && (FreeImage.FIFSupportsReading(fif) != false))
                {
                    FIBITMAP    Dib = FreeImage.Load(fif, FileName, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
                    uint        Bpp = FreeImage.GetBPP(Dib);
                    PixelFormat PF;
                    uint        Width, Height, Stride;
                    switch (Bpp)
                    {
                    case 1:
                        PF = PixelFormat.Format1bppIndexed; break;

                    case 4:
                        PF = PixelFormat.Format4bppIndexed; break;

                    case 8:
                        PF = PixelFormat.Format8bppIndexed; break;

                    case 16:
                        PF = PixelFormat.Format16bppRgb555; break;

                    case 24:
                        PF = PixelFormat.Format24bppRgb; break;

                    case 32:
                        PF = PixelFormat.Format32bppArgb; break;

                    default:
                        FreeImage.Unload(Dib);
                        return(null);
                    }
                    Width  = FreeImage.GetWidth(Dib);                       //  图像宽度
                    Height = FreeImage.GetHeight(Dib);                      //  图像高度
                    Stride = FreeImage.GetPitch(Dib);                       //  图像扫描行的大小,必然是4的整数倍

                    IntPtr Bits = FreeImage.GetBits(Dib);
                    Bmp = new Bitmap((int)Width, (int)Height, (int)Stride, PF, Bits);
                    Bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);         // 调用GDI+自己的旋转函数


                    if (Bpp <= 8)
                    {
                        ColorPalette Pal     = Bmp.Palette;                 //  设置调色板
                        RGBQUAD *    GdiPal  = (RGBQUAD *)FreeImage.GetPalette(Dib);
                        int          ClrUsed = FreeImage.GetUniqueColors(Dib);
                        for (int I = 0; I < ClrUsed; I++)
                        {
                            Pal.Entries[I] = Color.FromArgb(255, GdiPal[I].Red, GdiPal[I].Green, GdiPal[I].Blue);
                        }
                        Bmp.Palette = Pal;
                    }
                    FreeImage.Unload(Dib);          // 使用方案2则可以立马释放
                    return(Bmp);
                }
            }
            return(null);
        }
Example #12
0
        unsafe static private int ARGB32_To_NV12(
            int dwWidthInPixels,
            int dwHeightInPixels,
            int dwDestStride,
            IntPtr ipSrc,
            IntPtr ipDest
            )
        {
            Debug.Assert(dwWidthInPixels % 2 == 0);
            Debug.Assert(dwHeightInPixels % 2 == 0);
            Debug.Assert(dwDestStride >= dwWidthInPixels);

            RGBQUAD *pSrcRow = (RGBQUAD *)ipSrc;
            byte *   pDestY  = (byte *)ipDest;

            // Convert the Y plane.
            for (int y = 0; y < dwHeightInPixels; y++)
            {
                RGBQUAD *pSrcPixel = (RGBQUAD *)pSrcRow;

                for (int x = 0; x < dwWidthInPixels; x++)
                {
                    // Y0
                    pDestY[x] = (byte)(((66 * pSrcPixel[x].R + 129 * pSrcPixel[x].G + 25 * pSrcPixel[x].B + 128) >> 8) + 16);
                }
                pDestY  += dwDestStride;
                pSrcRow += dwWidthInPixels;
            }

            // Calculate the offsets for the V and U planes.
            // In NV12, each chroma plane has equal stride and half the height as the Y plane.
            byte *pDestUV = (byte *)ipDest;

            pDestUV += (dwDestStride * dwHeightInPixels);

            // Convert the V and U planes.
            // NV12 is a 4:2:0 format, so each chroma sample is derived from four RGB pixels.
            // The chroma samples are packed in one plane (U,V)
            pSrcRow = (RGBQUAD *)ipSrc;
            for (int y = 0; y < dwHeightInPixels; y += 2)
            {
                RGBQUAD *pSrcPixel   = (RGBQUAD *)pSrcRow;
                RGBQUAD *pNextSrcRow = (RGBQUAD *)(pSrcRow + dwWidthInPixels);

                byte *pbUV = pDestUV;

                for (int x = 0; x < dwWidthInPixels; x += 2)
                {
                    // Use a simple average to downsample the chroma.

                    // U
                    *pbUV++ = (byte)((
                                         (byte)(((-38 * pSrcPixel[x].R - 74 * pSrcPixel[x].G + 112 * pSrcPixel[x].B + 128) >> 8) + 128) +
                                         (byte)(((-38 * pSrcPixel[x + 1].R - 74 * pSrcPixel[x + 1].G + 112 * pSrcPixel[x + 1].B + 128) >> 8) + 128) +
                                         (byte)(((-38 * pNextSrcRow[x].R - 74 * pNextSrcRow[x].G + 112 * pNextSrcRow[x].B + 128) >> 8) + 128) +
                                         (byte)(((-38 * pNextSrcRow[x + 1].R - 74 * pNextSrcRow[x + 1].G + 112 * pNextSrcRow[x + 1].B + 128) >> 8) + 128)
                                         ) / 4);

                    // V
                    *pbUV++ = (byte)((
                                         (byte)(((112 * pSrcPixel[x].R - 94 * pSrcPixel[x].G - 18 * pSrcPixel[x].B + 128) >> 8) + 128) +
                                         (byte)(((112 * pSrcPixel[x + 1].R - 94 * pSrcPixel[x + 1].G - 18 * pSrcPixel[x + 1].B + 128) >> 8) + 128) +
                                         (byte)(((112 * pNextSrcRow[x].R - 94 * pNextSrcRow[x].G - 18 * pNextSrcRow[x].B + 128) >> 8) + 128) +
                                         (byte)(((112 * pNextSrcRow[x + 1].R - 94 * pNextSrcRow[x + 1].G - 18 * pNextSrcRow[x + 1].B + 128) >> 8) + 128)
                                         ) / 4);
                }
                pDestUV += dwDestStride;

                // Skip two lines on the source image.
                pSrcRow += (dwWidthInPixels * 2);
            }

            return((int)(pDestUV - (byte *)ipDest));
        }
        public GR.Memory.ByteBuffer CreateHDIBAsBuffer()
        {
            GR.Memory.ByteBuffer result = new GR.Memory.ByteBuffer();
            BITMAPINFOHEADER     bi     = new BITMAPINFOHEADER();
            int    dwLen;
            IntPtr hDIB;

            if ((BitsPerPixel != 1) &&
                (BitsPerPixel != 2) &&
                (BitsPerPixel != 4) &&
                (BitsPerPixel != 8) &&
                (BitsPerPixel != 15) &&
                (BitsPerPixel != 16) &&
                (BitsPerPixel != 24) &&
                (BitsPerPixel != 32))
            {
                // not supported depth
                return(null);
            }

            bi.biSize     = System.Runtime.InteropServices.Marshal.SizeOf(bi);
            bi.biWidth    = Width;
            bi.biHeight   = Height;
            bi.biPlanes   = 1;
            bi.biBitCount = (short)BitsPerPixel;
            if (bi.biBitCount == 15)
            {
                bi.biBitCount = 16;
            }
            bi.biCompression = (int)BitmapCompression.BI_RGB;

            bi.biSizeImage     = (int)(((((uint)bi.biWidth * bi.biBitCount) + 31) / 32 * 4) * bi.biHeight);
            bi.biXPelsPerMeter = 0;
            bi.biYPelsPerMeter = 0;
            bi.biClrUsed       = 0;
            bi.biClrImportant  = 0;

            // calculate size of memory block required to store BITMAPINFO
            dwLen = bi.biSize + PaletteSize(bi) + bi.biSizeImage;

            hDIB = System.Runtime.InteropServices.Marshal.AllocHGlobal(dwLen);
            if (hDIB == IntPtr.Zero)
            {
                // uh oh
                return(null);
            }
            unsafe
            {
                // lock memory block and get pointer to it
                BITMAPINFOHEADER *lpbi = (BITMAPINFOHEADER *)GlobalLock(hDIB);

                // Daten in den Puffer kopieren
                *lpbi = bi;

                // Bild-Daten kopieren
                switch (bi.biBitCount)
                {
                case 1:
                {
                    // Palette in DC setzen
                    if (PaletteEntryCount > 0)
                    {
                        RGBQUAD *bmiColor;

                        bmiColor = (RGBQUAD *)((byte *)lpbi + lpbi->biSize);

                        for (int i = 0; i < 2; i++)
                        {
                            bmiColor[i].rgbRed      = PaletteRed(i);
                            bmiColor[i].rgbGreen    = PaletteGreen(i);
                            bmiColor[i].rgbBlue     = PaletteBlue(i);
                            bmiColor[i].rgbReserved = 0;
                        }
                    }

                    byte *pData = (byte *)lpbi + lpbi->biSize + PaletteSize(bi);

                    int iLO = Width / 8;
                    if ((Width & 7) != 0)
                    {
                        iLO++;
                    }
                    if ((iLO % 4) != 0)
                    {
                        iLO += 4 - (iLO % 4);
                    }

                    /*
                     * GR::Graphic::ContextDescriptor    cdImage( Image );
                     * GR::Graphic::ContextDescriptor    cdTarget;
                     *
                     * cdTarget.Attach( cdImage.Width(), cdImage.Height(), iLO, cdImage.ImageFormat(), pData );
                     *
                     * for ( int j = 0; j < Image.Height(); j++ )
                     * {
                     * cdTarget.HLine( 0, cdTarget.Width() - 1, j, 1 );
                     * cdTarget.HLine( 1, cdTarget.Width() - 2, j, 0 );
                     * }*/
                }
                break;

                case 4:
                {
                    // Palette in DC setzen
                    if (PaletteEntryCount > 0)
                    {
                        RGBQUAD *bmiColor = (RGBQUAD *)((byte *)lpbi + lpbi->biSize);

                        for (int i = 0; i < 16; i++)
                        {
                            bmiColor[i].rgbRed      = PaletteRed(i);
                            bmiColor[i].rgbGreen    = PaletteGreen(i);
                            bmiColor[i].rgbBlue     = PaletteBlue(i);
                            bmiColor[i].rgbReserved = 0;
                        }
                    }

                    byte *pData = (byte *)lpbi + lpbi->biSize + PaletteSize(bi);

                    int iLO = Width / 2;
                    if ((Width & 1) != 0)
                    {
                        iLO++;
                    }
                    if ((iLO % 4) != 0)
                    {
                        iLO += 4 - (iLO % 4);
                    }
                    for (int j = 0; j < Height; j++)
                    {
                        for (int i = 0; i < Width; i++)
                        {
                            ((byte *)pData)[i + (Height - j - 1) * iLO] = (byte)GetPixel(i, j);
                        }
                    }

                    /*
                     * GR::Graphic::ContextDescriptor    cdImage( Image );
                     * GR::Graphic::ContextDescriptor    cdTarget;
                     *
                     * cdTarget.Attach( cdImage.Width(), cdImage.Height(), iLO, cdImage.ImageFormat(), pData );
                     *
                     * for ( int j = 0; j < Image.Height(); j++ )
                     * {
                     * cdImage.CopyLine( 0, j, cdImage.Width(), 0, cdImage.Height() - j - 1, &cdTarget );
                     * }*/
                }
                break;

                case 8:
                {
                    // Palette in DC setzen
                    if (PaletteEntryCount > 0)
                    {
                        RGBQUAD *bmiColor;

                        bmiColor = (RGBQUAD *)((byte *)lpbi + lpbi->biSize);

                        for (int i = 0; i < 256; i++)
                        {
                            bmiColor[i].rgbRed      = PaletteRed(i);
                            bmiColor[i].rgbGreen    = PaletteGreen(i);
                            bmiColor[i].rgbBlue     = PaletteBlue(i);
                            bmiColor[i].rgbReserved = 0;
                        }
                    }

                    byte *pData = (byte *)lpbi + lpbi->biSize + PaletteSize(bi);

                    int iLO = Width;
                    if ((iLO % 4) != 0)
                    {
                        iLO += 4 - (iLO % 4);
                    }
                    for (int j = 0; j < Height; j++)
                    {
                        for (int i = 0; i < Width; i++)
                        {
                            ((byte *)pData)[i + (Height - j - 1) * iLO] = (byte)GetPixel(i, j);
                        }
                    }
                }
                break;

                case 16:
                {
                    byte *pData = (byte *)lpbi + lpbi->biSize + PaletteSize(bi);

                    int iLO = Width * 2;
                    if ((iLO % 4) != 0)
                    {
                        iLO += 4 - (iLO % 4);
                    }
                    for (int j = 0; j < Height; j++)
                    {
                        for (int i = 0; i < Width; i++)
                        {
                            ((ushort *)pData)[i + (Height - j - 1) * iLO / 2] = (ushort)GetPixel(i, j);
                        }
                    }
                }
                break;

                /*
                 * case 24:
                 * {
                 * byte    *pData = (byte*)lpbi + lpbi->biSize + PaletteSize( bi );
                 *
                 * int iLO = Width * 3;
                 * if ( ( iLO % 4 ) != 0 )
                 * {
                 *  iLO += 4 - ( iLO % 4 );
                 * }
                 * for ( int j = 0; j < Height; j++ )
                 * {
                 *  for ( int i = 0; i < Width; i++ )
                 *  {
                 *    ( (byte*)pData )[3 * i + ( Height - j - 1 ) * iLO] = (byte)*( (byte*)Image.Data() + 3 * ( i + j * Image.Width() ) );
                 *    ( (byte*)pData )[3 * i + ( Height - j - 1 ) * iLO + 1] = (byte)*( (byte*)Image.Data() + 3 * ( i + j * Image.Width() ) + 1 );
                 *    ( (byte*)pData )[3 * i + ( Height - j - 1 ) * iLO + 2] = (byte)*( (byte*)Image.Data() + 3 * ( i + j * Image.Width() ) + 2 );
                 *  }
                 * }
                 * }
                 * break;*/
                case 32:
                {
                    byte *pData = (byte *)lpbi + lpbi->biSize + PaletteSize(bi);

                    int iLO = Width;
                    for (int j = 0; j < Height; j++)
                    {
                        for (int i = 0; i < Width; i++)
                        {
                            ((uint *)pData)[i + (Height - j - 1) * iLO] = GetPixel(i, j);
                        }
                    }
                }
                break;

                default:
                    Debug.Log("CreateHDIBAsBuffer unsupported depth " + bi.biBitCount);
                    break;
                }

                byte *pDIBData = (byte *)lpbi;
                for (int i = 0; i < bi.biSize + PaletteSize(bi) + bi.biSizeImage; ++i)
                {
                    result.AppendU8(pDIBData[i]);
                }

                //bi = *lpbi;
                GlobalUnlock(hDIB);

                System.Runtime.InteropServices.Marshal.FreeHGlobal(hDIB);
            }

            return(result);
        }
Example #14
0
        //SFFV2 从索引获取图像数据
        public byte[] getSprDataV2(int index, out byte[] pp, FI_FORMAT type, bool loadPal = true)
        {
            byte[]   sprData;
            byte[]   palData = null;
            int      sprSize;
            IntPtr   dib;
            sprMsgV2 spr = getSprMsgV2(index);

            if (spr.dataLen == 0)
            {
                //链接型图像
                return(getSprDataV2(spr.linkIndex, out pp, type));
            }
            seek((spr.flags == 1 ? msgV2.tdataOffset : msgV2.ldataOffset) + spr.dataOffset);

            //压缩算法(fmt)常量声明这里省略了,直接使用值
            //0 无压缩
            //2 Rle8压缩
            //3 Rle5压缩 几乎不会用到 直接省略
            //4 Lz5压缩
            //10 PNG8
            //11 PNG24
            //12 PNG32
            if (spr.fmt == 0)
            {
                sprData = br.ReadBytes(spr.dataLen);
            }
            else
            {
                sprSize = br.ReadInt32();                //解压后的校验长度,这里省略了校验
                sprData = br.ReadBytes(spr.dataLen - 4);
            }
            switch (spr.fmt)
            {
            case 0:
                if (loadPal)
                {
                    palData = getPalData(spr.palIndex);
                }
                pp = palData;
                break;

            case 2:
                sprData = sffV2Decompress.unRle8(sprData);
                if (loadPal)
                {
                    palData = getPalData(spr.palIndex);
                }
                pp = palData;
                break;

            case 4:
                sprData = sffV2Decompress.unLz5(sprData);
                if (loadPal)
                {
                    palData = getPalData(spr.palIndex);
                }
                pp = palData;
                break;

            case 10:
                //压缩算法为PNG算法时读取的数据默认都是一个完整的PNG文件 可以直接载入
                palData = getPalData(spr.palIndex);
                dib     = FI.LoadFromMemory(sprData, FI_FORMAT.FIF_PNG);
                //PNG8调色板校正
                RGBQUAD *pale = FI.GetPalette(dib);
                for (int n = 0; n < 256; n++)
                {
                    pale [n].Red   = palData [n * 4];
                    pale [n].Green = palData [n * 4 + 1];
                    pale [n].Blue  = palData [n * 4 + 2];
                }
                FI.SaveToMemory(dib, ref sprData, type);
                pp = palData;
                return(sprData);

            case 11:
            case 12:
                pp = null;
                return(sprData);

            default:
                sprData = new byte[0];
                pp      = new byte[0];
                return(sprData);
            }

            if (type != FI_FORMAT.FIF_UNKNOWN)
            {
                //对于无压缩、Rle8和Lz5压缩的图像读取的数据是原始的像素数据 不能直接载入
                dib = FI.ConvertFromRawBits(sprData, spr.width, spr.height, spr.width, 8, 0, 0, 0, true);
                RGBQUAD *pal      = FI.GetPalette(dib);
                int      colorNum = palData.Length / 4;
                for (int n = 0; n < colorNum; n++)
                {
                    pal [n].Red   = palData [n * 4];
                    pal [n].Green = palData [n * 4 + 1];
                    pal [n].Blue  = palData [n * 4 + 2];
                }
                FI.SaveToMemory(dib, ref sprData, type);
                FI.Free(dib);
                return(sprData);
            }
            else
            {
                return(sprData);
            }
        }
Example #15
0
        //SFFV1 从索引获取指定图像数据
        public byte[] getSprDataV1(int index, out byte[] pp, FI_FORMAT type)
        {
            int      offset = msgV1.sprOffset;
            sprMsgV1 spr    = new sprMsgV1();

            byte[] facePalData = new byte[0];
            byte[] palData     = new byte[0];
            byte[] sprData     = new byte[0];
            for (int i = 0; i < msgV1.sprNum; i++)
            {
                seek(offset);
                offset         = br.ReadInt32();
                spr.pcxDataLen = br.ReadInt32();
                spr.x          = br.ReadInt16();
                spr.y          = br.ReadInt16();
                spr.group      = br.ReadUInt16();
                spr.index      = br.ReadUInt16();
                spr.linkIndex  = br.ReadUInt16();
                spr.palType    = br.ReadByte();
                if (i == 0)
                {
                    //第一张图强制为独立色表
                    spr.palType = 0;
                }
                seek(13, SeekOrigin.Current);
                if ((spr.group == 0 && spr.index == 0 || spr.group == 9000 && spr.index == 0) && facePalData.Length != 0)
                {
                    //0,0和9000,0强制为独立色表,且使用第一张色表
                    palData = facePalData;
                }
                if (i == index)
                {
                    if (spr.pcxDataLen == 0)
                    {
                        //链接型图像
                        return(getSprDataV1(spr.linkIndex, out pp, type));
                    }

                    sprData = br.ReadBytes(spr.pcxDataLen);
                    if (type != FI_FORMAT.FIF_UNKNOWN)
                    {
                        IntPtr dib = FI.LoadFromMemory(sprData, FI_FORMAT.FIF_PCX);
                        if (spr.palType == 1)
                        {
                            RGBQUAD *pal = FI.GetPalette(dib);
                            for (int n = 0; n < 256; n++)
                            {
                                pal[n].Red   = palData[n * 3];
                                pal[n].Green = palData[n * 3 + 1];
                                pal[n].Blue  = palData[n * 3 + 2];
                            }
                        }
                        FI.SaveToMemory(dib, ref sprData, type);


                        //释放图像流
                        FI.Free(dib);
                    }

                    pp = palData;
                    return(sprData);
                }
                else
                {
                    if (spr.palType == 0)
                    {
                        //读取PCX尾部色表数据
                        seek(spr.pcxDataLen - 768, SeekOrigin.Current);
                        palData = br.ReadBytes(768);
                        if (i == 0)
                        {
                            //保留第一张图的色表
                            facePalData = palData;
                        }
                    }
                }
            }

            pp = null;
            return(null);
        }