1 | // ximage.cpp : main implementation file
|
---|
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 | ////////////////////////////////////////////////////////////////////////////////
|
---|
9 | // CxImage
|
---|
10 | ////////////////////////////////////////////////////////////////////////////////
|
---|
11 | /**
|
---|
12 | * Initialize the internal structures
|
---|
13 | */
|
---|
14 | void CxImage::Startup(DWORD imagetype)
|
---|
15 | {
|
---|
16 | //init pointers
|
---|
17 | pDib = pSelection = pAlpha = NULL;
|
---|
18 | ppLayers = ppFrames = NULL;
|
---|
19 | //init structures
|
---|
20 | memset(&head,0,sizeof(BITMAPINFOHEADER));
|
---|
21 | memset(&info,0,sizeof(CXIMAGEINFO));
|
---|
22 | //init default attributes
|
---|
23 | info.dwType = imagetype;
|
---|
24 | info.fQuality = 90.0f;
|
---|
25 | info.nAlphaMax = 255;
|
---|
26 | info.nBkgndIndex = -1;
|
---|
27 | info.bEnabled = true;
|
---|
28 | SetXDPI(CXIMAGE_DEFAULT_DPI);
|
---|
29 | SetYDPI(CXIMAGE_DEFAULT_DPI);
|
---|
30 |
|
---|
31 | short test = 1;
|
---|
32 | info.bLittleEndianHost = (*((char *) &test) == 1);
|
---|
33 | }
|
---|
34 | ////////////////////////////////////////////////////////////////////////////////
|
---|
35 | /**
|
---|
36 | * Empty image constructor
|
---|
37 | * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
|
---|
38 | */
|
---|
39 | CxImage::CxImage(DWORD imagetype)
|
---|
40 | {
|
---|
41 | Startup(imagetype);
|
---|
42 | }
|
---|
43 | ////////////////////////////////////////////////////////////////////////////////
|
---|
44 | /**
|
---|
45 | * Call this function to destroy image pixels, alpha channel, selection and sub layers.
|
---|
46 | * - Attributes are not erased, but IsValid returns false.
|
---|
47 | *
|
---|
48 | * \return true if everything is freed, false if the image is a Ghost
|
---|
49 | */
|
---|
50 | bool CxImage::Destroy()
|
---|
51 | {
|
---|
52 | //free this only if it's valid and it's not a ghost
|
---|
53 | if (info.pGhost==NULL){
|
---|
54 | if (ppLayers) {
|
---|
55 | for(long n=0; n<info.nNumLayers;n++){ delete ppLayers[n]; }
|
---|
56 | delete [] ppLayers; ppLayers=0; info.nNumLayers = 0;
|
---|
57 | }
|
---|
58 | if (pSelection) {free(pSelection); pSelection=0;}
|
---|
59 | if (pAlpha) {free(pAlpha); pAlpha=0;}
|
---|
60 | if (pDib) {free(pDib); pDib=0;}
|
---|
61 | return true;
|
---|
62 | }
|
---|
63 | return false;
|
---|
64 | }
|
---|
65 | ////////////////////////////////////////////////////////////////////////////////
|
---|
66 | bool CxImage::DestroyFrames()
|
---|
67 | {
|
---|
68 | if (info.pGhost==NULL) {
|
---|
69 | if (ppFrames) {
|
---|
70 | for (long n=0; n<info.nNumFrames; n++) { delete ppFrames[n]; }
|
---|
71 | delete [] ppFrames; ppFrames = NULL; info.nNumFrames = 0;
|
---|
72 | }
|
---|
73 | return true;
|
---|
74 | }
|
---|
75 | return false;
|
---|
76 | }
|
---|
77 | ////////////////////////////////////////////////////////////////////////////////
|
---|
78 | /**
|
---|
79 | * Sized image constructor
|
---|
80 | * \param dwWidth: width
|
---|
81 | * \param dwHeight: height
|
---|
82 | * \param wBpp: bit per pixel, can be 1, 4, 8, 24
|
---|
83 | * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
|
---|
84 | */
|
---|
85 | CxImage::CxImage(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype)
|
---|
86 | {
|
---|
87 | Startup(imagetype);
|
---|
88 | Create(dwWidth,dwHeight,wBpp,imagetype);
|
---|
89 | }
|
---|
90 | ////////////////////////////////////////////////////////////////////////////////
|
---|
91 | /**
|
---|
92 | * image constructor from existing source
|
---|
93 | * \param src: source image.
|
---|
94 | * \param copypixels: copy the pixels from the source image into the new image.
|
---|
95 | * \param copyselection: copy the selection from source
|
---|
96 | * \param copyalpha: copy the alpha channel from source
|
---|
97 | * \sa Copy
|
---|
98 | */
|
---|
99 | CxImage::CxImage(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)
|
---|
100 | {
|
---|
101 | Startup(src.GetType());
|
---|
102 | Copy(src,copypixels,copyselection,copyalpha);
|
---|
103 | }
|
---|
104 | ////////////////////////////////////////////////////////////////////////////////
|
---|
105 | /**
|
---|
106 | * Copies the image from an exsisting source
|
---|
107 | * \param src: source image.
|
---|
108 | * \param copypixels: copy the pixels from the source image into the new image.
|
---|
109 | * \param copyselection: copy the selection from source
|
---|
110 | * \param copyalpha: copy the alpha channel from source
|
---|
111 | */
|
---|
112 | void CxImage::Copy(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)
|
---|
113 | {
|
---|
114 | // if the source is a ghost, the copy is still a ghost
|
---|
115 | if (src.info.pGhost){
|
---|
116 | Ghost(&src);
|
---|
117 | return;
|
---|
118 | }
|
---|
119 | //copy the attributes
|
---|
120 | memcpy(&info,&src.info,sizeof(CXIMAGEINFO));
|
---|
121 | memcpy(&head,&src.head,sizeof(BITMAPINFOHEADER)); // [andy] - fix for bitmap header DPI
|
---|
122 | //rebuild the image
|
---|
123 | Create(src.GetWidth(),src.GetHeight(),src.GetBpp(),src.GetType());
|
---|
124 | //copy the pixels and the palette, or at least copy the palette only.
|
---|
125 | if (copypixels && pDib && src.pDib) memcpy(pDib,src.pDib,GetSize());
|
---|
126 | else SetPalette(src.GetPalette());
|
---|
127 | long nSize = head.biWidth * head.biHeight;
|
---|
128 | //copy the selection
|
---|
129 | if (copyselection && src.pSelection){
|
---|
130 | if (pSelection) free(pSelection);
|
---|
131 | pSelection = (BYTE*)malloc(nSize);
|
---|
132 | memcpy(pSelection,src.pSelection,nSize);
|
---|
133 | }
|
---|
134 | //copy the alpha channel
|
---|
135 | if (copyalpha && src.pAlpha){
|
---|
136 | if (pAlpha) free(pAlpha);
|
---|
137 | pAlpha = (BYTE*)malloc(nSize);
|
---|
138 | memcpy(pAlpha,src.pAlpha,nSize);
|
---|
139 | }
|
---|
140 | }
|
---|
141 | ////////////////////////////////////////////////////////////////////////////////
|
---|
142 | /**
|
---|
143 | * Copies the image attributes from an existing image.
|
---|
144 | * - Works only on an empty image, and the image will be still empty.
|
---|
145 | * - <b> Use it before Create() </b>
|
---|
146 | */
|
---|
147 | void CxImage::CopyInfo(const CxImage &src)
|
---|
148 | {
|
---|
149 | if (pDib==NULL) memcpy(&info,&src.info,sizeof(CXIMAGEINFO));
|
---|
150 | }
|
---|
151 | ////////////////////////////////////////////////////////////////////////////////
|
---|
152 | /**
|
---|
153 | * \sa Copy
|
---|
154 | */
|
---|
155 | CxImage& CxImage::operator = (const CxImage& isrc)
|
---|
156 | {
|
---|
157 | if (this != &isrc) Copy(isrc);
|
---|
158 | return *this;
|
---|
159 | }
|
---|
160 | ////////////////////////////////////////////////////////////////////////////////
|
---|
161 | /**
|
---|
162 | * Initializes or rebuilds the image.
|
---|
163 | * \param dwWidth: width
|
---|
164 | * \param dwHeight: height
|
---|
165 | * \param wBpp: bit per pixel, can be 1, 4, 8, 24
|
---|
166 | * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
|
---|
167 | * \return pointer to the internal pDib object; NULL if an error occurs.
|
---|
168 | */
|
---|
169 | void* CxImage::Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype)
|
---|
170 | {
|
---|
171 | // destroy the existing image (if any)
|
---|
172 | if (!Destroy())
|
---|
173 | return NULL;
|
---|
174 |
|
---|
175 | // prevent further actions if width or height are not vaild <Balabasnia>
|
---|
176 | if ((dwWidth == 0) || (dwHeight == 0)){
|
---|
177 | strcpy(info.szLastError,"CxImage::Create : width and height must be greater than zero");
|
---|
178 | return NULL;
|
---|
179 | }
|
---|
180 |
|
---|
181 | // Make sure bits per pixel is valid
|
---|
182 | if (wBpp <= 1) wBpp = 1;
|
---|
183 | else if (wBpp <= 4) wBpp = 4;
|
---|
184 | else if (wBpp <= 8) wBpp = 8;
|
---|
185 | else wBpp = 24;
|
---|
186 |
|
---|
187 | // limit memory requirements (and also a check for bad parameters)
|
---|
188 | if (((dwWidth*dwHeight*wBpp)>>3) > CXIMAGE_MAX_MEMORY ||
|
---|
189 | ((dwWidth*dwHeight*wBpp)/wBpp) != (dwWidth*dwHeight))
|
---|
190 | {
|
---|
191 | strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded");
|
---|
192 | return NULL;
|
---|
193 | }
|
---|
194 |
|
---|
195 | // set the correct bpp value
|
---|
196 | switch (wBpp){
|
---|
197 | case 1:
|
---|
198 | head.biClrUsed = 2; break;
|
---|
199 | case 4:
|
---|
200 | head.biClrUsed = 16; break;
|
---|
201 | case 8:
|
---|
202 | head.biClrUsed = 256; break;
|
---|
203 | default:
|
---|
204 | head.biClrUsed = 0;
|
---|
205 | }
|
---|
206 |
|
---|
207 | //set the common image informations
|
---|
208 | info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4);
|
---|
209 | info.dwType = imagetype;
|
---|
210 |
|
---|
211 | // initialize BITMAPINFOHEADER
|
---|
212 | head.biSize = sizeof(BITMAPINFOHEADER); //<ralphw>
|
---|
213 | head.biWidth = dwWidth; // fill in width from parameter
|
---|
214 | head.biHeight = dwHeight; // fill in height from parameter
|
---|
215 | head.biPlanes = 1; // must be 1
|
---|
216 | head.biBitCount = (WORD)wBpp; // from parameter
|
---|
217 | head.biCompression = BI_RGB;
|
---|
218 | head.biSizeImage = info.dwEffWidth * dwHeight;
|
---|
219 | // head.biXPelsPerMeter = 0; See SetXDPI
|
---|
220 | // head.biYPelsPerMeter = 0; See SetYDPI
|
---|
221 | // head.biClrImportant = 0; See SetClrImportant
|
---|
222 |
|
---|
223 | pDib = malloc(GetSize()); // alloc memory block to store our bitmap
|
---|
224 | if (!pDib){
|
---|
225 | strcpy(info.szLastError,"CxImage::Create can't allocate memory");
|
---|
226 | return NULL;
|
---|
227 | }
|
---|
228 |
|
---|
229 | //clear the palette
|
---|
230 | RGBQUAD* pal=GetPalette();
|
---|
231 | if (pal) memset(pal,0,GetPaletteSize());
|
---|
232 | //Destroy the existing selection
|
---|
233 | #if CXIMAGE_SUPPORT_SELECTION
|
---|
234 | if (pSelection) SelectionDelete();
|
---|
235 | #endif //CXIMAGE_SUPPORT_SELECTION
|
---|
236 | //Destroy the existing alpha channel
|
---|
237 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
238 | if (pAlpha) AlphaDelete();
|
---|
239 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
240 |
|
---|
241 | // use our bitmap info structure to fill in first part of
|
---|
242 | // our DIB with the BITMAPINFOHEADER
|
---|
243 | BITMAPINFOHEADER* lpbi;
|
---|
244 | lpbi = (BITMAPINFOHEADER*)(pDib);
|
---|
245 | *lpbi = head;
|
---|
246 |
|
---|
247 | info.pImage=GetBits();
|
---|
248 |
|
---|
249 | return pDib; //return handle to the DIB
|
---|
250 | }
|
---|
251 | ////////////////////////////////////////////////////////////////////////////////
|
---|
252 | /**
|
---|
253 | * \return pointer to the image pixels. <b> USE CAREFULLY </b>
|
---|
254 | */
|
---|
255 | BYTE* CxImage::GetBits(DWORD row)
|
---|
256 | {
|
---|
257 | if (pDib){
|
---|
258 | if (row) {
|
---|
259 | if (row<(DWORD)head.biHeight){
|
---|
260 | return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize() + (info.dwEffWidth * row));
|
---|
261 | } else {
|
---|
262 | return NULL;
|
---|
263 | }
|
---|
264 | } else {
|
---|
265 | return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize());
|
---|
266 | }
|
---|
267 | }
|
---|
268 | return NULL;
|
---|
269 | }
|
---|
270 | ////////////////////////////////////////////////////////////////////////////////
|
---|
271 | /**
|
---|
272 | * \return the size in bytes of the internal pDib object
|
---|
273 | */
|
---|
274 | long CxImage::GetSize()
|
---|
275 | {
|
---|
276 | return head.biSize + head.biSizeImage + GetPaletteSize();
|
---|
277 | }
|
---|
278 | ////////////////////////////////////////////////////////////////////////////////
|
---|
279 | /**
|
---|
280 | * Checks if the coordinates are inside the image
|
---|
281 | * \return true if x and y are both inside the image
|
---|
282 | */
|
---|
283 | bool CxImage::IsInside(long x, long y)
|
---|
284 | {
|
---|
285 | return (0<=y && y<head.biHeight && 0<=x && x<head.biWidth);
|
---|
286 | }
|
---|
287 | ////////////////////////////////////////////////////////////////////////////////
|
---|
288 | /**
|
---|
289 | * Sets the image bits to the specified value
|
---|
290 | * - for indexed images, the output color is set by the palette entries.
|
---|
291 | * - for RGB images, the output color is a shade of gray.
|
---|
292 | */
|
---|
293 | void CxImage::Clear(BYTE bval)
|
---|
294 | {
|
---|
295 | if (pDib == 0) return;
|
---|
296 |
|
---|
297 | if (GetBpp() == 1){
|
---|
298 | if (bval > 0) bval = 255;
|
---|
299 | }
|
---|
300 | if (GetBpp() == 4){
|
---|
301 | bval = (BYTE)(17*(0x0F & bval));
|
---|
302 | }
|
---|
303 |
|
---|
304 | memset(info.pImage,bval,head.biSizeImage);
|
---|
305 | }
|
---|
306 | ////////////////////////////////////////////////////////////////////////////////
|
---|
307 | /**
|
---|
308 | * Transfers the image from an existing source image. The source becomes empty.
|
---|
309 | * \return true if everything is ok
|
---|
310 | */
|
---|
311 | bool CxImage::Transfer(CxImage &from, bool bTransferFrames /*=true*/)
|
---|
312 | {
|
---|
313 | if (!Destroy())
|
---|
314 | return false;
|
---|
315 |
|
---|
316 | memcpy(&head,&from.head,sizeof(BITMAPINFOHEADER));
|
---|
317 | memcpy(&info,&from.info,sizeof(CXIMAGEINFO));
|
---|
318 |
|
---|
319 | pDib = from.pDib;
|
---|
320 | pSelection = from.pSelection;
|
---|
321 | pAlpha = from.pAlpha;
|
---|
322 | ppLayers = from.ppLayers;
|
---|
323 |
|
---|
324 | memset(&from.head,0,sizeof(BITMAPINFOHEADER));
|
---|
325 | memset(&from.info,0,sizeof(CXIMAGEINFO));
|
---|
326 | from.pDib = from.pSelection = from.pAlpha = NULL;
|
---|
327 | from.ppLayers = NULL;
|
---|
328 |
|
---|
329 | if (bTransferFrames){
|
---|
330 | DestroyFrames();
|
---|
331 | ppFrames = from.ppFrames;
|
---|
332 | from.ppFrames = NULL;
|
---|
333 | }
|
---|
334 |
|
---|
335 | return true;
|
---|
336 | }
|
---|
337 | ////////////////////////////////////////////////////////////////////////////////
|
---|
338 | /**
|
---|
339 | * (this) points to the same pDib owned by (*from), the image remains in (*from)
|
---|
340 | * but (this) has the access to the pixels. <b>Use carefully !!!</b>
|
---|
341 | */
|
---|
342 | void CxImage::Ghost(const CxImage *from)
|
---|
343 | {
|
---|
344 | if (from){
|
---|
345 | memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER));
|
---|
346 | memcpy(&info,&from->info,sizeof(CXIMAGEINFO));
|
---|
347 | pDib = from->pDib;
|
---|
348 | pSelection = from->pSelection;
|
---|
349 | pAlpha = from->pAlpha;
|
---|
350 | ppLayers = from->ppLayers;
|
---|
351 | ppFrames = from->ppFrames;
|
---|
352 | info.pGhost=(CxImage *)from;
|
---|
353 | }
|
---|
354 | }
|
---|
355 | ////////////////////////////////////////////////////////////////////////////////
|
---|
356 | /**
|
---|
357 | * turns a 16 or 32 bit bitfield image into a RGB image
|
---|
358 | */
|
---|
359 | void CxImage::Bitfield2RGB(BYTE *src, DWORD redmask, DWORD greenmask, DWORD bluemask, BYTE bpp)
|
---|
360 | {
|
---|
361 | switch (bpp){
|
---|
362 | case 16:
|
---|
363 | {
|
---|
364 | DWORD ns[3]={0,0,0};
|
---|
365 | // compute the number of shift for each mask
|
---|
366 | for (int i=0;i<16;i++){
|
---|
367 | if ((redmask>>i)&0x01) ns[0]++;
|
---|
368 | if ((greenmask>>i)&0x01) ns[1]++;
|
---|
369 | if ((bluemask>>i)&0x01) ns[2]++;
|
---|
370 | }
|
---|
371 | ns[1]+=ns[0]; ns[2]+=ns[1]; ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8;
|
---|
372 | // dword aligned width for 16 bit image
|
---|
373 | long effwidth2=(((head.biWidth + 1) / 2) * 4);
|
---|
374 | WORD w;
|
---|
375 | long y2,y3,x2,x3;
|
---|
376 | BYTE *p=info.pImage;
|
---|
377 | // scan the buffer in reverse direction to avoid reallocations
|
---|
378 | for (long y=head.biHeight-1; y>=0; y--){
|
---|
379 | y2=effwidth2*y;
|
---|
380 | y3=info.dwEffWidth*y;
|
---|
381 | for (long x=head.biWidth-1; x>=0; x--){
|
---|
382 | x2 = 2*x+y2;
|
---|
383 | x3 = 3*x+y3;
|
---|
384 | w = (WORD)(src[x2]+256*src[1+x2]);
|
---|
385 | p[ x3]=(BYTE)((w & bluemask)<<ns[0]);
|
---|
386 | p[1+x3]=(BYTE)((w & greenmask)>>ns[1]);
|
---|
387 | p[2+x3]=(BYTE)((w & redmask)>>ns[2]);
|
---|
388 | }
|
---|
389 | }
|
---|
390 | break;
|
---|
391 | }
|
---|
392 | case 32:
|
---|
393 | {
|
---|
394 | DWORD ns[3]={0,0,0};
|
---|
395 | // compute the number of shift for each mask
|
---|
396 | for (int i=8;i<32;i+=8){
|
---|
397 | if (redmask>>i) ns[0]++;
|
---|
398 | if (greenmask>>i) ns[1]++;
|
---|
399 | if (bluemask>>i) ns[2]++;
|
---|
400 | }
|
---|
401 | // dword aligned width for 32 bit image
|
---|
402 | long effwidth4 = head.biWidth * 4;
|
---|
403 | long y4,y3,x4,x3;
|
---|
404 | BYTE *p=info.pImage;
|
---|
405 | // scan the buffer in reverse direction to avoid reallocations
|
---|
406 | for (long y=head.biHeight-1; y>=0; y--){
|
---|
407 | y4=effwidth4*y;
|
---|
408 | y3=info.dwEffWidth*y;
|
---|
409 | for (long x=head.biWidth-1; x>=0; x--){
|
---|
410 | x4 = 4*x+y4;
|
---|
411 | x3 = 3*x+y3;
|
---|
412 | p[ x3]=src[ns[2]+x4];
|
---|
413 | p[1+x3]=src[ns[1]+x4];
|
---|
414 | p[2+x3]=src[ns[0]+x4];
|
---|
415 | }
|
---|
416 | }
|
---|
417 | }
|
---|
418 |
|
---|
419 | }
|
---|
420 | return;
|
---|
421 | }
|
---|
422 | ////////////////////////////////////////////////////////////////////////////////
|
---|
423 | /**
|
---|
424 | * Creates an image from a generic buffer
|
---|
425 | * \param pArray: source memory buffer
|
---|
426 | * \param dwWidth: image width
|
---|
427 | * \param dwHeight: image height
|
---|
428 | * \param dwBitsperpixel: can be 1,4,8,24,32
|
---|
429 | * \param dwBytesperline: line alignment, in bytes, for a single row stored in pArray
|
---|
430 | * \param bFlipImage: tune this parameter if the image is upsidedown
|
---|
431 | * \return true if everything is ok
|
---|
432 | */
|
---|
433 | bool CxImage::CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage)
|
---|
434 | {
|
---|
435 | if (pArray==NULL) return false;
|
---|
436 | if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||
|
---|
437 | (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;
|
---|
438 |
|
---|
439 | if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;
|
---|
440 |
|
---|
441 | if (dwBitsperpixel<24) SetGrayPalette();
|
---|
442 |
|
---|
443 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
444 | if (dwBitsperpixel==32) AlphaCreate();
|
---|
445 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
446 |
|
---|
447 | BYTE *dst,*src;
|
---|
448 |
|
---|
449 | for (DWORD y = 0; y<dwHeight; y++) {
|
---|
450 | dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
|
---|
451 | src = pArray + y * dwBytesperline;
|
---|
452 | if (dwBitsperpixel==32){
|
---|
453 | for(DWORD x=0;x<dwWidth;x++){
|
---|
454 | *dst++=src[0];
|
---|
455 | *dst++=src[1];
|
---|
456 | *dst++=src[2];
|
---|
457 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
458 | AlphaSet(x,(bFlipImage?(dwHeight-1-y):y),src[3]);
|
---|
459 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
460 | src+=4;
|
---|
461 | }
|
---|
462 | } else {
|
---|
463 | memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));
|
---|
464 | }
|
---|
465 | }
|
---|
466 | return true;
|
---|
467 | }
|
---|
468 | ////////////////////////////////////////////////////////////////////////////////
|
---|
469 | /**
|
---|
470 | * \sa CreateFromArray
|
---|
471 | */
|
---|
472 | bool CxImage::CreateFromMatrix(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage)
|
---|
473 | {
|
---|
474 | if (ppMatrix==NULL) return false;
|
---|
475 | if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||
|
---|
476 | (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;
|
---|
477 |
|
---|
478 | if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;
|
---|
479 |
|
---|
480 | if (dwBitsperpixel<24) SetGrayPalette();
|
---|
481 |
|
---|
482 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
483 | if (dwBitsperpixel==32) AlphaCreate();
|
---|
484 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
485 |
|
---|
486 | BYTE *dst,*src;
|
---|
487 |
|
---|
488 | for (DWORD y = 0; y<dwHeight; y++) {
|
---|
489 | dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
|
---|
490 | src = ppMatrix[y];
|
---|
491 | if (src){
|
---|
492 | if (dwBitsperpixel==32){
|
---|
493 | for(DWORD x=0;x<dwWidth;x++){
|
---|
494 | *dst++=src[0];
|
---|
495 | *dst++=src[1];
|
---|
496 | *dst++=src[2];
|
---|
497 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
498 | AlphaSet(x,(bFlipImage?(dwHeight-1-y):y),src[3]);
|
---|
499 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
500 | src+=4;
|
---|
501 | }
|
---|
502 | } else {
|
---|
503 | memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));
|
---|
504 | }
|
---|
505 | }
|
---|
506 | }
|
---|
507 | return true;
|
---|
508 | }
|
---|
509 | ////////////////////////////////////////////////////////////////////////////////
|
---|
510 | /**
|
---|
511 | * \return lightness difference between elem1 and elem2
|
---|
512 | */
|
---|
513 | int CxImage::CompareColors(const void *elem1, const void *elem2)
|
---|
514 | {
|
---|
515 | RGBQUAD* c1 = (RGBQUAD*)elem1;
|
---|
516 | RGBQUAD* c2 = (RGBQUAD*)elem2;
|
---|
517 |
|
---|
518 | int g1 = (int)RGB2GRAY(c1->rgbRed,c1->rgbGreen,c1->rgbBlue);
|
---|
519 | int g2 = (int)RGB2GRAY(c2->rgbRed,c2->rgbGreen,c2->rgbBlue);
|
---|
520 |
|
---|
521 | return (g1-g2);
|
---|
522 | }
|
---|
523 | ////////////////////////////////////////////////////////////////////////////////
|
---|
524 | /**
|
---|
525 | * simply calls "if (memblock) free(memblock);".
|
---|
526 | * Useful when calling Encode for a memory buffer,
|
---|
527 | * from a DLL compiled with different memory management options.
|
---|
528 | * CxImage::FreeMemory will use the same memory environment used by Encode.
|
---|
529 | * \author [livecn]
|
---|
530 | */
|
---|
531 | void CxImage::FreeMemory(void* memblock)
|
---|
532 | {
|
---|
533 | if (memblock)
|
---|
534 | free(memblock);
|
---|
535 | }
|
---|
536 | ////////////////////////////////////////////////////////////////////////////////
|
---|
537 | //EOF
|
---|