1
//-----------------------------------------------------------------------------
4
// Copyright (C) 2000-2002 by Denton Woods
5
// Last modified: 02/21/2002 <--Y2K Compliant! =]
7
// Filename: src-IL/src/il_dds.c
9
// Description: Reads from a DirectDraw Surface (.dds) file.
11
//-----------------------------------------------------------------------------
16
// Note: Almost all this code is from nVidia's DDS-loading example at
17
// http://www.nvidia.com/view.asp?IO=dxtc_decompression_code
18
// and from the specs at
19
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/hh/dx8_c/graphics_using_0j03.asp
21
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/ProgrammersGuide/Appendix/DDSFileFormat/ovwDDSFileFormat.asp
22
// However, some not really valid .dds files are also read, for example
23
// Volume Textures without the COMPLEX bit set, so the specs aren't taken
24
// too strictly while reading.
27
#include "il_internal.h"
33
DDSHEAD Head; // Image header
34
ILubyte *CompData; // Compressed data
35
ILuint CompSize; // Compressed size
36
ILuint CompLineSize; // Compressed line size
37
ILuint CompFormat; // Compressed format
39
ILint Width, Height, Depth;
42
ILuint CubemapDirections[CUBEMAP_SIDES] = {
43
DDS_CUBEMAP_POSITIVEX,
44
DDS_CUBEMAP_NEGATIVEX,
45
DDS_CUBEMAP_POSITIVEY,
46
DDS_CUBEMAP_NEGATIVEY,
47
DDS_CUBEMAP_POSITIVEZ,
52
//! Checks if the file specified in FileName is a valid .dds file.
53
ILboolean ilIsValidDds(const ILstring FileName)
56
ILboolean bDds = IL_FALSE;
58
if (!iCheckExtension(FileName, IL_TEXT("dds"))) {
59
ilSetError(IL_INVALID_EXTENSION);
63
DdsFile = iopenr(FileName);
64
if (DdsFile == NULL) {
65
ilSetError(IL_COULD_NOT_OPEN_FILE);
69
bDds = ilIsValidDdsF(DdsFile);
76
//! Checks if the ILHANDLE contains a valid .dds file at the current position.
77
ILboolean ilIsValidDdsF(ILHANDLE File)
85
iseek(FirstPos, IL_SEEK_SET);
91
//! Checks if Lump is a valid .dds lump.
92
ILboolean ilIsValidDdsL(ILvoid *Lump, ILuint Size)
94
iSetInputLump(Lump, Size);
99
// Internal function used to get the .dds header from the current file.
100
ILboolean iGetDdsHead(DDSHEAD *Header)
102
if (iread(Header, sizeof(DDSHEAD), 1) != 1)
106
Int(&Header->Flags1);
107
Int(&Header->Height);
109
Int(&Header->LinearSize);
111
Int(&Header->MipMapCount);
112
Int(&Header->AlphaBitDepth);
114
Int(&Header->Flags2);
115
Int(&Header->FourCC);
116
Int(&Header->RGBBitCount);
117
Int(&Header->RBitMask);
118
Int(&Header->GBitMask);
119
Int(&Header->BBitMask);
120
Int(&Header->RGBAlphaBitMask);
121
Int(&Header->ddsCaps1);
122
Int(&Header->ddsCaps2);
123
Int(&Header->ddsCaps3);
124
Int(&Header->ddsCaps4);
125
Int(&Header->TextureStage);
134
// Internal function to get the header and check it.
135
ILboolean iIsValidDds()
141
iseek(-(ILint)sizeof(DDSHEAD), IL_SEEK_CUR); // Go ahead and restore to previous state
143
IsValid = iCheckDds(&Head);
149
// Internal function used to check if the HEADER is a valid .dds header.
150
ILboolean iCheckDds(DDSHEAD *Head)
152
if (strnicmp(Head->Signature, "DDS ", 4))
154
if (Head->Size1 != 124)
156
if (Head->Size2 != 32)
158
if (Head->Width == 0 || Head->Height == 0)
164
//! Reads a .dds file
165
ILboolean ilLoadDds(const ILstring FileName)
168
ILboolean bDds = IL_FALSE;
170
DdsFile = iopenr(FileName);
171
if (DdsFile == NULL) {
172
ilSetError(IL_COULD_NOT_OPEN_FILE);
176
bDds = ilLoadDdsF(DdsFile);
183
//! Reads an already-opened .dds file
184
ILboolean ilLoadDdsF(ILHANDLE File)
191
bRet = iLoadDdsInternal();
192
iseek(FirstPos, IL_SEEK_SET);
198
//! Reads from a memory "lump" that contains a .dds
199
ILboolean ilLoadDdsL(ILvoid *Lump, ILuint Size)
201
iSetInputLump(Lump, Size);
202
return iLoadDdsInternal();
206
ILboolean iLoadDdsCubemapInternal()
214
if (CompFormat == PF_RGB || CompFormat == PF_3DC)
220
// run through cube map possibilities
221
for (i = 0; i < CUBEMAP_SIDES; i++) {
224
Height = Head.Height;
226
if (Head.ddsCaps2 & CubemapDirections[i]) {
228
Image->Next = ilNewImage(Width, Height, Depth, Bpp, 1);
229
if (Image->Next == NULL)
233
startImage->NumNext++;
234
ilBindImage(ilGetCurName()); // Set to parent image first.
238
Image->CubeFlags = CubemapDirections[i];
255
if (!ReadMipmaps()) {
268
ilBindImage(ilGetCurName()); // Set to parent image first.
273
ILboolean iLoadDdsInternal()
277
if (iCurImage == NULL) {
278
ilSetError(IL_ILLEGAL_OPERATION);
282
if (!iGetDdsHead(&Head)) {
283
ilSetError(IL_INVALID_FILE_HEADER);
286
if(!iCheckDds(&Head)) {
287
ilSetError(IL_INVALID_FILE_HEADER);
292
if (CompFormat == PF_UNKNOWN) {
293
ilSetError(IL_INVALID_FILE_HEADER);
296
/*else if (CompFormat == PF_3DC) {
297
ilSetError(IL_FORMAT_NOT_SUPPORTED);
300
// Microsoft bug, they're not following their own documentation.
301
if (!(Head.Flags1 & (DDS_LINEARSIZE | DDS_PITCH))) {
302
Head.Flags1 |= DDS_LINEARSIZE;
303
Head.LinearSize = BlockSize;
307
if (Head.ddsCaps1 & DDS_COMPLEX) {
308
if (Head.ddsCaps2 & DDS_CUBEMAP) {
309
if (!iLoadDdsCubemapInternal())
315
Height = Head.Height;
318
AdjustVolumeTexture(&Head);
333
if (!ReadMipmaps()) {
342
ilBindImage(ilGetCurName()); // Set to parent image first.
347
ILvoid DecodePixelFormat()
349
if (Head.Flags2 & DDS_FOURCC) {
350
BlockSize = ((Head.Width + 3)/4) * ((Head.Height + 3)/4) * ((Head.Depth + 3)/4);
353
case IL_MAKEFOURCC('D','X','T','1'):
354
CompFormat = PF_DXT1;
358
case IL_MAKEFOURCC('D','X','T','2'):
359
CompFormat = PF_DXT2;
363
case IL_MAKEFOURCC('D','X','T','3'):
364
CompFormat = PF_DXT3;
368
case IL_MAKEFOURCC('D','X','T','4'):
369
CompFormat = PF_DXT4;
373
case IL_MAKEFOURCC('D','X','T','5'):
374
CompFormat = PF_DXT5;
378
case IL_MAKEFOURCC('A', 'T', 'I', '2'):
384
CompFormat = PF_UNKNOWN;
389
// This dds texture isn't compressed so write out ARGB format
390
if (Head.Flags2 & DDS_ALPHAPIXELS) {
391
CompFormat = PF_ARGB;
395
BlockSize = (Head.Width * Head.Height * Head.Depth * (Head.RGBBitCount >> 3));
401
// The few volume textures that I have don't have consistent LinearSize
402
// entries, even thouh the DDS_LINEARSIZE flag is set.
403
ILvoid AdjustVolumeTexture(DDSHEAD *Head)
405
if (Head->Depth <= 1)
408
// All volume textures I've seem so far didn't have the DDS_COMPLEX flag set,
409
// even though this is normally required. But because noone does set it,
410
// also read images without it (TODO: check file size for 3d texture?)
411
if (/*!(Head->ddsCaps1 & DDS_COMPLEX) ||*/ !(Head->ddsCaps2 & DDS_VOLUME)) {
420
Head->LinearSize = IL_MAX(1,Head->Width) * IL_MAX(1,Head->Height) *
421
(Head->RGBBitCount / 8);
425
Head->LinearSize = IL_MAX(1,Head->Width/4) * IL_MAX(1,Head->Height/4) * 8;
433
Head->LinearSize = IL_MAX(1,Head->Width/4) * IL_MAX(1,Head->Height/4) * 16;
437
Head->Flags1 |= DDS_LINEARSIZE;
438
Head->LinearSize *= Head->Depth;
444
// Reads the compressed data
452
if (CompFormat == PF_RGB || CompFormat == PF_3DC)
462
if (Head.Flags1 & DDS_LINEARSIZE) {
463
//Head.LinearSize = Head.LinearSize * Depth;
465
CompData = (ILubyte*)ialloc(Head.LinearSize);
466
if (CompData == NULL) {
470
if (iread(CompData, 1, Head.LinearSize) != (ILuint)Head.LinearSize) {
476
Bps = Width * Head.RGBBitCount / 8;
477
CompSize = Bps * Height * Depth;
480
CompData = (ILubyte*)ialloc(CompSize);
481
if (CompData == NULL) {
486
for (z = 0; z < Depth; z++) {
487
for (y = 0; y < Height; y++) {
488
if (iread(Temp, 1, Bps) != Bps) {
501
ILboolean AllocImage()
506
if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL))
510
if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL))
514
//right now there's no OpenGL api to use the compressed 3dc data, so
515
//throw it away (I don't know how DirectX works, though)?
516
if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL))
520
if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL))
522
if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) {
523
iCurImage->DxtcData = (ILubyte*)ialloc(Head.LinearSize);
524
if (iCurImage->DxtcData == NULL)
526
iCurImage->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1;
527
iCurImage->DxtcSize = Head.LinearSize;
528
memcpy(iCurImage->DxtcData, CompData, iCurImage->DxtcSize);
533
Image->Origin = IL_ORIGIN_UPPER_LEFT;
539
ILboolean Decompress()
545
return DecompressARGB();
548
return DecompressDXT1();
551
return DecompressDXT2();
554
return DecompressDXT3();
557
return DecompressDXT4();
560
return DecompressDXT5();
563
return Decompress3Dc();
573
ILboolean ReadMipmaps()
575
ILuint i, CompFactor=0;
577
ILimage *StartImage, *TempImage;
581
if (CompFormat == PF_RGB || CompFormat == PF_3DC)
586
if (Head.Flags1 & DDS_LINEARSIZE) {
587
CompFactor = (Width * Height * Depth * Bpp) / Head.LinearSize;
592
if (!(Head.Flags1 & DDS_MIPMAPCOUNT) || Head.MipMapCount == 0) {
593
//some .dds-files have their mipmap flag set,
594
//but a mipmapcount of 0. Because mipMapCount is an uint, 0 - 1 gives
595
//overflow - don't let this happen:
596
Head.MipMapCount = 1;
599
LastLinear = Head.LinearSize;
600
for (i = 0; i < Head.MipMapCount - 1; i++) {
612
//TODO: mipmaps don't keep DXT data???
613
Image->Next = ilNewImage(Width, Height, Depth, Bpp, 1);
614
if (Image->Next == NULL)
617
Image->Origin = IL_ORIGIN_UPPER_LEFT;
619
if (Head.Flags1 & DDS_LINEARSIZE) {
622
if ((CompFormat != PF_RGB) && (CompFormat != PF_ARGB)) {
623
minW = IL_MAX(4, Width);
624
minH = IL_MAX(4, Height);
625
Head.LinearSize = (minW * minH * Depth * Bpp) / CompFactor;
628
Head.LinearSize = Width * Height * Depth * (Head.RGBBitCount >> 3);
632
Head.LinearSize >>= 1;
641
Head.LinearSize = LastLinear;
642
StartImage->Mipmaps = StartImage->Next;
643
StartImage->Next = NULL;
644
StartImage->NumMips = Head.MipMapCount - 1;
651
StartImage = StartImage->Next;
653
TempImage = StartImage;
654
StartImage = StartImage->Next;
661
ILboolean DecompressDXT1()
663
int x, y, z, i, j, k, Select;
665
Color565 *color_0, *color_1;
666
Color8888 colours[4], *col;
667
ILuint bitmask, Offset;
671
for (z = 0; z < Depth; z++) {
672
for (y = 0; y < Height; y += 4) {
673
for (x = 0; x < Width; x += 4) {
675
color_0 = ((Color565*)Temp);
676
color_1 = ((Color565*)(Temp+2));
677
bitmask = ((ILuint*)Temp)[1];
680
colours[0].r = color_0->nRed << 3;
681
colours[0].g = color_0->nGreen << 2;
682
colours[0].b = color_0->nBlue << 3;
685
colours[1].r = color_1->nRed << 3;
686
colours[1].g = color_1->nGreen << 2;
687
colours[1].b = color_1->nBlue << 3;
691
if (*((ILushort*)color_0) > *((ILushort*)color_1)) {
692
// Four-color block: derive the other two colors.
693
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
694
// These 2-bit codes correspond to the 2-bit fields
695
// stored in the 64-bit block.
696
colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
697
colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
698
colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
701
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
702
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
703
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
707
// Three-color block: derive the other color.
708
// 00 = color_0, 01 = color_1, 10 = color_2,
710
// These 2-bit codes correspond to the 2-bit fields
711
// stored in the 64-bit block.
712
colours[2].b = (colours[0].b + colours[1].b) / 2;
713
colours[2].g = (colours[0].g + colours[1].g) / 2;
714
colours[2].r = (colours[0].r + colours[1].r) / 2;
717
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
718
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
719
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
723
for (j = 0, k = 0; j < 4; j++) {
724
for (i = 0; i < 4; i++, k++) {
726
Select = (bitmask & (0x03 << k*2)) >> k*2;
727
col = &colours[Select];
729
if (((x + i) < Width) && ((y + j) < Height)) {
730
Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp;
731
Image->Data[Offset + 0] = col->r;
732
Image->Data[Offset + 1] = col->g;
733
Image->Data[Offset + 2] = col->b;
734
Image->Data[Offset + 3] = col->a;
746
ILboolean DecompressDXT2()
748
// Can do color & alpha same as dxt3, but color is pre-multiplied
749
// so the result will be wrong unless corrected.
750
if (!DecompressDXT3())
758
ILboolean DecompressDXT3()
760
int x, y, z, i, j, k, Select;
762
Color565 *color_0, *color_1;
763
Color8888 colours[4], *col;
764
ILuint bitmask, Offset;
766
DXTAlphaBlockExplicit *alpha;
770
for (z = 0; z < Depth; z++) {
771
for (y = 0; y < Height; y += 4) {
772
for (x = 0; x < Width; x += 4) {
773
alpha = (DXTAlphaBlockExplicit*)Temp;
775
color_0 = ((Color565*)Temp);
776
color_1 = ((Color565*)(Temp+2));
777
bitmask = ((ILuint*)Temp)[1];
780
colours[0].r = color_0->nRed << 3;
781
colours[0].g = color_0->nGreen << 2;
782
colours[0].b = color_0->nBlue << 3;
785
colours[1].r = color_1->nRed << 3;
786
colours[1].g = color_1->nGreen << 2;
787
colours[1].b = color_1->nBlue << 3;
790
// Four-color block: derive the other two colors.
791
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
792
// These 2-bit codes correspond to the 2-bit fields
793
// stored in the 64-bit block.
794
colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
795
colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
796
colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
799
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
800
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
801
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
805
for (j = 0; j < 4; j++) {
806
for (i = 0; i < 4; i++, k++) {
808
Select = (bitmask & (0x03 << k*2)) >> k*2;
809
col = &colours[Select];
811
if (((x + i) < Width) && ((y + j) < Height)) {
812
Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp;
813
Image->Data[Offset + 0] = col->r;
814
Image->Data[Offset + 1] = col->g;
815
Image->Data[Offset + 2] = col->b;
820
for (j = 0; j < 4; j++) {
821
word = alpha->row[j];
822
for (i = 0; i < 4; i++) {
823
if (((x + i) < Width) && ((y + j) < Height)) {
824
Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 3;
825
Image->Data[Offset] = word & 0x0F;
826
Image->Data[Offset] = Image->Data[Offset] | (Image->Data[Offset] << 4);
840
ILboolean DecompressDXT4()
842
// Can do color & alpha same as dxt5, but color is pre-multiplied
843
// so the result will be wrong unless corrected.
844
if (!DecompressDXT5())
852
ILboolean DecompressDXT5()
854
int x, y, z, i, j, k, Select;
856
Color565 *color_0, *color_1;
857
Color8888 colours[4], *col;
858
ILuint bitmask, Offset;
859
ILubyte alphas[8], *alphamask;
863
for (z = 0; z < Depth; z++) {
864
for (y = 0; y < Height; y += 4) {
865
for (x = 0; x < Width; x += 4) {
866
if (y >= Height || x >= Width)
870
alphamask = Temp + 2;
872
color_0 = ((Color565*)Temp);
873
color_1 = ((Color565*)(Temp+2));
874
bitmask = ((ILuint*)Temp)[1];
877
colours[0].r = color_0->nRed << 3;
878
colours[0].g = color_0->nGreen << 2;
879
colours[0].b = color_0->nBlue << 3;
882
colours[1].r = color_1->nRed << 3;
883
colours[1].g = color_1->nGreen << 2;
884
colours[1].b = color_1->nBlue << 3;
887
// Four-color block: derive the other two colors.
888
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
889
// These 2-bit codes correspond to the 2-bit fields
890
// stored in the 64-bit block.
891
colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
892
colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
893
colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
896
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
897
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
898
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
902
for (j = 0; j < 4; j++) {
903
for (i = 0; i < 4; i++, k++) {
905
Select = (bitmask & (0x03 << k*2)) >> k*2;
906
col = &colours[Select];
908
// only put pixels out < width or height
909
if (((x + i) < Width) && ((y + j) < Height)) {
910
Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp;
911
Image->Data[Offset + 0] = col->r;
912
Image->Data[Offset + 1] = col->g;
913
Image->Data[Offset + 2] = col->b;
918
// 8-alpha or 6-alpha block?
919
if (alphas[0] > alphas[1]) {
920
// 8-alpha block: derive the other six alphas.
921
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
922
alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7; // bit code 010
923
alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7; // bit code 011
924
alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7; // bit code 100
925
alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7; // bit code 101
926
alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7; // bit code 110
927
alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7; // bit code 111
931
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
932
alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5; // Bit code 010
933
alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5; // Bit code 011
934
alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5; // Bit code 100
935
alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5; // Bit code 101
936
alphas[6] = 0x00; // Bit code 110
937
alphas[7] = 0xFF; // Bit code 111
940
// Note: Have to separate the next two loops,
941
// it operates on a 6-byte system.
944
bits = *((ILint*)alphamask);
945
for (j = 0; j < 2; j++) {
946
for (i = 0; i < 4; i++) {
947
// only put pixels out < width or height
948
if (((x + i) < Width) && ((y + j) < Height)) {
949
Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 3;
950
Image->Data[Offset] = alphas[bits & 0x07];
957
bits = *((ILint*)&alphamask[3]);
958
for (j = 2; j < 4; j++) {
959
for (i = 0; i < 4; i++) {
960
// only put pixels out < width or height
961
if (((x + i) < Width) && ((y + j) < Height)) {
962
Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 3;
963
Image->Data[Offset] = alphas[bits & 0x07];
975
ILboolean Decompress3Dc()
977
int x, y, z, i, j, k, t1, t2;
978
ILubyte *Temp, *Temp2;
979
ILubyte XColours[8], YColours[8];
980
ILuint bitmask, bitmask2, Offset, CurrOffset;
985
for (z = 0; z < Depth; z++) {
986
for (y = 0; y < Height; y += 4) {
987
for (x = 0; x < Width; x += 4) {
991
t1 = YColours[0] = Temp[0];
992
t2 = YColours[1] = Temp[1];
995
for (i = 2; i < 8; ++i)
996
YColours[i] = t1 + ((t2 - t1)*(i - 1))/7;
998
for (i = 2; i < 6; ++i)
999
YColours[i] = t1 + ((t2 - t1)*(i - 1))/5;
1005
t1 = XColours[0] = Temp2[0];
1006
t2 = XColours[1] = Temp2[1];
1009
for (i = 2; i < 8; ++i)
1010
XColours[i] = t1 + ((t2 - t1)*(i - 1))/7;
1012
for (i = 2; i < 6; ++i)
1013
XColours[i] = t1 + ((t2 - t1)*(i - 1))/5;
1018
//decompress pixel data
1019
CurrOffset = Offset;
1020
for (k = 0; k < 4; k += 2) {
1021
// First three bytes
1022
bitmask = ((ILuint)(Temp[0]) << 0) | ((ILuint)(Temp[1]) << 8) | ((ILuint)(Temp[2]) << 16);
1023
bitmask2 = ((ILuint)(Temp2[0]) << 0) | ((ILuint)(Temp2[1]) << 8) | ((ILuint)(Temp2[2]) << 16);
1024
for (j = 0; j < 2; j++) {
1025
// only put pixels out < height
1026
if ((y + k + j) < Height) {
1027
for (i = 0; i < 4; i++) {
1028
// only put pixels out < width
1029
if (((x + i) < Width)) {
1032
t1 = CurrOffset + (x + i)*3;
1033
Image->Data[t1 + 1] = ty = YColours[bitmask & 0x07];
1034
Image->Data[t1 + 0] = tx = XColours[bitmask2 & 0x07];
1036
//calculate b (z) component ((r/255)^2 + (g/255)^2 + (b/255)^2 = 1
1037
t = 127*128 - (tx - 127)*(tx - 128) - (ty - 127)*(ty - 128);
1039
Image->Data[t1 + 2] = (ILubyte)(iSqrt(t) + 128);
1041
Image->Data[t1 + 2] = 0x7F;
1046
CurrOffset += Image->Bps;
1053
//skip bytes that were read via Temp2
1056
Offset += Image->Bps*4;
1063
ILvoid CorrectPreMult()
1067
for (i = 0; i < Image->SizeOfData; i += 4) {
1068
if (Image->Data[i+3] != 0) { // Cannot divide by 0.
1069
Image->Data[i] = (ILubyte)(((ILuint)Image->Data[i] << 8) / Image->Data[i+3]);
1070
Image->Data[i+1] = (ILubyte)(((ILuint)Image->Data[i+1] << 8) / Image->Data[i+3]);
1071
Image->Data[i+2] = (ILubyte)(((ILuint)Image->Data[i+2] << 8) / Image->Data[i+3]);
1079
ILboolean DecompressARGB()
1081
ILuint i, ReadI, RedL, RedR, GreenL, GreenR, BlueL, BlueR, AlphaL, AlphaR;
1084
GetBitsFromMask(Head.RBitMask, &RedL, &RedR);
1085
GetBitsFromMask(Head.GBitMask, &GreenL, &GreenR);
1086
GetBitsFromMask(Head.BBitMask, &BlueL, &BlueR);
1087
GetBitsFromMask(Head.RGBAlphaBitMask, &AlphaL, &AlphaR);
1090
for (i = 0; i < Image->SizeOfData; i += Image->Bpp) {
1091
ReadI = *((ILuint*)Temp);
1092
Temp += (Head.RGBBitCount / 8);
1094
Image->Data[i] = ((ReadI & Head.RBitMask) >> RedR) << RedL;
1095
Image->Data[i+1] = ((ReadI & Head.GBitMask) >> GreenR) << GreenL;
1096
Image->Data[i+2] = ((ReadI & Head.BBitMask) >> BlueR) << BlueL;
1098
if (Image->Bpp == 4) {
1099
Image->Data[i+3] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL;
1101
Image->Data[i+3] = Image->Data[i+3] ? 0xFF : 0x00;
1103
else if (AlphaL >= 4) {
1104
Image->Data[i+3] = Image->Data[i+3] | (Image->Data[i+3] >> 4);
1113
// @TODO: Look at using the BSF/BSR operands for inline ASM here.
1114
ILvoid GetBitsFromMask(ILuint Mask, ILuint *ShiftLeft, ILuint *ShiftRight)
1119
*ShiftLeft = *ShiftRight = 0;
1124
for (i = 0; i < 32; i++, Temp >>= 1) {
1130
// Temp is preserved, so use it again:
1131
for (i = 0; i < 8; i++, Temp >>= 1) {