Ejemplo n.º 1
0
Color LimitedScaleColor (const Color& c1, const Color& c2, float factor)
{
	return Color ( LimitedScaleColor (c1.GetA(), c2.GetA(), factor)
				, LimitedScaleColor (c1.GetR(), c2.GetR(), factor)
				, LimitedScaleColor (c1.GetG(), c2.GetG(), factor)
				, LimitedScaleColor (c1.GetB(), c2.GetB(), factor));
}
Ejemplo n.º 2
0
void GPCreateFlashFrame( Bitmap& bmpSrc, CRect& rcBegin, CRect& rcEnd, Bitmap& bmpDes, CRect& rcDes, double dPercent )
{
	int  nWidth = bmpSrc.GetWidth();
	int  nHeight = bmpSrc.GetHeight();
	double dPercent2 = 1.0 - dPercent;
	int  nWidthDes = bmpDes.GetWidth();
	int  nHeightDes = bmpDes.GetHeight();
	CRect rcBmpSrc(0,0, nWidth, nHeight);
	CRect rcBmpDes(0,0, nWidthDes, nHeightDes);

	ASSERT(IsInRect(rcBegin, rcBmpSrc));
	ASSERT(IsInRect(rcEnd, rcBmpSrc));
	ASSERT(IsInRect(rcDes, rcBmpDes));
	ASSERT(rcBegin.Size() == rcEnd.Size());
	ASSERT(rcEnd.Size() == rcDes.Size());
	int nLoopWidth = rcBegin.Width();
	int nLoopHeight = rcBegin.Height();
	for (int i = 0; i <nLoopWidth; i++)
	{
		for (int j = 0; j < nLoopHeight; j++)
		{
			Color clrBegin;
			bmpSrc.GetPixel(i+ rcBegin.left, j+ rcBegin.top, &clrBegin);
			Color clrEnd;
			bmpSrc.GetPixel(i+ rcEnd.left, j+ rcEnd.top, &clrEnd);
			Color clrDes = Color::MakeARGB(clrBegin.GetA()*dPercent + clrEnd.GetA()* dPercent2, 
				clrBegin.GetR()*dPercent + clrEnd.GetR()* dPercent2,
				clrBegin.GetG()*dPercent + clrEnd.GetG()* dPercent2,
				clrBegin.GetB()*dPercent + clrEnd.GetB()* dPercent2);
			bmpDes.SetPixel(rcDes.left + i, rcDes.top+j, clrDes);
		}
	}
	

}
Ejemplo n.º 3
0
void Graphics::fillRect(Rect r, Color c1, Color c2, Color c3, Color c4)
{
    glPushMatrix();

        glTranslated(r.getX()+(Scalar)r.getWidth()/2+0.375f,r.getY()+(Scalar)r.getHeight()/2+0.375f,0);
        //DrawStuff
        glRotated(r.getRot(),0,0,-1);

        int w = (int)r.getWidth();
        int h = (int)r.getHeight();

        glDisable(GL_TEXTURE_2D);
        glBegin(GL_QUADS);
            glColor4d(c1.GetR(),c1.GetG(),c1.GetB(),c1.GetA());
            glVertex2d(-.5*w,-.5*h);
            glColor4d(c3.GetR(),c3.GetG(),c3.GetB(),c3.GetA());
            glVertex2d(-.5*w,.5*h);
            glColor4d(c4.GetR(),c4.GetG(),c4.GetB(),c4.GetA());
            glVertex2d(.5*w,.5*h);
            glColor4d(c2.GetR(),c2.GetG(),c2.GetB(),c2.GetA());
            glVertex2d(.5*w,-.5*h);
        glEnd();
        glEnable(GL_TEXTURE_2D);

    glPopMatrix();
}
Ejemplo n.º 4
0
Color Blend(Color c1, Color c2, int alpha)
{
	int a = (alpha >> 7) + alpha;
	return Color(min(((a * (c2.GetR() - c1.GetR())) >> 8) + c1.GetR(), 255),
	             min(((a * (c2.GetG() - c1.GetG())) >> 8) + c1.GetG(), 255),
	             min(((a * (c2.GetB() - c1.GetB())) >> 8) + c1.GetB(), 255));
}
Ejemplo n.º 5
0
BYTE MaxComponentDiff (const Color& c1, const Color& c2)
{
	int rDiff = abs ((int)c1.GetR() - (int)c2.GetR());
	int gDiff = abs ((int)c1.GetG() - (int)c2.GetG());
	int bDiff = abs ((int)c1.GetB() - (int)c2.GetB());

	return (BYTE) max (max (rDiff, gDiff), bDiff);
}
Ejemplo n.º 6
0
  void MapPainterOpenGL::DrawPath(const Projection& /*projection*/,
                                  const MapParameter& /*parameter*/,
                                  const Color& color,
                                  double width,
                                  const std::vector<double>& /*dash*/,
                                  LineStyle::CapStyle /*startCap*/,
                                  LineStyle::CapStyle /*endCap*/,
                                  size_t transStart, size_t transEnd)
  {
    // TODO:
    // There is a limit in the OpenGL lineWidth, we need to
    // fallback to using quads instead of lines for this.

    glColor4d(color.GetR(),
              color.GetG(),
              color.GetB(),
              color.GetA());

    glLineWidth(width);

    glBegin(GL_LINE_STRIP);

    for (size_t i=transStart; i<=transEnd; i++) {
      glVertex3d(coordBuffer->buffer[i].GetX(),
                 coordBuffer->buffer[i].GetY(),
                 0.0);
    }

    glEnd();
  }
Ejemplo n.º 7
0
// 리스트의 폰트 스타일이 관리된다.
void CCherryComboBox::SetDropDownListFont(LPCTSTR lpszFontName, LONG lFontSize, Color fontColor, DWORD dwFontStyle)
{
	m_font.DeleteObject();

	int nWeight = FW_NORMAL;
	BYTE byItalic = FALSE;
	BYTE byUnderline = FALSE;
	BYTE byStrikeOut = FALSE;

	if (dwFontStyle & STYLE_BOLD)
		nWeight = FW_BOLD;
	if (dwFontStyle & STYLE_ITALIC)
		byItalic = TRUE;
	if (dwFontStyle & STYLE_UNDERLINE)
		byUnderline = TRUE;
	if (dwFontStyle & STYLE_STRIKEOUT)
		byStrikeOut = TRUE;

	// Color -> COLORREF
	m_textColor = RGB(fontColor.GetR(), fontColor.GetG(), fontColor.GetB());

	m_font.CreateFont(lFontSize, 0, 0, 0, nWeight, byItalic, byUnderline, byStrikeOut, DEFAULT_CHARSET
		, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, lpszFontName);
	SetFont(&m_font);

	// SetFont() 후에 클라이언트 사이즈가 변경되기 때문에 여기서 텍스트 영역을 갱신한다.
	GetClientRect(m_textRect);
	// Offset pixel은 항상 반영
	m_textRect.OffsetRect(m_nOffsetTextLeft, m_nOffsetTextTop);

	CCherryFont::SetCherryFont(lpszFontName, static_cast<float>(lFontSize), fontColor, dwFontStyle);
}
Ejemplo n.º 8
0
Color Darken (const Color& c)
{
	return Color ( 0xff
				, Darken (c.GetR())
				, Darken (c.GetG())
				, Darken (c.GetB()));
}
Ejemplo n.º 9
0
void CAggMemoryDC::Line(
    const PointF& p1,
    const PointF& p2, 
    const Color& clr)
{
    if (m_buf==0)
        return;

    CPoint _p1 = p1;
    CPoint _p2 = p2;

    pixel_format pixf(m_rbuf);
    ren_base renb(pixf);

    outline_renderer outline_rd(renb, s_lineprof);
    outline_rasterizer_aa outline_rt(outline_rd);

    outline_rd.profile(s_lineprof);
    outline_rd.color(agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA()));
    outline_rd.clip_box(0, 0, m_rcUpdate.Width(), m_rcUpdate.Height());

    double p1x(p1.x), p1y(p1.y), p2x(p2.x), p2y(p2.y);
    m_mtx.transform(&p1x,&p1y);
    m_mtx.transform(&p2x,&p2y);

    outline_rt.move_to_d(p1x, p1y);
    outline_rt.line_to_d(p2x, p2y);
    //outline_rt.round_cap( 1 );
    outline_rt.render(false);
}
Ejemplo n.º 10
0
static XPicture sGetSolidFill(Color c)
{
	int q = GetHashValue(c) % (int)XRSolidFillCount;
	XRSolidFill& f = sFill[q];
	if(f.color == c && f.picture)
		return f.picture;
	if(f.picture)
		XRenderFreePicture(Xdisplay, f.picture);
	if(f.pixmap)
		XFreePixmap(Xdisplay, f.pixmap);
	f.pixmap = XCreatePixmap(Xdisplay, Xroot, 1, 1, 32);
	XRenderPictureAttributes attr;
	attr.repeat = XTrue;
	f.picture = XRenderCreatePicture(Xdisplay, f.pixmap,
	                                 XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
	                                                           CPRepeat, &attr);
	f.color = c;
	XRenderColor xc;
	xc.red = s255d16(c.GetR());
	xc.green = s255d16(c.GetG());
	xc.blue = s255d16(c.GetB());
	xc.alpha = 65535;
	XRenderFillRectangle(Xdisplay, PictOpSrc, f.picture, &xc, 0, 0, 1, 1);
	return f.picture;
}
Ejemplo n.º 11
0
void Splash::DrawString(const wchar_t* str, float x, float y, RSPL_TEXT_PROPS* prop, bool bFree)
{
	// Check alpha
	if(prop->cAlpha == 0)
		return;

	// Get length
	int len = (int)wcslen(str);
	
	// Setup point
	PointF pos(x, y);

	// Set alpha
	Color col;
	prop->brshBrush->GetColor(&col);
	Color ncol(prop->cAlpha, col.GetR(), col.GetG(), col.GetB());
	prop->brshBrush->SetColor(ncol);

	// Draw
	_oGrphInf.graphics->DrawString(str, len, prop->fntFont, pos, prop->sfFormat, prop->brshBrush);

	// Flush
	_oGrphInf.graphics->Flush();

	// Release string if needed
	if(bFree)
		LocalFree((LPVOID)str);
}
 int MapPainterCanvas::GetColorInt(Color color)
 {
   return GetColorInt(color.GetR(),
                      color.GetG(),
                      color.GetB(),
                      color.GetA());
 }
Ejemplo n.º 13
0
void Image::draw(int x, int y, int x1, int y1, int w, int h, Scalar ScaleX, Scalar ScaleY, Scalar Rot, Color c)
{
    glPushMatrix();

        glTranslated(x+(Scalar)w/2,y+(Scalar)h/2,0);
        //DrawStuff
        glRotated(Rot,0,0,-1);

        glBindTexture(GL_TEXTURE_2D, imageTag);
        glBegin(GL_QUADS);
            glColor4d(c.GetR(),c.GetG(),c.GetB(),c.GetA());
            //tex((Scalar)x1/width,(Scalar)y1/height);
            glTexCoord2d((Scalar)(x1+0.375f)/texSize,Scalar(y1+0.375f)/texSize);
            glVertex2d(-.5*w*ScaleX,-.5*h*ScaleY);
            //tex((Scalar)x1/width,(Scalar)(y1+h)/height);
            glTexCoord2d((Scalar)(x1+0.357f)/texSize,(Scalar)(y1+h-0.625f)/texSize);
            glVertex2d(-.5*w*ScaleX,.5*h*ScaleY);
            //tex((Scalar)(x1+w)/width,(Scalar)(y1+h)/height);
            glTexCoord2d(((Scalar)x1+w-0.625f)/texSize,(Scalar)(y1+h-0.625f)/texSize);
            glVertex2d(.5*w*ScaleX,.5*h*ScaleY);
            //tex((Scalar)(x1+w)/width,(Scalar)y1/height);
            glTexCoord2d(((Scalar)x1+w-0.625f)/texSize,(Scalar)(y1+0.375f)/texSize);
            glVertex2d(.5*w*ScaleX,-.5*h*ScaleY);
        glEnd();

    glPopMatrix();
}
Ejemplo n.º 14
0
void CAggMemoryDC::Lines(
    const PointFVector& pts,
    const Color& clr,
    const REAL width/*=1.0*/)
{
    if (m_buf==0)
        return;

    unsigned count=pts.size()/2;
    ATLASSERT(count>0);
    ATLASSERT((float)count/2.0f>0);

    pixel_format pixf(m_rbuf);
    ren_base renb(pixf);
    solid_renderer ren_solid(renb);

    m_path.remove_all();

    for(unsigned i=0; i<count; ++i)
    {
        m_path.move_to(pts[i*2].x, pts[i*2].y);
        m_path.line_to(pts[i*2+1].x, pts[i*2+1].y);
    }

    typedef agg::conv_stroke<conv_path_trans_type> conv_stroke_outline;
    conv_stroke_outline stroke(m_transpath);
    stroke.width(width);

    m_ras_aa.add_path(stroke);

    ren_solid.color(agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA()));
    agg::render_scanlines(m_ras_aa, m_sl, ren_solid);
}
Ejemplo n.º 15
0
void AADrawBASE(PixelBlock& w, int x, int y, Color c)
{
	if(!Rect(w.GetSize()).Contains(Rect(x, y, x + 6, y + 11)))
		return;
	const byte *s = op;
	dword *a = w.PointAdr(x, y);
	int d = w.LineDelta();
	byte tr = c.GetR();
	byte tg = c.GetG();
	byte tb = c.GetB();
	int q = 0;
	for(;;) {
		byte c = *s++;
		if(c) {
			byte *m = (byte *)&a[q];
			int alpha = c + (c >> 7);
			m[0] += alpha * (tr - m[0]) >> 8;
			m[1] += alpha * (tg - m[1]) >> 8;
			m[2] += alpha * (tb - m[2]) >> 8;
			q++;
		}
		else {
			c = *s++;
			if(c)
				q += c;
			else {
				if(s[0] == 0 && s[1] == 255)
					return;
				a += d;
				q = 0;
			}
		}
	}
Ejemplo n.º 16
0
String AsString(const Color& c) {
	if(IsNull(c))
		return "Color(Null)";
	if(c.GetRaw() & 0x80000000)
		return Format("Color(%d, 0)", int(c.GetRaw() & ~0x80000000));
	return Format("Color(%d, %d, %d)", c.GetR(), c.GetG(), c.GetB());
}
Ejemplo n.º 17
0
NAMESPACE_UPP

void SystemDraw::PutRect(const Rect& r, Color color)
{
	LLOG("Ctrl::PutRect " << r << ", color " << color);
	Ctrl::stat_putrect++;
	Point p = r.TopLeft();
	if(color == InvertColor()) {
		Ctrl::Put8(Ctrl::INVERTRECT);
		Ctrl::Put(r);
	}
	else {
		Size sz = r.GetSize();
		Point dp = p - pos;
		if(abs(dp.x) < 256 && abs(dp.y) < 256 && sz.cx < 256 && sz.cy < 256 && 0) {
			Ctrl::Put8(dp.x < 0 ? dp.y < 0 ? Ctrl::RECTNN : Ctrl::RECTNP
			                    : dp.y < 0 ? Ctrl::RECTPN : Ctrl::RECTPP);
			Ctrl::Put8(abs(dp.x));
			Ctrl::Put8(abs(dp.y));
			Ctrl::Put8(sz.cx);
			Ctrl::Put8(sz.cy);
		}
		else {
			Ctrl::Put8(Ctrl::RECT);
			Ctrl::Put(r);
		}
		Ctrl::Put8(color.GetR());
		Ctrl::Put8(color.GetG());
		Ctrl::Put8(color.GetB());
	}
	pos = p;
}
Ejemplo n.º 18
0
void CAggMemoryDC::SolidPolygon(
    const PointF* points, 
    const Color& clr,
    unsigned point_count)
{
    if (m_buf==0)
        return;

    if(m_npaths>0)
    {
        m_pathCache.close_polygon();
        m_colorsCache[m_countpaths] = agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA());
        m_path_idxCache[m_countpaths] = m_pathCache.start_new_path();
        m_countpaths++;
        m_pathCache.move_to(points->x, points->y);
        while(--point_count>0)
        {
            points++;
            m_pathCache.line_to(points->x, points->y);
        }
    }
    else
    {
        pixel_format pixf(m_rbuf);
        ren_base renb(pixf);
        solid_renderer ren_solid(renb);


        ATLASSERT(point_count>0);

        m_path.remove_all();
        m_path.move_to(points->x, points->y);
        while(--point_count>0)
        {
            points++;
            m_path.line_to(points->x, points->y);
        }

        m_ras_aa.reset();
        m_ras_aa.clip_box(0, 0, m_rcUpdate.Width(), m_rcUpdate.Height()); 
        m_ras_aa.add_path(m_transpath);

        ren_solid.color(agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA()));
        agg::render_scanlines(m_ras_aa, m_sl, ren_solid);
    }
}
Ejemplo n.º 19
0
void CTransparentPen::SetColor(Color crColor)
{
	BYTE r = crColor.GetR();
	BYTE g = crColor.GetG();
	BYTE b = crColor.GetB();

	ARGB argb = Color::MakeARGB(m_nAlpha, r, g, b);
	m_crColor.SetValue(argb);
}
Ejemplo n.º 20
0
RGBA operator*(int alpha, Color c)
{
	RGBA r;
	r.a = alpha;
	alpha += (alpha >> 7);
	r.r = (alpha * c.GetR()) >> 8;
	r.g = (alpha * c.GetG()) >> 8;
	r.b = (alpha * c.GetB()) >> 8;
	return r;
}
Ejemplo n.º 21
0
EscValue EscColor(Color c)
{
	EscValue v;
	if(!IsNull(c)) {
		v.MapSet("r", c.GetR());
		v.MapSet("g", c.GetG());
		v.MapSet("b", c.GetB());
	}
	return v;
}
Ejemplo n.º 22
0
void CAggMemoryDC::SolidPolygon(
    const PointF* points, 
    const Color& clr,
    unsigned point_count,
    REAL widthoutline,
    const Color& clroutline )
{
    if (m_buf==0)
        return;

    ATLASSERT(point_count>0);

    pixel_format pixf(m_rbuf);
    ren_base renb(pixf);

    solid_renderer ren_solid(renb);
    m_ras_aa.reset();

    m_path.remove_all();
    m_path.move_to(points->x, points->y);
    while(--point_count>0)
    {
        points++;
        m_path.line_to(points->x, points->y);
    }
    m_path.close_polygon();

    m_ras_aa.add_path(m_transpath);
    ren_solid.color(agg::rgba8(clr.GetR(), clr.GetG(), clr.GetB(), clr.GetA()));
    agg::render_scanlines(m_ras_aa, m_sl, ren_solid);

    if(widthoutline>REAL(0))
    {
        typedef agg::conv_stroke<conv_path_trans_type> conv_trans_stroke_outline;
        ren_solid.color(agg::rgba8(clroutline.GetR(),
            clroutline.GetG(), clroutline.GetB(), clroutline.GetA()));
        conv_trans_stroke_outline stroke(m_transpath);
        stroke.width(widthoutline);
        m_ras_aa.add_path(stroke);
        agg::render_scanlines(m_ras_aa, m_sl, ren_solid);
    }
}
Ejemplo n.º 23
0
void QTFDisplayCls::Paint(Draw& draw, const Rect& r, const Value& v, Color ink, Color paper, dword style) const
{
	String s;
	s << "[@(" << ink.GetR() << "." << ink.GetG() << "." << ink.GetB() << ") " << v;
	RichText rtext = ParseQTF(s);
	rtext.ApplyZoom(GetRichTextStdScreenZoom());
	draw.DrawRect(r, paper);
	draw.Clipoff(r);
	rtext.Paint(Zoom(1, 1), draw, 0, 0, r.Width());
	draw.End();
}
Ejemplo n.º 24
0
Color GetColorGradient(Color c1, Color c2, int ratio1, int ratio2, double gamma)
{
	double h1, s1, v1;
	double h2, s2, v2;
	RGBtoHSV(pow(c1.GetR() / 255.0, gamma), pow(c1.GetG() / 255.0, gamma), pow(c1.GetB() / 255.0, gamma), h1, s1, v1);
	RGBtoHSV(pow(c2.GetR() / 255.0, gamma), pow(c2.GetG() / 255.0, gamma), pow(c2.GetB() / 255.0, gamma), h2, s2, v2);
	if(s1 == 0)
		h1 = h2;
	else if(s2 == 0)
		h2 = h1;
	double r = ratio1 / (double)ratio2;
	gamma = 1 / gamma;
	if(h2 > h1 + 0.5)
		h1 = ((h1 += (h2 - 1 - h1) * r) < 0 ? h1 + 1 : h1);
	else if(h1 > h2 + 0.5)
		h1 = ((h1 += (h2 + 1 - h1) * r) > 1 ? h1 - 1 : h1);
	else
		h1 += (h2 - h1) * r;
	HSVtoRGB(h1, s1 + (s2 - s1) * r, v1 + (v2 - v1) * r, h1, s1, v1);
	return Color(fround(pow(h1, gamma) * 255.0), fround(pow(s1, gamma) * 255.0), fround(pow(v1, gamma) * 255.0));
}
Ejemplo n.º 25
0
void Sphere::DrawMe()
{
  btTransform trans;
  getMotionState()->getWorldTransform(trans);

  GLfloat mat_amb_diff[] = { _color.GetR(), _color.GetG(), _color.GetB(), 1.0 };
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_amb_diff);

  glPushMatrix();
  glTranslatef(trans.getOrigin().getX(), trans.getOrigin().getY(), trans.getOrigin().getZ());
  glutSolidSphere(_radius, 50, 50);
  glPopMatrix();
}
Ejemplo n.º 26
0
void Graphics::drawPoint(int x, int y, Color c)
{
    glPushMatrix();
    glLoadIdentity();
    //glScalef(ScaleX,ScaleY,1.0f);
    glTranslatef(0.375f,0.375f,0);
    //DrawStuff
    glDisable(GL_TEXTURE_2D);
    glBegin(GL_POINTS);
        glColor4d(c.GetR(),c.GetG(),c.GetB(),c.GetA());
        glVertex2d(x,y);
    glEnd();
    glEnable(GL_TEXTURE_2D);
    glPopMatrix();
}
Ejemplo n.º 27
0
void Box::DrawMe()
{
  translate(btVector3(15,0,0));

  btTransform trans;
  getMotionState()->getWorldTransform(trans);

  GLfloat mat_amb_diff[] = { _color.GetR(), _color.GetG(), _color.GetB(), 1.0 };
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_amb_diff);

  glPushMatrix();
  glTranslatef(trans.getOrigin().getX(), trans.getOrigin().getY(), trans.getOrigin().getZ());
  glutSolidCube(_side_size);
  glPopMatrix();
}
Ejemplo n.º 28
0
Image CreateBall(int r, Color color)
{
	int rr = 2 * r;
	int r2 = r * r;
	ImageBuffer b(rr, rr);
	b.SetHotSpot(Point(4, 4));
	for(int y = 0; y < rr; y++)
		for(int x = 0; x < rr; x++) {
			RGBA& a = b[y][x];
			a.r = color.GetR();
			a.g = color.GetG();
			a.b = color.GetB();
			int q = ((x - r) * (x - r) + (y - r) * (y - r)) * 256 / r2;
			a.a = q <= 255 ? q : 0;
		}
	return b;
}
Ejemplo n.º 29
0
UCHAR ImageArray::GetUCharAtLCDMem(UINT x, UINT y)
{
    UCHAR val = 0;

    if (x < GetColumns() && y < GetRows()) {
        Points points;
        m_packer->GetPoints(points, x, y);
        Points::iterator point = points.begin();
        while (point != points.end()) {
            Color c;
            m_img->GetPixel((*point).GetX(), (*point).GetY(), &c);
            UCHAR gray = Gray(c.GetR(), c.GetG(), c.GetB());
            val |= (m_packer->Pack(gray, (*point).GetPackOffset(), m_invert));
            point++;
        }
    }
    return val;
}
Ejemplo n.º 30
0
    //=================================================
    // Helper Functions
    //=================================================
    Color OffsetColor(Color clr, short sOffset)
    {
        BYTE bRed = 0;
        BYTE bGreen = 0;
        BYTE bBlue = 0;
        short sOffsetR = sOffset;
        short sOffsetG = sOffset;
        short sOffsetB = sOffset;

        if((sOffset < -255) || (sOffset > 255))
            return clr;

        // Get RGB components of specified color
        bRed = clr.GetR();
        bGreen = clr.GetG();
        bBlue = clr.GetB();

        // Calculate max. allowed real offset
        if(sOffset > 0)
        {
            if((bRed + sOffset) > 255)
                sOffsetR = (255 - bRed);
            if((bGreen + sOffset) > 255)
                sOffsetG = (255 - bGreen);
            if((bBlue + sOffset) > 255)
                sOffsetB = (255 - bBlue);

            sOffset = min(min(sOffsetR, sOffsetG), sOffsetB);
        }
        else
        {
            if((bRed + sOffset) < 0)
                sOffsetR = -bRed;
            if((bGreen + sOffset) < 0)
                sOffsetG = -bGreen;
            if((bBlue + sOffset) < 0)
                sOffsetB = -bBlue;

            sOffset = max(max(sOffsetR, sOffsetG), sOffsetB);
        }

        return Color(clr.GetAlpha(), (BYTE)(bRed + sOffset),
            (BYTE)(bGreen + sOffset), (BYTE)(bBlue + sOffset));
    }