in Sources/Imaging/Microsoft.Psi.Imaging/ImageExtensions.cs [1623:1803]
public static void CopyTo(this Image srcImage, Rectangle srcRect, Image destImage, Point destTopLeftCorner, Image maskImage)
{
if (destImage.PixelFormat != srcImage.PixelFormat)
{
throw new ArgumentOutOfRangeException("destImage.PixelFormat", "destination image pixel format doesn't match source image pixel format");
}
if (maskImage != null)
{
if (srcImage.Width != maskImage.Width || srcImage.Height != maskImage.Height)
{
throw new ArgumentException("Mask image size must match source image size");
}
if (maskImage.PixelFormat != PixelFormat.Gray_8bpp)
{
throw new ArgumentException("Mask image must be of type PixelFormat.Gray_8bpp");
}
}
// Clip source rectangle against source image size
int srcX = (srcRect.X < 0) ? 0 : srcRect.X;
int srcY = (srcRect.Y < 0) ? 0 : srcRect.Y;
int srcW = (srcRect.X + srcRect.Width > srcImage.Width) ? (srcImage.Width - srcRect.X) : srcRect.Width;
int srcH = (srcRect.Y + srcRect.Height > srcImage.Height) ? (srcImage.Height - srcRect.Y) : srcRect.Height;
// Clip destination point against destination image
int dstX = (destTopLeftCorner.X < 0) ? 0 : destTopLeftCorner.X;
int dstY = (destTopLeftCorner.Y < 0) ? 0 : destTopLeftCorner.Y;
dstX = (dstX >= destImage.Width) ? destImage.Width - 1 : dstX;
dstY = (dstY >= destImage.Height) ? destImage.Height - 1 : dstY;
// Next clip further if rect of that size would lie outside the destination image
srcW = (dstX + srcW > destImage.Width) ? (destImage.Width - dstX) : srcW;
srcH = (dstY + srcH > destImage.Height) ? (destImage.Height - dstY) : srcH;
PixelFormat srcFormat = srcImage.PixelFormat;
PixelFormat dstFormat = destImage.PixelFormat;
System.IntPtr sourceBuffer = srcImage.ImageData;
System.IntPtr destBuffer = destImage.ImageData;
System.IntPtr maskBuffer = (maskImage != null) ? maskImage.ImageData : System.IntPtr.Zero;
unsafe
{
int srcBytesPerPixel = srcFormat.GetBytesPerPixel();
int dstBytesPerPixel = dstFormat.GetBytesPerPixel();
int maskBytesPerPixel = PixelFormat.Gray_8bpp.GetBytesPerPixel();
byte* srcRow = (byte*)sourceBuffer.ToPointer() + (srcY * srcImage.Stride) + (srcX * srcBytesPerPixel);
byte* dstRow = (byte*)destBuffer.ToPointer() + (dstY * destImage.Stride) + (dstX * dstBytesPerPixel);
byte* maskRow = null;
if (maskImage != null)
{
maskRow = (byte*)maskBuffer.ToPointer() + (srcY * maskImage.Stride) + (srcX * maskBytesPerPixel);
}
for (int i = 0; i < srcH; i++)
{
byte* srcCol = srcRow;
byte* dstCol = dstRow;
byte* maskCol = maskRow;
for (int j = 0; j < srcW; j++)
{
bool copyPixel = true;
if (maskImage != null)
{
if (*maskCol == 0)
{
copyPixel = false;
}
}
if (copyPixel)
{
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
switch (srcFormat)
{
case PixelFormat.Gray_8bpp:
red = green = blue = srcCol[0];
break;
case PixelFormat.Gray_16bpp:
red = green = blue = ((ushort*)srcCol)[0];
break;
case PixelFormat.BGR_24bpp:
blue = srcCol[0];
green = srcCol[1];
red = srcCol[2];
break;
case PixelFormat.BGRX_32bpp:
blue = srcCol[0];
green = srcCol[1];
red = srcCol[2];
break;
case PixelFormat.BGRA_32bpp:
blue = srcCol[0];
green = srcCol[1];
red = srcCol[2];
alpha = srcCol[3];
break;
case PixelFormat.RGB_24bpp:
red = srcCol[0];
green = srcCol[1];
blue = srcCol[2];
break;
case PixelFormat.RGBA_64bpp:
red = ((ushort*)srcCol)[0];
green = ((ushort*)srcCol)[1];
blue = ((ushort*)srcCol)[2];
alpha = ((ushort*)srcCol)[3];
break;
case PixelFormat.Undefined:
default:
throw new ArgumentException(Image.ExceptionDescriptionUnexpectedPixelFormat);
}
switch (dstFormat)
{
case PixelFormat.Gray_8bpp:
dstCol[0] = Operators.Rgb2Gray((byte)red, (byte)green, (byte)blue);
break;
case PixelFormat.Gray_16bpp:
((ushort*)dstCol)[0] = Operators.Rgb2Gray((ushort)red, (ushort)green, (ushort)blue);
break;
case PixelFormat.BGR_24bpp:
case PixelFormat.BGRX_32bpp:
dstCol[0] = (byte)blue;
dstCol[1] = (byte)green;
dstCol[2] = (byte)red;
dstCol[3] = 255;
break;
case PixelFormat.BGRA_32bpp:
dstCol[0] = (byte)blue;
dstCol[1] = (byte)green;
dstCol[2] = (byte)red;
dstCol[3] = (byte)alpha;
break;
case PixelFormat.RGB_24bpp:
dstCol[0] = (byte)red;
dstCol[1] = (byte)green;
dstCol[2] = (byte)blue;
break;
case PixelFormat.RGBA_64bpp:
((ushort*)dstCol)[0] = (ushort)red;
((ushort*)dstCol)[1] = (ushort)green;
((ushort*)dstCol)[2] = (ushort)blue;
((ushort*)dstCol)[3] = (ushort)alpha;
break;
case PixelFormat.Undefined:
default:
throw new ArgumentException(Image.ExceptionDescriptionUnexpectedPixelFormat);
}
}
srcCol += srcBytesPerPixel;
dstCol += dstBytesPerPixel;
maskCol += maskBytesPerPixel;
}
srcRow += srcImage.Stride;
dstRow += destImage.Stride;
if (maskImage != null)
{
maskRow += maskImage.Stride;
}
}
}
}