unsafe static void Hsl2Rgb360(double h, double s, double l, RgbData *prgb) { // Convert 0..360 to 0..1 double r, g, b; Hsl2Rgb(h / 360.0, s, l, &r, &g, &b); prgb->bRed = (byte)(r * 255.0); prgb->bGreen = (byte)(g * 255.0); prgb->bBlue = (byte)(b * 255.0); }
// Skips dst where src has transparent color. // Darkens dst where src has shadow color. // Translates side colors. // NOTE: Performs dst but not src clipping!!! // NOTE: Assumes src and dst BitmapData are PixelFormat.Format24bppRgb public unsafe void SuperBlt8(int xSrc, int ySrc, BitmapData bmdDst, int xDst, int yDst, int cx, int cy, bool fMapSideColors) { // If completely off dst bounds, just return. if ((xDst >= bmdDst.Width || xDst + cx < 0) || (yDst >= bmdDst.Height) || (yDst + cy < 0)) { return; } // Dst clip if (xDst + cx > bmdDst.Width) { cx = bmdDst.Width - xDst; } if (yDst + cy > bmdDst.Height) { cy = bmdDst.Height - yDst; } if (xDst < 0) { cx += xDst; xSrc -= xDst; xDst = 0; } if (yDst < 0) { cy += yDst; ySrc -= yDst; yDst = 0; } BitmapData bmdSrc = m_bm.LockBits( new Rectangle(0, 0, m_bm.Width, m_bm.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); RgbData *prgbSrc = (RgbData *)((byte *)bmdSrc.Scan0 + (ySrc * bmdSrc.Stride) + (xSrc * sizeof(RgbData))); RgbData *prgbDst = (RgbData *)((byte *)bmdDst.Scan0 + (yDst * bmdDst.Stride) + (xDst * sizeof(RgbData))); while (cy-- > 0) { RgbData *prgbDstT = prgbDst; RgbData *prgbSrcT = prgbSrc; for (int x = 0; x < cx; x++) { RgbData rgbSrc = *prgbSrcT++; // Handle shadow color if (rgbSrc.bRed == 156 && rgbSrc.bGreen == 212 & rgbSrc.bBlue == 248) { prgbDstT->bRed = (byte)((prgbDstT->bRed * 60) / 100); prgbDstT->bGreen = (byte)((prgbDstT->bGreen * 60) / 100); prgbDstT->bBlue = (byte)((prgbDstT->bBlue * 60) / 100); prgbDstT++; // Handle transparent color } else if (rgbSrc.bRed == 255 && rgbSrc.bGreen == 0 && rgbSrc.bBlue == 255) { prgbDstT++; // Handle side colors } else if (fMapSideColors) { if (rgbSrc.bRed == 0 && rgbSrc.bGreen == 116 && rgbSrc.bBlue == 232) { *prgbDstT++ = argbSide[0]; } else if (rgbSrc.bRed == 0 && rgbSrc.bGreen == 96 && rgbSrc.bBlue == 196) { *prgbDstT++ = argbSide[1]; } else if (rgbSrc.bRed == 0 && rgbSrc.bGreen == 64 && rgbSrc.bBlue == 120) { *prgbDstT++ = argbSide[2]; } else if (rgbSrc.bRed == 0 && rgbSrc.bGreen == 48 && rgbSrc.bBlue == 92) { *prgbDstT++ = argbSide[3]; } else if (rgbSrc.bRed == 0 && rgbSrc.bGreen == 32 && rgbSrc.bBlue == 64) { *prgbDstT++ = argbSide[4]; } else { *prgbDstT++ = rgbSrc; } // Just copy everything else unaltered } else { *prgbDstT++ = rgbSrc; } } // Advance to next scan line prgbDst = (RgbData *)(((byte *)prgbDst) + bmdDst.Stride); prgbSrc = (RgbData *)(((byte *)prgbSrc) + bmdSrc.Stride); } m_bm.UnlockBits(bmdSrc); }
public unsafe void SuperBlt32(int xSrc, int ySrc, BitmapData bmdDst, int xDst, int yDst, int cx, int cy, bool fMapSideColors) { // If completely off dst bounds, just return. if ((xDst >= bmdDst.Width || xDst + cx < 0) || (yDst >= bmdDst.Height) || (yDst + cy < 0)) { return; } // Dst clip if (xDst + cx > bmdDst.Width) { cx = bmdDst.Width - xDst; } if (yDst + cy > bmdDst.Height) { cy = bmdDst.Height - yDst; } if (xDst < 0) { cx += xDst; xSrc -= xDst; xDst = 0; } if (yDst < 0) { cy += yDst; ySrc -= yDst; yDst = 0; } BitmapData bmdSrc = m_bm.LockBits( new Rectangle(0, 0, m_bm.Width, m_bm.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); BitmapData bmdSrcBlack = m_bmBlack.LockBits( new Rectangle(0, 0, m_bmBlack.Width, m_bmBlack.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); RgbaData *prgbSrc = (RgbaData *)((byte *)bmdSrc.Scan0 + (ySrc * bmdSrc.Stride) + (xSrc * sizeof(RgbaData))); RgbaData *prgbSrcBlack = (RgbaData *)((byte *)bmdSrcBlack.Scan0 + (ySrc * bmdSrcBlack.Stride) + (xSrc * sizeof(RgbaData))); RgbData *prgbDst = (RgbData *)((byte *)bmdDst.Scan0 + (yDst * bmdDst.Stride) + (xDst * sizeof(RgbData))); while (cy-- > 0) { RgbaData *prgbSrcT = prgbSrc; RgbaData *prgbSrcBlackT = prgbSrcBlack; RgbData * prgbDstT = prgbDst; for (int x = 0; x < cx; x++) { RgbaData rgbSrc = *prgbSrcT++; RgbaData rgbSrcBlack = *prgbSrcBlackT++; // rgbSrc = huemap(rgbSrc - rgbSrcBlack) + rgbSrcBlack RgbData rgbT; int v; v = rgbSrc.bRed - rgbSrcBlack.bRed; if (v < 0) { v = 0; } rgbT.bRed = (byte)v; v = rgbSrc.bGreen - rgbSrcBlack.bGreen; if (v < 0) { v = 0; } rgbT.bGreen = (byte)v; v = rgbSrc.bBlue - rgbSrcBlack.bBlue; if (v < 0) { v = 0; } rgbT.bBlue = (byte)v; Color clrT = Color.FromArgb(rgbT.bRed, rgbT.bGreen, rgbT.bBlue); double hue = clrT.GetHue(); if (fMapSideColors) { hue -= 235.0; if (hue < 0.0) { hue += 360.0; } } Hsl2Rgb360(hue, clrT.GetSaturation(), clrT.GetBrightness(), &rgbT); // Add new rgb back to black v = rgbSrcBlack.bRed + rgbT.bRed; if (v > 255) { v = 255; } rgbSrc.bRed = (byte)v; v = rgbSrcBlack.bGreen + rgbT.bGreen; if (v > 255) { v = 255; } rgbSrc.bGreen = (byte)v; v = rgbSrcBlack.bBlue + rgbT.bBlue; if (v > 255) { v = 255; } rgbSrc.bBlue = (byte)v; // Alpha blend into dest double alpha = (double)rgbSrc.bAlpha / 255.0; double d; d = (double)rgbSrc.bRed * alpha + (double)prgbDstT->bRed * (1.0 - alpha); if (d > 255.0) { d = 255.0; } prgbDstT->bRed = (byte)d; d = (double)rgbSrc.bGreen * alpha + (double)prgbDstT->bGreen * (1.0 - alpha); if (d > 255.0) { d = 255.0; } prgbDstT->bGreen = (byte)d; d = (double)rgbSrc.bBlue * alpha + (double)prgbDstT->bBlue * (1.0 - alpha); if (d > 255.0) { d = 255.0; } prgbDstT->bBlue = (byte)d; prgbDstT++; } // Advance to next scan line prgbDst = (RgbData *)(((byte *)prgbDst) + bmdDst.Stride); prgbSrc = (RgbaData *)(((byte *)prgbSrc) + bmdSrc.Stride); prgbSrcBlack = (RgbaData *)(((byte *)prgbSrcBlack) + bmdSrcBlack.Stride); } m_bm.UnlockBits(bmdSrc); m_bmBlack.UnlockBits(bmdSrcBlack); }