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); }
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); } } } } } }
//------------------------------------------------------------------- // 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; } }
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); }
//------------------------------------------------------------------- // 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; } }
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)); }
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]]; } } } } } } }
public unsafe static extern void CopyMemory(RGBQUAD *dest, byte *src, int cb);
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); }
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); }
//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); } }
//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); }