/// <summary> /// Draw the specified x, y, source and considerAlpha. /// </summary> /// <param name="x">The x coordinate.</param> /// <param name="y">The y coordinate.</param> /// <param name="source">Source.</param> /// <param name="considerAlpha">If set to <c>true</c> consider alpha.</param> public void Draw(int x, int y, Image8i source, bool considerAlpha) { if (!considerAlpha || source.ChannelFormat == ChannelFormat.BGR || source.ChannelFormat == ChannelFormat.RGB || source.ChannelFormat == ChannelFormat.Gray) { Draw(x, y, source); return; } if (x >= Width || y >= Height) throw new ArgumentOutOfRangeException("x or y", "Out of image."); if (x + source.Width < 0 || y + source.Height < 0) throw new ArgumentOutOfRangeException("x or y", "Out of image."); Image8i sourceImage = null; switch (ChannelFormat) { case ChannelFormat.Gray: { sourceImage = source.ToChannelFormatGrayAlpha(); break; } case ChannelFormat.GrayAlpha: { sourceImage = source.ToChannelFormatGrayAlpha(); break; } case ChannelFormat.RGB: { sourceImage = source.ToChannelFormatRGBA(); break; } case ChannelFormat.RGBA: { sourceImage = source.ToChannelFormatRGBA(); break; } case ChannelFormat.BGR: { sourceImage = source.ToChannelFormatBGRA(); break; } case ChannelFormat.BGRA: { sourceImage = source.ToChannelFormatBGRA(); break; } } uint bpp = GetBytePerPixelFromChannelFormat(source.ChannelFormat); unsafe { fixed(byte* src_=sourceImage.imageData, dst_=imageData) { uint start = (uint)System.Math.Max(-x, 0); uint end = (uint)System.Math.Min(source.Width, Width - x); uint jstart = (uint)System.Math.Max(-y, 0); uint jend = (uint)System.Math.Min(source.Height, Height - y); if (ChannelFormat == ChannelFormat.BGR || ChannelFormat == ChannelFormat.RGB || ChannelFormat == ChannelFormat.Gray) { uint dbpp = GetBytePerPixelFromChannelFormat(ChannelFormat); byte* src__ = src_ + start * bpp; byte* dst__ = dst_ + x * dbpp + start * dbpp; uint sw = source.Width * bpp; uint dw = Width * dbpp; if (ChannelFormat == ChannelFormat.BGR || ChannelFormat == ChannelFormat.RGB) { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sr = *src++; byte sg = *src++; byte sb = *src++; byte sa = *src++; if (sa != 0) { byte dr = *dst++; byte dg = *dst++; byte db = *dst++; dst -= 3; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dr * a1 + sr * a2); *dst++ = (byte)(dg * a1 + sg * a2); *dst++ = (byte)(db * a1 + sb * a2); } else dst += 3; } } } else // GRAY { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sg = *src++; byte sa = *src++; if (sa != 0) { byte dg = *dst; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dg * a1 + sg * a2); } else dst++; } } } // end if RGB || BGR } else // 2x alpha image { byte* src__ = src_ + start * bpp; byte* dst__ = dst_ + x * bpp + start * bpp; uint sw = source.Width * bpp; uint dw = Width * bpp; if (ChannelFormat == ChannelFormat.BGRA || ChannelFormat == ChannelFormat.RGBA) { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sr = *src++; byte sg = *src++; byte sb = *src++; byte sa = *src++; if (sa != 0) { byte dr = *dst++; byte dg = *dst++; byte db = *dst++; byte da = *dst++; dst -= 4; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dr * a1 + sr * a2); *dst++ = (byte)(dg * a1 + sg * a2); *dst++ = (byte)(db * a1 + sb * a2); *dst++ = da; } else dst += 4; } } } else // GRAYALPHA { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sg = *src++; byte sa = *src++; if (sa != 0) { byte dg = *dst++; byte da = *dst++; dst -= 2; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dg * a1 + sg * a2); *dst++ = da; } else dst += 2; } } } // end if RGBA || BGRA } // end if 2x Alpha-Bild } // fixed } // unsafe }