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