- Main Page
- Data Structures
- Files

- File List

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

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods
    00005 // Last modified: 12/14/2008
    00006 //
    00007 // Filename: src-IL/src/il_wdp.c
    00008 //
    00009 // Description: Reads a Microsoft HD Photo (.wdp or .hdp)
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "il_internal.h"
    00015 #ifndef IL_NO_WDP
    00016 #include "il_wdp.h"
    00017
    00018
    00020 ILboolean ilIsValidWdp(ILconst_string FileName)
    00021 {
    00022         ILHANDLE        WdpFile;
    00023         ILboolean       bWdp = IL_FALSE;
    00024
    00025         if (!iCheckExtension(FileName, IL_TEXT("wdp")) &&
    00026                 !iCheckExtension(FileName, IL_TEXT("hdp"))) {
    00027                 ilSetError(IL_INVALID_EXTENSION);
    00028                 return bWdp;
    00029         }
    00030
    00031         WdpFile = iopenr(FileName);
    00032         if (WdpFile == NULL) {
    00033                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00034                 return bWdp;
    00035         }
    00036
    00037         bWdp = ilIsValidWdpF(WdpFile);
    00038         icloser(WdpFile);
    00039
    00040         return bWdp;
    00041 }
    00042
    00043
    00045 ILboolean ilIsValidWdpF(ILHANDLE File)
    00046 {
    00047         ILuint          FirstPos;
    00048         ILboolean       bRet;
    00049
    00050         iSetInputFile(File);
    00051         FirstPos = itell();
    00052         bRet = iIsValidWdp();
    00053         iseek(FirstPos, IL_SEEK_SET);
    00054
    00055         return bRet;
    00056 }
    00057
    00058
    00060 ILboolean ilIsValidWdpL(const void *Lump, ILuint Size)
    00061 {
    00062         iSetInputLump(Lump, Size);
    00063         return iIsValidWdp();
    00064 }
    00065
    00066
    00067 // Internal function used to get the Wdp header from the current file.
    00068 ILboolean iGetWdpHead(WDPHEAD *Header)
    00069 {
    00070         // Must be "II"
    00071         Header->Encoding[0] = (ILubyte)igetc();
    00072         Header->Encoding[1] = (ILubyte)igetc();
    00073         // Must be 0xBC
    00074         Header->UniqueID = (ILubyte)igetc();
    00075         // Currently 1
    00076         Header->Version = (ILubyte)igetc();
    00077         // Offset from the beginning of the file
    00078         Header->Offset = GetLittleUInt();
    00079
    00080         return IL_TRUE;
    00081 }
    00082
    00083
    00084 // Internal function to get the header and check it.
    00085 ILboolean iIsValidWdp()
    00086 {
    00087         WDPHEAD Head;
    00088
    00089         if (!iGetWdpHead(&Head))
    00090                 return IL_FALSE;
    00091         iseek(-(ILint)sizeof(WDPHEAD), IL_SEEK_CUR);
    00092
    00093         return iCheckWdp(&Head);
    00094 }
    00095
    00096
    00097 // Internal function used to check if the HEADER is a valid Wdp header.
    00098 ILboolean iCheckWdp(WDPHEAD *Header)
    00099 {
    00100         if (Header->Encoding[0] != 'I' || Header->Encoding[1] != 'I')
    00101                 return IL_FALSE;
    00102         if (Header->UniqueID != 0xBC)
    00103                 return IL_FALSE;
    00104         // Currently 1... 0 is prerelease.
    00105         if (Header->Version != 1)
    00106                 return IL_FALSE;
    00107
    00108         return IL_TRUE;
    00109 }
    00110
    00111
    00113 ILboolean ilLoadWdp(ILconst_string FileName)
    00114 {
    00115         ILHANDLE        WdpFile;
    00116         ILboolean       bWdp = IL_FALSE;
    00117
    00118         WdpFile = iopenr(FileName);
    00119         if (WdpFile == NULL) {
    00120                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00121                 return bWdp;
    00122         }
    00123
    00124         bWdp = ilLoadWdpF(WdpFile);
    00125         icloser(WdpFile);
    00126
    00127         return bWdp;
    00128 }
    00129
    00130
    00132 ILboolean ilLoadWdpF(ILHANDLE File)
    00133 {
    00134         ILuint          FirstPos;
    00135         ILboolean       bRet;
    00136
    00137         iSetInputFile(File);
    00138         FirstPos = itell();
    00139         bRet = iLoadWdpInternal();
    00140         iseek(FirstPos, IL_SEEK_SET);
    00141
    00142         return bRet;
    00143 }
    00144
    00145
    00147 ILboolean ilLoadWdpL(const void *Lump, ILuint Size)
    00148 {
    00149         iSetInputLump(Lump, Size);
    00150         return iLoadWdpInternal();
    00151 }
    00152
    00153
    00154 // Internal function used to load the Wdp.
    00155 ILboolean iLoadWdpInternal()
    00156 {
    00157         WDPHEAD         Header;
    00158         WDPIFD          Dir;
    00159         WDPGUID         Guid;
    00160         ILushort        NumEntries;
    00161         WDPIMGHEAD      ImgHead;
    00162         WDPIMGPLANE     ImgPlane;
    00163         WDPDCQUANT      DcQuant;
    00164         WDPTILE         Tile;
    00165         ILuint          TempInt, TempInt1, i;
    00166
    00167         if (iCurImage == NULL) {
    00168                 ilSetError(IL_ILLEGAL_OPERATION);
    00169                 return IL_FALSE;
    00170         }
    00171
    00172         if (!iGetWdpHead(&Header)) {
    00173                 ilSetError(IL_INVALID_FILE_HEADER);
    00174                 return IL_FALSE;
    00175         }
    00176         if (!iCheckWdp(&Header)) {
    00177                 ilSetError(IL_INVALID_FILE_HEADER);
    00178                 return IL_FALSE;
    00179         }
    00180
    00181         // Offset is from the beginning of the file.
    00182         iseek(Header.Offset, IL_SEEK_SET);
    00183
    00184         NumEntries = GetLittleUShort();
    00185
    00186         Dir.Tag = GetLittleUShort();
    00187         Dir.Type = GetLittleUShort();
    00188         Dir.Count = GetLittleUInt();
    00189         Dir.ValOff = GetLittleUInt();
    00190         Dir.NextOff = GetLittleUInt();
    00191
    00192         GetLittleUInt();
    00193
    00194         iseek(Dir.ValOff, IL_SEEK_SET);
    00195         if (Dir.Type == 1) {
    00196                 //iseek(Dir.Count * 1, IL_SEEK_CUR);
    00197 //@TODO: Take care of other types.
    00198
    00199                 Guid.First = GetLittleUInt();
    00200                 Guid.Second = GetLittleUShort();
    00201                 Guid.Third = GetLittleUShort();
    00202                 Guid.Fourth = GetLittleUInt();
    00203                 Guid.Fifth = GetLittleUInt();
    00204         }
    00205
    00206         // Support other formats
    00207         if (Guid.First != 0x6fddc324 || Guid.Second != 0x4e03 || Guid.Third != 0x4bfe ||
    00208                 Guid.Fourth != 0x773d85b1) {
    00209                 ilSetError(IL_ILLEGAL_FILE_VALUE);
    00210                 return IL_FALSE;
    00211         }
    00212
    00213         // Read the image header.
    00214         //@TODO: Take care of more formats
    00215         switch (Guid.Fifth)
    00216         {
    00217                 // 8-bit RGB (24 bpp)
    00218                 case 0x0cc98d76:
    00219                         ImgHead.GDISignature[0] = GetLittleUInt();
    00220                         ImgHead.GDISignature[1] = GetLittleUInt();
    00221                         ImgHead.Codec    = (ILubyte)igetc();
    00222                         ImgHead.Flags[0] = (ILubyte)igetc();
    00223                         ImgHead.Flags[1] = (ILubyte)igetc();
    00224                         ImgHead.Format   = (ILubyte)igetc();
    00225
    00226                         // GUID is "WMPHOTO", and codec version is only 1 in the current spec (1.0).
    00227                         if (ImgHead.GDISignature[0] != 0x48504D57 || ImgHead.GDISignature[1] != 0x004F544F ||
    00228                                 ((ImgHead.Codec & WDP_CODEC) >> 4) != 1) {
    00229                                 ilSetError(IL_ILLEGAL_FILE_VALUE);
    00230                                 return IL_FALSE;
    00231                         }
    00232
    00233                         //@TODO: Take care of more formats.
    00234                         if (!(ImgHead.Format & WDP_RGB)) {
    00235                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00236                                 return IL_FALSE;
    00237                         }
    00238                         //@TODO: Take care of extra pixels.
    00239                         if (ImgHead.Flags[1] & WDP_WINDOWING) {
    00240                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00241                                 return IL_FALSE;
    00242                         }
    00243                         //@TODO: Alpha channel
    00244                         if (ImgHead.Flags[1] & WDP_ALPHACHANNEL) {
    00245                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00246                                 return IL_FALSE;
    00247                         }
    00248
    00249                         if (ImgHead.Flags[1] & WDP_SHORT_HEADER) {
    00250                                 ImgHead.Width  = GetBigUShort() + 1;
    00251                                 ImgHead.Height = GetBigUShort() + 1;
    00252                         } else {
    00253                                 ImgHead.Width  = GetBigUInt() + 1;
    00254                                 ImgHead.Height = GetBigUInt() + 1;
    00255                         }
    00256
    00257                         if (ImgHead.Flags[0] & WDP_TILING_FLAG) {
    00258                                 ImgHead.VertTiles = (ILubyte)igetc();
    00259                                 TempInt = igetc();
    00260                                 ImgHead.VertTiles = ImgHead.VertTiles + ((TempInt & 0xF0) << 4);
    00261                                 UInt(&ImgHead.VertTiles);  // Take care of endianness
    00262
    00263                                 ImgHead.HorzTiles = (ILubyte)igetc() << 8;
    00264                                 ImgHead.HorzTiles = ImgHead.VertTiles + (TempInt & 0x0F);
    00265                                 UInt(&ImgHead.VertTiles);  // Take care of endianness
    00266
    00267                                 //@TODO:  Interpret tiles
    00268                                 return IL_FALSE;
    00269
    00270                                 for (i = 0; i < ImgHead.VertTiles; i++) {
    00271                                         if (ImgHead.Flags[1] & WDP_SHORT_HEADER) {
    00272                                                 igetc();
    00273                                         }
    00274                                         else {
    00275                                                 GetBigUShort();
    00276                                         }
    00277                                 }
    00278                         }
    00279
    00280                         //@TODO: Take orientation into account.
    00281
    00282                         // Read the image plane header
    00283                         ImgPlane.Flags1 = (ILubyte)igetc();
    00284                         TempInt = (ImgPlane.Flags1 & WDP_CLR_FMT)>>5;
    00285                         if ((TempInt == WDP_YUV_444) || (TempInt == WDP_N_CHANNEL)) {
    00286                                 //@TODO: Do anything with this for YUV_444?
    00287                                 ImgPlane.Color = (ILubyte)igetc();
    00288                         }
    00289
    00290                         if (TempInt == WDP_N_CHANNEL) {
    00291                                 ImgPlane.NumChannels = ((ImgPlane.Color & WDP_NUM_CHANS) >> 4) + 1;
    00292                         }
    00293                         else if (TempInt == WDP_Y_ONLY) {
    00294                                 ImgPlane.NumChannels = 1;
    00295                         }
    00296                         else if ((TempInt == WDP_YUV_420) || (TempInt == WDP_YUV_422) || (TempInt == WDP_YUV_444)) {
    00297                                 ImgPlane.NumChannels = 3;
    00298                         }
    00299                         else if ((TempInt == WDP_CMYK) || (TempInt == WDP_BAYER)) {
    00300                                 ImgPlane.NumChannels = 4;
    00301                         }
    00302                         else {  // The above if statements have all the possible values.
    00303                                 ilSetError(IL_ILLEGAL_FILE_VALUE);
    00304                                 return IL_FALSE;
    00305                         }
    00306
    00307
    00308                         //@TODO: Implement
    00309                         //if ((ImgPlane.Flags1 & WDP_CLR_FMT)>>5 == WDP_YUV_444) {
    00310                         //      ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00311                         //      return IL_FALSE;
    00312                         //}
    00313                         //@TODO: Implement
    00314                         if ((ImgPlane.Flags1 & WDP_CLR_FMT)>>5 == WDP_BAYER) {
    00315                                 ImgPlane.Bayer = (ILubyte)igetc();
    00316                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00317                                 return IL_FALSE;
    00318                         }
    00319
    00320                         TempInt = ImgHead.Format & WDP_BITDEPTH;
    00321                         //@TODO: Implement
    00322                         if (TempInt == WDP_BD_16 || TempInt == WDP_BD_16S || TempInt == WDP_BD_32 || TempInt == WDP_BD_32S) {
    00323                                 ImgPlane.ShiftBits = (ILubyte)igetc();
    00324                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00325                                 return IL_FALSE;
    00326                         }
    00327                         //@TODO: Implement
    00328                         if (TempInt == WDP_BD_32F) {
    00329                                 ImgPlane.Mantissa = (ILubyte)igetc();
    00330                                 ImgPlane.Expbias  = (ILubyte)igetc();
    00331                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00332                                 return IL_FALSE;
    00333                         }
    00334
    00335                         // Read the second set of image plane header flags.
    00336                         ImgPlane.Flags2 = (ILubyte)igetc();
    00337                         //@TODO: Implement
    00338                         if (ImgPlane.Flags2 & WDP_DC_FRAME) {
    00339                                 if (ImgPlane.NumChannels == 1) {
    00340                                         DcQuant.ChMode = WDP_CH_UNIFORM;
    00341                                 }
    00342                                 else {
    00343                                         DcQuant.ChMode = (ImgPlane.Flags2 & 0x60) >> 5;
    00344                                 }
    00345
    00346                                 if (DcQuant.ChMode == WDP_CH_UNIFORM) {
    00347                                         TempInt = igetc();
    00348                                         DcQuant.DcQuant = ((ImgPlane.Flags2 & 0x1F) << 3) + ((TempInt & 0xE0) >> 5);
    00349                                 }
    00350                                 else if (DcQuant.ChMode == WDP_CH_SEPARATE) {
    00351                                         TempInt1 = igetc();
    00352                                         TempInt = igetc();
    00353                                         DcQuant.DcQuantY = ((ImgPlane.Flags2 & 0x1F) << 3) + ((TempInt1 & 0xE0) >> 5);
    00354                                         DcQuant.DcQuantUV = ((TempInt1 & 0x1F) << 3) + ((TempInt & 0xE0) >> 5);
    00355                                 }
    00356                                 //@TODO: Implement
    00357                                 else if (DcQuant.ChMode == WDP_CH_INDEPENDENT) {
    00358                                         ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00359                                         return IL_FALSE;
    00360                                 }
    00361                                 else {  // Not a valid channel mode
    00362                                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00363                                         return IL_FALSE;
    00364                                 }
    00365                         }
    00366                         else {
    00367                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00368                                 return IL_FALSE;
    00369                         }
    00370
    00371                         // Bitstream is in spatial mode.
    00372                         if ((ImgHead.Flags[0] & WDP_BITSTREAM_FMT) == 0) {
    00373 //@TODO: Find out what exactly these are.
    00374                                 iseek(6, IL_SEEK_CUR);
    00375                                 Tile.StartCode = (igetc() << 16) + (igetc() << 8) + igetc();
    00376                                 UInt(&Tile.StartCode);
    00377                                 Tile.HashAndType = igetc();
    00378
    00379                                 if (Tile.StartCode != 1 && (Tile.HashAndType & WDP_TILE_TYPE) != WDP_FLEXBITS_TILE) {  // Invalid tile
    00380                                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00381                                         return IL_FALSE;
    00382                                 }
    00383
    00384                                 //@TODO: Implement
    00385                                 if (ImgHead.Flags[1] & WDP_TRIM_FLEXBITS) {
    00386                                         ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00387                                         return IL_FALSE;
    00388                                 }
    00389
    00390                                 // Here's where TILE_SPATIAL goes.
    00391                                 //ImgPlane.Flags1 & WDP_BANDS_PRESENT  // No need to shift, since lower.
    00392                         }
    00393                         // Bitstream is in frequency mode.
    00394                         //@TODO: Implement this.
    00395                         else {
    00396                                 ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00397                                 return IL_FALSE;
    00398                         }
    00399
    00400
    00401
    00402                         if (!ilTexImage(ImgHead.Width, ImgHead.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) {
    00403                                 //@TODO: Free any memory from above.
    00404                                 return IL_FALSE;
    00405                         }
    00406
    00407
    00408                         break;
    00409
    00410                 default:
    00411                         ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00412                         return IL_FALSE;
    00413         }
    00414
    00415
    00416         return IL_TRUE;
    00417 }
    00418
    00419
    00420 ILuint VLWESC()
    00421 {
    00422         ILubyte First, Second;
    00423         ILuint  Value;
    00424
    00425         First = (ILubyte)igetc();
    00426         if (First < 0xfb) {
    00427                 Second = (ILubyte)igetc();
    00428                 Value = First * 256 + Second;
    00429         }
    00430         else if (First == 0x0fb) {
    00431                 Value = GetBigUInt();
    00432         }
    00433     //else if (First == 0x0fc) {
    00434     //    EIGHT_BYTES
    00435     //    Value = EIGHT_BYTES
    00436     //}
    00437         else { // FIRST_BYTE == 0xfd||0xfe||0xff
    00438                 Value = 0; // Escape Mode
    00439         }
    00440
    00441         return Value;
    00442 }
    00443
    00444
    00445
    00446 #endif//IL_NO_WDP