source: liacs/MIR2010/SourceCode/cximage/ximalpha.cpp@ 244

Last change on this file since 244 was 95, checked in by Rick van der Zwet, 15 years ago

Bad boy, improper move of directory

File size: 10.2 KB
Line 
1// xImalpha.cpp : Alpha channel functions
2/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
3 * CxImage version 6.0.0 02/Feb/2008
4 */
5
6#include "ximage.h"
7
8#if CXIMAGE_SUPPORT_ALPHA
9
10////////////////////////////////////////////////////////////////////////////////
11/**
12 * \sa AlphaSetMax
13 */
14BYTE CxImage::AlphaGetMax() const
15{
16 return info.nAlphaMax;
17}
18////////////////////////////////////////////////////////////////////////////////
19/**
20 * Sets global Alpha (opacity) value applied to the whole image,
21 * valid only for painting functions.
22 * \param nAlphaMax: can be from 0 to 255
23 */
24void CxImage::AlphaSetMax(BYTE nAlphaMax)
25{
26 info.nAlphaMax=nAlphaMax;
27}
28////////////////////////////////////////////////////////////////////////////////
29/**
30 * Checks if the image has a valid alpha channel.
31 */
32bool CxImage::AlphaIsValid()
33{
34 return pAlpha!=0;
35}
36////////////////////////////////////////////////////////////////////////////////
37/**
38 * Enables the alpha palette, so the Draw() function changes its behavior.
39 */
40void CxImage::AlphaPaletteEnable(bool enable)
41{
42 info.bAlphaPaletteEnabled=enable;
43}
44////////////////////////////////////////////////////////////////////////////////
45/**
46 * True if the alpha palette is enabled for painting.
47 */
48bool CxImage::AlphaPaletteIsEnabled()
49{
50 return info.bAlphaPaletteEnabled;
51}
52////////////////////////////////////////////////////////////////////////////////
53/**
54 * Sets the alpha channel to full transparent. AlphaSet(0) has the same effect
55 */
56void CxImage::AlphaClear()
57{
58 if (pAlpha) memset(pAlpha,0,head.biWidth * head.biHeight);
59}
60////////////////////////////////////////////////////////////////////////////////
61/**
62 * Sets the alpha level for the whole image.
63 * \param level : from 0 (transparent) to 255 (opaque)
64 */
65void CxImage::AlphaSet(BYTE level)
66{
67 if (pAlpha) memset(pAlpha,level,head.biWidth * head.biHeight);
68}
69////////////////////////////////////////////////////////////////////////////////
70/**
71 * Allocates an empty (opaque) alpha channel.
72 */
73bool CxImage::AlphaCreate()
74{
75 if (pAlpha==NULL) {
76 pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);
77 if (pAlpha) memset(pAlpha,255,head.biWidth * head.biHeight);
78 }
79 return (pAlpha!=0);
80}
81////////////////////////////////////////////////////////////////////////////////
82void CxImage::AlphaDelete()
83{
84 if (pAlpha) { free(pAlpha); pAlpha=0; }
85}
86////////////////////////////////////////////////////////////////////////////////
87void CxImage::AlphaInvert()
88{
89 if (pAlpha) {
90 BYTE *iSrc=pAlpha;
91 long n=head.biHeight*head.biWidth;
92 for(long i=0; i < n; i++){
93 *iSrc=(BYTE)~(*(iSrc));
94 iSrc++;
95 }
96 }
97}
98////////////////////////////////////////////////////////////////////////////////
99/**
100 * Imports an existing alpa channel from another image with the same width and height.
101 */
102bool CxImage::AlphaCopy(CxImage &from)
103{
104 if (from.pAlpha == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
105 if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);
106 if (pAlpha==NULL) return false;
107 memcpy(pAlpha,from.pAlpha,head.biWidth * head.biHeight);
108 info.nAlphaMax=from.info.nAlphaMax;
109 return true;
110}
111////////////////////////////////////////////////////////////////////////////////
112/**
113 * Creates the alpha channel from a gray scale image.
114 */
115bool CxImage::AlphaSet(CxImage &from)
116{
117 if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
118 if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);
119 BYTE* src = from.info.pImage;
120 BYTE* dst = pAlpha;
121 if (src==NULL || dst==NULL) return false;
122 for (long y=0; y<head.biHeight; y++){
123 memcpy(dst,src,head.biWidth);
124 dst += head.biWidth;
125 src += from.info.dwEffWidth;
126 }
127 return true;
128}
129////////////////////////////////////////////////////////////////////////////////
130/**
131 * Sets the alpha level for a single pixel
132 */
133void CxImage::AlphaSet(const long x,const long y,const BYTE level)
134{
135 if (pAlpha && IsInside(x,y)) pAlpha[x+y*head.biWidth]=level;
136}
137////////////////////////////////////////////////////////////////////////////////
138/**
139 * Gets the alpha level for a single pixel
140 */
141BYTE CxImage::AlphaGet(const long x,const long y)
142{
143 if (pAlpha && IsInside(x,y)) return pAlpha[x+y*head.biWidth];
144 return 0;
145}
146////////////////////////////////////////////////////////////////////////////////
147/**
148 * Returns pointer to alpha data for pixel (x,y).
149 *
150 * \author ***bd*** 2.2004
151 */
152BYTE* CxImage::AlphaGetPointer(const long x,const long y)
153{
154 if (pAlpha && IsInside(x,y)) return pAlpha+x+y*head.biWidth;
155 return 0;
156}
157////////////////////////////////////////////////////////////////////////////////
158/**
159 * Get alpha value without boundscheck (a bit faster). Pixel must be inside the image.
160 *
161 * \author ***bd*** 2.2004
162 */
163BYTE CxImage::BlindAlphaGet(const long x,const long y)
164{
165#ifdef _DEBUG
166 if (!IsInside(x,y) || (pAlpha==0))
167 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
168 throw 0;
169 #else
170 return 0;
171 #endif
172#endif
173 return pAlpha[x+y*head.biWidth];
174}
175////////////////////////////////////////////////////////////////////////////////
176/**
177 * Resets the alpha palette
178 */
179void CxImage::AlphaPaletteClear()
180{
181 RGBQUAD c;
182 for(WORD ip=0; ip<head.biClrUsed;ip++){
183 c=GetPaletteColor((BYTE)ip);
184 c.rgbReserved=0;
185 SetPaletteColor((BYTE)ip,c);
186 }
187}
188////////////////////////////////////////////////////////////////////////////////
189/**
190 * Checks if the image has a valid alpha palette.
191 */
192bool CxImage::AlphaPaletteIsValid()
193{
194 RGBQUAD c;
195 for(WORD ip=0; ip<head.biClrUsed;ip++){
196 c=GetPaletteColor((BYTE)ip);
197 if (c.rgbReserved != 0) return true;
198 }
199 return false;
200}
201////////////////////////////////////////////////////////////////////////////////
202/**
203 * Blends the alpha channel and the alpha palette with the pixels. The result is a 24 bit image.
204 * The background color can be selected using SetTransColor().
205 */
206void CxImage::AlphaStrip()
207{
208 bool bAlphaPaletteIsValid = AlphaPaletteIsValid();
209 bool bAlphaIsValid = AlphaIsValid();
210 if (!(bAlphaIsValid || bAlphaPaletteIsValid)) return;
211 RGBQUAD c;
212 long a, a1;
213 if (head.biBitCount==24){
214 for(long y=0; y<head.biHeight; y++){
215 for(long x=0; x<head.biWidth; x++){
216 c = BlindGetPixelColor(x,y);
217 if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;
218 a1 = 256-a;
219 c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
220 c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
221 c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
222 BlindSetPixelColor(x,y,c);
223 }
224 }
225 AlphaDelete();
226 } else {
227 CxImage tmp(head.biWidth,head.biHeight,24);
228 if (!tmp.IsValid()){
229 strcpy(info.szLastError,tmp.GetLastError());
230 return;
231 }
232
233 for(long y=0; y<head.biHeight; y++){
234 for(long x=0; x<head.biWidth; x++){
235 c = BlindGetPixelColor(x,y);
236 if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;
237 if (bAlphaPaletteIsValid) a=(c.rgbReserved*a)/255;
238 a1 = 256-a;
239 c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
240 c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
241 c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
242 tmp.BlindSetPixelColor(x,y,c);
243 }
244 }
245 Transfer(tmp);
246 }
247 return;
248}
249////////////////////////////////////////////////////////////////////////////////
250bool CxImage::AlphaFlip()
251{
252 if (!pAlpha) return false;
253
254 BYTE *buff = (BYTE*)malloc(head.biWidth);
255 if (!buff) return false;
256
257 BYTE *iSrc,*iDst;
258 iSrc = pAlpha + (head.biHeight-1)*head.biWidth;
259 iDst = pAlpha;
260 for (long i=0; i<(head.biHeight/2); ++i)
261 {
262 memcpy(buff, iSrc, head.biWidth);
263 memcpy(iSrc, iDst, head.biWidth);
264 memcpy(iDst, buff, head.biWidth);
265 iSrc-=head.biWidth;
266 iDst+=head.biWidth;
267 }
268
269 free(buff);
270
271 return true;
272}
273////////////////////////////////////////////////////////////////////////////////
274bool CxImage::AlphaMirror()
275{
276 if (!pAlpha) return false;
277 BYTE* pAlpha2 = (BYTE*)malloc(head.biWidth * head.biHeight);
278 if (!pAlpha2) return false;
279 BYTE *iSrc,*iDst;
280 long wdt=head.biWidth-1;
281 iSrc=pAlpha + wdt;
282 iDst=pAlpha2;
283 for(long y=0; y < head.biHeight; y++){
284 for(long x=0; x <= wdt; x++)
285 *(iDst+x)=*(iSrc-x);
286 iSrc+=head.biWidth;
287 iDst+=head.biWidth;
288 }
289 free(pAlpha);
290 pAlpha=pAlpha2;
291 return true;
292}
293////////////////////////////////////////////////////////////////////////////////
294/**
295 * Exports the alpha channel in a 8bpp grayscale image.
296 */
297bool CxImage::AlphaSplit(CxImage *dest)
298{
299 if (!pAlpha || !dest) return false;
300
301 CxImage tmp(head.biWidth,head.biHeight,8);
302 if (!tmp.IsValid()){
303 strcpy(info.szLastError,tmp.GetLastError());
304 return false;
305 }
306
307 for(long y=0; y<head.biHeight; y++){
308 for(long x=0; x<head.biWidth; x++){
309 tmp.BlindSetPixelIndex(x,y,pAlpha[x+y*head.biWidth]);
310 }
311 }
312
313 tmp.SetGrayPalette();
314 dest->Transfer(tmp);
315
316 return true;
317}
318////////////////////////////////////////////////////////////////////////////////
319/**
320 * Exports the alpha palette channel in a 8bpp grayscale image.
321 */
322bool CxImage::AlphaPaletteSplit(CxImage *dest)
323{
324 if (!AlphaPaletteIsValid() || !dest) return false;
325
326 CxImage tmp(head.biWidth,head.biHeight,8);
327 if (!tmp.IsValid()){
328 strcpy(info.szLastError,tmp.GetLastError());
329 return false;
330 }
331
332 for(long y=0; y<head.biHeight; y++){
333 for(long x=0; x<head.biWidth; x++){
334 tmp.BlindSetPixelIndex(x,y,BlindGetPixelColor(x,y).rgbReserved);
335 }
336 }
337
338 tmp.SetGrayPalette();
339 dest->Transfer(tmp);
340
341 return true;
342}
343////////////////////////////////////////////////////////////////////////////////
344/**
345 * Merge in the alpha layer the transparent color mask
346 * (previously set with SetTransColor or SetTransIndex)
347 */
348bool CxImage::AlphaFromTransparency()
349{
350 if (!IsValid() || !IsTransparent())
351 return false;
352
353 AlphaCreate();
354
355 for(long y=0; y<head.biHeight; y++){
356 for(long x=0; x<head.biWidth; x++){
357 if (IsTransparent(x,y)){
358 AlphaSet(x,y,0);
359 }
360 }
361 }
362 return true;
363}
364////////////////////////////////////////////////////////////////////////////////
365#endif //CXIMAGE_SUPPORT_ALPHA
Note: See TracBrowser for help on using the repository browser.