1 // xImaPal.cpp : Palette and Pixel functions
2 /* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
3 * CxImage version 6.0.0 02/Feb/2008
8 ////////////////////////////////////////////////////////////////////////////////
10 * returns the palette dimension in byte
12 DWORD CxImage::GetPaletteSize()
14 return (head.biClrUsed * sizeof(RGBQUAD));
16 ////////////////////////////////////////////////////////////////////////////////
17 void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha)
19 if ((pDib)&&(head.biClrUsed)){
20 BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
21 if (idx<head.biClrUsed){
22 long ldx=idx*sizeof(RGBQUAD);
23 iDst[ldx++] = (BYTE) b;
24 iDst[ldx++] = (BYTE) g;
25 iDst[ldx++] = (BYTE) r;
26 iDst[ldx] = (BYTE) alpha;
27 info.last_c_isvalid = false;
31 ////////////////////////////////////////////////////////////////////////////////
32 void CxImage::SetPaletteColor(BYTE idx, RGBQUAD c)
34 if ((pDib)&&(head.biClrUsed)){
35 BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
36 if (idx<head.biClrUsed){
37 long ldx=idx*sizeof(RGBQUAD);
38 iDst[ldx++] = (BYTE) c.rgbBlue;
39 iDst[ldx++] = (BYTE) c.rgbGreen;
40 iDst[ldx++] = (BYTE) c.rgbRed;
41 iDst[ldx] = (BYTE) c.rgbReserved;
42 info.last_c_isvalid = false;
46 ////////////////////////////////////////////////////////////////////////////////
47 void CxImage::SetPaletteColor(BYTE idx, COLORREF cr)
49 if ((pDib)&&(head.biClrUsed)){
50 BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
51 if (idx<head.biClrUsed){
52 long ldx=idx*sizeof(RGBQUAD);
53 iDst[ldx++] = (BYTE) GetBValue(cr);
54 iDst[ldx++] = (BYTE) GetGValue(cr);
55 iDst[ldx++] = (BYTE) GetRValue(cr);
57 info.last_c_isvalid = false;
61 ////////////////////////////////////////////////////////////////////////////////
63 * returns the pointer to the first palette index
65 RGBQUAD* CxImage::GetPalette() const
67 if ((pDib)&&(head.biClrUsed))
68 return (RGBQUAD*)((BYTE*)pDib + sizeof(BITMAPINFOHEADER));
71 ////////////////////////////////////////////////////////////////////////////////
73 * Returns the color of the specified index.
75 RGBQUAD CxImage::GetPaletteColor(BYTE idx)
77 RGBQUAD rgb = {0,0,0,0};
78 if ((pDib)&&(head.biClrUsed)){
79 BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
80 if (idx<head.biClrUsed){
81 long ldx=idx*sizeof(RGBQUAD);
82 rgb.rgbBlue = iDst[ldx++];
83 rgb.rgbGreen=iDst[ldx++];
84 rgb.rgbRed =iDst[ldx++];
85 rgb.rgbReserved = iDst[ldx];
90 ////////////////////////////////////////////////////////////////////////////////
92 * Returns the palette index of the specified pixel.
94 BYTE CxImage::GetPixelIndex(long x,long y)
96 if ((pDib==NULL)||(head.biClrUsed==0)) return 0;
98 if ((x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) {
99 if (info.nBkgndIndex >= 0) return (BYTE)info.nBkgndIndex;
100 else return *info.pImage;
102 if (head.biBitCount==8){
103 return info.pImage[y*info.dwEffWidth + x];
106 BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];
107 if (head.biBitCount==4){
108 pos = (BYTE)(4*(1-x%2));
110 return (BYTE)(iDst >> pos);
111 } else if (head.biBitCount==1){
114 return (BYTE)(iDst >> pos);
119 ////////////////////////////////////////////////////////////////////////////////
120 BYTE CxImage::BlindGetPixelIndex(const long x,const long y)
123 if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y))
124 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
131 if (head.biBitCount==8){
132 return info.pImage[y*info.dwEffWidth + x];
135 BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];
136 if (head.biBitCount==4){
137 pos = (BYTE)(4*(1-x%2));
139 return (BYTE)(iDst >> pos);
140 } else if (head.biBitCount==1){
143 return (BYTE)(iDst >> pos);
148 ////////////////////////////////////////////////////////////////////////////////
149 RGBQUAD CxImage::GetPixelColor(long x,long y, bool bGetAlpha)
151 // RGBQUAD rgb={0,0,0,0};
152 RGBQUAD rgb=info.nBkgndColor; //<mpwolski>
153 if ((pDib==NULL)||(x<0)||(y<0)||
154 (x>=head.biWidth)||(y>=head.biHeight)){
155 if (info.nBkgndIndex >= 0){
156 if (head.biBitCount<24) return GetPaletteColor((BYTE)info.nBkgndIndex);
157 else return info.nBkgndColor;
158 } else if (pDib) return GetPixelColor(0,0);
163 rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
165 BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;
166 rgb.rgbBlue = *iDst++;
167 rgb.rgbGreen= *iDst++;
170 #if CXIMAGE_SUPPORT_ALPHA
171 if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);
174 #endif //CXIMAGE_SUPPORT_ALPHA
177 ////////////////////////////////////////////////////////////////////////////////
179 * This is (a bit) faster version of GetPixelColor.
180 * It tests bounds only in debug mode (_DEBUG defined).
182 * It is an error to request out-of-borders pixel with this method.
183 * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode.
184 * \author ***bd*** 2.2004
186 RGBQUAD CxImage::BlindGetPixelColor(const long x,const long y, bool bGetAlpha)
190 if ((pDib==NULL) || !IsInside(x,y))
191 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
194 {rgb.rgbReserved = 0; return rgb;}
199 rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
201 BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;
202 rgb.rgbBlue = *iDst++;
203 rgb.rgbGreen= *iDst++;
205 rgb.rgbReserved = 0; //needed for images without alpha layer
207 #if CXIMAGE_SUPPORT_ALPHA
208 if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);
211 #endif //CXIMAGE_SUPPORT_ALPHA
214 ////////////////////////////////////////////////////////////////////////////////
215 BYTE CxImage::GetPixelGray(long x, long y)
217 RGBQUAD color = GetPixelColor(x,y);
218 return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
220 ////////////////////////////////////////////////////////////////////////////////
221 void CxImage::BlindSetPixelIndex(long x,long y,BYTE i)
224 if ((pDib==NULL)||(head.biClrUsed==0)||
225 (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight))
226 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
233 if (head.biBitCount==8){
234 info.pImage[y*info.dwEffWidth + x]=i;
238 BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);
239 if (head.biBitCount==4){
240 pos = (BYTE)(4*(1-x%2));
241 *iDst &= ~(0x0F<<pos);
242 *iDst |= ((i & 0x0F)<<pos);
244 } else if (head.biBitCount==1){
246 *iDst &= ~(0x01<<pos);
247 *iDst |= ((i & 0x01)<<pos);
252 ////////////////////////////////////////////////////////////////////////////////
253 void CxImage::SetPixelIndex(long x,long y,BYTE i)
255 if ((pDib==NULL)||(head.biClrUsed==0)||
256 (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ;
258 if (head.biBitCount==8){
259 info.pImage[y*info.dwEffWidth + x]=i;
263 BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);
264 if (head.biBitCount==4){
265 pos = (BYTE)(4*(1-x%2));
266 *iDst &= ~(0x0F<<pos);
267 *iDst |= ((i & 0x0F)<<pos);
269 } else if (head.biBitCount==1){
271 *iDst &= ~(0x01<<pos);
272 *iDst |= ((i & 0x01)<<pos);
277 ////////////////////////////////////////////////////////////////////////////////
278 void CxImage::SetPixelColor(long x,long y,COLORREF cr)
280 SetPixelColor(x,y,RGBtoRGBQUAD(cr));
282 ////////////////////////////////////////////////////////////////////////////////
283 void CxImage::BlindSetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)
286 if ((pDib==NULL)||(x<0)||(y<0)||
287 (x>=head.biWidth)||(y>=head.biHeight))
288 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
295 BlindSetPixelIndex(x,y,GetNearestIndex(c));
297 BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;
299 *iDst++ = c.rgbGreen;
302 #if CXIMAGE_SUPPORT_ALPHA
303 if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);
304 #endif //CXIMAGE_SUPPORT_ALPHA
306 ////////////////////////////////////////////////////////////////////////////////
307 void CxImage::SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)
309 if ((pDib==NULL)||(x<0)||(y<0)||
310 (x>=head.biWidth)||(y>=head.biHeight)) return;
312 BlindSetPixelIndex(x,y,GetNearestIndex(c));
314 BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;
316 *iDst++ = c.rgbGreen;
319 #if CXIMAGE_SUPPORT_ALPHA
320 if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);
321 #endif //CXIMAGE_SUPPORT_ALPHA
323 ////////////////////////////////////////////////////////////////////////////////
325 * Blends the current pixel color with a new color.
327 * \param c = new color
328 * \param blend = can be from 0 (no effect) to 1 (full effect).
329 * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved
331 void CxImage::BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha)
333 if ((pDib==NULL)||(x<0)||(y<0)||
334 (x>=head.biWidth)||(y>=head.biHeight)) return;
336 int a0 = (int)(256*blend);
339 RGBQUAD c0 = BlindGetPixelColor(x,y);
340 c.rgbRed = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8);
341 c.rgbBlue = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8);
342 c.rgbGreen = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8);
345 BlindSetPixelIndex(x,y,GetNearestIndex(c));
347 BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;
349 *iDst++ = c.rgbGreen;
351 #if CXIMAGE_SUPPORT_ALPHA
352 if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);
353 #endif //CXIMAGE_SUPPORT_ALPHA
356 ////////////////////////////////////////////////////////////////////////////////
358 * Returns the best palette index that matches a specified color.
360 BYTE CxImage::GetNearestIndex(RGBQUAD c)
362 if ((pDib==NULL)||(head.biClrUsed==0)) return 0;
364 // <RJ> check matching with the previous result
365 if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index;
367 info.last_c_isvalid = true;
369 BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
370 long distance=200000;
373 int m = (int)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant);
374 for(i=0,l=0;i<m;i++,l+=sizeof(RGBQUAD)){
375 k = (iDst[l]-c.rgbBlue)*(iDst[l]-c.rgbBlue)+
376 (iDst[l+1]-c.rgbGreen)*(iDst[l+1]-c.rgbGreen)+
377 (iDst[l+2]-c.rgbRed)*(iDst[l+2]-c.rgbRed);
378 // k = abs(iDst[l]-c.rgbBlue)+abs(iDst[l+1]-c.rgbGreen)+abs(iDst[l+2]-c.rgbRed);
388 info.last_c_index = (BYTE)j;
391 ////////////////////////////////////////////////////////////////////////////////
393 * swaps the blue and red components (for RGB images)
394 * \param buffer : pointer to the pixels
395 * \param length : number of bytes to swap. lenght may not exceed the scan line.
397 void CxImage::RGBtoBGR(BYTE *buffer, int length)
399 if (buffer && (head.biClrUsed==0)){
401 length = min(length,(int)info.dwEffWidth);
402 length = min(length,(int)(3*head.biWidth));
403 for (int i=0;i<length;i+=3){
404 temp = buffer[i]; buffer[i] = buffer[i+2]; buffer[i+2] = temp;
408 ////////////////////////////////////////////////////////////////////////////////
409 RGBQUAD CxImage::RGBtoRGBQUAD(COLORREF cr)
412 c.rgbRed = GetRValue(cr); /* get R, G, and B out of DWORD */
413 c.rgbGreen = GetGValue(cr);
414 c.rgbBlue = GetBValue(cr);
418 ////////////////////////////////////////////////////////////////////////////////
419 COLORREF CxImage::RGBQUADtoRGB (RGBQUAD c)
421 return RGB(c.rgbRed,c.rgbGreen,c.rgbBlue);
423 ////////////////////////////////////////////////////////////////////////////////
425 * Returns the color of the specified index.
426 * \param i = palette index
427 * \param r, g, b = output color channels
429 bool CxImage::GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b)
431 RGBQUAD* ppal=GetPalette();
434 *g = ppal[i].rgbGreen;
435 *b = ppal[i].rgbBlue;
440 ////////////////////////////////////////////////////////////////////////////////
441 void CxImage::SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b)
443 if ((!r)||(pDib==NULL)||(head.biClrUsed==0)) return;
446 RGBQUAD* ppal=GetPalette();
447 DWORD m=min(n,head.biClrUsed);
448 for (DWORD i=0; i<m;i++){
450 ppal[i].rgbGreen=g[i];
451 ppal[i].rgbBlue=b[i];
453 info.last_c_isvalid = false;
455 ////////////////////////////////////////////////////////////////////////////////
456 void CxImage::SetPalette(rgb_color *rgb,DWORD nColors)
458 if ((!rgb)||(pDib==NULL)||(head.biClrUsed==0)) return;
459 RGBQUAD* ppal=GetPalette();
460 DWORD m=min(nColors,head.biClrUsed);
461 for (DWORD i=0; i<m;i++){
462 ppal[i].rgbRed=rgb[i].r;
463 ppal[i].rgbGreen=rgb[i].g;
464 ppal[i].rgbBlue=rgb[i].b;
466 info.last_c_isvalid = false;
468 ////////////////////////////////////////////////////////////////////////////////
469 void CxImage::SetPalette(RGBQUAD* pPal,DWORD nColors)
471 if ((pPal==NULL)||(pDib==NULL)||(head.biClrUsed==0)) return;
472 memcpy(GetPalette(),pPal,min(GetPaletteSize(),nColors*sizeof(RGBQUAD)));
473 info.last_c_isvalid = false;
475 ////////////////////////////////////////////////////////////////////////////////
477 * Sets (or replaces) the palette to gray scale palette.
478 * The function doesn't change the pixels; for standard
479 * gray scale conversion use GrayScale().
481 void CxImage::SetGrayPalette()
483 if ((pDib==NULL)||(head.biClrUsed==0)) return;
484 RGBQUAD* pal=GetPalette();
485 for (DWORD ni=0;ni<head.biClrUsed;ni++)
486 pal[ni].rgbBlue=pal[ni].rgbGreen = pal[ni].rgbRed = (BYTE)(ni*(255/(head.biClrUsed-1)));
488 ////////////////////////////////////////////////////////////////////////////////
490 * Colorize the palette.
493 void CxImage::BlendPalette(COLORREF cr,long perc)
495 if ((pDib==NULL)||(head.biClrUsed==0)) return;
496 BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
498 RGBQUAD* pPal=(RGBQUAD*)iDst;
502 if (perc>100) perc=100;
503 for(i=0;i<head.biClrUsed;i++){
504 pPal[i].rgbBlue=(BYTE)((pPal[i].rgbBlue*(100-perc)+b*perc)/100);
505 pPal[i].rgbGreen =(BYTE)((pPal[i].rgbGreen*(100-perc)+g*perc)/100);
506 pPal[i].rgbRed =(BYTE)((pPal[i].rgbRed*(100-perc)+r*perc)/100);
509 ////////////////////////////////////////////////////////////////////////////////
511 * Returns true if the image has 256 colors and a linear grey scale palette.
513 bool CxImage::IsGrayScale()
515 RGBQUAD* ppal=GetPalette();
516 if(!(pDib && ppal && head.biClrUsed)) return false;
517 for(DWORD i=0;i<head.biClrUsed;i++){
518 if (ppal[i].rgbBlue!=i || ppal[i].rgbGreen!=i || ppal[i].rgbRed!=i) return false;
522 ////////////////////////////////////////////////////////////////////////////////
524 * swap two indexes in the image and their colors in the palette
526 void CxImage::SwapIndex(BYTE idx1, BYTE idx2)
528 RGBQUAD* ppal=GetPalette();
529 if(!(pDib && ppal)) return;
531 RGBQUAD tempRGB=GetPaletteColor(idx1);
532 SetPaletteColor(idx1,GetPaletteColor(idx2));
533 SetPaletteColor(idx2,tempRGB);
536 for(long y=0; y < head.biHeight; y++){
537 for(long x=0; x < head.biWidth; x++){
538 idx=BlindGetPixelIndex(x,y);
539 if (idx==idx1) BlindSetPixelIndex(x,y,idx2);
540 if (idx==idx2) BlindSetPixelIndex(x,y,idx1);
544 ////////////////////////////////////////////////////////////////////////////////
546 * swap Red and Blue colors
548 void CxImage::SwapRGB2BGR()
553 RGBQUAD* ppal=GetPalette();
556 for(WORD a=0;a<head.biClrUsed;a++){
557 b=ppal[a].rgbBlue; ppal[a].rgbBlue=ppal[a].rgbRed; ppal[a].rgbRed=b;
560 for(long y=0;y<head.biHeight;y++){
561 RGBtoBGR(GetBits(y),3*head.biWidth);
565 ////////////////////////////////////////////////////////////////////////////////
566 bool CxImage::IsTransparent(long x, long y)
568 if (!pDib) return false;
570 if (info.nBkgndIndex>=0){
572 if (GetPixelIndex(x,y) == info.nBkgndIndex) return true;
574 RGBQUAD ct = info.nBkgndColor;
575 RGBQUAD c = GetPixelColor(x,y,false);
576 if (*(long*)&c==*(long*)&ct) return true;
580 #if CXIMAGE_SUPPORT_ALPHA
581 if (pAlpha) return AlphaGet(x,y)==0;
586 ////////////////////////////////////////////////////////////////////////////////
587 bool CxImage::GetTransparentMask(CxImage* iDst)
589 if (!pDib) return false;
592 tmp.Create(head.biWidth, head.biHeight, 1, GetType());
596 for(long y=0; y<head.biHeight; y++){
597 for(long x=0; x<head.biWidth; x++){
598 if (IsTransparent(x,y)){
599 tmp.BlindSetPixelIndex(x,y,1);
604 if (iDst) iDst->Transfer(tmp);
609 ////////////////////////////////////////////////////////////////////////////////
611 * Checks if image has the same palette, if any.
612 * \param img = image to compare.
613 * \param bCheckAlpha = check also the rgbReserved field.
615 bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha)
617 if (head.biClrUsed != img.head.biClrUsed)
619 if (head.biClrUsed == 0)
623 for (DWORD n=0; n<head.biClrUsed; n++){
624 c1 = GetPaletteColor((BYTE)n);
625 c2 = img.GetPaletteColor((BYTE)n);
626 if (c1.rgbRed != c2.rgbRed) return false;
627 if (c1.rgbBlue != c2.rgbBlue) return false;
628 if (c1.rgbGreen != c2.rgbGreen) return false;
629 if (bCheckAlpha && (c1.rgbReserved != c2.rgbReserved)) return false;
633 ////////////////////////////////////////////////////////////////////////////////
635 * \sa SetClrImportant
637 DWORD CxImage::GetClrImportant() const
639 return head.biClrImportant;
641 ////////////////////////////////////////////////////////////////////////////////
643 * sets the maximum number of colors that some functions like
644 * DecreaseBpp() or GetNearestIndex() will use on indexed images
645 * \param ncolors should be less than 2^bpp,
646 * or 0 if all the colors are important.
648 void CxImage::SetClrImportant(DWORD ncolors)
650 if (ncolors==0 || ncolors>256) {
651 head.biClrImportant = 0;
655 switch(head.biBitCount){
657 head.biClrImportant = min(ncolors,2);
660 head.biClrImportant = min(ncolors,16);
663 head.biClrImportant = ncolors;
668 ////////////////////////////////////////////////////////////////////////////////
670 * Returns pointer to pixel. Currently implemented only for truecolor images.
672 * \param x,y - coordinates
674 * \return pointer to first byte of pixel data
676 * \author ***bd*** 2.2004
678 void* CxImage::BlindGetPixelPointer(const long x, const long y)
681 if ((pDib==NULL) || !IsInside(x,y))
682 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
689 return info.pImage + y*info.dwEffWidth + x*3;
693 ////////////////////////////////////////////////////////////////////////////////
694 void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr)
696 DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr));
698 ////////////////////////////////////////////////////////////////////////////////
699 void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha)
702 //////////////////////////////////////////////////////
703 // Draws a line using the Bresenham line algorithm
704 // Thanks to Jordan DeLozier <JDL>
705 //////////////////////////////////////////////////////
708 int x = x1; // Start x off at the first pixel
709 int y = y1; // Start y off at the first pixel
713 int xinc1,xinc2,yinc1,yinc2; // Increasing values
714 int den, num, numadd,numpixels;
715 int deltax = abs(x2 - x1); // The difference between the x's
716 int deltay = abs(y2 - y1); // The difference between the y's
718 // Get Increasing Values
719 if (x2 >= x1) { // The x-values are increasing
722 } else { // The x-values are decreasing
727 if (y2 >= y1) { // The y-values are increasing
730 } else { // The y-values are decreasing
735 // Actually draw the line
736 if (deltax >= deltay) // There is at least one x-value for every y-value
738 xinc1 = 0; // Don't change the x when numerator >= denominator
739 yinc2 = 0; // Don't change the y for every iteration
743 numpixels = deltax; // There are more x-values than y-values
745 else // There is at least one y-value for every x-value
747 xinc2 = 0; // Don't change the x for every iteration
748 yinc1 = 0; // Don't change the y when numerator >= denominator
752 numpixels = deltay; // There are more y-values than x-values
755 for (int curpixel = 0; curpixel <= numpixels; curpixel++)
757 // Draw the current pixel
758 SetPixelColor(x,y,color,bSetAlpha);
760 num += numadd; // Increase the numerator by the top of the fraction
761 if (num >= den) // Check if numerator >= denominator
763 num -= den; // Calculate the new numerator value
764 x += xinc1; // Change the x as appropriate
765 y += yinc1; // Change the y as appropriate
767 x += xinc2; // Change the x as appropriate
768 y += yinc2; // Change the y as appropriate
771 ////////////////////////////////////////////////////////////////////////////////
773 * Sets a palette with standard colors for 1, 4 and 8 bpp images.
775 void CxImage::SetStdPalette()
778 switch (head.biBitCount){
781 const BYTE pal256[1024] = {0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,
782 192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0,
783 72,184,255,0,37,170,255,0,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,
784 50,80,0,212,227,255,0,177,199,255,0,142,171,255,0,107,143,255,0,72,115,255,0,37,87,255,0,0,
785 85,255,0,0,73,220,0,0,61,185,0,0,49,150,0,0,37,115,0,0,25,80,0,212,212,255,0,177,177,255,0,
786 142,142,255,0,107,107,255,0,72,72,255,0,37,37,255,0,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,
787 0,0,115,0,0,0,80,0,227,212,255,0,199,177,255,0,171,142,255,0,143,107,255,0,115,72,255,0,
788 87,37,255,0,85,0,255,0,73,0,220,0,61,0,185,0,49,0,150,0,37,0,115,0,25,0,80,0,240,212,255,0,
789 226,177,255,0,212,142,255,0,198,107,255,0,184,72,255,0,170,37,255,0,170,0,255,0,146,0,220,0,
790 122,0,185,0,98,0,150,0,74,0,115,0,50,0,80,0,255,212,255,0,255,177,255,0,255,142,255,0,255,107,255,0,
791 255,72,255,0,255,37,255,0,254,0,254,0,220,0,220,0,185,0,185,0,150,0,150,0,115,0,115,0,80,0,80,0,
792 255,212,240,0,255,177,226,0,255,142,212,0,255,107,198,0,255,72,184,0,255,37,170,0,255,0,170,0,
793 220,0,146,0,185,0,122,0,150,0,98,0,115,0,74,0,80,0,50,0,255,212,227,0,255,177,199,0,255,142,171,0,
794 255,107,143,0,255,72,115,0,255,37,87,0,255,0,85,0,220,0,73,0,185,0,61,0,150,0,49,0,115,0,37,0,
795 80,0,25,0,255,212,212,0,255,177,177,0,255,142,142,0,255,107,107,0,255,72,72,0,255,37,37,0,254,0,
796 0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,0,255,227,212,0,255,199,177,0,255,171,142,0,
797 255,143,107,0,255,115,72,0,255,87,37,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,115,37,0,
798 0,80,25,0,0,255,240,212,0,255,226,177,0,255,212,142,0,255,198,107,0,255,184,72,0,255,170,37,0,
799 255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,0,255,255,212,0,255,255,177,0,
800 255,255,142,0,255,255,107,0,255,255,72,0,255,255,37,0,254,254,0,0,220,220,0,0,185,185,0,0,150,150,0,
801 0,115,115,0,0,80,80,0,0,240,255,212,0,226,255,177,0,212,255,142,0,198,255,107,0,184,255,72,0,
802 170,255,37,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,50,80,0,0,227,255,212,0,
803 199,255,177,0,171,255,142,0,143,255,107,0,115,255,72,0,87,255,37,0,85,255,0,0,73,220,0,0,61,185,0,
804 0,49,150,0,0,37,115,0,0,25,80,0,0,212,255,212,0,177,255,177,0,142,255,142,0,107,255,107,0,72,255,72,0,
805 37,255,37,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,212,255,227,0,177,255,199,0,
806 142,255,171,0,107,255,143,0,72,255,115,0,37,255,87,0,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,
807 115,37,0,0,80,25,0,212,255,240,0,177,255,226,0,142,255,212,0,107,255,198,0,72,255,184,0,37,255,170,0,
808 0,255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,212,255,255,0,177,255,255,0,
809 142,255,255,0,107,255,255,0,72,255,255,0,37,255,255,0,0,254,254,0,0,220,220,0,0,185,185,0,0,
810 150,150,0,0,115,115,0,0,80,80,0,242,242,242,0,230,230,230,0,218,218,218,0,206,206,206,0,194,194,194,0,
811 182,182,182,0,170,170,170,0,158,158,158,0,146,146,146,0,134,134,134,0,122,122,122,0,110,110,110,0,
812 98,98,98,0,86,86,86,0,74,74,74,0,62,62,62,0,50,50,50,0,38,38,38,0,26,26,26,0,14,14,14,0,240,251,255,0,
813 164,160,160,0,128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};
814 memcpy(GetPalette(),pal256,1024);
819 const BYTE pal16[64]={0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,
820 128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};
821 memcpy(GetPalette(),pal16,64);
826 const BYTE pal2[8]={0,0,0,0,255,255,255,0};
827 memcpy(GetPalette(),pal2,8);
831 info.last_c_isvalid = false;
834 ////////////////////////////////////////////////////////////////////////////////