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