813 lines
32 KiB
C#
813 lines
32 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Drawing.Drawing2D;
|
|
|
|
namespace TextDesignerCSLibrary
|
|
{
|
|
/// <summary>
|
|
/// Class to store the font info to pass as parameter to the drawing methods.
|
|
/// </summary>
|
|
public class TextContext
|
|
{
|
|
public TextContext()
|
|
{
|
|
fontFamily = new System.Drawing.FontFamily("Arial");
|
|
fontStyle = System.Drawing.FontStyle.Regular;
|
|
nfontSize = 20;
|
|
pszText = null;
|
|
ptDraw = new System.Drawing.Point(0, 0);
|
|
strFormat = new System.Drawing.StringFormat();
|
|
}
|
|
|
|
/// <summary>
|
|
/// fontFamily is the font family
|
|
/// </summary>
|
|
public System.Drawing.FontFamily fontFamily;
|
|
/// <summary>
|
|
/// fontStyle is the font style, eg, bold, italic or bold
|
|
/// </summary>
|
|
public System.Drawing.FontStyle fontStyle;
|
|
/// <summary>
|
|
/// nfontSize is font size
|
|
/// </summary>
|
|
public int nfontSize;
|
|
/// <summary>
|
|
/// pszText is the text to be displayed
|
|
/// </summary>
|
|
public string pszText;
|
|
/// <summary>
|
|
/// ptDraw is the point to draw
|
|
/// </summary>
|
|
public System.Drawing.Point ptDraw;
|
|
/// <summary>
|
|
/// strFormat is the string format
|
|
/// </summary>
|
|
public System.Drawing.StringFormat strFormat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Class to draw text outlines
|
|
/// </summary>
|
|
public class Canvas
|
|
{
|
|
/// <summary>
|
|
/// Generate Text Glow strategy
|
|
/// </summary>
|
|
/// <param name="clrText">is the color of the text</param>
|
|
/// <param name="clrOutline">is the color of the glow outline</param>
|
|
/// <param name="nThickness">is the thickness of the outline in pixels</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextGlow(
|
|
System.Drawing.Color clrText,
|
|
System.Drawing.Color clrOutline,
|
|
int nThickness)
|
|
{
|
|
TextGlowStrategy strat = new TextGlowStrategy();
|
|
strat.Init(clrText, clrOutline, nThickness);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate Text Glow strategy
|
|
/// </summary>
|
|
/// <param name="brushText">is the brush of the text</param>
|
|
/// <param name="clrOutline">is the color of the glow outline</param>
|
|
/// <param name="nThickness">is the thickness of the outline in pixels</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextGlow(
|
|
System.Drawing.Brush brushText,
|
|
System.Drawing.Color clrOutline,
|
|
int nThickness)
|
|
{
|
|
TextGlowStrategy strat = new TextGlowStrategy();
|
|
strat.Init(brushText, clrOutline, nThickness);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate Text Outline strategy
|
|
/// </summary>
|
|
/// <param name="clrText">is the color of the text</param>
|
|
/// <param name="clrOutline">is the color of the outline</param>
|
|
/// <param name="nThickness">is the thickness of the outline in pixels</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextOutline(
|
|
System.Drawing.Color clrText,
|
|
System.Drawing.Color clrOutline,
|
|
int nThickness)
|
|
{
|
|
TextOutlineStrategy strat = new TextOutlineStrategy();
|
|
strat.Init(clrText, clrOutline, nThickness);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate Text Outline strategy
|
|
/// </summary>
|
|
/// <param name="brushText">is the brush of the text</param>
|
|
/// <param name="clrOutline">is the color of the outline</param>
|
|
/// <param name="nThickness">is the thickness of the outline in pixels</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextOutline(
|
|
System.Drawing.Brush brushText,
|
|
System.Drawing.Color clrOutline,
|
|
int nThickness)
|
|
{
|
|
TextOutlineStrategy strat = new TextOutlineStrategy();
|
|
strat.Init(brushText, clrOutline, nThickness);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting Gradient Outlined Text effect
|
|
/// </summary>
|
|
/// <param name="clrText">is the text color</param>
|
|
/// <param name="clrOutline1">is the inner outline color</param>
|
|
/// <param name="clrOutline2">is the outer outline color</param>
|
|
/// <param name="nThickness">is the outline thickness</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextGradOutline(
|
|
System.Drawing.Color clrText,
|
|
System.Drawing.Color clrOutline1,
|
|
System.Drawing.Color clrOutline2,
|
|
int nThickness)
|
|
{
|
|
TextGradOutlineStrategy strat = new TextGradOutlineStrategy();
|
|
strat.Init(clrText, clrOutline1, clrOutline2, nThickness);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting Gradient Outlined Text effect
|
|
/// </summary>
|
|
/// <param name="brushText">is the text brush</param>
|
|
/// <param name="clrOutline1">is the inner outline color</param>
|
|
/// <param name="clrOutline2">is the outer outline color</param>
|
|
/// <param name="nThickness">is the outline thickness</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextGradOutline(
|
|
System.Drawing.Brush brushText,
|
|
System.Drawing.Color clrOutline1,
|
|
System.Drawing.Color clrOutline2,
|
|
int nThickness)
|
|
{
|
|
TextGradOutlineStrategy strat = new TextGradOutlineStrategy();
|
|
strat.Init(brushText, clrOutline1, clrOutline2, nThickness);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting just Text effect with no outline
|
|
/// </summary>
|
|
/// <param name="clrText">is the text color</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextNoOutline(
|
|
System.Drawing.Color clrText)
|
|
{
|
|
TextNoOutlineStrategy strat = new TextNoOutlineStrategy();
|
|
strat.Init(clrText);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting just Text effect with no outline
|
|
/// </summary>
|
|
/// <param name="brushText">is the text brush</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextNoOutline(
|
|
System.Drawing.Brush brushText)
|
|
{
|
|
TextNoOutlineStrategy strat = new TextNoOutlineStrategy();
|
|
strat.Init(brushText);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting Outlined Text effect with no text fill
|
|
/// </summary>
|
|
/// <param name="clrOutline">is the outline color</param>
|
|
/// <param name="nThickness">is the outline thickness</param>
|
|
/// <param name="bRoundedEdge">specifies rounded or sharp edges</param>
|
|
/// <returns>valid ITextStrategy pointer if successful</returns>
|
|
public static ITextStrategy TextOnlyOutline(
|
|
System.Drawing.Color clrOutline,
|
|
int nThickness,
|
|
bool bRoundedEdge)
|
|
{
|
|
TextOnlyOutlineStrategy strat = new TextOnlyOutlineStrategy();
|
|
strat.Init(clrOutline, nThickness, bRoundedEdge);
|
|
|
|
return strat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate a canvas image based on width and height
|
|
/// </summary>
|
|
/// <param name="width">is the image width</param>
|
|
/// <param name="height">is the image height</param>
|
|
/// <returns>a valid canvas image if successful</returns>
|
|
public static System.Drawing.Bitmap GenImage(int width, int height)
|
|
{
|
|
return new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate a canvas image based on width and height
|
|
/// </summary>
|
|
/// <param name="width">is the image width</param>
|
|
/// <param name="height">is the image height</param>
|
|
/// <param name="colors">is the list of colors for the gradient</param>
|
|
/// <param name="horizontal">specifies whether the gradient is horizontal</param>
|
|
/// <returns>a valid canvas image if successful</returns>
|
|
public static System.Drawing.Bitmap GenImage(int width, int height, List<System.Drawing.Color> colors, bool horizontal)
|
|
{
|
|
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
|
|
|
|
DrawGradient.Draw(bmp, colors, horizontal);
|
|
|
|
return bmp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate a canvas image based on width and height
|
|
/// </summary>
|
|
/// <param name="width">is the image width</param>
|
|
/// <param name="height">is the image height</param>
|
|
/// <param name="clr">is the color to paint the image</param>
|
|
/// <returns>a valid canvas image if successful</returns>
|
|
public static System.Drawing.Bitmap GenImage(int width, int height, System.Drawing.Color clr)
|
|
{
|
|
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
|
|
|
|
BitmapData bitmapData = new BitmapData();
|
|
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
|
|
|
bmp.LockBits(
|
|
rect,
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapData);
|
|
|
|
unsafe
|
|
{
|
|
uint* pixels = (uint*)bitmapData.Scan0;
|
|
|
|
if (pixels == null)
|
|
return null;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapData.Stride >> 2;
|
|
uint color = (uint)(clr.A << 24 | clr.R << 16 | clr.G << 8 | clr.G);
|
|
for (uint row = 0; row < bitmapData.Height; ++row)
|
|
{
|
|
for (col = 0; col < bitmapData.Width; ++col)
|
|
{
|
|
uint index = (uint)(row * stride + col);
|
|
|
|
pixels[index] = color;
|
|
}
|
|
}
|
|
}
|
|
bmp.UnlockBits(bitmapData);
|
|
|
|
return bmp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate a canvas image based on width and height
|
|
/// </summary>
|
|
/// <param name="width">is the image width</param>
|
|
/// <param name="height">is the image height</param>
|
|
/// <param name="clr">is the color to paint the image</param>
|
|
/// <param name="alpha">is alpha of the color</param>
|
|
/// <returns>a valid canvas image if successful</returns>
|
|
public static System.Drawing.Bitmap GenImage(int width, int height, System.Drawing.Color clr, byte alpha)
|
|
{
|
|
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
|
|
|
|
BitmapData bitmapData = new BitmapData();
|
|
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
|
|
|
bmp.LockBits(
|
|
rect,
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapData);
|
|
|
|
unsafe
|
|
{
|
|
uint* pixels = (uint*)bitmapData.Scan0;
|
|
|
|
if (pixels == null)
|
|
return null;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapData.Stride >> 2;
|
|
uint color = (uint)(alpha << 24 | clr.R << 16 | clr.G << 8 | clr.G);
|
|
for (uint row = 0; row < bitmapData.Height; ++row)
|
|
{
|
|
for (col = 0; col < bitmapData.Width; ++col)
|
|
{
|
|
uint index = (uint)(row * stride + col);
|
|
|
|
pixels[index] = color;
|
|
}
|
|
}
|
|
}
|
|
bmp.UnlockBits(bitmapData);
|
|
|
|
return bmp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate mask image of the text strategy.
|
|
/// </summary>
|
|
/// <param name="strategy">is text strategy</param>
|
|
/// <param name="width">is the mask image width</param>
|
|
/// <param name="height">is the mask image height</param>
|
|
/// <param name="offset">offsets the text (typically used for shadows)</param>
|
|
/// <param name="textContext">is text context</param>
|
|
/// <returns>a valid mask image if successful</returns>
|
|
public static System.Drawing.Bitmap GenMask(
|
|
ITextStrategy strategy,
|
|
int width,
|
|
int height,
|
|
System.Drawing.Point offset,
|
|
TextContext textContext)
|
|
{
|
|
if (strategy == null || textContext == null)
|
|
return null;
|
|
|
|
System.Drawing.Bitmap pBmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
|
|
|
|
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(pBmp))
|
|
{
|
|
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
|
|
strategy.DrawString(graphics,
|
|
textContext.fontFamily,
|
|
textContext.fontStyle,
|
|
textContext.nfontSize,
|
|
textContext.pszText,
|
|
new System.Drawing.Point(textContext.ptDraw.X + offset.X, textContext.ptDraw.Y + offset.Y),
|
|
textContext.strFormat);
|
|
}
|
|
|
|
return pBmp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Measure the mask image based on the mask color.
|
|
/// </summary>
|
|
/// <param name="mask">is the mask image to be measured</param>
|
|
/// <param name="maskColor">is mask color used in mask image</param>
|
|
/// <param name="top">returns the topmost Y </param>
|
|
/// <param name="left">returns the leftmost X</param>
|
|
/// <param name="bottom">returns the bottommost Y</param>
|
|
/// <param name="right">returns the rightmost X</param>
|
|
/// <returns>true if successful</returns>
|
|
public static bool MeasureMaskLength(
|
|
System.Drawing.Bitmap mask,
|
|
System.Drawing.Color maskColor,
|
|
ref uint top,
|
|
ref uint left,
|
|
ref uint bottom,
|
|
ref uint right)
|
|
{
|
|
top = 30000;
|
|
left = 30000;
|
|
bottom = 0;
|
|
right = 0;
|
|
|
|
if (mask == null)
|
|
return false;
|
|
|
|
BitmapData bitmapDataMask = new BitmapData();
|
|
Rectangle rect = new Rectangle(0, 0, mask.Width, mask.Height);
|
|
|
|
mask.LockBits(
|
|
rect,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataMask);
|
|
|
|
unsafe
|
|
{
|
|
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
|
|
|
|
if (pixelsMask == null)
|
|
return false;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapDataMask.Stride >> 2;
|
|
for (uint row = 0; row < bitmapDataMask.Height; ++row)
|
|
{
|
|
for (col = 0; col < bitmapDataMask.Width; ++col)
|
|
{
|
|
uint index = (uint)(row * stride + col);
|
|
byte nAlpha = 0;
|
|
|
|
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
|
|
nAlpha = (Byte)((pixelsMask[index] & 0xff0000) >> 16);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
|
|
nAlpha = (Byte)((pixelsMask[index] & 0xff00) >> 8);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
|
|
nAlpha = (Byte)(pixelsMask[index] & 0xff);
|
|
|
|
if (nAlpha > 0)
|
|
{
|
|
if (col < left)
|
|
left = col;
|
|
if (row < top)
|
|
top = row;
|
|
if (col > right)
|
|
right = col;
|
|
if (row > bottom)
|
|
bottom = row;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mask.UnlockBits(bitmapDataMask);
|
|
|
|
return true;
|
|
|
|
}
|
|
/// <summary>
|
|
/// Apply image to mask onto the canvas
|
|
/// </summary>
|
|
/// <param name="image">is the image to be used</param>
|
|
/// <param name="mask">is the mask image to be read</param>
|
|
/// <param name="canvas">is the destination image to be draw upon</param>
|
|
/// <param name="maskColor">is mask color used in mask image</param>
|
|
/// <returns>true if successful</returns>
|
|
public static bool ApplyImageToMask(
|
|
System.Drawing.Bitmap image,
|
|
System.Drawing.Bitmap mask,
|
|
System.Drawing.Bitmap canvas,
|
|
System.Drawing.Color maskColor)
|
|
{
|
|
if (image == null || mask == null || canvas == null)
|
|
return false;
|
|
|
|
BitmapData bitmapDataImage = new BitmapData();
|
|
BitmapData bitmapDataMask = new BitmapData();
|
|
BitmapData bitmapDataCanvas = new BitmapData();
|
|
Rectangle rectCanvas = new Rectangle(0, 0, canvas.Width, canvas.Height);
|
|
Rectangle rectMask = new Rectangle(0, 0, mask.Width, mask.Height);
|
|
Rectangle rectImage = new Rectangle(0, 0, image.Width, image.Height);
|
|
|
|
image.LockBits(
|
|
rectImage,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataImage);
|
|
|
|
mask.LockBits(
|
|
rectMask,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataMask);
|
|
|
|
canvas.LockBits(
|
|
rectCanvas,
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataCanvas);
|
|
|
|
unsafe
|
|
{
|
|
uint* pixelsImage = (uint*)bitmapDataImage.Scan0;
|
|
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
|
|
uint* pixelsCanvas = (uint*)bitmapDataCanvas.Scan0;
|
|
|
|
if (pixelsImage == null || pixelsMask == null || pixelsCanvas == null)
|
|
return false;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapDataCanvas.Stride >> 2;
|
|
for (uint row = 0; row < bitmapDataCanvas.Height; ++row)
|
|
{
|
|
for (col = 0; col < bitmapDataCanvas.Width; ++col)
|
|
{
|
|
if (row >= bitmapDataImage.Height || col >= bitmapDataImage.Width)
|
|
continue;
|
|
if (row >= bitmapDataMask.Height || col >= bitmapDataMask.Width)
|
|
continue;
|
|
|
|
uint index = (uint)(row * stride + col);
|
|
uint indexMask = (uint)(row * (bitmapDataMask.Stride >> 2) + col);
|
|
uint indexImage = (uint)(row * (bitmapDataImage.Stride >> 2) + col);
|
|
|
|
byte maskByte = 0;
|
|
|
|
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
|
|
maskByte = (Byte)((pixelsMask[indexMask] & 0xff0000) >> 16);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
|
|
maskByte = (Byte)((pixelsMask[indexMask] & 0xff00) >> 8);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
|
|
maskByte = (Byte)(pixelsMask[indexMask] & 0xff);
|
|
|
|
if (maskByte > 0)
|
|
pixelsCanvas[index] = Alphablend(pixelsCanvas[index], pixelsImage[indexImage], (Byte)(pixelsMask[indexMask] >> 24), (Byte)(pixelsMask[indexMask] >> 24));
|
|
}
|
|
}
|
|
}
|
|
canvas.UnlockBits(bitmapDataCanvas);
|
|
mask.UnlockBits(bitmapDataMask);
|
|
image.UnlockBits(bitmapDataImage);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply color to mask onto the canvas
|
|
/// </summary>
|
|
/// <param name="clr">is the color to be used</param>
|
|
/// <param name="mask">is the mask image to be read</param>
|
|
/// <param name="canvas">is the destination image to be draw upon</param>
|
|
/// <param name="maskColor">is mask color used in mask image</param>
|
|
/// <returns>true if successful</returns>
|
|
public static bool ApplyColorToMask(
|
|
System.Drawing.Color clr,
|
|
System.Drawing.Bitmap mask,
|
|
System.Drawing.Bitmap canvas,
|
|
System.Drawing.Color maskColor)
|
|
{
|
|
if (mask == null || canvas == null)
|
|
return false;
|
|
|
|
BitmapData bitmapDataMask = new BitmapData();
|
|
BitmapData bitmapDataCanvas = new BitmapData();
|
|
Rectangle rectCanvas = new Rectangle(0, 0, canvas.Width, canvas.Height);
|
|
Rectangle rectMask = new Rectangle(0, 0, mask.Width, mask.Height);
|
|
|
|
mask.LockBits(
|
|
rectMask,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataMask);
|
|
|
|
canvas.LockBits(
|
|
rectCanvas,
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataCanvas);
|
|
|
|
unsafe
|
|
{
|
|
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
|
|
uint* pixelsCanvas = (uint*)bitmapDataCanvas.Scan0;
|
|
|
|
if (pixelsMask == null || pixelsCanvas == null)
|
|
return false;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapDataCanvas.Stride >> 2;
|
|
for (uint row = 0; row < bitmapDataCanvas.Height; ++row)
|
|
{
|
|
for (col = 0; col < bitmapDataCanvas.Width; ++col)
|
|
{
|
|
if (row >= bitmapDataMask.Height || col >= bitmapDataMask.Width)
|
|
continue;
|
|
|
|
uint index = (uint)(row * stride + col);
|
|
uint indexMask = (uint)(row * (bitmapDataMask.Stride >> 2) + col);
|
|
|
|
byte maskByte = 0;
|
|
|
|
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
|
|
maskByte = (Byte)((pixelsMask[indexMask] & 0xff0000) >> 16);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
|
|
maskByte = (Byte)((pixelsMask[indexMask] & 0xff00) >> 8);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
|
|
maskByte = (Byte)(pixelsMask[indexMask] & 0xff);
|
|
|
|
uint color = (uint)(0xff << 24 | clr.R << 16 | clr.G << 8 | clr.B);
|
|
|
|
if (maskByte > 0)
|
|
pixelsCanvas[index] = Alphablend(pixelsCanvas[index], color, (Byte)(pixelsMask[indexMask] >> 24), (Byte)(pixelsMask[indexMask] >> 24));
|
|
}
|
|
}
|
|
}
|
|
canvas.UnlockBits(bitmapDataCanvas);
|
|
mask.UnlockBits(bitmapDataMask);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply color to mask onto the canvas
|
|
/// </summary>
|
|
/// <param name="clr">is the color to be used</param>
|
|
/// <param name="mask">is the mask image to be read</param>
|
|
/// <param name="canvas">is the destination image to be draw upon</param>
|
|
/// <param name="maskColor">is mask color used in mask image</param>
|
|
/// <param name="offset">determine how much to offset the mask</param>
|
|
/// <returns>true if successful</returns>
|
|
public static bool ApplyColorToMask(
|
|
System.Drawing.Color clr,
|
|
System.Drawing.Bitmap mask,
|
|
System.Drawing.Bitmap canvas,
|
|
System.Drawing.Color maskColor,
|
|
System.Drawing.Point offset)
|
|
{
|
|
if (mask == null || canvas == null)
|
|
return false;
|
|
|
|
BitmapData bitmapDataMask = new BitmapData();
|
|
BitmapData bitmapDataCanvas = new BitmapData();
|
|
Rectangle rectCanvas = new Rectangle(0, 0, canvas.Width, canvas.Height);
|
|
Rectangle rectMask = new Rectangle(0, 0, mask.Width, mask.Height);
|
|
|
|
mask.LockBits(
|
|
rectMask,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataMask);
|
|
|
|
canvas.LockBits(
|
|
rectCanvas,
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataCanvas);
|
|
|
|
unsafe
|
|
{
|
|
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
|
|
uint* pixelsCanvas = (uint*)bitmapDataCanvas.Scan0;
|
|
|
|
if (pixelsMask == null || pixelsCanvas == null)
|
|
return false;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapDataCanvas.Stride >> 2;
|
|
for (uint row = 0; row < bitmapDataCanvas.Height; ++row)
|
|
{
|
|
for (col = 0; col < bitmapDataCanvas.Width; ++col)
|
|
{
|
|
if ((row - offset.Y) >= bitmapDataMask.Height || (col - offset.X) >= bitmapDataMask.Width ||
|
|
(row - offset.Y) < 0 || (col - offset.X) < 0)
|
|
continue;
|
|
|
|
uint index = (uint)(row * stride + col);
|
|
uint indexMask = (uint)((row - offset.Y) * (bitmapDataMask.Stride >> 2) + (col - offset.X));
|
|
|
|
byte maskByte = 0;
|
|
|
|
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
|
|
maskByte = (Byte)((pixelsMask[indexMask] & 0xff0000) >> 16);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
|
|
maskByte = (Byte)((pixelsMask[indexMask] & 0xff00) >> 8);
|
|
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
|
|
maskByte = (Byte)(pixelsMask[indexMask] & 0xff);
|
|
|
|
uint color = (uint)(0xff << 24 | clr.R << 16 | clr.G << 8 | clr.B);
|
|
|
|
if (maskByte > 0)
|
|
pixelsCanvas[index] = Alphablend(pixelsCanvas[index], color, (Byte)(pixelsMask[indexMask] >> 24), (Byte)(pixelsMask[indexMask] >> 24));
|
|
}
|
|
}
|
|
}
|
|
canvas.UnlockBits(bitmapDataCanvas);
|
|
mask.UnlockBits(bitmapDataMask);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draw outline on image
|
|
/// </summary>
|
|
/// <param name="strategy">is text strategy</param>
|
|
/// <param name="image">is the image to be draw upon</param>
|
|
/// <param name="offset">offsets the text (typically used for shadows)</param>
|
|
/// <param name="textContext">is text context</param>
|
|
/// <returns>true if successful</returns>
|
|
public static bool DrawTextImage(
|
|
ITextStrategy strategy,
|
|
System.Drawing.Bitmap image,
|
|
System.Drawing.Point offset,
|
|
TextContext textContext)
|
|
{
|
|
if (strategy == null || image == null || textContext == null)
|
|
return false;
|
|
|
|
bool bRet = false;
|
|
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(image))
|
|
{
|
|
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
|
|
bRet = strategy.DrawString(graphics,
|
|
textContext.fontFamily,
|
|
textContext.fontStyle,
|
|
textContext.nfontSize,
|
|
textContext.pszText,
|
|
new System.Drawing.Point(textContext.ptDraw.X + offset.X, textContext.ptDraw.Y + offset.Y),
|
|
textContext.strFormat);
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set alpha to color
|
|
/// </summary>
|
|
/// <param name="dest">is destination color in ARGB</param>
|
|
/// <param name="source">is source color in ARGB</param>
|
|
/// <param name="nAlpha">is nAlpha is alpha channel</param>
|
|
/// <returns></returns>
|
|
private static UInt32 AddAlpha(UInt32 dest, UInt32 source, Byte nAlpha)
|
|
{
|
|
if (0 == nAlpha)
|
|
return dest;
|
|
|
|
if (255 == nAlpha)
|
|
return source;
|
|
|
|
Byte nSrcRed = (Byte)((source & 0xff0000) >> 16);
|
|
Byte nSrcGreen = (Byte)((source & 0xff00) >> 8);
|
|
Byte nSrcBlue = (Byte)((source & 0xff));
|
|
|
|
Byte nRed = (Byte)(nSrcRed);
|
|
Byte nGreen = (Byte)(nSrcGreen);
|
|
Byte nBlue = (Byte)(nSrcBlue);
|
|
|
|
return (UInt32)(nAlpha << 24 | nRed << 16 | nGreen << 8 | nBlue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Performs Alphablend
|
|
/// </summary>
|
|
/// <param name="dest">is destination color in ARGB</param>
|
|
/// <param name="source">is source color in ARGB</param>
|
|
/// <param name="nAlpha">is nAlpha is alpha channel</param>
|
|
/// <param name="nAlphaFinal">sets alpha channel of the returned UInt32</param>
|
|
/// <returns>destination color</returns>
|
|
private static UInt32 Alphablend(UInt32 dest, UInt32 source, Byte nAlpha, Byte nAlphaFinal)
|
|
{
|
|
if (0 == nAlpha)
|
|
return dest;
|
|
|
|
if (255 == nAlpha)
|
|
return source;
|
|
|
|
Byte nInvAlpha = (Byte)(~nAlpha);
|
|
|
|
Byte nSrcRed = (Byte)((source & 0xff0000) >> 16);
|
|
Byte nSrcGreen = (Byte)((source & 0xff00) >> 8);
|
|
Byte nSrcBlue = (Byte)((source & 0xff));
|
|
|
|
Byte nDestRed = (Byte)((dest & 0xff0000) >> 16);
|
|
Byte nDestGreen = (Byte)((dest & 0xff00) >> 8);
|
|
Byte nDestBlue = (Byte)(dest & 0xff);
|
|
|
|
Byte nRed = (Byte)((nSrcRed * nAlpha + nDestRed * nInvAlpha) >> 8);
|
|
Byte nGreen = (Byte)((nSrcGreen * nAlpha + nDestGreen * nInvAlpha) >> 8);
|
|
Byte nBlue = (Byte)((nSrcBlue * nAlpha + nDestBlue * nInvAlpha) >> 8);
|
|
|
|
return (UInt32)(nAlphaFinal << 24 | nRed << 16 | nGreen << 8 | nBlue);
|
|
}
|
|
/// <summary>
|
|
/// Performs Alphablend
|
|
/// </summary>
|
|
/// <param name="dest">is destination color in ARGB</param>
|
|
/// <param name="source">is source color in ARGB</param>
|
|
/// <returns>destination color</returns>
|
|
private static UInt32 PreMultipliedAlphablend(UInt32 dest, UInt32 source)
|
|
{
|
|
Byte Alpha = (Byte)((source & 0xff000000) >> 24);
|
|
Byte nInvAlpha = (Byte)(255 - Alpha);
|
|
|
|
Byte nSrcRed = (Byte)((source & 0xff0000) >> 16);
|
|
Byte nSrcGreen = (Byte)((source & 0xff00) >> 8);
|
|
Byte nSrcBlue = (Byte)((source & 0xff));
|
|
|
|
Byte nDestRed = (Byte)((dest & 0xff0000) >> 16);
|
|
Byte nDestGreen = (Byte)((dest & 0xff00) >> 8);
|
|
Byte nDestBlue = (Byte)(dest & 0xff);
|
|
|
|
Byte nRed = (Byte)(nSrcRed + ((nDestRed * nInvAlpha) >> 8));
|
|
Byte nGreen = (Byte)(nSrcGreen + ((nDestGreen * nInvAlpha) >> 8));
|
|
Byte nBlue = (Byte)(nSrcBlue + ((nDestBlue * nInvAlpha) >> 8));
|
|
|
|
return (UInt32)(0xff << 24 | nRed << 16 | nGreen << 8 | nBlue);
|
|
}
|
|
|
|
}
|
|
}
|