1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 03/07/2009
6 //
7 // Filename: src-IL/src/il_convert.c
8 //
9 // Description: Converts between several image formats
10 //
11 //-----------------------------------------------------------------------------
12
13
14 #include "il_internal.h"
15 #include "il_manip.h"
16 #include <limits.h>
17
18
iConvertPalette(ILimage * Image,ILenum DestFormat)19 ILimage *iConvertPalette(ILimage *Image, ILenum DestFormat)
20 {
21 static const ILfloat LumFactor[3] = { 0.212671f, 0.715160f, 0.072169f }; // http://www.inforamp.net/~poynton/ and libpng's libpng.txt - Used for conversion to luminance.
22 ILimage *NewImage = NULL, *CurImage = NULL;
23 ILuint i, j, k, c, Size, LumBpp = 1;
24 ILfloat Resultf;
25 ILubyte *Temp = NULL;
26 ILboolean Converted;
27 ILboolean HasAlpha;
28
29 NewImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0.
30 if (NewImage == NULL) {
31 return IL_FALSE;
32 }
33
34 ilCopyImageAttr(NewImage, Image);
35
36 if (!Image->Pal.Palette || !Image->Pal.PalSize || Image->Pal.PalType == IL_PAL_NONE || Image->Bpp != 1) {
37 ilCloseImage(NewImage);
38 ilSetError(IL_ILLEGAL_OPERATION);
39 return NULL;
40 }
41
42 if (DestFormat == IL_LUMINANCE || DestFormat == IL_LUMINANCE_ALPHA) {
43 if (NewImage->Pal.Palette)
44 ifree(NewImage->Pal.Palette);
45 if (DestFormat == IL_LUMINANCE_ALPHA)
46 LumBpp = 2;
47
48 switch (iCurImage->Pal.PalType)
49 {
50 case IL_PAL_RGB24:
51 case IL_PAL_RGB32:
52 case IL_PAL_RGBA32:
53 Temp = (ILubyte*)ialloc(LumBpp * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType));
54 if (Temp == NULL)
55 goto alloc_error;
56
57 Size = ilGetBppPal(Image->Pal.PalType);
58 for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += LumBpp) {
59 Resultf = 0.0f;
60 for (c = 0; c < Size; c++) {
61 Resultf += Image->Pal.Palette[i + c] * LumFactor[c];
62 }
63 Temp[k] = (ILubyte)Resultf;
64 if (LumBpp == 2) {
65 if (iCurImage->Pal.PalType == IL_PAL_RGBA32)
66 Temp[k+1] = Image->Pal.Palette[i + 3];
67 else
68 Temp[k+1] = 0xff;
69 }
70 }
71
72 break;
73
74 case IL_PAL_BGR24:
75 case IL_PAL_BGR32:
76 case IL_PAL_BGRA32:
77 Temp = (ILubyte*)ialloc(LumBpp * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType));
78 if (Temp == NULL)
79 goto alloc_error;
80
81 Size = ilGetBppPal(Image->Pal.PalType);
82 for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += LumBpp) {
83 Resultf = 0.0f; j = 2;
84 for (c = 0; c < Size; c++, j--) {
85 Resultf += Image->Pal.Palette[i + c] * LumFactor[j];
86 }
87 Temp[k] = (ILubyte)Resultf;
88 if (LumBpp == 2) {
89 if (iCurImage->Pal.PalType == IL_PAL_RGBA32)
90 Temp[k+1] = Image->Pal.Palette[i + 3];
91 else
92 Temp[k+1] = 0xff;
93 }
94 }
95
96 break;
97 }
98
99 NewImage->Pal.Palette = NULL;
100 NewImage->Pal.PalSize = 0;
101 NewImage->Pal.PalType = IL_PAL_NONE;
102 NewImage->Format = DestFormat;
103 NewImage->Bpp = LumBpp;
104 NewImage->Bps = NewImage->Width * LumBpp;
105 NewImage->SizeOfData = NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height;
106 NewImage->Data = (ILubyte*)ialloc(NewImage->SizeOfData);
107 if (NewImage->Data == NULL)
108 goto alloc_error;
109
110 if (LumBpp == 2) {
111 for (i = 0; i < Image->SizeOfData; i++) {
112 NewImage->Data[i*2] = Temp[Image->Data[i] * 2];
113 NewImage->Data[i*2+1] = Temp[Image->Data[i] * 2 + 1];
114 }
115 }
116 else {
117 for (i = 0; i < Image->SizeOfData; i++) {
118 NewImage->Data[i] = Temp[Image->Data[i]];
119 }
120 }
121
122 ifree(Temp);
123
124 return NewImage;
125 }
126 else if (DestFormat == IL_ALPHA) {
127 if (NewImage->Pal.Palette)
128 ifree(NewImage->Pal.Palette);
129
130 switch (iCurImage->Pal.PalType)
131 {
132 // Opaque, so all the values are 0xFF.
133 case IL_PAL_RGB24:
134 case IL_PAL_RGB32:
135 case IL_PAL_BGR24:
136 case IL_PAL_BGR32:
137 HasAlpha = IL_FALSE;
138 break;
139
140 case IL_PAL_BGRA32:
141 case IL_PAL_RGBA32:
142 HasAlpha = IL_TRUE;
143 Temp = (ILubyte*)ialloc(1 * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType));
144 if (Temp == NULL)
145 goto alloc_error;
146
147 Size = ilGetBppPal(Image->Pal.PalType);
148 for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += 1) {
149 Temp[k] = Image->Pal.Palette[i + 3];
150 }
151
152 break;
153 }
154
155 NewImage->Pal.Palette = NULL;
156 NewImage->Pal.PalSize = 0;
157 NewImage->Pal.PalType = IL_PAL_NONE;
158 NewImage->Format = DestFormat;
159 NewImage->Bpp = LumBpp;
160 NewImage->Bps = NewImage->Width * 1; // Alpha is only one byte.
161 NewImage->SizeOfData = NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height;
162 NewImage->Data = (ILubyte*)ialloc(NewImage->SizeOfData);
163 if (NewImage->Data == NULL)
164 goto alloc_error;
165
166 if (HasAlpha) {
167 for (i = 0; i < Image->SizeOfData; i++) {
168 NewImage->Data[i*2] = Temp[Image->Data[i] * 2];
169 NewImage->Data[i*2+1] = Temp[Image->Data[i] * 2 + 1];
170 }
171 }
172 else { // No alpha, opaque.
173 for (i = 0; i < Image->SizeOfData; i++) {
174 NewImage->Data[i] = 0xFF;
175 }
176 }
177
178 ifree(Temp);
179
180 return NewImage;
181 }
182
183 //NewImage->Format = ilGetPalBaseType(iCurImage->Pal.PalType);
184 NewImage->Format = DestFormat;
185
186 if (ilGetBppFormat(NewImage->Format) == 0) {
187 ilCloseImage(NewImage);
188 ilSetError(IL_ILLEGAL_OPERATION);
189 return NULL;
190 }
191
192 CurImage = iCurImage;
193 ilSetCurImage(NewImage);
194
195 switch (DestFormat)
196 {
197 case IL_RGB:
198 Converted = ilConvertPal(IL_PAL_RGB24);
199 break;
200
201 case IL_BGR:
202 Converted = ilConvertPal(IL_PAL_BGR24);
203 break;
204
205 case IL_RGBA:
206 Converted = ilConvertPal(IL_PAL_RGB32);
207 break;
208
209 case IL_BGRA:
210 Converted = ilConvertPal(IL_PAL_BGR32);
211 break;
212
213 case IL_COLOUR_INDEX:
214 // Just copy the original image over.
215 NewImage->Data = (ILubyte*)ialloc(CurImage->SizeOfData);
216 if (NewImage->Data == NULL)
217 goto alloc_error;
218 NewImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
219 if (NewImage->Pal.Palette == NULL)
220 goto alloc_error;
221 memcpy(NewImage->Data, CurImage->Data, CurImage->SizeOfData);
222 memcpy(NewImage->Pal.Palette, Image->Pal.Palette, Image->Pal.PalSize);
223 NewImage->Pal.PalSize = Image->Pal.PalSize;
224 NewImage->Pal.PalType = Image->Pal.PalType;
225 ilSetCurImage(CurImage);
226 return NewImage;
227
228 default:
229 ilCloseImage(NewImage);
230 ilSetError(IL_INVALID_CONVERSION);
231 return NULL;
232 }
233
234 // Resize to new bpp
235 ilResizeImage(NewImage, NewImage->Width, NewImage->Height, NewImage->Depth, ilGetBppFormat(DestFormat), /*ilGetBpcType(DestType)*/1);
236
237 // ilConvertPal already sets the error message - no need to confuse the user.
238 if (!Converted) {
239 ilSetCurImage(CurImage);
240 ilCloseImage(NewImage);
241 return NULL;
242 }
243
244 Size = ilGetBppPal(NewImage->Pal.PalType);
245 for (i = 0; i < Image->SizeOfData; i++) {
246 for (c = 0; c < NewImage->Bpp; c++) {
247 NewImage->Data[i * NewImage->Bpp + c] = NewImage->Pal.Palette[Image->Data[i] * Size + c];
248 }
249 }
250
251 ifree(NewImage->Pal.Palette);
252
253 NewImage->Pal.Palette = NULL;
254 NewImage->Pal.PalSize = 0;
255 NewImage->Pal.PalType = IL_PAL_NONE;
256 ilSetCurImage(CurImage);
257
258 return NewImage;
259
260 alloc_error:
261 ifree(Temp);
262 if (NewImage)
263 ilCloseImage(NewImage);
264 if (CurImage != iCurImage)
265 ilSetCurImage(CurImage);
266 return NULL;
267 }
268
269
270 // In il_quantizer.c
271 ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols);
272 // In il_neuquant.c
273 ILimage *iNeuQuant(ILimage *Image, ILuint NumCols);
274
275 // Converts an image from one format to another
iConvertImage(ILimage * Image,ILenum DestFormat,ILenum DestType)276 ILAPI ILimage* ILAPIENTRY iConvertImage(ILimage *Image, ILenum DestFormat, ILenum DestType)
277 {
278 ILimage *NewImage, *CurImage;
279 ILuint i;
280 ILubyte *NewData;
281
282 CurImage = Image;
283 if (Image == NULL) {
284 ilSetError(IL_ILLEGAL_OPERATION);
285 return IL_FALSE;
286 }
287
288 // We don't support 16-bit color indices (or higher).
289 if (DestFormat == IL_COLOUR_INDEX && DestType >= IL_SHORT) {
290 ilSetError(IL_INVALID_CONVERSION);
291 return NULL;
292 }
293
294 if (Image->Format == IL_COLOUR_INDEX) {
295 NewImage = iConvertPalette(Image, DestFormat);
296
297 //added test 2003-09-01
298 if (NewImage == NULL)
299 return NULL;
300
301 if (DestType == NewImage->Type)
302 return NewImage;
303
304 NewData = (ILubyte*)ilConvertBuffer(NewImage->SizeOfData, NewImage->Format, DestFormat, NewImage->Type, DestType, NULL, NewImage->Data);
305 if (NewData == NULL) {
306 ifree(NewImage); // ilCloseImage not needed.
307 return NULL;
308 }
309 ifree(NewImage->Data);
310 NewImage->Data = NewData;
311
312 ilCopyImageAttr(NewImage, Image);
313 NewImage->Format = DestFormat;
314 NewImage->Type = DestType;
315 NewImage->Bpc = ilGetBpcType(DestType);
316 NewImage->Bpp = ilGetBppFormat(DestFormat);
317 NewImage->Bps = NewImage->Bpp * NewImage->Bpc * NewImage->Width;
318 NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height;
319 NewImage->SizeOfData = NewImage->SizeOfPlane * NewImage->Depth;
320 }
321 else if (DestFormat == IL_COLOUR_INDEX && Image->Format != IL_LUMINANCE) {
322 if (iGetInt(IL_QUANTIZATION_MODE) == IL_NEU_QUANT)
323 return iNeuQuant(Image, iGetInt(IL_MAX_QUANT_INDICES));
324 else // Assume IL_WU_QUANT otherwise.
325 return iQuantizeImage(Image, iGetInt(IL_MAX_QUANT_INDICES));
326 }
327 else {
328 NewImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0.
329 if (NewImage == NULL) {
330 return NULL;
331 }
332
333 if (ilGetBppFormat(DestFormat) == 0) {
334 ilSetError(IL_INVALID_PARAM);
335 ifree(NewImage);
336 return NULL;
337 }
338
339 ilCopyImageAttr(NewImage, Image);
340 NewImage->Format = DestFormat;
341 NewImage->Type = DestType;
342 NewImage->Bpc = ilGetBpcType(DestType);
343 NewImage->Bpp = ilGetBppFormat(DestFormat);
344 NewImage->Bps = NewImage->Bpp * NewImage->Bpc * NewImage->Width;
345 NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height;
346 NewImage->SizeOfData = NewImage->SizeOfPlane * NewImage->Depth;
347
348 if (DestFormat == IL_COLOUR_INDEX && Image->Format == IL_LUMINANCE) {
349 NewImage->Pal.PalSize = 768;
350 NewImage->Pal.PalType = IL_PAL_RGB24;
351 NewImage->Pal.Palette = (ILubyte*)ialloc(768);
352 for (i = 0; i < 256; i++) {
353 NewImage->Pal.Palette[i * 3] = i;
354 NewImage->Pal.Palette[i * 3 + 1] = i;
355 NewImage->Pal.Palette[i * 3 + 2] = i;
356 }
357 NewImage->Data = (ILubyte*)ialloc(Image->SizeOfData);
358 if (NewImage->Data == NULL) {
359 ilCloseImage(NewImage);
360 return NULL;
361 }
362 memcpy(NewImage->Data, Image->Data, Image->SizeOfData);
363 }
364 else {
365 NewImage->Data = (ILubyte*)ilConvertBuffer(Image->SizeOfData, Image->Format, DestFormat, Image->Type, DestType, NULL, Image->Data);
366 if (NewImage->Data == NULL) {
367 ifree(NewImage); // ilCloseImage not needed.
368 return NULL;
369 }
370 }
371 }
372
373 return NewImage;
374 }
375
376
377 //! Converts the current image to the DestFormat format.
378 /*! \param DestFormat An enum of the desired output format. Any format values are accepted.
379 \param DestType An enum of the desired output type. Any type values are accepted.
380 \exception IL_ILLEGAL_OPERATION No currently bound image
381 \exception IL_INVALID_CONVERSION DestFormat or DestType was an invalid identifier.
382 \exception IL_OUT_OF_MEMORY Could not allocate enough memory.
383 \return Boolean value of failure or success*/
ilConvertImage(ILenum DestFormat,ILenum DestType)384 ILboolean ILAPIENTRY ilConvertImage(ILenum DestFormat, ILenum DestType)
385 {
386 ILimage *Image, *pCurImage;
387
388 if (iCurImage == NULL) {
389 ilSetError(IL_ILLEGAL_OPERATION);
390 return IL_FALSE;
391 }
392
393 if (DestFormat == iCurImage->Format && DestType == iCurImage->Type)
394 return IL_TRUE; // No conversion needed.
395
396 if (DestType == iCurImage->Type) {
397 if (iFastConvert(DestFormat)) {
398 iCurImage->Format = DestFormat;
399 return IL_TRUE;
400 }
401 }
402
403 if (ilIsEnabled(IL_USE_KEY_COLOUR)) {
404 ilAddAlphaKey(iCurImage);
405 }
406
407 pCurImage = iCurImage;
408 while (pCurImage != NULL)
409 {
410 Image = iConvertImage(pCurImage, DestFormat, DestType);
411 if (Image == NULL)
412 return IL_FALSE;
413
414 //ilCopyImageAttr(pCurImage, Image); // Destroys subimages.
415
416 // We don't copy the colour profile here, since it stays the same.
417 // Same with the DXTC data.
418 pCurImage->Format = DestFormat;
419 pCurImage->Type = DestType;
420 pCurImage->Bpc = ilGetBpcType(DestType);
421 pCurImage->Bpp = ilGetBppFormat(DestFormat);
422 pCurImage->Bps = pCurImage->Width * pCurImage->Bpc * pCurImage->Bpp;
423 pCurImage->SizeOfPlane = pCurImage->Bps * pCurImage->Height;
424 pCurImage->SizeOfData = pCurImage->Depth * pCurImage->SizeOfPlane;
425 if (pCurImage->Pal.Palette && pCurImage->Pal.PalSize && pCurImage->Pal.PalType != IL_PAL_NONE)
426 ifree(pCurImage->Pal.Palette);
427 pCurImage->Pal.Palette = Image->Pal.Palette;
428 pCurImage->Pal.PalSize = Image->Pal.PalSize;
429 pCurImage->Pal.PalType = Image->Pal.PalType;
430 Image->Pal.Palette = NULL;
431 ifree(pCurImage->Data);
432 pCurImage->Data = Image->Data;
433 Image->Data = NULL;
434 ilCloseImage(Image);
435
436 pCurImage = pCurImage->Next;
437 }
438
439 return IL_TRUE;
440 }
441
442
443 // Swaps the colour order of the current image (rgb(a)->bgr(a) or vice-versa).
444 // Must be either an 8, 24 or 32-bit (coloured) image (or palette).
ilSwapColours()445 ILboolean ilSwapColours()
446 {
447 ILuint i = 0, Size = iCurImage->Bpp * iCurImage->Width * iCurImage->Height;
448 ILbyte PalBpp = ilGetBppPal(iCurImage->Pal.PalType);
449 ILushort *ShortPtr;
450 ILuint *IntPtr, Temp;
451 ILdouble *DoublePtr, DoubleTemp;
452
453 if ((iCurImage->Bpp != 1 && iCurImage->Bpp != 3 && iCurImage->Bpp != 4)) {
454 ilSetError(IL_INVALID_VALUE);
455 return IL_FALSE;
456 }
457
458 // Just check before we change the format.
459 if (iCurImage->Format == IL_COLOUR_INDEX) {
460 if (PalBpp == 0 || iCurImage->Format != IL_COLOUR_INDEX) {
461 ilSetError(IL_ILLEGAL_OPERATION);
462 return IL_FALSE;
463 }
464 }
465
466 switch (iCurImage->Format)
467 {
468 case IL_RGB:
469 iCurImage->Format = IL_BGR;
470 break;
471 case IL_RGBA:
472 iCurImage->Format = IL_BGRA;
473 break;
474 case IL_BGR:
475 iCurImage->Format = IL_RGB;
476 break;
477 case IL_BGRA:
478 iCurImage->Format = IL_RGBA;
479 break;
480 case IL_ALPHA:
481 case IL_LUMINANCE:
482 case IL_LUMINANCE_ALPHA:
483 return IL_TRUE; // No need to do anything to luminance or alpha images.
484 case IL_COLOUR_INDEX:
485 switch (iCurImage->Pal.PalType)
486 {
487 case IL_PAL_RGB24:
488 iCurImage->Pal.PalType = IL_PAL_BGR24;
489 break;
490 case IL_PAL_RGB32:
491 iCurImage->Pal.PalType = IL_PAL_BGR32;
492 break;
493 case IL_PAL_RGBA32:
494 iCurImage->Pal.PalType = IL_PAL_BGRA32;
495 break;
496 case IL_PAL_BGR24:
497 iCurImage->Pal.PalType = IL_PAL_RGB24;
498 break;
499 case IL_PAL_BGR32:
500 iCurImage->Pal.PalType = IL_PAL_RGB32;
501 break;
502 case IL_PAL_BGRA32:
503 iCurImage->Pal.PalType = IL_PAL_RGBA32;
504 break;
505 default:
506 ilSetError(IL_ILLEGAL_OPERATION);
507 return IL_FALSE;
508 }
509 break;
510 default:
511 ilSetError(IL_ILLEGAL_OPERATION);
512 return IL_FALSE;
513 }
514
515 if (iCurImage->Format == IL_COLOUR_INDEX) {
516 for (; i < iCurImage->Pal.PalSize; i += PalBpp) {
517 Temp = iCurImage->Pal.Palette[i];
518 iCurImage->Pal.Palette[i] = iCurImage->Pal.Palette[i+2];
519 iCurImage->Pal.Palette[i+2] = Temp;
520 }
521 }
522 else {
523 ShortPtr = (ILushort*)iCurImage->Data;
524 IntPtr = (ILuint*)iCurImage->Data;
525 DoublePtr = (ILdouble*)iCurImage->Data;
526 switch (iCurImage->Bpc)
527 {
528 case 1:
529 for (; i < Size; i += iCurImage->Bpp) {
530 Temp = iCurImage->Data[i];
531 iCurImage->Data[i] = iCurImage->Data[i+2];
532 iCurImage->Data[i+2] = Temp;
533 }
534 break;
535 case 2:
536 for (; i < Size; i += iCurImage->Bpp) {
537 Temp = ShortPtr[i];
538 ShortPtr[i] = ShortPtr[i+2];
539 ShortPtr[i+2] = Temp;
540 }
541 break;
542 case 4: // Works fine with ILint, ILuint and ILfloat.
543 for (; i < Size; i += iCurImage->Bpp) {
544 Temp = IntPtr[i];
545 IntPtr[i] = IntPtr[i+2];
546 IntPtr[i+2] = Temp;
547 }
548 break;
549 case 8:
550 for (; i < Size; i += iCurImage->Bpp) {
551 DoubleTemp = DoublePtr[i];
552 DoublePtr[i] = DoublePtr[i+2];
553 DoublePtr[i+2] = DoubleTemp;
554 }
555 break;
556 }
557 }
558
559 return IL_TRUE;
560 }
561
562
563 // Adds an opaque alpha channel to a 24-bit image
ilAddAlpha()564 ILboolean ilAddAlpha()
565 {
566 ILubyte *NewData, NewBpp;
567 ILuint i = 0, j = 0, Size;
568
569 if (iCurImage == NULL) {
570 ilSetError(IL_ILLEGAL_OPERATION);
571 return IL_FALSE;
572 }
573
574 if (iCurImage->Bpp != 3) {
575 ilSetError(IL_INVALID_VALUE);
576 return IL_FALSE;
577 }
578
579 Size = iCurImage->Bps * iCurImage->Height / iCurImage->Bpc;
580 NewBpp = (ILubyte)(iCurImage->Bpp + 1);
581
582 NewData = (ILubyte*)ialloc(NewBpp * iCurImage->Bpc * iCurImage->Width * iCurImage->Height);
583 if (NewData == NULL) {
584 return IL_FALSE;
585 }
586
587 switch (iCurImage->Type)
588 {
589 case IL_BYTE:
590 case IL_UNSIGNED_BYTE:
591 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
592 NewData[j] = iCurImage->Data[i];
593 NewData[j+1] = iCurImage->Data[i+1];
594 NewData[j+2] = iCurImage->Data[i+2];
595 NewData[j+3] = UCHAR_MAX; // Max opaqueness
596 }
597 break;
598
599 case IL_SHORT:
600 case IL_UNSIGNED_SHORT:
601 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
602 ((ILushort*)NewData)[j] = ((ILushort*)iCurImage->Data)[i];
603 ((ILushort*)NewData)[j+1] = ((ILushort*)iCurImage->Data)[i+1];
604 ((ILushort*)NewData)[j+2] = ((ILushort*)iCurImage->Data)[i+2];
605 ((ILushort*)NewData)[j+3] = USHRT_MAX;
606 }
607 break;
608
609 case IL_INT:
610 case IL_UNSIGNED_INT:
611 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
612 ((ILuint*)NewData)[j] = ((ILuint*)iCurImage->Data)[i];
613 ((ILuint*)NewData)[j+1] = ((ILuint*)iCurImage->Data)[i+1];
614 ((ILuint*)NewData)[j+2] = ((ILuint*)iCurImage->Data)[i+2];
615 ((ILuint*)NewData)[j+3] = UINT_MAX;
616 }
617 break;
618
619 case IL_FLOAT:
620 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
621 ((ILfloat*)NewData)[j] = ((ILfloat*)iCurImage->Data)[i];
622 ((ILfloat*)NewData)[j+1] = ((ILfloat*)iCurImage->Data)[i+1];
623 ((ILfloat*)NewData)[j+2] = ((ILfloat*)iCurImage->Data)[i+2];
624 ((ILfloat*)NewData)[j+3] = 1.0f;
625 }
626 break;
627
628 case IL_DOUBLE:
629 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
630 ((ILdouble*)NewData)[j] = ((ILdouble*)iCurImage->Data)[i];
631 ((ILdouble*)NewData)[j+1] = ((ILdouble*)iCurImage->Data)[i+1];
632 ((ILdouble*)NewData)[j+2] = ((ILdouble*)iCurImage->Data)[i+2];
633 ((ILdouble*)NewData)[j+3] = 1.0;
634 }
635 break;
636
637 default:
638 ifree(NewData);
639 ilSetError(IL_INTERNAL_ERROR);
640 return IL_FALSE;
641 }
642
643
644 iCurImage->Bpp = NewBpp;
645 iCurImage->Bps = iCurImage->Width * iCurImage->Bpc * NewBpp;
646 iCurImage->SizeOfPlane = iCurImage->Bps * iCurImage->Height;
647 iCurImage->SizeOfData = iCurImage->SizeOfPlane * iCurImage->Depth;
648 ifree(iCurImage->Data);
649 iCurImage->Data = NewData;
650
651 switch (iCurImage->Format)
652 {
653 case IL_RGB:
654 iCurImage->Format = IL_RGBA;
655 break;
656 case IL_BGR:
657 iCurImage->Format = IL_BGRA;
658 break;
659 }
660
661 return IL_TRUE;
662 }
663
664
665 //ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0;
666
ilKeyColour(ILclampf Red,ILclampf Green,ILclampf Blue,ILclampf Alpha)667 void ILAPIENTRY ilKeyColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha)
668 {
669 ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0;
670 KeyRed = Red;
671 KeyGreen = Green;
672 KeyBlue = Blue;
673 KeyAlpha = Alpha;
674 return;
675 }
676
677
678 // Adds an alpha channel to an 8 or 24-bit image,
679 // making the image transparent where Key is equal to the pixel.
ilAddAlphaKey(ILimage * Image)680 ILboolean ilAddAlphaKey(ILimage *Image)
681 {
682 ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0;
683 ILubyte *NewData, NewBpp;
684 ILfloat KeyColour[3];
685 ILuint i = 0, j = 0, c, Size;
686 ILboolean Same;
687
688 if (Image == NULL) {
689 ilSetError(IL_ILLEGAL_OPERATION);
690 return IL_FALSE;
691 }
692
693 if (Image->Format != IL_COLOUR_INDEX) {
694 if (Image->Bpp != 3) {
695 ilSetError(IL_INVALID_VALUE);
696 return IL_FALSE;
697 }
698
699 if (Image->Format == IL_BGR || Image->Format == IL_BGRA) {
700 KeyColour[0] = KeyBlue;
701 KeyColour[1] = KeyGreen;
702 KeyColour[2] = KeyRed;
703 }
704 else {
705 KeyColour[0] = KeyRed;
706 KeyColour[1] = KeyGreen;
707 KeyColour[2] = KeyBlue;
708 }
709
710 Size = Image->Bps * Image->Height / Image->Bpc;
711
712 NewBpp = (ILubyte)(Image->Bpp + 1);
713
714 NewData = (ILubyte*)ialloc(NewBpp * Image->Bpc * Image->Width * Image->Height);
715 if (NewData == NULL) {
716 return IL_FALSE;
717 }
718
719 switch (Image->Type)
720 {
721 case IL_BYTE:
722 case IL_UNSIGNED_BYTE:
723 for (; i < Size; i += Image->Bpp, j += NewBpp) {
724 NewData[j] = Image->Data[i];
725 NewData[j+1] = Image->Data[i+1];
726 NewData[j+2] = Image->Data[i+2];
727 Same = IL_TRUE;
728 for (c = 0; c < Image->Bpp; c++) {
729 if (Image->Data[i+c] != KeyColour[c] * UCHAR_MAX)
730 Same = IL_FALSE;
731 }
732
733 if (Same)
734 NewData[j+3] = 0; // Transparent - matches key colour
735 else
736 NewData[j+3] = UCHAR_MAX;
737 }
738 break;
739
740 case IL_SHORT:
741 case IL_UNSIGNED_SHORT:
742 for (; i < Size; i += Image->Bpp, j += NewBpp) {
743 ((ILushort*)NewData)[j] = ((ILushort*)Image->Data)[i];
744 ((ILushort*)NewData)[j+1] = ((ILushort*)Image->Data)[i+1];
745 ((ILushort*)NewData)[j+2] = ((ILushort*)Image->Data)[i+2];
746 Same = IL_TRUE;
747 for (c = 0; c < Image->Bpp; c++) {
748 if (((ILushort*)Image->Data)[i+c] != KeyColour[c] * USHRT_MAX)
749 Same = IL_FALSE;
750 }
751
752 if (Same)
753 ((ILushort*)NewData)[j+3] = 0;
754 else
755 ((ILushort*)NewData)[j+3] = USHRT_MAX;
756 }
757 break;
758
759 case IL_INT:
760 case IL_UNSIGNED_INT:
761 for (; i < Size; i += Image->Bpp, j += NewBpp) {
762 ((ILuint*)NewData)[j] = ((ILuint*)Image->Data)[i];
763 ((ILuint*)NewData)[j+1] = ((ILuint*)Image->Data)[i+1];
764 ((ILuint*)NewData)[j+2] = ((ILuint*)Image->Data)[i+2];
765 Same = IL_TRUE;
766 for (c = 0; c < Image->Bpp; c++) {
767 if (((ILuint*)Image->Data)[i+c] != KeyColour[c] * UINT_MAX)
768 Same = IL_FALSE;
769 }
770
771 if (Same)
772 ((ILuint*)NewData)[j+3] = 0;
773 else
774 ((ILuint*)NewData)[j+3] = UINT_MAX;
775 }
776 break;
777
778 case IL_FLOAT:
779 for (; i < Size; i += Image->Bpp, j += NewBpp) {
780 ((ILfloat*)NewData)[j] = ((ILfloat*)Image->Data)[i];
781 ((ILfloat*)NewData)[j+1] = ((ILfloat*)Image->Data)[i+1];
782 ((ILfloat*)NewData)[j+2] = ((ILfloat*)Image->Data)[i+2];
783 Same = IL_TRUE;
784 for (c = 0; c < Image->Bpp; c++) {
785 if (((ILfloat*)Image->Data)[i+c] != KeyColour[c])
786 Same = IL_FALSE;
787 }
788
789 if (Same)
790 ((ILfloat*)NewData)[j+3] = 0.0f;
791 else
792 ((ILfloat*)NewData)[j+3] = 1.0f;
793 }
794 break;
795
796 case IL_DOUBLE:
797 for (; i < Size; i += Image->Bpp, j += NewBpp) {
798 ((ILdouble*)NewData)[j] = ((ILdouble*)Image->Data)[i];
799 ((ILdouble*)NewData)[j+1] = ((ILdouble*)Image->Data)[i+1];
800 ((ILdouble*)NewData)[j+2] = ((ILdouble*)Image->Data)[i+2];
801 Same = IL_TRUE;
802 for (c = 0; c < Image->Bpp; c++) {
803 if (((ILdouble*)Image->Data)[i+c] != KeyColour[c])
804 Same = IL_FALSE;
805 }
806
807 if (Same)
808 ((ILdouble*)NewData)[j+3] = 0.0;
809 else
810 ((ILdouble*)NewData)[j+3] = 1.0;
811 }
812 break;
813
814 default:
815 ifree(NewData);
816 ilSetError(IL_INTERNAL_ERROR);
817 return IL_FALSE;
818 }
819
820
821 Image->Bpp = NewBpp;
822 Image->Bps = Image->Width * Image->Bpc * NewBpp;
823 Image->SizeOfPlane = Image->Bps * Image->Height;
824 Image->SizeOfData = Image->SizeOfPlane * Image->Depth;
825 ifree(Image->Data);
826 Image->Data = NewData;
827
828 switch (Image->Format)
829 {
830 case IL_RGB:
831 Image->Format = IL_RGBA;
832 break;
833 case IL_BGR:
834 Image->Format = IL_BGRA;
835 break;
836 }
837 }
838 else { // IL_COLOUR_INDEX
839 if (Image->Bpp != 1) {
840 ilSetError(IL_INTERNAL_ERROR);
841 return IL_FALSE;
842 }
843
844 Size = ilGetInteger(IL_PALETTE_NUM_COLS);
845 if (Size == 0) {
846 ilSetError(IL_INTERNAL_ERROR);
847 return IL_FALSE;
848 }
849
850 if ((ILuint)(KeyAlpha * UCHAR_MAX) > Size) {
851 ilSetError(IL_INVALID_VALUE);
852 return IL_FALSE;
853 }
854
855 switch (Image->Pal.PalType)
856 {
857 case IL_PAL_RGB24:
858 case IL_PAL_RGB32:
859 case IL_PAL_RGBA32:
860 if (!ilConvertPal(IL_PAL_RGBA32))
861 return IL_FALSE;
862 break;
863 case IL_PAL_BGR24:
864 case IL_PAL_BGR32:
865 case IL_PAL_BGRA32:
866 if (!ilConvertPal(IL_PAL_BGRA32))
867 return IL_FALSE;
868 break;
869 default:
870 ilSetError(IL_INTERNAL_ERROR);
871 return IL_FALSE;
872 }
873
874 // Set the colour index to be transparent.
875 Image->Pal.Palette[(ILuint)(KeyAlpha * UCHAR_MAX) * 4 + 3] = 0;
876
877 // @TODO: Check if this is the required behaviour.
878
879 if (Image->Pal.PalType == IL_PAL_RGBA32)
880 ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
881 else
882 ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
883 }
884
885 return IL_TRUE;
886 }
887
888
889 // Removes alpha from a 32-bit image
890 // Should we maybe add an option that changes the image based on the alpha?
ilRemoveAlpha()891 ILboolean ilRemoveAlpha()
892 {
893 ILubyte *NewData, NewBpp;
894 ILuint i = 0, j = 0, Size;
895
896 if (iCurImage == NULL) {
897 ilSetError(IL_INVALID_PARAM);
898 return IL_FALSE;
899 }
900
901 if (iCurImage->Bpp != 4) {
902 ilSetError(IL_INVALID_VALUE);
903 return IL_FALSE;
904 }
905
906 Size = iCurImage->Bps * iCurImage->Height;
907 NewBpp = (ILubyte)(iCurImage->Bpp - 1);
908
909 NewData = (ILubyte*)ialloc(NewBpp * iCurImage->Bpc * iCurImage->Width * iCurImage->Height);
910 if (NewData == NULL) {
911 return IL_FALSE;
912 }
913
914 switch (iCurImage->Type)
915 {
916 case IL_BYTE:
917 case IL_UNSIGNED_BYTE:
918 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
919 NewData[j] = iCurImage->Data[i];
920 NewData[j+1] = iCurImage->Data[i+1];
921 NewData[j+2] = iCurImage->Data[i+2];
922 }
923 break;
924
925 case IL_SHORT:
926 case IL_UNSIGNED_SHORT:
927 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
928 ((ILushort*)NewData)[j] = ((ILushort*)iCurImage->Data)[i];
929 ((ILushort*)NewData)[j+1] = ((ILushort*)iCurImage->Data)[i+1];
930 ((ILushort*)NewData)[j+2] = ((ILushort*)iCurImage->Data)[i+2];
931 }
932 break;
933
934 case IL_INT:
935 case IL_UNSIGNED_INT:
936 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
937 ((ILuint*)NewData)[j] = ((ILuint*)iCurImage->Data)[i];
938 ((ILuint*)NewData)[j+1] = ((ILuint*)iCurImage->Data)[i+1];
939 ((ILuint*)NewData)[j+2] = ((ILuint*)iCurImage->Data)[i+2];
940 }
941 break;
942
943 case IL_FLOAT:
944 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
945 ((ILfloat*)NewData)[j] = ((ILfloat*)iCurImage->Data)[i];
946 ((ILfloat*)NewData)[j+1] = ((ILfloat*)iCurImage->Data)[i+1];
947 ((ILfloat*)NewData)[j+2] = ((ILfloat*)iCurImage->Data)[i+2];
948 }
949 break;
950
951 case IL_DOUBLE:
952 for (; i < Size; i += iCurImage->Bpp, j += NewBpp) {
953 ((ILdouble*)NewData)[j] = ((ILdouble*)iCurImage->Data)[i];
954 ((ILdouble*)NewData)[j+1] = ((ILdouble*)iCurImage->Data)[i+1];
955 ((ILdouble*)NewData)[j+2] = ((ILdouble*)iCurImage->Data)[i+2];
956 }
957 break;
958
959 default:
960 ifree(NewData);
961 ilSetError(IL_INTERNAL_ERROR);
962 return IL_FALSE;
963 }
964
965
966 iCurImage->Bpp = NewBpp;
967 iCurImage->Bps = iCurImage->Width * iCurImage->Bpc * NewBpp;
968 iCurImage->SizeOfPlane = iCurImage->Bps * iCurImage->Height;
969 iCurImage->SizeOfData = iCurImage->SizeOfPlane * iCurImage->Depth;
970 ifree(iCurImage->Data);
971 iCurImage->Data = NewData;
972
973 switch (iCurImage->Format)
974 {
975 case IL_RGBA:
976 iCurImage->Format = IL_RGB;
977 break;
978 case IL_BGRA:
979 iCurImage->Format = IL_BGR;
980 break;
981 }
982
983 return IL_TRUE;
984 }
985
986
ilFixCur()987 ILboolean ilFixCur()
988 {
989 if (ilIsEnabled(IL_ORIGIN_SET)) {
990 if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
991 if (!ilFlipImage()) {
992 return IL_FALSE;
993 }
994 }
995 }
996
997 if (ilIsEnabled(IL_TYPE_SET)) {
998 if ((ILenum)ilGetInteger(IL_TYPE_MODE) != iCurImage->Type) {
999 if (!ilConvertImage(iCurImage->Format, ilGetInteger(IL_TYPE_MODE))) {
1000 return IL_FALSE;
1001 }
1002 }
1003 }
1004 if (ilIsEnabled(IL_FORMAT_SET)) {
1005 if ((ILenum)ilGetInteger(IL_FORMAT_MODE) != iCurImage->Format) {
1006 if (!ilConvertImage(ilGetInteger(IL_FORMAT_MODE), iCurImage->Type)) {
1007 return IL_FALSE;
1008 }
1009 }
1010 }
1011
1012 if (iCurImage->Format == IL_COLOUR_INDEX) {
1013 if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) {
1014 if (!ilConvertImage(IL_BGR, IL_UNSIGNED_BYTE)) {
1015 return IL_FALSE;
1016 }
1017 }
1018 }
1019 /* Swap Colors on Big Endian !!!!!
1020 #if BYTE_ORDER == BIG_ENDIAN
1021 // Swap endian
1022 EndianSwapData(iCurImage);
1023 #endif
1024 */
1025 return IL_TRUE;
1026 }
1027
1028 /*
1029 ILboolean ilFixImage()
1030 {
1031 ILuint NumImages, i;
1032
1033 NumImages = ilGetInteger(IL_NUM_IMAGES);
1034 for (i = 0; i < NumImages; i++) {
1035 ilBindImage(ilGetCurName()); // Set to parent image first.
1036 if (!ilActiveImage(i+1))
1037 return IL_FALSE;
1038 if (!ilFixCur())
1039 return IL_FALSE;
1040 }
1041
1042 NumImages = ilGetInteger(IL_NUM_MIPMAPS);
1043 for (i = 0; i < NumImages; i++) {
1044 ilBindImage(ilGetCurName()); // Set to parent image first.
1045 if (!ilActiveMipmap(i+1))
1046 return IL_FALSE;
1047 if (!ilFixCur())
1048 return IL_FALSE;
1049 }
1050
1051 NumImages = ilGetInteger(IL_NUM_LAYERS);
1052 for (i = 0; i < NumImages; i++) {
1053 ilBindImage(ilGetCurName()); // Set to parent image first.
1054 if (!ilActiveLayer(i+1))
1055 return IL_FALSE;
1056 if (!ilFixCur())
1057 return IL_FALSE;
1058 }
1059
1060 ilBindImage(ilGetCurName());
1061 ilFixCur();
1062
1063 return IL_TRUE;
1064 }
1065 */
1066
1067 /*
1068 This function was replaced 20050304, because the previous version
1069 didn't fix the mipmaps of the subimages etc. This version is not
1070 completely correct either, because the subimages of the subimages
1071 etc. are not fixed, but at the moment no images of this type can
1072 be loaded anyway. Thanks to Chris Lux for pointing this out.
1073 */
1074
ilFixImage()1075 ILboolean ilFixImage()
1076 {
1077 ILuint NumFaces, f;
1078 ILuint NumImages, i;
1079 ILuint NumMipmaps,j;
1080 ILuint NumLayers, k;
1081
1082 NumImages = ilGetInteger(IL_NUM_IMAGES);
1083 for (i = 0; i <= NumImages; i++) {
1084 ilBindImage(ilGetCurName()); // Set to parent image first.
1085 if (!ilActiveImage(i))
1086 return IL_FALSE;
1087
1088 NumFaces = ilGetInteger(IL_NUM_FACES);
1089 for (f = 0; f <= NumFaces; f++) {
1090 ilBindImage(ilGetCurName()); // Set to parent image first.
1091 if (!ilActiveImage(i))
1092 return IL_FALSE;
1093 if (!ilActiveFace(f))
1094 return IL_FALSE;
1095
1096 NumLayers = ilGetInteger(IL_NUM_LAYERS);
1097 for (k = 0; k <= NumLayers; k++) {
1098 ilBindImage(ilGetCurName()); // Set to parent image first.
1099 if (!ilActiveImage(i))
1100 return IL_FALSE;
1101 if (!ilActiveFace(f))
1102 return IL_FALSE;
1103 if (!ilActiveLayer(k))
1104 return IL_FALSE;
1105
1106 NumMipmaps = ilGetInteger(IL_NUM_MIPMAPS);
1107 for (j = 0; j <= NumMipmaps; j++) {
1108 ilBindImage(ilGetCurName()); // Set to parent image first.
1109 if (!ilActiveImage(i))
1110 return IL_FALSE;
1111 if (!ilActiveFace(f))
1112 return IL_FALSE;
1113 if (!ilActiveLayer(k))
1114 return IL_FALSE;
1115 if (!ilActiveMipmap(j))
1116 return IL_FALSE;
1117 if (!ilFixCur())
1118 return IL_FALSE;
1119 }
1120 }
1121 }
1122 }
1123 ilBindImage(ilGetCurName());
1124
1125 return IL_TRUE;
1126 }
1127