1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 01/24/2009
6 //
7 // Filename: src-IL/src/il_manip.c
8 //
9 // Description: Image manipulation
10 //
11 //-----------------------------------------------------------------------------
12 
13 #include "il_internal.h"
14 #include "il_manip.h"
15 
16 
iFlipBuffer(ILubyte * buff,ILuint depth,ILuint line_size,ILuint line_num)17 ILAPI void ILAPIENTRY iFlipBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num)
18 {
19 	ILubyte *StartPtr, *EndPtr;
20 	ILuint y, d;
21 	const ILuint size = line_num * line_size;
22 
23 	for (d = 0; d < depth; d++) {
24 		StartPtr = buff + d * size;
25 		EndPtr   = buff + d * size + size;
26 
27 		for (y = 0; y < (line_num/2); y++) {
28 			EndPtr -= line_size;
29 			iMemSwap(StartPtr, EndPtr, line_size);
30 			StartPtr += line_size;
31 		}
32 	}
33 }
34 
35 // Just created for internal use.
iFlipNewBuffer(ILubyte * buff,ILuint depth,ILuint line_size,ILuint line_num)36 ILubyte* iFlipNewBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num)
37 {
38 	ILubyte *data;
39 	ILubyte *s1, *s2;
40 	ILuint y, d;
41 	const ILuint size = line_num * line_size;
42 
43 	if ((data = (ILubyte*)ialloc(depth*size)) == NULL)
44 		return IL_FALSE;
45 
46 	for (d = 0; d < depth; d++) {
47 		s1 = buff + d * size;
48 		s2 = data + d * size+size;
49 
50 		for (y = 0; y < line_num; y++) {
51 			s2 -= line_size;
52 			memcpy(s2,s1,line_size);
53 			s1 += line_size;
54 		}
55 	}
56 	return data;
57 }
58 
59 
60 // Flips an image over its x axis
ilFlipImage()61 ILboolean ilFlipImage()
62 {
63 	if (iCurImage == NULL) {
64 		ilSetError(IL_ILLEGAL_OPERATION);
65 		return IL_FALSE;
66 	}
67 
68 	iCurImage->Origin = (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) ?
69 						IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT;
70 
71 	iFlipBuffer(iCurImage->Data,iCurImage->Depth,iCurImage->Bps,iCurImage->Height);
72 
73 	return IL_TRUE;
74 }
75 
76 // Just created for internal use.
iGetFlipped(ILimage * img)77 ILubyte* ILAPIENTRY iGetFlipped(ILimage *img)
78 {
79 	if (img == NULL) {
80 		ilSetError(IL_ILLEGAL_OPERATION);
81 		return NULL;
82 	}
83 	return iFlipNewBuffer(img->Data,img->Depth,img->Bps,img->Height);
84 }
85 
86 
87 //@JASON New routine created 28/03/2001
88 //! Mirrors an image over its y axis
iMirror()89 ILboolean ILAPIENTRY iMirror() {
90 	ILubyte		*Data, *DataPtr, *Temp;
91 	ILuint		y, d, PixLine;
92 	ILint		x, c;
93 	ILushort	*ShortPtr, *TempShort;
94 	ILuint		*IntPtr, *TempInt;
95 	ILdouble	*DblPtr, *TempDbl;
96 
97 	if (iCurImage == NULL) {
98 		ilSetError(IL_ILLEGAL_OPERATION);
99 		return IL_FALSE;
100 	}
101 
102 	Data = (ILubyte*)ialloc(iCurImage->SizeOfData);
103 	if (Data == NULL)
104 		return IL_FALSE;
105 
106 	PixLine = iCurImage->Bps / iCurImage->Bpc;
107 	switch (iCurImage->Bpc)
108 	{
109 		case 1:
110 			Temp = iCurImage->Data;
111 			for (d = 0; d < iCurImage->Depth; d++) {
112 				DataPtr = Data + d * iCurImage->SizeOfPlane;
113 				for (y = 0; y < iCurImage->Height; y++) {
114 					for (x = iCurImage->Width - 1; x >= 0; x--) {
115 						for (c = 0; c < iCurImage->Bpp; c++, Temp++) {
116 							DataPtr[y * PixLine + x * iCurImage->Bpp + c] = *Temp;
117 						}
118 					}
119 				}
120 			}
121 			break;
122 
123 		case 2:
124 			TempShort = (ILushort*)iCurImage->Data;
125 			for (d = 0; d < iCurImage->Depth; d++) {
126 				ShortPtr = (ILushort*)(Data + d * iCurImage->SizeOfPlane);
127 				for (y = 0; y < iCurImage->Height; y++) {
128 					for (x = iCurImage->Width - 1; x >= 0; x--) {
129 						for (c = 0; c < iCurImage->Bpp; c++, TempShort++) {
130 							ShortPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempShort;
131 						}
132 					}
133 				}
134 			}
135 			break;
136 
137 		case 4:
138 			TempInt = (ILuint*)iCurImage->Data;
139 			for (d = 0; d < iCurImage->Depth; d++) {
140 				IntPtr = (ILuint*)(Data + d * iCurImage->SizeOfPlane);
141 				for (y = 0; y < iCurImage->Height; y++) {
142 					for (x = iCurImage->Width - 1; x >= 0; x--) {
143 						for (c = 0; c < iCurImage->Bpp; c++, TempInt++) {
144 							IntPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempInt;
145 						}
146 					}
147 				}
148 			}
149 			break;
150 
151 		case 8:
152 			TempDbl = (ILdouble*)iCurImage->Data;
153 			for (d = 0; d < iCurImage->Depth; d++) {
154 				DblPtr = (ILdouble*)(Data + d * iCurImage->SizeOfPlane);
155 				for (y = 0; y < iCurImage->Height; y++) {
156 					for (x = iCurImage->Width - 1; x >= 0; x--) {
157 						for (c = 0; c < iCurImage->Bpp; c++, TempDbl++) {
158 							DblPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempDbl;
159 						}
160 					}
161 				}
162 			}
163 			break;
164 	}
165 
166 	ifree(iCurImage->Data);
167 	iCurImage->Data = Data;
168 
169 	return IL_TRUE;
170 }
171 
172 
173 // Should we add type to the parameter list?
174 // Copies a 1d block of pixels to the buffer pointed to by Data.
ilCopyPixels1D(ILuint XOff,ILuint Width,void * Data)175 ILboolean ilCopyPixels1D(ILuint XOff, ILuint Width, void *Data)
176 {
177 	ILuint	x, c, NewBps, NewOff, PixBpp;
178 	ILubyte	*Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
179 
180 	if (ilIsEnabled(IL_ORIGIN_SET)) {
181 		if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
182 			TempData = iGetFlipped(iCurImage);
183 			if (TempData == NULL)
184 				return IL_FALSE;
185 		}
186 	}
187 
188 	PixBpp = iCurImage->Bpp * iCurImage->Bpc;
189 
190 	if (iCurImage->Width < XOff + Width) {
191 		NewBps = (iCurImage->Width - XOff) * PixBpp;
192 	}
193 	else {
194 		NewBps = Width * PixBpp;
195 	}
196 	NewOff = XOff * PixBpp;
197 
198 	for (x = 0; x < NewBps; x += PixBpp) {
199 		for (c = 0; c < PixBpp; c++) {
200 			Temp[x + c] = TempData[(x + NewOff) + c];
201 		}
202 	}
203 
204 	if (TempData != iCurImage->Data)
205 		ifree(TempData);
206 
207 	return IL_TRUE;
208 }
209 
210 
211 // Copies a 2d block of pixels to the buffer pointed to by Data.
ilCopyPixels2D(ILuint XOff,ILuint YOff,ILuint Width,ILuint Height,void * Data)212 ILboolean ilCopyPixels2D(ILuint XOff, ILuint YOff, ILuint Width, ILuint Height, void *Data)
213 {
214 	ILuint	x, y, c, NewBps, DataBps, NewXOff, NewHeight, PixBpp;
215 	ILubyte	*Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
216 
217 	if (ilIsEnabled(IL_ORIGIN_SET)) {
218 		if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
219 			TempData = iGetFlipped(iCurImage);
220 			if (TempData == NULL)
221 				return IL_FALSE;
222 		}
223 	}
224 
225 	PixBpp = iCurImage->Bpp * iCurImage->Bpc;
226 
227 	if (iCurImage->Width < XOff + Width)
228 		NewBps = (iCurImage->Width - XOff) * PixBpp;
229 	else
230 		NewBps = Width * PixBpp;
231 
232 	if (iCurImage->Height < YOff + Height)
233 		NewHeight = iCurImage->Height - YOff;
234 	else
235 		NewHeight = Height;
236 
237 	DataBps = Width * PixBpp;
238 	NewXOff = XOff * PixBpp;
239 
240 	for (y = 0; y < NewHeight; y++) {
241 		for (x = 0; x < NewBps; x += PixBpp) {
242 			for (c = 0; c < PixBpp; c++) {
243 				Temp[y * DataBps + x + c] =
244 					TempData[(y + YOff) * iCurImage->Bps + x + NewXOff + c];
245 			}
246 		}
247 	}
248 
249 	if (TempData != iCurImage->Data)
250 		ifree(TempData);
251 
252 	return IL_TRUE;
253 }
254 
255 
256 // Copies a 3d block of pixels to the buffer pointed to by Data.
ilCopyPixels3D(ILuint XOff,ILuint YOff,ILuint ZOff,ILuint Width,ILuint Height,ILuint Depth,void * Data)257 ILboolean ilCopyPixels3D(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, void *Data)
258 {
259 	ILuint	x, y, z, c, NewBps, DataBps, NewSizePlane, NewH, NewD, NewXOff, PixBpp;
260 	ILubyte	*Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
261 
262 	if (ilIsEnabled(IL_ORIGIN_SET)) {
263 		if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
264 			TempData = iGetFlipped(iCurImage);
265 			if (TempData == NULL)
266 				return IL_FALSE;
267 		}
268 	}
269 
270 	PixBpp = iCurImage->Bpp * iCurImage->Bpc;
271 
272 	if (iCurImage->Width < XOff + Width)
273 		NewBps = (iCurImage->Width - XOff) * PixBpp;
274 	else
275 		NewBps = Width * PixBpp;
276 
277 	if (iCurImage->Height < YOff + Height)
278 		NewH = iCurImage->Height - YOff;
279 	else
280 		NewH = Height;
281 
282 	if (iCurImage->Depth < ZOff + Depth)
283 		NewD = iCurImage->Depth - ZOff;
284 	else
285 		NewD = Depth;
286 
287 	DataBps = Width * PixBpp;
288 	NewSizePlane = NewBps * NewH;
289 
290 	NewXOff = XOff * PixBpp;
291 
292 	for (z = 0; z < NewD; z++) {
293 		for (y = 0; y < NewH; y++) {
294 			for (x = 0; x < NewBps; x += PixBpp) {
295 				for (c = 0; c < PixBpp; c++) {
296 					Temp[z * NewSizePlane + y * DataBps + x + c] =
297 						TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + x + NewXOff + c];
298 						//TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * iCurImage->Bpp + c];
299 				}
300 			}
301 		}
302 	}
303 
304 	if (TempData != iCurImage->Data)
305 		ifree(TempData);
306 
307 	return IL_TRUE;
308 }
309 
310 
ilCopyPixels(ILuint XOff,ILuint YOff,ILuint ZOff,ILuint Width,ILuint Height,ILuint Depth,ILenum Format,ILenum Type,void * Data)311 ILuint ILAPIENTRY ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data)
312 {
313 	void	*Converted = NULL;
314 	ILubyte	*TempBuff = NULL;
315 	ILuint	SrcSize, DestSize;
316 
317 	if (iCurImage == NULL) {
318 		ilSetError(IL_ILLEGAL_OPERATION);
319 		return 0;
320 	}
321 	DestSize = Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type);
322 	if (DestSize == 0) {
323 		return DestSize;
324 	}
325 	if (Data == NULL || Format == IL_COLOUR_INDEX) {
326 		ilSetError(IL_INVALID_PARAM);
327 		return 0;
328 	}
329 	SrcSize = Width * Height * Depth * iCurImage->Bpp * iCurImage->Bpc;
330 
331 	if (Format == iCurImage->Format && Type == iCurImage->Type) {
332 		TempBuff = (ILubyte*)Data;
333 	}
334 	else {
335 		TempBuff = (ILubyte*)ialloc(SrcSize);
336 		if (TempBuff == NULL) {
337 			return 0;
338 		}
339 	}
340 
341 	if (YOff + Height <= 1) {
342 		if (!ilCopyPixels1D(XOff, Width, TempBuff)) {
343 			goto failed;
344 		}
345 	}
346 	else if (ZOff + Depth <= 1) {
347 		if (!ilCopyPixels2D(XOff, YOff, Width, Height, TempBuff)) {
348 			goto failed;
349 		}
350 	}
351 	else {
352 		if (!ilCopyPixels3D(XOff, YOff, ZOff, Width, Height, Depth, TempBuff)) {
353 			goto failed;
354 		}
355 	}
356 
357 	if (Format == iCurImage->Format && Type == iCurImage->Type) {
358 		return DestSize;
359 	}
360 
361 	Converted = ilConvertBuffer(SrcSize, iCurImage->Format, Format, iCurImage->Type, Type, &iCurImage->Pal, TempBuff);
362 	if (Converted == NULL)
363 		goto failed;
364 
365 	memcpy(Data, Converted, DestSize);
366 
367 	ifree(Converted);
368 	if (TempBuff != Data)
369 		ifree(TempBuff);
370 
371 	return DestSize;
372 
373 failed:
374 	if (TempBuff != Data)
375 		ifree(TempBuff);
376 	ifree(Converted);
377 	return 0;
378 }
379 
380 
ilSetPixels1D(ILint XOff,ILuint Width,void * Data)381 ILboolean ilSetPixels1D(ILint XOff, ILuint Width, void *Data)
382 {
383 	ILuint	c, SkipX = 0, PixBpp;
384 	ILint	x, NewWidth;
385 	ILubyte	*Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
386 
387 	if (ilIsEnabled(IL_ORIGIN_SET)) {
388 		if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
389 			TempData = iGetFlipped(iCurImage);
390 			if (TempData == NULL)
391 				return IL_FALSE;
392 		}
393 	}
394 
395 	PixBpp = iCurImage->Bpp * iCurImage->Bpc;
396 
397 	if (XOff < 0) {
398 		SkipX = abs(XOff);
399 		XOff = 0;
400 	}
401 
402 	if (iCurImage->Width < XOff + Width) {
403 		NewWidth = iCurImage->Width - XOff;
404 	}
405 	else {
406 		NewWidth = Width;
407 	}
408 
409 	NewWidth -= SkipX;
410 
411 	for (x = 0; x < NewWidth; x++) {
412 		for (c = 0; c < PixBpp; c++) {
413 			TempData[(x + XOff) * PixBpp + c] = Temp[(x + SkipX) * PixBpp + c];
414 		}
415 	}
416 
417 	if (TempData != iCurImage->Data) {
418 		ifree(iCurImage->Data);
419 		iCurImage->Data = TempData;
420 	}
421 
422 	return IL_TRUE;
423 }
424 
425 
ilSetPixels2D(ILint XOff,ILint YOff,ILuint Width,ILuint Height,void * Data)426 ILboolean ilSetPixels2D(ILint XOff, ILint YOff, ILuint Width, ILuint Height, void *Data)
427 {
428 	ILuint	c, SkipX = 0, SkipY = 0, NewBps, PixBpp;
429 	ILint	x, y, NewWidth, NewHeight;
430 	ILubyte	*Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
431 
432 	if (ilIsEnabled(IL_ORIGIN_SET)) {
433 		if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
434 			TempData = iGetFlipped(iCurImage);
435 			if (TempData == NULL)
436 				return IL_FALSE;
437 		}
438 	}
439 
440 	PixBpp = iCurImage->Bpp * iCurImage->Bpc;
441 
442 	if (XOff < 0) {
443 		SkipX = abs(XOff);
444 		XOff = 0;
445 	}
446 	if (YOff < 0) {
447 		SkipY = abs(YOff);
448 		YOff = 0;
449 	}
450 
451 	if (iCurImage->Width < XOff + Width)
452 		NewWidth = iCurImage->Width - XOff;
453 	else
454 		NewWidth = Width;
455 	NewBps = Width * PixBpp;
456 
457 	if (iCurImage->Height < YOff + Height)
458 		NewHeight = iCurImage->Height - YOff;
459 	else
460 		NewHeight = Height;
461 
462 	NewWidth -= SkipX;
463 	NewHeight -= SkipY;
464 
465 	for (y = 0; y < NewHeight; y++) {
466 		for (x = 0; x < NewWidth; x++) {
467 			for (c = 0; c < PixBpp; c++) {
468 				TempData[(y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] =
469 					Temp[(y + SkipY) * NewBps + (x + SkipX) * PixBpp + c];
470 			}
471 		}
472 	}
473 
474 	if (TempData != iCurImage->Data) {
475 		ifree(iCurImage->Data);
476 		iCurImage->Data = TempData;
477 	}
478 
479 	return IL_TRUE;
480 }
481 
482 
ilSetPixels3D(ILint XOff,ILint YOff,ILint ZOff,ILuint Width,ILuint Height,ILuint Depth,void * Data)483 ILboolean ilSetPixels3D(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, void *Data)
484 {
485 	ILuint	SkipX = 0, SkipY = 0, SkipZ = 0, c, NewBps, NewSizePlane, PixBpp;
486 	ILint	x, y, z, NewW, NewH, NewD;
487 	ILubyte	*Temp = (ILubyte*)Data, *TempData = iCurImage->Data;
488 
489 	if (ilIsEnabled(IL_ORIGIN_SET)) {
490 		if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) {
491 			TempData = iGetFlipped(iCurImage);
492 			if (TempData == NULL)
493 				return IL_FALSE;
494 		}
495 	}
496 
497 	PixBpp = iCurImage->Bpp * iCurImage->Bpc;
498 
499 	if (XOff < 0) {
500 		SkipX = abs(XOff);
501 		XOff = 0;
502 	}
503 	if (YOff < 0) {
504 		SkipY = abs(YOff);
505 		YOff = 0;
506 	}
507 	if (ZOff < 0) {
508 		SkipZ = abs(ZOff);
509 		ZOff = 0;
510 	}
511 
512 	if (iCurImage->Width < XOff + Width)
513 		NewW = iCurImage->Width - XOff;
514 	else
515 		NewW = Width;
516 	NewBps = Width * PixBpp;
517 
518 	if (iCurImage->Height < YOff + Height)
519 		NewH = iCurImage->Height - YOff;
520 	else
521 		NewH = Height;
522 
523 	if (iCurImage->Depth < ZOff + Depth)
524 		NewD = iCurImage->Depth - ZOff;
525 	else
526 		NewD = Depth;
527 	NewSizePlane = NewBps * Height;
528 
529 	NewW -= SkipX;
530 	NewH -= SkipY;
531 	NewD -= SkipZ;
532 
533 	for (z = 0; z < NewD; z++) {
534 		for (y = 0; y < NewH; y++) {
535 			for (x = 0; x < NewW; x++) {
536 				for (c = 0; c < PixBpp; c++) {
537 					TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] =
538 						Temp[(z + SkipZ) * NewSizePlane + (y + SkipY) * NewBps + (x + SkipX) * PixBpp + c];
539 				}
540 			}
541 		}
542 	}
543 
544 	if (TempData != iCurImage->Data) {
545 		ifree(iCurImage->Data);
546 		iCurImage->Data = TempData;
547 	}
548 
549 	return IL_TRUE;
550 }
551 
552 
ilSetPixels(ILint XOff,ILint YOff,ILint ZOff,ILuint Width,ILuint Height,ILuint Depth,ILenum Format,ILenum Type,void * Data)553 void ILAPIENTRY ilSetPixels(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data)
554 {
555 	void *Converted;
556 
557 	if (iCurImage == NULL) {
558 		ilSetError(IL_ILLEGAL_OPERATION);
559 		return;
560 	}
561 	if (Data == NULL) {
562 		ilSetError(IL_INVALID_PARAM);
563 		return;
564 	}
565 
566 	if (Format == iCurImage->Format && Type == iCurImage->Type) {
567 		Converted = (void*)Data;
568 	}
569 	else {
570 		Converted = ilConvertBuffer(Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type), Format, iCurImage->Format, Type, iCurImage->Type, NULL, Data);
571 		if (!Converted)
572 			return;
573 	}
574 
575 	if (YOff + Height <= 1) {
576 		ilSetPixels1D(XOff, Width, Converted);
577 	}
578 	else if (ZOff + Depth <= 1) {
579 		ilSetPixels2D(XOff, YOff, Width, Height, Converted);
580 	}
581 	else {
582 		ilSetPixels3D(XOff, YOff, ZOff, Width, Height, Depth, Converted);
583 	}
584 
585 	if (Format == iCurImage->Format && Type == iCurImage->Type) {
586 		return;
587 	}
588 
589 	if (Converted != Data)
590 		ifree(Converted);
591 
592 	return;
593 }
594 
595 
596 
597 //	Ripped from Platinum (Denton's sources)
598 //	This could very well easily be changed to a 128x128 image instead...needed?
599 
600 //! Creates an ugly 64x64 black and yellow checkerboard image.
ilDefaultImage()601 ILboolean ILAPIENTRY ilDefaultImage()
602 {
603 	ILubyte *TempData;
604 	ILubyte Yellow[3] = { 18, 246, 243 };
605 	ILubyte Black[3]  = { 0, 0, 0 };
606 	ILubyte *ColorPtr = Yellow;  // The start color
607 	ILboolean Color = IL_TRUE;
608 
609 	// Loop Variables
610 	ILint v, w, x, y;
611 
612 	if (iCurImage == NULL) {
613 		ilSetError(IL_ILLEGAL_OPERATION);
614 		return IL_FALSE;
615 	}
616 
617 	if (!ilTexImage(64, 64, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) {
618 		return IL_FALSE;
619 	}
620 	iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
621 	TempData = iCurImage->Data;
622 
623 	for (v = 0; v < 8; v++) {
624 		// We do this because after a "block" line ends, the next row of blocks
625 		// above starts with the ending colour, but the very inner loop switches them.
626 		if (Color) {
627 			Color = IL_FALSE;
628 			ColorPtr = Black;
629 		}
630 		else {
631 			Color = IL_TRUE;
632 			ColorPtr = Yellow;
633 		}
634 
635 		for (w = 0; w < 8; w++) {
636 			for (x = 0; x < 8; x++) {
637 				for (y = 0; y < 8; y++, TempData += iCurImage->Bpp) {
638 					TempData[0] = ColorPtr[0];
639 					TempData[1] = ColorPtr[1];
640 					TempData[2] = ColorPtr[2];
641 				}
642 
643 				// Switch to alternate between black and yellow
644 				if (Color) {
645 					Color = IL_FALSE;
646 					ColorPtr = Black;
647 				}
648 				else {
649 					Color = IL_TRUE;
650 					ColorPtr = Yellow;
651 				}
652 			}
653 		}
654 	}
655 
656 	return IL_TRUE;
657 }
658 
659 
ilGetAlpha(ILenum Type)660 ILubyte* ILAPIENTRY ilGetAlpha(ILenum Type)
661 {
662 	ILimage		*TempImage;
663 	ILubyte		*Alpha;
664 	ILushort	*AlphaShort;
665 	ILuint		*AlphaInt;
666 	ILdouble	*AlphaDbl;
667 	ILuint		i, j, Bpc, Size, AlphaOff;
668 
669 	if (iCurImage == NULL) {
670 		ilSetError(IL_ILLEGAL_OPERATION);
671 		return IL_FALSE;
672 	}
673 
674 	Bpc = ilGetBpcType(Type);
675 	if (Bpc == 0) {
676 		ilSetError(IL_INVALID_PARAM);
677 		return NULL;
678 	}
679 
680 	if (iCurImage->Type == Type) {
681 		TempImage = iCurImage;
682 	} else {
683 		TempImage = iConvertImage(iCurImage, iCurImage->Format, Type);
684 		if (TempImage == NULL)
685 			return NULL;
686 	}
687 
688 	Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * TempImage->Bpp;
689 	Alpha = (ILubyte*)ialloc(Size / TempImage->Bpp * Bpc);
690 	if (Alpha == NULL) {
691 		if (TempImage != iCurImage)
692 			ilCloseImage(TempImage);
693 		return NULL;
694 	}
695 
696 	switch (TempImage->Format)
697 	{
698 		case IL_RGB:
699 		case IL_BGR:
700 		case IL_LUMINANCE:
701 		case IL_COLOUR_INDEX:  // @TODO: Make IL_COLOUR_INDEX separate.
702 			memset(Alpha, 0xFF, Size / TempImage->Bpp * Bpc);
703 			if (TempImage != iCurImage)
704 				ilCloseImage(TempImage);
705 			return Alpha;
706 	}
707 
708 	// If our format is alpha, just return a copy.
709 	if (TempImage->Format == IL_ALPHA) {
710 		memcpy(Alpha, TempImage->Data, TempImage->SizeOfData);
711 		return Alpha;
712 	}
713 
714 	if (TempImage->Format == IL_LUMINANCE_ALPHA)
715 		AlphaOff = 2;
716 	else
717 		AlphaOff = 4;
718 
719 	switch (TempImage->Type)
720 	{
721 		case IL_BYTE:
722 		case IL_UNSIGNED_BYTE:
723 			for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
724 				Alpha[j] = TempImage->Data[i];
725 			break;
726 
727 		case IL_SHORT:
728 		case IL_UNSIGNED_SHORT:
729 			AlphaShort = (ILushort*)Alpha;
730 			for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
731 				AlphaShort[j] = ((ILushort*)TempImage->Data)[i];
732 			break;
733 
734 		case IL_INT:
735 		case IL_UNSIGNED_INT:
736 		case IL_FLOAT:  // Can throw float in here, because it's the same size.
737 			AlphaInt = (ILuint*)Alpha;
738 			for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
739 				AlphaInt[j] = ((ILuint*)TempImage->Data)[i];
740 			break;
741 
742 		case IL_DOUBLE:
743 			AlphaDbl = (ILdouble*)Alpha;
744 			for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
745 				AlphaDbl[j] = ((ILdouble*)TempImage->Data)[i];
746 			break;
747 	}
748 
749 	if (TempImage != iCurImage)
750 		ilCloseImage(TempImage);
751 
752 	return Alpha;
753 }
754 
755 // sets the Alpha value to a specific value for each pixel in the image
ilSetAlpha(ILdouble AlphaValue)756 ILboolean ILAPIENTRY ilSetAlpha(ILdouble AlphaValue)
757 {
758 	ILboolean	ret = IL_TRUE;
759 	ILuint		i,Size;
760 	ILimage		*Image = iCurImage;
761 	ILuint		AlphaOff;
762 
763 	if (Image == NULL) {
764 		ilSetError(IL_ILLEGAL_OPERATION);
765 		return IL_FALSE;
766 	}
767 
768 	AlphaValue = IL_CLAMP(AlphaValue);
769 
770 	switch (Image->Format)
771 	{
772 		case IL_RGB:
773 			ret = ilConvertImage(IL_RGBA, Image->Type);
774 		case IL_RGBA:
775 			AlphaOff = 4;
776 		break;
777 		case IL_BGR:
778 			ret = ilConvertImage(IL_BGRA, Image->Type);
779 		case IL_BGRA:
780 			AlphaOff = 4;
781 			break;
782 		case IL_LUMINANCE:
783 			ret = ilConvertImage(IL_LUMINANCE_ALPHA, Image->Type);
784 		case IL_LUMINANCE_ALPHA:
785 			AlphaOff = 2;
786 			break;
787 		case IL_ALPHA:
788 			AlphaOff = 1;
789 		case IL_COLOUR_INDEX: //@TODO use palette with alpha
790 			ret = ilConvertImage(IL_RGBA, Image->Type);
791 			AlphaOff = 4;
792 			break;
793 	}
794 	if (ret == IL_FALSE) {
795 		// Error has been set by ilConvertImage.
796 		return IL_FALSE;
797 	}
798 	Size = Image->Width * Image->Height * Image->Depth * Image->Bpp;
799 
800 	switch (iCurImage->Type)
801 	{
802 		case IL_BYTE:
803 		case IL_UNSIGNED_BYTE: {
804 			const ILbyte alpha = (ILubyte)(AlphaValue * IL_MAX_UNSIGNED_BYTE + .5);
805 			for (i = AlphaOff-1; i < Size; i += AlphaOff)
806 				Image->Data[i] = alpha;
807 			break;
808 		}
809 		case IL_SHORT:
810 		case IL_UNSIGNED_SHORT: {
811 			const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_SHORT + .5);
812 			for (i = AlphaOff-1; i < Size; i += AlphaOff)
813 				((ILushort*)Image->Data)[i] = alpha;
814 			break;
815 		}
816 		case IL_INT:
817 		case IL_UNSIGNED_INT: {
818 			const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_INT + .5);
819 			for (i = AlphaOff-1; i < Size; i += AlphaOff)
820 				((ILuint*)Image->Data)[i] = alpha;
821 			break;
822 		}
823 		case IL_FLOAT: {
824 			const ILfloat alpha = (ILfloat)AlphaValue;
825 			for (i = AlphaOff-1; i < Size; i += AlphaOff)
826 				((ILfloat*)Image->Data)[i] = alpha;
827 			break;
828 		}
829 		case IL_DOUBLE: {
830 			const ILdouble alpha  = AlphaValue;
831 			for (i = AlphaOff-1; i < Size; i += AlphaOff)
832 				((ILdouble*)Image->Data)[i] = alpha;
833 			break;
834 		}
835 	}
836 
837 	return IL_TRUE;
838 }
839 
ilModAlpha(ILdouble AlphaValue)840 void ILAPIENTRY ilModAlpha(ILdouble AlphaValue)
841 {
842     ILuint AlphaOff = 0;
843     ILboolean ret = IL_FALSE;
844     ILuint i,j,Size;
845 
846     union {
847         ILubyte alpha_byte;
848         ILushort alpha_short;
849         ILuint alpha_int;
850         ILfloat alpha_float;
851         ILdouble alpha_double;
852     } Alpha;
853 
854 
855     if (iCurImage == NULL) {
856         ilSetError(IL_ILLEGAL_OPERATION);
857         return;
858     }
859 
860     switch (iCurImage->Format)
861 	{
862             case IL_RGB:
863                 ret = ilConvertImage(IL_RGBA,iCurImage->Type);
864                 AlphaOff = 4;
865                 break;
866             case IL_BGR:
867                 ret = ilConvertImage(IL_BGRA,iCurImage->Type);
868                 AlphaOff = 4;
869                 break;
870             case IL_LUMINANCE:
871                 ret = ilConvertImage(IL_LUMINANCE_ALPHA,iCurImage->Type);
872                 AlphaOff = 2;
873                 break;
874             case IL_COLOUR_INDEX:
875                 ret = ilConvertImage(IL_RGBA,iCurImage->Type);
876                 AlphaOff = 4;
877                 break;
878     }
879     Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * iCurImage->Bpp;
880 
881     if (!ret)
882 		return;
883 
884     switch (iCurImage->Type)
885 	{
886         case IL_BYTE:
887         case IL_UNSIGNED_BYTE:
888             Alpha.alpha_byte = (ILubyte)(AlphaValue * 0x000000FF + .5);
889             for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
890                 iCurImage->Data[i] = Alpha.alpha_byte;
891             break;
892         case IL_SHORT:
893         case IL_UNSIGNED_SHORT:
894             Alpha.alpha_short = (ILushort)(AlphaValue * 0x0000FFFF + .5);
895             for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
896                 ((ILushort*)iCurImage->Data)[i] = Alpha.alpha_short;
897             break;
898         case IL_INT:
899         case IL_UNSIGNED_INT:
900             Alpha.alpha_int = (ILuint)(AlphaValue * 0xFFFFFFFF + .5);
901             for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
902                 ((ILuint*)iCurImage->Data)[i] = Alpha.alpha_int;
903             break;
904         case IL_FLOAT:
905             Alpha.alpha_float = (ILfloat)AlphaValue;
906             for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
907                 ((ILfloat*)iCurImage->Data)[i] = Alpha.alpha_float;
908             break;
909         case IL_DOUBLE:
910             Alpha.alpha_double = AlphaValue;
911             for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++)
912                 ((ILdouble*)iCurImage->Data)[i] = Alpha.alpha_double;
913             break;
914     }
915 
916 	return;
917 }
918 
919 
920 //! Clamps data values of unsigned bytes from 16 to 235 for display on an
921 //   NTSC television.  Reasoning for this is given at
922 //   http://msdn.microsoft.com/en-us/library/bb174608.aspx.
ilClampNTSC(void)923 ILboolean ILAPIENTRY ilClampNTSC(void)
924 {
925 	ILuint x, y, z, c;
926 	ILuint Offset = 0;
927 
928     if (iCurImage == NULL) {
929         ilSetError(IL_ILLEGAL_OPERATION);
930         return IL_FALSE;
931     }
932 
933 	if (iCurImage->Type != IL_UNSIGNED_BYTE)  // Should we set an error here?
934 		return IL_FALSE;
935 
936 	for (z = 0; z < iCurImage->Depth; z++) {
937 		for (y = 0; y < iCurImage->Height; y++) {
938 			for (x = 0; x < iCurImage->Width; x++) {
939 				for (c = 0; c < iCurImage->Bpp; c++) {
940 					iCurImage->Data[Offset + c] = IL_LIMIT(iCurImage->Data[Offset + c], 16, 235);
941 				}
942 			Offset += iCurImage->Bpp;
943 			}
944 		}
945 	}
946 
947 	return IL_TRUE;
948 }
949