1
//-----------------------------------------------------------------------------
3
// ImageLib Utility Sources
4
// Copyright (C) 2000-2002 by Denton Woods
5
// Last modified: 08/11/2001 <--Y2K Compliant! =]
7
// Filename: src-ILU/src/ilu_manip.c
9
// Description: Generates mipmaps for the current image
11
//-----------------------------------------------------------------------------
14
#include "ilu_internal.h"
15
#include "ilu_mipmap.h"
16
#include "ilu_states.h"
19
ILimage *Original; // So we can increment NumMips
22
// Note: If any image is a non-power-of-2 image, it will automatically be
23
// converted to a power-of-2 image by iluScaleImage, which is likely to
24
// uglify the image. =]
27
// @TODO: Check for 1 bpp textures!
30
// Currently changes all textures to powers of 2...should we change?
31
ILboolean iluBuild2DMipmaps()
34
ILboolean Resized = IL_FALSE;
38
iluCurImage = Original = ilGetCurImage();
39
if (Original == NULL) {
40
ilSetError(ILU_ILLEGAL_OPERATION);
44
// Get rid of any existing mipmaps.
45
if (Original->Mipmaps) {
46
ilCloseImage(Original->Mipmaps);
47
Original->Mipmaps = NULL;
49
Original->NumMips = 0;
51
Width = ilNextPower2(iluCurImage->Width);
52
Height = ilNextPower2(iluCurImage->Height);
53
if (iluCurImage->Width != Width || iluCurImage->Height != Height) {
55
Temp = ilCopyImage_(ilGetCurImage());
57
OldFilter = iluFilter;
58
iluImageParameter(ILU_FILTER, ILU_BILINEAR);
59
iluScale(Width, Height, 1);
60
iluImageParameter(ILU_FILTER, OldFilter);
61
iluCurImage = ilGetCurImage();
65
iBuild2DMipmaps_(iluCurImage->Width >> 1, iluCurImage->Height >> 1);
68
Original->Mipmaps = iluCurImage->Mipmaps;
69
iluCurImage->Mipmaps = NULL;
70
ilCloseImage(iluCurImage);
71
ilSetCurImage(Original);
78
ILboolean iluBuild3DMipmaps()
81
ILboolean Resized = IL_FALSE;
82
ILuint Width, Height, Depth;
84
iluCurImage = Original = ilGetCurImage();
85
if (Original == NULL) {
86
ilSetError(ILU_ILLEGAL_OPERATION);
90
// Get rid of any existing mipmaps.
91
if (Original->Mipmaps) {
92
ilCloseImage(Original->Mipmaps);
93
Original->Mipmaps = NULL;
95
Original->NumMips = 0;
97
Width = ilNextPower2(iluCurImage->Width);
98
Height = ilNextPower2(iluCurImage->Height);
99
Depth = ilNextPower2(iluCurImage->Depth);
100
if (iluCurImage->Width != Width || iluCurImage->Height != Height || iluCurImage->Depth != Depth) {
102
Temp = ilCopyImage_(ilGetCurImage());
104
iluImageParameter(ILU_FILTER, ILU_BILINEAR);
105
iluScale(Width, Height, Depth);
106
iluImageParameter(ILU_FILTER, iluFilter);
107
iluCurImage = ilGetCurImage();
111
iBuild3DMipmaps_(iluCurImage->Width >> 1, iluCurImage->Height >> 1, iluCurImage->Depth >> 1);
114
Original->Mipmaps = iluCurImage->Mipmaps;
115
iluCurImage->Mipmaps = NULL;
116
ilCloseImage(iluCurImage);
117
ilSetCurImage(Original);
124
ILboolean ILAPIENTRY iluBuildMipmaps()
126
iluCurImage = ilGetCurImage();
127
if (iluCurImage == NULL) {
128
ilSetError(ILU_ILLEGAL_OPERATION);
132
if (iluCurImage->Depth > 1)
133
return iluBuild3DMipmaps();
134
/*if (iluCurImage->Height <= 1)
135
return iluBuild1DMipmaps();*/ // 8-8-2001
136
return iluBuild2DMipmaps();
140
ILboolean iBuild1DMipmaps_(ILuint Width)
145
if (CurMipMap->Width <= 1) { // Already at the last mipmap
146
CurMipMap->Next = NULL; // Terminate the list
150
MipMap = ilNewImage(Width, 1, 1, iluCurImage->Bpp, iluCurImage->Bpc);
151
if (MipMap == NULL) {
152
if (CurMipMap != NULL)
153
CurMipMap->Next = NULL;
158
MipMap->Origin = iluCurImage->Origin; // 8-11-2001
159
MipMap->Format = iluCurImage->Format;
160
MipMap->Type = iluCurImage->Type;
161
MipMap->Pal.PalSize = iluCurImage->Pal.PalSize;
162
MipMap->Pal.PalType = iluCurImage->Pal.PalType;
163
if (iluCurImage->Pal.Palette && MipMap->Pal.PalSize > 0 && MipMap->Pal.PalType != IL_PAL_NONE) {
164
MipMap->Pal.Palette = (ILubyte*)ialloc(iluCurImage->Pal.PalSize);
165
if (MipMap->Pal.Palette == NULL) {
166
ilCloseImage(MipMap);
169
memcpy(MipMap->Pal.Palette, iluCurImage->Pal.Palette, MipMap->Pal.PalSize);
172
if (CurMipMap == NULL) { // First mipmap
173
iluCurImage->Mipmaps = MipMap;
176
CurMipMap->Next = MipMap;
179
for (c = 0; c < CurMipMap->Bpp; c++) { // 8-12-2001
180
for (i = 0, j = 0; i < Width; i++) {
181
MipMap->Data[i * MipMap->Bpp + c] = CurMipMap->Data[(j++ * MipMap->Bpp) + c];
182
MipMap->Data[i * MipMap->Bpp + c] += CurMipMap->Data[(j++ * MipMap->Bpp) + c];
183
MipMap->Data[i * MipMap->Bpp + c] >>= 1;
188
iBuild1DMipmaps_(MipMap->Width >> 1);
195
ILboolean iBuild1DMipmapsVertical_(ILuint Height)
197
ILimage *MipMap, *Src;
198
ILuint i = 0, j = 0, c;
200
if (CurMipMap->Height <= 1) { // Already at the last mipmap
201
CurMipMap->Next = NULL; // Terminate the list
205
MipMap = ilNewImage(1, Height, 1, iluCurImage->Bpp, iluCurImage->Bpc);
206
if (MipMap == NULL) {
207
if (CurMipMap != NULL)
208
CurMipMap->Next = NULL;
213
MipMap->Origin = iluCurImage->Origin; // 8-11-2001
214
MipMap->Format = iluCurImage->Format;
215
MipMap->Type = iluCurImage->Type;
216
MipMap->Pal.PalSize = iluCurImage->Pal.PalSize;
217
MipMap->Pal.PalType = iluCurImage->Pal.PalType;
218
if (iluCurImage->Pal.Palette && MipMap->Pal.PalSize > 0 && MipMap->Pal.PalType != IL_PAL_NONE) {
219
MipMap->Pal.Palette = (ILubyte*)ialloc(iluCurImage->Pal.PalSize);
220
if (MipMap->Pal.Palette == NULL) {
221
ilCloseImage(MipMap);
224
memcpy(MipMap->Pal.Palette, iluCurImage->Pal.Palette, MipMap->Pal.PalSize);
227
if (CurMipMap == NULL) { // First mipmap
228
iluCurImage->Mipmaps = MipMap;
232
CurMipMap->Next = MipMap;
236
for (c = 0; c < CurMipMap->Bpp; c++) { // 8-12-2001
238
for (i = 0, j = 0; i < Height; i++) {
239
MipMap->Data[i * MipMap->Bpp + c] = CurMipMap->Data[(j++ * MipMap->Bpp) + c];
240
MipMap->Data[i * MipMap->Bpp + c] += CurMipMap->Data[(j++ * MipMap->Bpp) + c];
241
MipMap->Data[i * MipMap->Bpp + c] >>= 1;
246
iBuild1DMipmapsVertical_(MipMap->Height >> 1);
253
ILboolean iBuild2DMipmaps_(ILuint Width, ILuint Height)
255
ILimage *MipMap, *Src;
256
ILuint x1 = 0, x2 = 0, y1 = 0, y2 = 0, c;
259
if (CurMipMap->Width == 1 && CurMipMap->Height == 1) { // Already at the last mipmap
260
CurMipMap->Next = NULL; // Terminate the list
264
if (/*CurMipMap->*/Height == 1) {
265
return iBuild1DMipmaps_(Width);
268
if (/*CurMipMap->*/Width == 1) {
269
return iBuild1DMipmapsVertical_(Height);
272
else if (iluCurImage->Width <= 1 && iluCurImage->Height <= 1) { // 8-9-2001 - Not sure...
273
ilSetError(ILU_ILLEGAL_OPERATION);
277
if (Height == 0 && Width == 0) {
278
ilSetError(ILU_INTERNAL_ERROR);
281
// 8-9-2001 - Should these two if statements read == 0 || == 1?
283
return iBuild1DMipmaps_(Width);
286
return iBuild1DMipmapsVertical_(Height); // 8-9-2001
289
MipMap = ilNewImage(Width, Height, 1, iluCurImage->Bpp, iluCurImage->Bpc);
290
if (MipMap == NULL) {
291
if (CurMipMap != NULL)
292
CurMipMap->Next = NULL;
297
MipMap->Origin = iluCurImage->Origin; // 8-11-2001
298
MipMap->Format = iluCurImage->Format;
299
MipMap->Type = iluCurImage->Type;
300
MipMap->Pal.PalSize = iluCurImage->Pal.PalSize;
301
MipMap->Pal.PalType = iluCurImage->Pal.PalType;
302
if (iluCurImage->Pal.Palette && MipMap->Pal.PalSize > 0 && MipMap->Pal.PalType != IL_PAL_NONE) {
303
MipMap->Pal.Palette = (ILubyte*)ialloc(iluCurImage->Pal.PalSize);
304
if (MipMap->Pal.Palette == NULL) {
305
ilCloseImage(MipMap);
308
memcpy(MipMap->Pal.Palette, iluCurImage->Pal.Palette, MipMap->Pal.PalSize);
311
if (CurMipMap == NULL) { // First mipmap
312
iluCurImage->Mipmaps = MipMap;
316
CurMipMap->Next = MipMap;
320
if (MipMap->Type == IL_FLOAT) {
321
ILfloat *DestFData = (ILfloat*)MipMap->Data;
322
ILfloat *SrcFData = (ILfloat*)Src->Data;
323
ILuint DestStride = MipMap->Bps / 4;
324
ILuint SrcStride = Src->Bps / 4;
325
for (y1 = 0; y1 < Height; y1++, y2 += 2) {
327
for (; x1 < Width; x1++, x2 += 2) {
328
for (c = 0; c < MipMap->Bpp; c++) {
329
DestFData[y1 * DestStride + x1 * MipMap->Bpp + c] = (
330
SrcFData[y2 * SrcStride + x2 * MipMap->Bpp + c] +
331
SrcFData[y2 * SrcStride + (x2 + 1) * MipMap->Bpp + c] +
332
SrcFData[(y2 + 1) * SrcStride + x2 * MipMap->Bpp + c] +
333
SrcFData[(y2 + 1) * SrcStride + (x2 + 1) * MipMap->Bpp + c]) * .25f;
339
for (y1 = 0; y1 < Height; y1++, y2 += 2) {
341
for (; x1 < Width; x1++, x2 += 2) {
342
for (c = 0; c < MipMap->Bpp; c++) {
343
MipMap->Data[y1 * MipMap->Bps + x1 * MipMap->Bpp + c] = (
344
Src->Data[y2 * Src->Bps + x2 * MipMap->Bpp + c] +
345
Src->Data[y2 * Src->Bps + (x2 + 1) * MipMap->Bpp + c] +
346
Src->Data[(y2 + 1) * Src->Bps + x2 * MipMap->Bpp + c] +
347
Src->Data[(y2 + 1) * Src->Bps + (x2 + 1) * MipMap->Bpp + c]) >> 2;
354
iBuild2DMipmaps_(MipMap->Width >> 1, MipMap->Height >> 1);
361
ILboolean iBuild3DMipmaps_(ILuint Width, ILuint Height, ILuint Depth)
363
ILimage *MipMap, *Src;
364
ILuint x1 = 0, x2 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0, z3, z4, z5, c;
367
// Already at the last mipmap
368
if (CurMipMap->Width == 1 && CurMipMap->Height == 1 && CurMipMap->Depth == 1) {
369
CurMipMap->Next = NULL; // Terminate the list
373
if (CurMipMap->Depth == 1) {
374
return iBuild2DMipmaps_(Width, Height);
376
if (CurMipMap->Height == 1) {
377
return iBuild3DMipmapsHorizontal_(Width, Depth);
380
if (CurMipMap->Width == 1) {
381
return iBuild3DMipmapsVertical_(Height, Depth);
384
else if (iluCurImage->Width <= 1 && iluCurImage->Height <= 1 && iluCurImage->Height <= 1) {
385
ilSetError(ILU_ILLEGAL_OPERATION);
389
if (Height == 0 && Width == 0 && Depth == 0) {
390
ilSetError(ILU_INTERNAL_ERROR);
394
return iBuild2DMipmaps_(Width, Height);
397
return iBuild3DMipmapsHorizontal_(Width, Depth);
400
return iBuild3DMipmapsVertical_(Height, Depth);
403
MipMap = ilNewImage(Width, Height, Depth, iluCurImage->Bpp, iluCurImage->Bpc);
404
if (MipMap == NULL) {
405
if (CurMipMap != NULL)
406
CurMipMap->Next = NULL;
411
MipMap->Origin = iluCurImage->Origin; // 8-11-2001
412
MipMap->Format = iluCurImage->Format;
413
MipMap->Type = iluCurImage->Type;
414
MipMap->Pal.PalSize = iluCurImage->Pal.PalSize;
415
MipMap->Pal.PalType = iluCurImage->Pal.PalType;
416
if (iluCurImage->Pal.Palette && MipMap->Pal.PalSize > 0 && MipMap->Pal.PalType != IL_PAL_NONE) {
417
MipMap->Pal.Palette = (ILubyte*)ialloc(iluCurImage->Pal.PalSize);
418
if (MipMap->Pal.Palette == NULL) {
419
ilCloseImage(MipMap);
422
memcpy(MipMap->Pal.Palette, iluCurImage->Pal.Palette, MipMap->Pal.PalSize);
425
if (CurMipMap == NULL) { // First mipmap
426
iluCurImage->Mipmaps = MipMap;
430
CurMipMap->Next = MipMap;
434
for (z1 = 0; z1 < Depth; z1++, z2 += 2) {
435
z3 = z1 * MipMap->SizeOfPlane;
436
z4 = z2 * Src->SizeOfPlane;
437
z5 = (z2 + 1) * Src->SizeOfPlane;
440
for (; y1 < Height; y1++, y2 += 2) {
442
for (; x1 < Width; x1++, x2 += 2) {
443
for (c = 0; c < MipMap->Bpp; c++) {
444
MipMap->Data[z1 * MipMap->SizeOfPlane + y1 * MipMap->Bps + x1 * MipMap->Bpp + c] = (
445
Src->Data[z2 * Src->SizeOfPlane + y2 * Src->Bps + x2 * Src->Bpp + c] +
446
Src->Data[z2 * Src->SizeOfPlane + y2 * Src->Bps + (x2 + 1) * Src->Bpp + c] +
447
Src->Data[z2 * Src->SizeOfPlane + (y2 + 1) * Src->Bps + x2 * Src->Bpp + c] +
448
Src->Data[z2 * Src->SizeOfPlane + (y2 + 1) * Src->Bps + (x2 + 1) * Src->Bpp + c] +
449
Src->Data[(z2 + 1) * Src->SizeOfPlane + y2 * Src->Bps + x2 * Src->Bpp + c] +
450
Src->Data[(z2 + 1) * Src->SizeOfPlane + y2 * Src->Bps + (x2 + 1) * Src->Bpp + c] +
451
Src->Data[(z2 + 1) * Src->SizeOfPlane + (y2 + 1) * Src->Bps + x2 * Src->Bpp + c] +
452
Src->Data[(z2 + 1) * Src->SizeOfPlane + (y2 + 1) * Src->Bps + (x2 + 1) * Src->Bpp + c]) / 8;
459
iBuild3DMipmaps_(MipMap->Width >> 1, MipMap->Height >> 1, MipMap->Depth >> 1);
466
ILboolean iBuild3DMipmapsVertical_(ILuint Height, ILuint Depth)
468
ILimage *MipMap, *Src;
469
ILuint y1 = 0, y2 = 0, z1 = 0, z2 = 0, z3, z4, z5, c;
472
// Already at the last mipmap
473
if (CurMipMap->Width == 1 && CurMipMap->Height == 1 && CurMipMap->Depth == 1) {
474
CurMipMap->Next = NULL; // Terminate the list
478
if (CurMipMap->Depth == 1) {
479
return iBuild1DMipmapsVertical_(Height);
482
else if (iluCurImage->Height <= 1 && iluCurImage->Height <= 1) {
483
ilSetError(ILU_ILLEGAL_OPERATION);
487
if (Height == 0 && Depth == 0) {
488
ilSetError(ILU_INTERNAL_ERROR);
492
return iBuild1DMipmapsVertical_(Height);
495
MipMap = ilNewImage(1, Height, Depth, iluCurImage->Bpp, iluCurImage->Bpc);
496
if (MipMap == NULL) {
497
if (CurMipMap != NULL)
498
CurMipMap->Next = NULL;
503
MipMap->Format = iluCurImage->Format;
504
MipMap->Type = iluCurImage->Type;
505
MipMap->Pal.PalSize = iluCurImage->Pal.PalSize;
506
MipMap->Pal.PalType = iluCurImage->Pal.PalType;
507
if (iluCurImage->Pal.Palette && MipMap->Pal.PalSize > 0 && MipMap->Pal.PalType != IL_PAL_NONE) {
508
MipMap->Pal.Palette = (ILubyte*)ialloc(iluCurImage->Pal.PalSize);
509
if (MipMap->Pal.Palette == NULL) {
510
ilCloseImage(MipMap);
513
memcpy(MipMap->Pal.Palette, iluCurImage->Pal.Palette, MipMap->Pal.PalSize);
516
if (CurMipMap == NULL) { // First mipmap
517
iluCurImage->Mipmaps = MipMap;
521
CurMipMap->Next = MipMap;
525
for (z1 = 0; z1 < Depth; z1++, z2 += 2) {
526
z3 = z1 * iluCurImage->SizeOfPlane;
527
z4 = z2 * iluCurImage->SizeOfPlane;
528
z5 = (z2 + 1) * iluCurImage->SizeOfPlane;
530
for (y1 = 0; y1 < Height; y1++, y2 += 2) {
531
for (c = 0; c < MipMap->Bpp; c++) {
532
MipMap->Data[z3 + y1 * MipMap->Bps + c] = (
533
Src->Data[z4 + y2 * Src->Bps + c] +
534
Src->Data[z4 + y2 * Src->Bps + c] +
535
Src->Data[z4 + (y2 + 1) * Src->Bps + c] +
536
Src->Data[z4 + (y2 + 1) * Src->Bps + c]) >> 2;
542
iBuild3DMipmapsVertical_(MipMap->Height >> 1, MipMap->Depth >> 1);
549
ILboolean iBuild3DMipmapsHorizontal_(ILuint Width, ILuint Depth)
551
ILimage *MipMap, *Src;
552
ILuint x1 = 0, x2 = 0, z1 = 0, z2 = 0, z3, z4, z5, c;
555
// Already at the last mipmap
556
if (CurMipMap->Width == 1 && CurMipMap->Height == 1 && CurMipMap->Depth == 1) {
557
CurMipMap->Next = NULL; // Terminate the list
561
if (CurMipMap->Depth == 1) {
562
return iBuild1DMipmaps_(Width);
565
else if (iluCurImage->Width <= 1 && iluCurImage->Height <= 1) {
566
ilSetError(ILU_ILLEGAL_OPERATION);
570
if (Width == 0 && Depth == 0) {
571
ilSetError(ILU_INTERNAL_ERROR);
575
return iBuild1DMipmaps_(Width);
578
MipMap = ilNewImage(Width, 1, Depth, iluCurImage->Bpp, iluCurImage->Bpc);
579
if (MipMap == NULL) {
580
if (CurMipMap != NULL)
581
CurMipMap->Next = NULL;
586
MipMap->Format = iluCurImage->Format;
587
MipMap->Type = iluCurImage->Type;
588
MipMap->Pal.PalSize = iluCurImage->Pal.PalSize;
589
MipMap->Pal.PalType = iluCurImage->Pal.PalType;
590
if (iluCurImage->Pal.Palette && MipMap->Pal.PalSize > 0 && MipMap->Pal.PalType != IL_PAL_NONE) {
591
MipMap->Pal.Palette = (ILubyte*)ialloc(iluCurImage->Pal.PalSize);
592
if (MipMap->Pal.Palette == NULL) {
593
ilCloseImage(MipMap);
596
memcpy(MipMap->Pal.Palette, iluCurImage->Pal.Palette, MipMap->Pal.PalSize);
599
if (CurMipMap == NULL) { // First mipmap
600
iluCurImage->Mipmaps = MipMap;
604
CurMipMap->Next = MipMap;
608
for (z1 = 0; z1 < Depth; z1++, z2 += 2) {
609
z3 = z1 * iluCurImage->SizeOfPlane;
610
z4 = z2 * iluCurImage->SizeOfPlane;
611
z5 = (z2 + 1) * iluCurImage->SizeOfPlane;
614
for (; x1 < Width; x1++, x2 += 2) {
615
for (c = 0; c < MipMap->Bpp; c++) {
616
MipMap->Data[z3 + x1 * MipMap->Bpp + c] = (
617
Src->Data[z4 + x2 * MipMap->Bpp + c] +
618
Src->Data[z4 + (x2 + 1) * MipMap->Bpp + c] +
619
Src->Data[z4 + x2 * MipMap->Bpp + c] +
620
Src->Data[z4 + (x2 + 1) * MipMap->Bpp + c]) >> 2;
626
iBuild3DMipmapsHorizontal_(MipMap->Width >> 1, MipMap->Depth >> 1);