00001 /* 00002 /-------------------------------------------------------------------- 00003 | 00004 | $Id: plfiltercontrast.cpp,v 1.1 2004/05/21 21:02:53 maxx Exp $ 00005 | 00006 | Copyright (c) 1996-1998 Ulrich von Zadow 00007 | 00008 \-------------------------------------------------------------------- 00009 */ 00010 00011 #include "plstdpch.h" 00012 #include "plfiltercontrast.h" 00013 #include "plbitmap.h" 00014 #include "plpaintlibdefs.h" 00015 00016 PLFilterContrast::PLFilterContrast(double contrast, PLBYTE offset) 00017 : PLFilter(), 00018 m_contrast(contrast), 00019 m_offset((double) offset-125.0) 00020 { 00021 } 00022 00023 PLFilterContrast::~PLFilterContrast() 00024 { 00025 00026 } 00027 00028 void PLFilterContrast::Apply(PLBmp * pBmpSource, PLBmp * pBmpDest) const 00029 { 00030 // Consider a coordinate system with two axes: The x axis represents 00031 // an input RGB component or intensity, the y axis an output RGB 00032 // component or intensity. The ranges of input and output values go 00033 // from 0 - 255. 00034 // If I take a straight line that intersects (0,0) through (255,255), 00035 // I have defined a Null filter that leaves the image unchanged. 00036 00037 // Next step: Let's rotate this straight line around the point (125,125). 00038 // If I increase the slope, output values above (125,125) are increased 00039 // by the slope factor, output values below (125, 125) are decreased 00040 // likewise. This is how I create the contrast enhancement effect. 00041 00042 // Now we are having a problem: Increasing the slope means that our 00043 // straight line intersects the line (x, 255), creating output values 00044 // above 255 which are not defined in our RGB model. Since in the RGB world 00045 // there is nothing whiter than white, I'll set all these values to 255. A 00046 // similar thing happens on the lower left of our imaginary diagram: All 00047 // values smaller than 0 have to be set 0 - according to the fact that 00048 // there is nothing darker than absolute darkness... 00049 00050 // Ok, now what is that offset value good for? Remember the point 00051 // (125,125). At this position, input and output values of our filter 00052 // remain unchanged, independent of the slope of our straight line. Now 00053 // imagine we are shifting our line parallel to the x axis. Our filter 00054 // works quite differently now: We create a cut-off for the higher output 00055 // value range (shift right), or the lower ones (shift left). 00056 00057 register int inc=0; 00058 00059 double contrast = m_contrast; 00060 00061 PLASSERT (pBmpSource->GetBitsPerPixel() >= 24); 00062 00063 pBmpDest->Create (pBmpSource->GetWidth(), 00064 pBmpSource->GetHeight(), 00065 pBmpSource->GetBitsPerPixel(), 00066 pBmpSource->HasAlpha(), 00067 pBmpSource->GetResolution()); 00068 00069 PLBYTE ** pSrcLines = pBmpSource->GetLineArray(); 00070 PLBYTE ** pDstLines = pBmpDest->GetLineArray(); 00071 00072 register int destWidth = pBmpDest->GetWidth(); 00073 00074 if(pBmpSource->GetBitsPerPixel() == 24) 00075 inc = 3; 00076 00077 if(pBmpSource->GetBitsPerPixel() == 32) 00078 inc = sizeof(PLPixel32); 00079 00080 register double red, green, blue; 00081 register double csupp = contrast * (m_offset - 125.0) + 125.0; 00082 00083 for (int y = 0; y < pBmpDest->GetHeight(); ++y) 00084 { // For each line 00085 register PLBYTE * pSrcPixel = pSrcLines[y]; 00086 register PLBYTE * pDstPixel = pDstLines[y]; 00087 00088 for (register int x = 0; x < destWidth; ++x) 00089 { 00090 // Formel für Kontrastberechnung: 00091 // v = (contrast * (v - 125.0 + m_offset) + 125.0); 00092 red = contrast * ((double) (pSrcPixel[PL_RGBA_RED])) + csupp; 00093 green = contrast * ((double) (pSrcPixel[PL_RGBA_GREEN])) + csupp; 00094 blue = contrast * ((double) (pSrcPixel[PL_RGBA_BLUE])) + csupp; 00095 00096 if(red >= 255.0) 00097 pDstPixel[PL_RGBA_RED] = (PLBYTE) 255; 00098 else if (red < 0.0) 00099 pDstPixel[PL_RGBA_RED] = (PLBYTE) 0; 00100 else 00101 pDstPixel[PL_RGBA_RED] = (PLBYTE) red; 00102 00103 if(green >= 255.0) 00104 pDstPixel[PL_RGBA_GREEN] = (PLBYTE) 255; 00105 else if (green < 0.0) 00106 pDstPixel[PL_RGBA_GREEN] = (PLBYTE) 0; 00107 else 00108 pDstPixel[PL_RGBA_GREEN] = (PLBYTE) green; 00109 00110 if(blue >= 255.0) 00111 pDstPixel[PL_RGBA_BLUE] = (PLBYTE) 255; 00112 else if (blue < 0.0) 00113 pDstPixel[PL_RGBA_BLUE] = (PLBYTE) 0; 00114 else 00115 pDstPixel[PL_RGBA_BLUE] = (PLBYTE) blue; 00116 00117 pSrcPixel += inc; 00118 pDstPixel += inc; 00119 } 00120 } 00121 } 00122 00123 /* 00124 /-------------------------------------------------------------------- 00125 | 00126 | $Log: plfiltercontrast.cpp,v $ 00127 | Revision 1.1 2004/05/21 21:02:53 maxx 00128 | Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine. 00129 | 00130 | Revision 1.3 2003/01/25 02:54:41 mspindle 00131 | *** empty log message *** 00132 | 00133 | Revision 1.2 2003/01/07 16:14:59 sbergner 00134 | *** empty log message *** 00135 | 00136 | Revision 1.1 2002/11/13 01:59:47 mspindle 00137 | *** empty log message *** 00138 | 00139 | Revision 1.4 2001/10/16 17:12:26 uzadow 00140 | Added support for resolution information (Luca Piergentili) 00141 | 00142 | Revision 1.3 2001/10/06 22:03:26 uzadow 00143 | Added PL prefix to basic data types. 00144 | 00145 | Revision 1.2 2001/10/06 15:32:22 uzadow 00146 | Removed types LPBYTE, DWORD, UCHAR, VOID and INT from the code. 00147 | 00148 | Revision 1.1 2001/09/16 19:03:23 uzadow 00149 | Added global name prefix PL, changed most filenames. 00150 | 00151 | Revision 1.5 2001/02/04 14:31:52 uzadow 00152 | Member initialization list cleanup (Erik Hoffmann). 00153 | 00154 | Revision 1.4 2001/01/15 15:05:31 uzadow 00155 | Added PLBmp::ApplyFilter() and PLBmp::CreateFilteredCopy() 00156 | 00157 | Revision 1.3 2001/01/12 23:30:01 uzadow 00158 | Doc update. 00159 | 00160 | Revision 1.2 2000/12/18 22:42:53 uzadow 00161 | Replaced RGBAPIXEL with PLPixel32. 00162 | 00163 | Revision 1.1 2000/11/06 23:20:22 uzadow 00164 | Added Contrast, Intensity and Lightness filters by 00165 | Thomas Hirschmann 00166 | 00167 | 00168 \-------------------------------------------------------------------- 00169 */