- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_dcx.c

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods
    00005 // Last modified: 08/10/2006
    00006 //
    00007 // Filename: src-IL/src/il_dcx.c
    00008 //
    00009 // Description: Reads from a .dcx file.
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "il_internal.h"
    00015 #ifndef IL_NO_DCX
    00016 #include "il_dcx.h"
    00017 #include "il_manip.h"
    00018
    00019
    00021 ILboolean ilIsValidDcx(ILconst_string FileName)
    00022 {
    00023         ILHANDLE        DcxFile;
    00024         ILboolean       bDcx = IL_FALSE;
    00025
    00026         if (!iCheckExtension(FileName, IL_TEXT("dcx"))) {
    00027                 ilSetError(IL_INVALID_EXTENSION);
    00028                 return bDcx;
    00029         }
    00030
    00031         DcxFile = iopenr(FileName);
    00032         if (DcxFile == NULL) {
    00033                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00034                 return bDcx;
    00035         }
    00036
    00037         bDcx = ilIsValidDcxF(DcxFile);
    00038         icloser(DcxFile);
    00039
    00040         return bDcx;
    00041 }
    00042
    00043
    00045 ILboolean ilIsValidDcxF(ILHANDLE File)
    00046 {
    00047         ILuint          FirstPos;
    00048         ILboolean       bRet;
    00049
    00050         iSetInputFile(File);
    00051         FirstPos = itell();
    00052         bRet = iIsValidDcx();
    00053         iseek(FirstPos, IL_SEEK_SET);
    00054
    00055         return bRet;
    00056 }
    00057
    00058
    00060 ILboolean ilIsValidDcxL(const void *Lump, ILuint Size)
    00061 {
    00062         iSetInputLump(Lump, Size);
    00063         return iIsValidDcx();
    00064 }
    00065
    00066
    00067 // Internal function obtain the .dcx header from the current file.
    00068 ILboolean iGetDcxHead(DCXHEAD *Head)
    00069 {
    00070         Head->Xmin = GetLittleUShort();
    00071         Head->Ymin = GetLittleUShort();
    00072         Head->Xmax = GetLittleUShort();
    00073         Head->Ymax = GetLittleUShort();
    00074         Head->HDpi = GetLittleUShort();
    00075         Head->VDpi = GetLittleUShort();
    00076         Head->Bps = GetLittleUShort();
    00077         Head->PaletteInfo = GetLittleUShort();
    00078         Head->HScreenSize = GetLittleUShort();
    00079         Head->VScreenSize = GetLittleUShort();
    00080
    00081         return IL_TRUE;
    00082 }
    00083
    00084
    00085 // Internal function to get the header and check it.
    00086 ILboolean iIsValidDcx()
    00087 {
    00088         ILuint Signature;
    00089
    00090         if (iread(&Signature, 1, 4) != 4)
    00091                 return IL_FALSE;
    00092         iseek(-4, IL_SEEK_CUR);
    00093
    00094         return (Signature == 987654321);
    00095 }
    00096
    00097
    00098 // Internal function used to check if the HEADER is a valid .dcx header.
    00099 // Should we also do a check on Header->Bpp?
    00100 ILboolean iCheckDcx(DCXHEAD *Header)
    00101 {
    00102         ILuint  Test, i;
    00103
    00104         // There are other versions, but I am not supporting them as of yet.
    00105         //      Got rid of the Reserved check, because I've seen some .dcx files with invalid values in it.
    00106         if (Header->Manufacturer != 10 || Header->Version != 5 || Header->Encoding != 1/* || Header->Reserved != 0*/)
    00107                 return IL_FALSE;
    00108
    00109         // See if the padding size is correct
    00110         Test = Header->Xmax - Header->Xmin + 1;
    00111         /*if (Header->Bpp >= 8) {
    00112                 if (Test & 1) {
    00113                         if (Header->Bps != Test + 1)
    00114                                 return IL_FALSE;
    00115                 }
    00116                 else {
    00117                         if (Header->Bps != Test)  // No padding
    00118                                 return IL_FALSE;
    00119                 }
    00120         }*/
    00121
    00122         for (i = 0; i < 54; i++) {
    00123                 if (Header->Filler[i] != 0)
    00124                         return IL_FALSE;
    00125         }
    00126
    00127         return IL_TRUE;
    00128 }
    00129
    00130
    00132 ILboolean ilLoadDcx(ILconst_string FileName)
    00133 {
    00134         ILHANDLE        DcxFile;
    00135         ILboolean       bDcx = IL_FALSE;
    00136
    00137         DcxFile = iopenr(FileName);
    00138         if (DcxFile == NULL) {
    00139                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00140                 return bDcx;
    00141         }
    00142
    00143         bDcx = ilLoadDcxF(DcxFile);
    00144         icloser(DcxFile);
    00145
    00146         return bDcx;
    00147 }
    00148
    00149
    00151 ILboolean ilLoadDcxF(ILHANDLE File)
    00152 {
    00153         ILuint          FirstPos;
    00154         ILboolean       bRet;
    00155
    00156         iSetInputFile(File);
    00157         FirstPos = itell();
    00158         bRet = iLoadDcxInternal();
    00159         iseek(FirstPos, IL_SEEK_SET);
    00160
    00161         return bRet;
    00162 }
    00163
    00164
    00166 ILboolean ilLoadDcxL(const void *Lump, ILuint Size) {
    00167         iSetInputLump(Lump, Size);
    00168         return iLoadDcxInternal();
    00169 }
    00170
    00171
    00172 // Internal function used to load the .dcx.
    00173 ILboolean iLoadDcxInternal()
    00174 {
    00175         DCXHEAD Header;
    00176         ILuint  Signature, i, Entries[1024], Num = 0;
    00177         ILimage *Image, *Base;
    00178
    00179         if (iCurImage == NULL) {
    00180                 ilSetError(IL_ILLEGAL_OPERATION);
    00181                 return IL_FALSE;
    00182         }
    00183
    00184         if (!iIsValidDcx())
    00185                 return IL_FALSE;
    00186         iread(&Signature, 1, 4);
    00187
    00188         do {
    00189                 if (iread(&Entries[Num], 1, 4) != 4)
    00190                         return IL_FALSE;
    00191                 Num++;
    00192         } while (Entries[Num-1] != 0);
    00193
    00194         for (i = 0; i < Num; i++) {
    00195                 iseek(Entries[i], IL_SEEK_SET);
    00196                 iGetDcxHead(&Header);
    00197                 /*if (!iCheckDcx(&Header)) {
    00198                         ilSetError(IL_INVALID_FILE_HEADER);
    00199                         return IL_FALSE;
    00200                 }*/
    00201
    00202                 Image = iUncompressDcx(&Header);
    00203                 if (Image == NULL)
    00204                         return IL_FALSE;
    00205
    00206                 if (i == 0) {
    00207                         ilTexImage(Image->Width, Image->Height, 1, Image->Bpp, Image->Format, Image->Type, Image->Data);
    00208                         Base = iCurImage;
    00209                         Base->Origin = IL_ORIGIN_UPPER_LEFT;
    00210                         ilCloseImage(Image);
    00211                 }
    00212                 else {
    00213                         iCurImage->Next = Image;
    00214                         iCurImage = iCurImage->Next;
    00215                 }
    00216         }
    00217
    00218         ilFixImage();
    00219
    00220         return IL_TRUE;
    00221 }
    00222
    00223
    00224 // Internal function to uncompress the .dcx (all .dcx files are rle compressed)
    00225 ILimage *iUncompressDcx(DCXHEAD *Header)
    00226 {
    00227         ILubyte         ByteHead, Colour, *ScanLine = NULL /* Only one plane */;
    00228         ILuint          c, i, x, y;//, Read = 0;
    00229         ILimage         *Image = NULL;
    00230
    00231         if (Header->Bpp < 8) {
    00232                 /*ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00233                 return IL_FALSE;*/
    00234                 return iUncompressDcxSmall(Header);
    00235         }
    00236
    00237         Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1);
    00238         if (Image == NULL)
    00239                 return NULL;
    00240         /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) {
    00241                 return IL_FALSE;
    00242         }*/
    00243         Image->Origin = IL_ORIGIN_UPPER_LEFT;
    00244
    00245         ScanLine = (ILubyte*)ialloc(Header->Bps);
    00246         if (ScanLine == NULL)
    00247                 goto dcx_error;
    00248
    00249         switch (Image->Bpp)
    00250         {
    00251                 case 1:
    00252                         Image->Format = IL_COLOUR_INDEX;
    00253                         Image->Pal.PalType = IL_PAL_RGB24;
    00254                         Image->Pal.PalSize = 256 * 3; // Need to find out for sure...
    00255                         Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize);
    00256                         if (Image->Pal.Palette == NULL)
    00257                                 goto dcx_error;
    00258                         break;
    00259                 //case 2:  // No 16-bit images in the dcx format!
    00260                 case 3:
    00261                         Image->Format = IL_RGB;
    00262                         Image->Pal.Palette = NULL;
    00263                         Image->Pal.PalSize = 0;
    00264                         Image->Pal.PalType = IL_PAL_NONE;
    00265                         break;
    00266                 case 4:
    00267                         Image->Format = IL_RGBA;
    00268                         Image->Pal.Palette = NULL;
    00269                         Image->Pal.PalSize = 0;
    00270                         Image->Pal.PalType = IL_PAL_NONE;
    00271                         break;
    00272
    00273                 default:
    00274                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00275                         goto dcx_error;
    00276         }
    00277
    00278
    00279                 /*StartPos = itell();
    00280                 Compressed = (ILubyte*)ialloc(Image->SizeOfData * 4 / 3);
    00281                 iread(Compressed, 1, Image->SizeOfData * 4 / 3);
    00282
    00283                 for (y = 0; y < Image->Height; y++) {
    00284                         for (c = 0; c < Image->Bpp; c++) {
    00285                                 x = 0;
    00286                                 while (x < Header->Bps) {
    00287                                         ByteHead = Compressed[Read++];
    00288                                         if ((ByteHead & 0xC0) == 0xC0) {
    00289                                                 ByteHead &= 0x3F;
    00290                                                 Colour = Compressed[Read++];
    00291                                                 for (i = 0; i < ByteHead; i++) {
    00292                                                         ScanLine[x++] = Colour;
    00293                                                 }
    00294                                         }
    00295                                         else {
    00296                                                 ScanLine[x++] = ByteHead;
    00297                                         }
    00298                                 }
    00299
    00300                                 for (x = 0; x < Image->Width; x++) {  // 'Cleverly' ignores the pad bytes ;)
    00301                                         Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x];
    00302                                 }
    00303                         }
    00304                 }
    00305
    00306                 ifree(Compressed);
    00307                 iseek(StartPos + Read, IL_SEEK_SET);*/
    00308
    00309         //changed 2003-09-01
    00310         if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
    00311                 iPreCache(iCurImage->SizeOfData);
    00312
    00313         //TODO: because the .pcx-code was broken this
    00314         //code is probably broken, too
    00315         for (y = 0; y < Image->Height; y++) {
    00316                 for (c = 0; c < Image->Bpp; c++) {
    00317                         x = 0;
    00318                         while (x < Header->Bps) {
    00319                                 if (iread(&ByteHead, 1, 1) != 1) {
    00320                                         iUnCache();
    00321                                         goto dcx_error;
    00322                                 }
    00323                                 if ((ByteHead & 0xC0) == 0xC0) {
    00324                                         ByteHead &= 0x3F;
    00325                                         if (iread(&Colour, 1, 1) != 1) {
    00326                                                 iUnCache();
    00327                                                 goto dcx_error;
    00328                                         }
    00329                                         for (i = 0; i < ByteHead; i++) {
    00330                                                 ScanLine[x++] = Colour;
    00331                                         }
    00332                                 }
    00333                                 else {
    00334                                         ScanLine[x++] = ByteHead;
    00335                                 }
    00336                         }
    00337
    00338                         for (x = 0; x < Image->Width; x++) {  // 'Cleverly' ignores the pad bytes ;)
    00339                                 Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x];
    00340                         }
    00341                 }
    00342         }
    00343
    00344         iUnCache();
    00345
    00346
    00347         ifree(ScanLine);
    00348
    00349         // Read in the palette
    00350         if (Image->Bpp == 1) {
    00351                 ByteHead = igetc();     // the value 12, because it signals there's a palette for some reason...
    00352                                                         //      We should do a check to make certain it's 12...
    00353                 if (ByteHead != 12)
    00354                         iseek(-1, IL_SEEK_CUR);
    00355                 if (iread(Image->Pal.Palette, 1, Image->Pal.PalSize) != Image->Pal.PalSize) {
    00356                         ilCloseImage(Image);
    00357                         return NULL;
    00358                 }
    00359         }
    00360
    00361         return Image;
    00362
    00363 dcx_error:
    00364         ifree(ScanLine);
    00365         ilCloseImage(Image);
    00366         return NULL;
    00367 }
    00368
    00369
    00370 ILimage *iUncompressDcxSmall(DCXHEAD *Header)
    00371 {
    00372         ILuint  i = 0, j, k, c, d, x, y, Bps;
    00373         ILubyte HeadByte, Colour, Data = 0, *ScanLine = NULL;
    00374         ILimage *Image;
    00375
    00376         Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1);
    00377         if (Image == NULL)
    00378                 return NULL;
    00379
    00380         /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) {
    00381                 return IL_FALSE;
    00382         }*/
    00383         Image->Origin = IL_ORIGIN_UPPER_LEFT;
    00384
    00385         switch (Header->NumPlanes)
    00386         {
    00387                 case 1:
    00388                         Image->Format = IL_LUMINANCE;
    00389                         break;
    00390                 case 4:
    00391                         Image->Format = IL_COLOUR_INDEX;
    00392                         break;
    00393                 default:
    00394                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00395                         ilCloseImage(Image);
    00396                         return NULL;
    00397         }
    00398
    00399         if (Header->NumPlanes == 1) {
    00400                 for (j = 0; j < Image->Height; j++) {
    00401                         i = 0;
    00402                         while (i < Image->Width) {
    00403                                 if (iread(&HeadByte, 1, 1) != 1)
    00404                                         goto file_read_error;
    00405                                 if (HeadByte >= 192) {
    00406                                         HeadByte -= 192;
    00407                                         if (iread(&Data, 1, 1) != 1)
    00408                                                 goto file_read_error;
    00409
    00410                                         for (c = 0; c < HeadByte; c++) {
    00411                                                 k = 128;
    00412                                                 for (d = 0; d < 8 && i < Image->Width; d++) {
    00413                                                         Image->Data[j * Image->Width + i++] = (!!(Data & k) == 1 ? 255 : 0);
    00414                                                         k >>= 1;
    00415                                                 }
    00416                                         }
    00417                                 }
    00418                                 else {
    00419                                         k = 128;
    00420                                         for (c = 0; c < 8 && i < Image->Width; c++) {
    00421                                                 Image->Data[j * Image->Width + i++] = (!!(HeadByte & k) == 1 ? 255 : 0);
    00422                                                 k >>= 1;
    00423                                         }
    00424                                 }
    00425                         }
    00426                         if (Data != 0)
    00427                                 igetc();  // Skip pad byte if last byte not a 0
    00428                 }
    00429         }
    00430         else {   // 4-bit images
    00431                 Bps = Header->Bps * Header->NumPlanes * 2;
    00432                 Image->Pal.Palette = (ILubyte*)ialloc(16 * 3);  // Size of palette always (48 bytes).
    00433                 Image->Pal.PalSize = 16 * 3;
    00434                 Image->Pal.PalType = IL_PAL_RGB24;
    00435                 ScanLine = (ILubyte*)ialloc(Bps);
    00436                 if (Image->Pal.Palette == NULL || ScanLine == NULL) {
    00437                         ifree(ScanLine);
    00438                         ilCloseImage(Image);
    00439                         return NULL;
    00440                 }
    00441
    00442                 memcpy(Image->Pal.Palette, Header->ColMap, 16 * 3);
    00443                 imemclear(Image->Data, Image->SizeOfData);  // Since we do a += later.
    00444
    00445                 for (y = 0; y < Image->Height; y++) {
    00446                         for (c = 0; c < Header->NumPlanes; c++) {
    00447                                 x = 0;
    00448                                 while (x < Bps) {
    00449                                         if (iread(&HeadByte, 1, 1) != 1)
    00450                                                 goto file_read_error;
    00451                                         if ((HeadByte & 0xC0) == 0xC0) {
    00452                                                 HeadByte &= 0x3F;
    00453                                                 if (iread(&Colour, 1, 1) != 1)
    00454                                                         goto file_read_error;
    00455                                                 for (i = 0; i < HeadByte; i++) {
    00456                                                         k = 128;
    00457                                                         for (j = 0; j < 8; j++) {
    00458                                                                 ScanLine[x++] = !!(Colour & k);
    00459                                                                 k >>= 1;
    00460                                                         }
    00461                                                 }
    00462                                         }
    00463                                         else {
    00464                                                 k = 128;
    00465                                                 for (j = 0; j < 8; j++) {
    00466                                                         ScanLine[x++] = !!(HeadByte & k);
    00467                                                         k >>= 1;
    00468                                                 }
    00469                                         }
    00470                                 }
    00471
    00472                                 for (x = 0; x < Image->Width; x++) {  // 'Cleverly' ignores the pad bytes. ;)
    00473                                         Image->Data[y * Image->Width + x] += ScanLine[x] << c;
    00474                                 }
    00475                         }
    00476                 }
    00477                 ifree(ScanLine);
    00478         }
    00479
    00480         return Image;
    00481
    00482 file_read_error:
    00483         ifree(ScanLine);
    00484         ilCloseImage(Image);
    00485         return NULL;
    00486 }
    00487
    00488 #endif//IL_NO_DCX