/* Copyright (c) 2007 Ben Howell
* This software is licensed under the MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
namespace GoArrow.Huds
{
public static class GraphicsUtil
{
///
/// Copies image onto another. Both images must have the same pixel format.
///
/// The image to copy from.
/// The image to copy onto.
public static void BitBlt(Bitmap srcImg, Bitmap dstImg)
{
BitBlt(srcImg, 0, 0, srcImg.Width, srcImg.Height, dstImg, 0, 0);
}
///
/// Copies image onto another. Both images must have the same pixel format.
///
/// The image to copy from.
/// The image to copy onto.
/// The point on the destination image to copy to.
public static void BitBlt(Bitmap srcImg, Bitmap dstImg, Point dstPt)
{
BitBlt(srcImg, 0, 0, srcImg.Width, srcImg.Height, dstImg, dstPt.X, dstPt.Y);
}
///
/// Copies image onto another. Both images must have the same pixel format.
///
/// The image to copy from.
/// The image to copy onto.
/// The x-coordiate of the destiation rectangle.
/// The y-coordiate of the destiation rectangle.
public static void BitBlt(Bitmap srcImg, Bitmap dstImg, int dX, int dY)
{
BitBlt(srcImg, 0, 0, srcImg.Width, srcImg.Height, dstImg, dX, dY);
}
///
/// Copies part of one image onto another. Both images must have the
/// same pixel format.
///
/// The image to copy from.
/// The rectangle on the source image to copy from.
/// The image to copy onto.
/// The point on the destination image to copy to.
public static void BitBlt(Bitmap srcImg, Rectangle srcRect, Bitmap dstImg, Point dstPt)
{
BitBlt(srcImg, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, dstImg, dstPt.X, dstPt.Y);
}
///
/// Copies part of one image onto another. Both images must have the
/// same pixel format.
///
/// The image to copy from.
/// The x-coordinate of the source rectangle.
/// The y-coordinate to the source rectangle.
/// The width of the region to copy.
/// The height of the region to copy.
/// The image to copy onto.
/// The x-coordiate of the destiation rectangle.
/// The y-coordiate of the destiation rectangle.
/// The source and destination pixel
/// formats don't match, or aren't a supported format.
public static void BitBlt(Bitmap srcImg, int sX, int sY, int w, int h, Bitmap dstImg, int dX, int dY)
{
if (srcImg.PixelFormat != dstImg.PixelFormat)
{
throw new ArgumentException("Source and destination images must have the same pixel format");
}
// Copy the palette for indexed images
if ((srcImg.PixelFormat & PixelFormat.Indexed) != 0)
{
dstImg.Palette = srcImg.Palette;
}
// Adjust bounds if they go outside the images
if (sX < 0) { w += sX; dX -= sX; sX = 0; }
if (sY < 0) { h += sY; dY -= sY; sY = 0; }
if (dX < 0) { w += dX; sX -= dX; dX = 0; }
if (dY < 0) { h += dY; sY -= dY; dY = 0; }
if (sX + w > srcImg.Width) { w = srcImg.Width - sX; }
if (sY + h > srcImg.Height) { h = srcImg.Height - sY; }
if (dX + w > dstImg.Width) { w = dstImg.Width - dX; }
if (dY + h > dstImg.Height) { h = dstImg.Height - dY; }
if (w <= 0 || h <= 0 || sX > srcImg.Width || sY > srcImg.Height
|| dX > dstImg.Width || dY > dstImg.Height)
{
// Nothing to do
return;
}
BitmapData srcData = srcImg.LockBits(new Rectangle(sX, sY, w, h), ImageLockMode.ReadOnly, srcImg.PixelFormat);
BitmapData dstData = dstImg.LockBits(new Rectangle(dX, dY, w, h), ImageLockMode.WriteOnly, dstImg.PixelFormat);
try
{
unsafe
{
if (srcImg.PixelFormat == PixelFormat.Format8bppIndexed)
{
// 1 byte per pixel
byte* pSrc = (byte*)srcData.Scan0;
byte* pDst = (byte*)dstData.Scan0;
int srcRemain = srcData.Stride - w;
int dstRemain = dstData.Stride - w;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
*pDst = *pSrc;
pSrc++;
pDst++;
}
pSrc += srcRemain;
pDst += dstRemain;
}
}
else if (srcImg.PixelFormat == PixelFormat.Format16bppArgb1555
|| srcImg.PixelFormat == PixelFormat.Format16bppGrayScale
|| srcImg.PixelFormat == PixelFormat.Format16bppRgb555
|| srcImg.PixelFormat == PixelFormat.Format16bppRgb565)
{
// 2 bytes per pixel
Int16* pSrc = (Int16*)srcData.Scan0;
Int16* pDst = (Int16*)dstData.Scan0;
int srcRemain = srcData.Stride / 2 - w;
int dstRemain = dstData.Stride / 2 - w;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
*pDst = *pSrc;
pSrc++;
pDst++;
}
pSrc += srcRemain;
pDst += dstRemain;
}
}
else if (srcImg.PixelFormat == PixelFormat.Format24bppRgb)
{
// 3 bytes per pixel
byte* pSrc = (byte*)srcData.Scan0;
byte* pDst = (byte*)dstData.Scan0;
int srcRemain = srcData.Stride - w * 3;
int dstRemain = dstData.Stride - w * 3;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
pDst[0] = pSrc[0];
pDst[1] = pSrc[1];
pDst[2] = pSrc[2];
pSrc += 3;
pDst += 3;
}
pSrc += srcRemain;
pDst += dstRemain;
}
}
else if (srcImg.PixelFormat == PixelFormat.Format32bppArgb
|| srcImg.PixelFormat == PixelFormat.Format32bppPArgb)
{
// 4 bytes per pixel
Int32* pSrc = (Int32*)srcData.Scan0;
Int32* pDst = (Int32*)dstData.Scan0;
int srcRemain = srcData.Stride / 4 - w;
int dstRemain = dstData.Stride / 4 - w;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
*pDst = *pSrc;
pSrc++;
pDst++;
}
pSrc += srcRemain;
pDst += dstRemain;
}
}
else if (srcImg.PixelFormat == PixelFormat.Format48bppRgb)
{
// 6 bytes per pixel
byte* pSrc = (byte*)srcData.Scan0;
byte* pDst = (byte*)dstData.Scan0;
int srcRemain = srcData.Stride - w * 6;
int dstRemain = dstData.Stride - w * 6;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
pDst[0] = pSrc[0];
pDst[1] = pSrc[1];
pDst[2] = pSrc[2];
pDst[3] = pSrc[3];
pDst[4] = pSrc[4];
pDst[5] = pSrc[5];
pSrc += 6;
pDst += 6;
}
pSrc += srcRemain;
pDst += dstRemain;
}
}
else if (srcImg.PixelFormat == PixelFormat.Format64bppArgb)
{
// 8 bytes per pixel
Int64* pSrc = (Int64*)srcData.Scan0;
Int64* pDst = (Int64*)dstData.Scan0;
int srcRemain = srcData.Stride / 8 - w;
int dstRemain = dstData.Stride / 8 - w;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
*pDst = *pSrc;
pSrc++;
pDst++;
}
pSrc += srcRemain;
pDst += dstRemain;
}
}
else
{
throw new ArgumentException("Pixel format \"" + srcImg.PixelFormat
+ "\" is not supported");
}
}
}
finally
{
dstImg.UnlockBits(dstData);
srcImg.UnlockBits(srcData);
}
}
}
}