示例#1
0
CG32bitPixel CG32bitPixel::Blend (CG32bitPixel rgbDest, CG32bitPixel rgbSrc)

//	Blend
//
//	Combines rgbSrc with rgbDest, using rgbSrc as the source opacity.
//	We assume dest has no alpha component and we assume that rgbSrc does.

	{
	BYTE *pAlpha = g_Alpha8[rgbSrc.GetAlpha()];
	BYTE *pAlphaInv = g_Alpha8[rgbSrc.GetAlpha() ^ 0xff];	//	Equivalent to 255 - rgbSrc.GetAlpha()

	BYTE byRedResult = pAlphaInv[rgbDest.GetRed()] + pAlpha[rgbSrc.GetRed()];
	BYTE byGreenResult = pAlphaInv[rgbDest.GetGreen()] + pAlpha[rgbSrc.GetGreen()];
	BYTE byBlueResult = pAlphaInv[rgbDest.GetBlue()] + pAlpha[rgbSrc.GetBlue()];

	return CG32bitPixel(byRedResult, byGreenResult, byBlueResult);
	}
示例#2
0
CGlowingRingPainter::CGlowingRingPainter (CG32bitImage &Dest, int iRadius, int iWidth, CG32bitPixel rgbColor) :
		m_Dest(Dest),
		m_rcClip(Dest.GetClipRect()),
		m_iRadius(iRadius),
		m_iWidth(iWidth)

//	CGlowingRingPainter constructor

	{
	int i;

	if (m_iWidth <= 0)
		{
		m_pColorRamp = NULL;
		return;
		}

	//	Generate a color ramp

	int iCenter = m_iWidth / 2;
	int iExtra = m_iWidth % 2;
	int iOuter = iCenter - 1;
	int iInner = iCenter + iExtra;

	m_ColorRamp.InsertEmpty(m_iWidth);

	//	We expect the color ramp to be pre-multiplied

	CG32bitPixel rgbPreMult = CG32bitPixel::PreMult(rgbColor);

	//	Init the center

	if (iExtra)
		m_ColorRamp[iCenter] = rgbPreMult;

	//	Edges

	for (i = 0; i < iCenter; i++)
		{
		ASSERT(iOuter >= 0 && iOuter < m_iWidth);
		ASSERT(iInner >=0 && iInner < m_iWidth);

		BYTE byAlpha = (BYTE)Min((WORD)0xff, (WORD)(rgbPreMult.GetAlpha() * (iCenter - i) / (iCenter + 1)));
		BYTE byRed = (BYTE)Min((WORD)0xff, (WORD)(rgbPreMult.GetRed() * (iCenter - i) / (iCenter + 1)));
		BYTE byGreen = (BYTE)Min((WORD)0xff, (WORD)(rgbPreMult.GetGreen() * (iCenter - i) / (iCenter + 1)));
		BYTE byBlue = (BYTE)Min((WORD)0xff, (WORD)(rgbPreMult.GetBlue() * (iCenter - i) / (iCenter + 1)));

		m_ColorRamp[iOuter] = CG32bitPixel(byRed, byGreen, byBlue, byAlpha);
		m_ColorRamp[iInner] = CG32bitPixel(byRed, byGreen, byBlue, byAlpha);

		iOuter--;
		iInner++;
		}

	m_pColorRamp = &m_ColorRamp;
	}
示例#3
0
CGRealRGB::CGRealRGB (CG32bitPixel rgbColor) :
		m_rR(rgbColor.GetRed() / 255.0),
		m_rG(rgbColor.GetGreen() / 255.0),
		m_rB(rgbColor.GetBlue() / 255.0),
		m_rA(rgbColor.GetAlpha() / 255.0)

//	CGRealRGB constructor

	{
	}
示例#4
0
CG32bitPixel CG32bitPixel::Desaturate (CG32bitPixel rgbColor)

//	Desaturate
//
//	Desaturate the given color

	{
	BYTE byMax = Max(Max(rgbColor.GetRed(), rgbColor.GetGreen()), rgbColor.GetBlue());
	BYTE byMin = Min(Min(rgbColor.GetRed(), rgbColor.GetGreen()), rgbColor.GetBlue());
	return CG32bitPixel::FromGrayscale((BYTE)(((DWORD)byMax + (DWORD)byMin) / 2), rgbColor.GetAlpha());
	}
示例#5
0
CGlowingRingPainter::CGlowingRingPainter (CG32bitImage &Dest, int iRadius, int iWidth, const TArray<CG32bitPixel> &ColorRamp, BYTE byOpacity) :
		m_Dest(Dest),
		m_rcClip(Dest.GetClipRect()),
		m_iRadius(iRadius),
		m_iWidth(iWidth)

//	CGlowingRingPainter constructor

	{
	int i;

	//	Pre-multiply the color ramp

	m_ColorRamp.InsertEmpty(ColorRamp.GetCount());
	m_pColorRamp = &m_ColorRamp;

	if (byOpacity == 0xff)
		{
		for (i = 0; i < m_ColorRamp.GetCount(); i++)
			m_ColorRamp[i] = CG32bitPixel::PreMult(ColorRamp[i]);
		}
	else
		{
		for (i = 0; i < m_ColorRamp.GetCount(); i++)
			{
			CG32bitPixel rgbPreMult = CG32bitPixel::PreMult(ColorRamp[i]);
			m_ColorRamp[i] = CG32bitPixel(CG32bitPixel::Blend(0, rgbPreMult, byOpacity), CG32bitPixel::BlendAlpha(rgbPreMult.GetAlpha(), byOpacity));
			}
		}
	}
示例#6
0
void CGlowingRingPainter::DrawLine (int x, int y)

//	DrawLine
//
//	Draws a line

	{
	int xStart = m_xDest - x;
	int xEnd = m_xDest + x + 1;

	if (xEnd <= m_rcClip.left || xStart >= m_rcClip.right)
		return;

	//	See which lines we need to paint

	int yLine = m_yDest - y;
	bool bPaintTop = (yLine >= m_rcClip.top && yLine < m_rcClip.bottom);
	CG32bitPixel *pCenterTop = m_Dest.GetPixelPos(m_xDest, yLine);

	yLine = m_yDest + y;
	bool bPaintBottom = ((y > 0) && (yLine >= m_rcClip.top && yLine < m_rcClip.bottom));
	CG32bitPixel *pCenterBottom = m_Dest.GetPixelPos(m_xDest, yLine);

	//	Compute radius increment

	int iRadius = y;
	int d = -y;
	int deltaE = 3;
	int deltaSE = -2 * y + 1;

	//	Loop

	int xPos = 0;

	//	This will skip the center pixel in the circle (avoids a divide by
	//	zero in the inner loop).

	if (y == 0)
		{
		xPos = 1;
		d += deltaSE;
		deltaE += 2;
		iRadius++;
		}

	//	Blt the line 

	while (xPos <= x)
		{
		//	Figure out the radius of the pixel at this location

		if (d < 0)
			{
			d += deltaE;
			deltaE += 2;
			deltaSE += 2;
			}
		else
			{
			d += deltaSE;
			deltaE += 2;
			//  deltaSE += 0;
			iRadius++;
			}

		//	Compute the index into the ramp based on radius and ring thickness
		//	(If we're outside the ramp, then continue)

		int iIndex = m_iRadius - iRadius;
		if (iIndex >= m_iWidth || iIndex < 0)
			{
			xPos++;
			continue;
			}

		//	Compute the transparency

		CG32bitPixel rgbColor = m_pColorRamp->GetAt(iIndex);
		BYTE byOpacity = rgbColor.GetAlpha();

		//	Optimize opaque painting

		if (byOpacity == 0x00)
			;
		else if (byOpacity == 0xff)
			{
			if (m_xDest - xPos < m_rcClip.right && m_xDest - xPos >= m_rcClip.left)
				{
				if (bPaintTop)
					*(pCenterTop - xPos) = rgbColor;

				if (bPaintBottom)
					*(pCenterBottom - xPos) = rgbColor;
				}

			if (xPos > 0 && m_xDest + xPos < m_rcClip.right && m_xDest + xPos >= m_rcClip.left)
				{
				if (bPaintTop)
					*(pCenterTop + xPos) = rgbColor;

				if (bPaintBottom)
					*(pCenterBottom + xPos) = rgbColor;
				}
			}
		else
			{
			BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byOpacity ^ 0xff);

			WORD wRed = rgbColor.GetRed();
			WORD wGreen = rgbColor.GetGreen();
			WORD wBlue = rgbColor.GetBlue();

			//	Draw transparent

#define DRAW_PIXEL(pos)	\
			{ \
			BYTE byRedResult = (BYTE)Min((WORD)0xff, (WORD)(pAlphaInv[(pos)->GetRed()] + wRed)); \
			BYTE byGreenResult = (BYTE)Min((WORD)0xff, (WORD)(pAlphaInv[(pos)->GetGreen()] + wGreen)); \
			BYTE byBlueResult = (BYTE)Min((WORD)0xff, (WORD)(pAlphaInv[(pos)->GetBlue()] + wBlue)); \
			\
			*(pos) = CG32bitPixel(byRedResult, byGreenResult, byBlueResult); \
			}

			//	Paint

			if (m_xDest - xPos < m_rcClip.right && m_xDest - xPos >= m_rcClip.left)
				{
				if (bPaintTop)
					DRAW_PIXEL(pCenterTop - xPos);

				if (bPaintBottom)
					DRAW_PIXEL(pCenterBottom - xPos);
				}

			if (xPos > 0 && m_xDest + xPos < m_rcClip.right && m_xDest + xPos >= m_rcClip.left)
				{
				if (bPaintTop)
					DRAW_PIXEL(pCenterTop + xPos);

				if (bPaintBottom)
					DRAW_PIXEL(pCenterBottom + xPos);
				}
#undef DRAW_PIXEL
			}

		xPos++;
		}
	}
示例#7
0
void CG8bitSparseImage::MaskFill (CG32bitImage &Dest, int xDest, int yDest, int cxDest, int cyDest, int xSrc, int ySrc, CG32bitPixel rgbColor) const

//	MaskFill
//
//	Fills the destination image with the given color through our mask.

	{
	//	Make sure we're in bounds

	if (!Dest.AdjustCoords(&xSrc, &ySrc, GetWidth(), GetHeight(), 
			&xDest, &yDest,
			&cxDest, &cyDest))
		return;

	//	Short-circuit

	if (rgbColor.GetAlpha() == 0x00)
		return;

	//	Compute a pre-multiplied color

	BYTE *pAlpha = CG32bitPixel::AlphaTable(rgbColor.GetAlpha());
	CG32bitPixel rgbPreMultColor = CG32bitPixel(pAlpha[rgbColor.GetRed()], pAlpha[rgbColor.GetGreen()], pAlpha[rgbColor.GetBlue()], rgbColor.GetAlpha());

	//	Loop

	int yPos = ySrc;
	int yPosEnd = ySrc + cyDest;
	int yTile = yPos / m_cyTile;
	int yOffset = ClockMod(yPos, m_cyTile);
	int xTileStart = xSrc / m_cxTile;
	int xOffsetStart = ClockMod(xSrc, m_cxTile);

	int yDestPos = yDest;
	while (yPos < yPosEnd)
		{
		int cyTileLeft = Min(m_cyTile - yOffset, yPosEnd - yPos);

		//	Is this a valid tile row, then continue

		if (yTile >= 0 && yTile < m_yTileCount)
			{
			int xPos = xSrc;
			int xPosEnd = xSrc + cxDest;
			int xTile = xTileStart;
			int xOffset = xOffsetStart;

			int xDestPos = xDest;
			while (xPos < xPosEnd)
				{
				int cxTileLeft = Min(m_cxTile - xOffset, xPosEnd - xPos);

				//	If this is a valid tile, then we can continue

				if (xTile >= 0 && xTile < m_xTileCount)
					{
					const CNode &Tile = GetTile(xTile, yTile);

					switch (Tile.GetType())
						{
						case typeByte:
							{
							BYTE byAlpha = Tile.GetByte();
							if (byAlpha == 0x00)
								{}
							else if (byAlpha == 0xff)
								Dest.Fill(xDestPos, yDestPos, cxTileLeft, cyTileLeft, rgbColor);
							else
								//	We just modify the alpha on the original color (Fill will take care of the rest)
								Dest.Fill(xDestPos, yDestPos, cxTileLeft, cyTileLeft, CG32bitPixel(rgbColor, CG32bitPixel::BlendAlpha(rgbColor.GetAlpha(), byAlpha)));
							break;
							}

						case typeNodeArray:
							{
							CNode *Rows = Tile.GetNodeArray();
							CNode *pSrcRow = Rows + yOffset;
							CNode *pSrcRowEnd = pSrcRow + cyTileLeft;

							CG32bitPixel *pDestRow = Dest.GetPixelPos(xDestPos, yDestPos);

							while (pSrcRow < pSrcRowEnd)
								{
								CG32bitPixel *pDest = pDestRow;
								CG32bitPixel *pDestEnd = pDestRow + cxTileLeft;

								switch (pSrcRow->GetType())
									{
									case typeByte:
										{
										BYTE byAlpha = pSrcRow->GetByte();
										if (byAlpha == 0x00)
											{}
										else if (byAlpha == 0xff)
											{
											BYTE byFillAlpha = rgbColor.GetAlpha();
											if (byFillAlpha == 0xff)
												{
												while (pDest < pDestEnd)
													*pDest++ = rgbColor;
												}
											else
												{
												BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byFillAlpha ^ 0xff);

												BYTE byRed = rgbPreMultColor.GetRed();
												BYTE byGreen = rgbPreMultColor.GetGreen();
												BYTE byBlue = rgbPreMultColor.GetBlue();

												while (pDest < pDestEnd)
													{
													BYTE byRedResult = pAlphaInv[pDest->GetRed()] + byRed;
													BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + byGreen;
													BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + byBlue;

													*pDest++ = CG32bitPixel(byRedResult, byGreenResult, byBlueResult);
													}
												}
											}
										else
											{
											//	Blend the alphas together
											BYTE byFillAlpha = CG32bitPixel::BlendAlpha(byAlpha, rgbColor.GetAlpha());

											BYTE *pAlpha = CG32bitPixel::AlphaTable(byFillAlpha);
											BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byFillAlpha ^ 0xff);

											BYTE byRed = pAlpha[rgbColor.GetRed()];
											BYTE byGreen = pAlpha[rgbColor.GetBlue()];
											BYTE byBlue = pAlpha[rgbColor.GetGreen()];

											while (pDest < pDestEnd)
												{
												BYTE byRedResult = pAlphaInv[pDest->GetRed()] + byRed;
												BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + byGreen;
												BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + byBlue;

												*pDest++ = CG32bitPixel(byRedResult, byGreenResult, byBlueResult);
												}
											}
										break;
										}

									case typeByteArray:
										{
										BYTE *pSrcAlpha = pSrcRow->GetByteArray() + xOffset;
										BYTE *pSrcAlphaEnd = pSrcAlpha + cxTileLeft;

										BYTE byColorAlpha = rgbColor.GetAlpha();
										if (byColorAlpha == 0xff)
											{
											while (pSrcAlpha < pSrcAlphaEnd)
												{
												if (*pSrcAlpha == 0x00)
													{}
												else if (*pSrcAlpha == 0xff)
													*pDest = rgbColor;
												else
													{
													BYTE *pAlpha = CG32bitPixel::AlphaTable(*pSrcAlpha);
													BYTE *pAlphaInv = CG32bitPixel::AlphaTable(*pSrcAlpha ^ 0xff);

													BYTE byRedResult = pAlphaInv[pDest->GetRed()] + pAlpha[rgbColor.GetRed()];
													BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + pAlpha[rgbColor.GetGreen()];
													BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + pAlpha[rgbColor.GetBlue()];

													*pDest = CG32bitPixel(byRedResult, byGreenResult, byBlueResult);
													}

												pSrcAlpha++;
												pDest++;
												}
											}
										else
											{
											BYTE *pAlphaFFInv = CG32bitPixel::AlphaTable(byColorAlpha ^ 0xff);

											while (pSrcAlpha < pSrcAlphaEnd)
												{
												if (*pSrcAlpha == 0x00)
													{}
												else if (*pSrcAlpha == 0xff)
													{
													BYTE byRedResult = pAlphaFFInv[pDest->GetRed()] + rgbPreMultColor.GetRed();
													BYTE byGreenResult = pAlphaFFInv[pDest->GetGreen()] + rgbPreMultColor.GetGreen();
													BYTE byBlueResult = pAlphaFFInv[pDest->GetBlue()] + rgbPreMultColor.GetBlue();

													*pDest = CG32bitPixel(byRedResult, byGreenResult, byBlueResult);
													}
												else
													{
													BYTE byFillAlpha = CG32bitPixel::BlendAlpha(*pSrcAlpha, byColorAlpha);

													BYTE *pAlpha = CG32bitPixel::AlphaTable(byFillAlpha);
													BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byFillAlpha ^ 0xff);

													BYTE byRedResult = pAlphaInv[pDest->GetRed()] + pAlpha[rgbColor.GetRed()];
													BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + pAlpha[rgbColor.GetGreen()];
													BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + pAlpha[rgbColor.GetBlue()];

													*pDest = CG32bitPixel(byRedResult, byGreenResult, byBlueResult);
													}

												pSrcAlpha++;
												pDest++;
												}
											}
										break;
										}
									}

								pSrcRow++;
								pDestRow = Dest.NextRow(pDestRow);
								}

							break;
							}
						}
					}

				//	Move to the next tile

				xTile++;
				xOffset = 0;
				xPos += cxTileLeft;
				xDestPos += cxTileLeft;
				}
			}

		//	Next tile row

		yTile++;
		yOffset = 0;
		yPos += cyTileLeft;
		yDestPos += cyTileLeft;
		}
	}