diff options
Diffstat (limited to 'DevIL/src-IL/src/il_dpx.cpp')
-rw-r--r-- | DevIL/src-IL/src/il_dpx.cpp | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/DevIL/src-IL/src/il_dpx.cpp b/DevIL/src-IL/src/il_dpx.cpp new file mode 100644 index 00000000..bcc21035 --- /dev/null +++ b/DevIL/src-IL/src/il_dpx.cpp @@ -0,0 +1,325 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/26/2009 +// +// Filename: src-IL/src/il_dpx.c +// +// Description: Reads from a Digital Picture Exchange (.dpx) file. +// Specifications for this format were found at +// http://www.cineon.com/ff_draft.php and +// http://www.fileformat.info/format/dpx/. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_DPX +#include "il_dpx.h" +#include "il_bits.h" + +ILboolean iLoadDpxInternal(void); + + +//! Reads a DPX file +ILboolean ilLoadDpx(ILconst_string FileName) +{ + ILHANDLE DpxFile; + ILboolean bDpx = IL_FALSE; + + DpxFile = iopenr(FileName); + if (DpxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDpx; + } + + bDpx = ilLoadDpxF(DpxFile); + icloser(DpxFile); + + return bDpx; +} + + +//! Reads an already-opened DPX file +ILboolean ilLoadDpxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDpxInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a DPX +ILboolean ilLoadDpxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadDpxInternal(); +} + + +ILboolean DpxGetFileInfo(DPX_FILE_INFO *FileInfo) +{ + //if (iread(FileInfo, 768, 1) != 1) + // return IL_FALSE; + + FileInfo->MagicNum = GetBigUInt(); + FileInfo->Offset = GetBigUInt(); + iread(FileInfo->Vers, 8, 1); + FileInfo->FileSize = GetBigUInt(); + FileInfo->DittoKey = GetBigUInt(); + FileInfo->GenHdrSize = GetBigUInt(); + FileInfo->IndHdrSize = GetBigUInt(); + FileInfo->UserDataSize = GetBigUInt(); + iread(FileInfo->FileName, 100, 1); + iread(FileInfo->CreateTime, 24, 1); + iread(FileInfo->Creator, 100, 1); + iread(FileInfo->Project, 200, 1); + if (iread(FileInfo->Copyright, 200, 1) != 1) + return IL_FALSE; + FileInfo->Key = GetBigUInt(); + iseek(104, IL_SEEK_CUR); // Skip reserved section. + + return IL_TRUE; +} + + +ILboolean GetImageElement(DPX_IMAGE_ELEMENT *ImageElement) +{ + ImageElement->DataSign = GetBigUInt(); + ImageElement->RefLowData = GetBigUInt(); + iread(&ImageElement->RefLowQuantity, 1, 4); + ImageElement->RefHighData = GetBigUInt(); + iread(&ImageElement->RefHighQuantity, 1, 4); + ImageElement->Descriptor = igetc(); + ImageElement->Transfer = igetc(); + ImageElement->Colorimetric = igetc(); + ImageElement->BitSize = igetc(); + ImageElement->Packing = GetBigUShort(); + ImageElement->Encoding = GetBigUShort(); + ImageElement->DataOffset = GetBigUInt(); + ImageElement->EolPadding = GetBigUInt(); + ImageElement->EoImagePadding = GetBigUInt(); + if (iread(ImageElement->Description, 32, 1) != 1) + return IL_FALSE; + + return IL_TRUE; +} + + +ILboolean DpxGetImageInfo(DPX_IMAGE_INFO *ImageInfo) +{ + ILuint i; + + //if (iread(ImageInfo, sizeof(DPX_IMAGE_INFO), 1) != 1) + // return IL_FALSE; + ImageInfo->Orientation = GetBigUShort(); + ImageInfo->NumElements = GetBigUShort(); + ImageInfo->Width = GetBigUInt(); + ImageInfo->Height = GetBigUInt(); + + for (i = 0; i < 8; i++) { + GetImageElement(&ImageInfo->ImageElement[i]); + } + + iseek(52, IL_SEEK_CUR); // Skip padding bytes. + + return IL_TRUE; +} + + +ILboolean DpxGetImageOrient(DPX_IMAGE_ORIENT *ImageOrient) +{ + ImageOrient->XOffset = GetBigUInt(); + ImageOrient->YOffset = GetBigUInt(); + iread(&ImageOrient->XCenter, 4, 1); + iread(&ImageOrient->YCenter, 4, 1); + ImageOrient->XOrigSize = GetBigUInt(); + ImageOrient->YOrigSize = GetBigUInt(); + iread(ImageOrient->FileName, 100, 1); + iread(ImageOrient->CreationTime, 24, 1); + iread(ImageOrient->InputDev, 32, 1); + if (iread(ImageOrient->InputSerial, 32, 1) != 1) + return IL_FALSE; + ImageOrient->Border[0] = GetBigUShort(); + ImageOrient->Border[1] = GetBigUShort(); + ImageOrient->Border[2] = GetBigUShort(); + ImageOrient->Border[3] = GetBigUShort(); + ImageOrient->PixelAspect[0] = GetBigUInt(); + ImageOrient->PixelAspect[1] = GetBigUInt(); + iseek(28, IL_SEEK_CUR); // Skip reserved bytes. + + return IL_TRUE; +} + + +// Internal function used to load the DPX. +ILboolean iLoadDpxInternal(void) +{ + DPX_FILE_INFO FileInfo; + DPX_IMAGE_INFO ImageInfo; + DPX_IMAGE_ORIENT ImageOrient; +// BITFILE *File; + ILuint i, NumElements, CurElem = 0; + ILushort Val, *ShortData; + ILubyte Data[8]; + ILenum Format = 0; + ILubyte NumChans = 0; + + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!DpxGetFileInfo(&FileInfo)) + return IL_FALSE; + if (!DpxGetImageInfo(&ImageInfo)) + return IL_FALSE; + if (!DpxGetImageOrient(&ImageOrient)) + return IL_FALSE; + + iseek(ImageInfo.ImageElement[CurElem].DataOffset, IL_SEEK_SET); + +//@TODO: Deal with different origins! + + switch (ImageInfo.ImageElement[CurElem].Descriptor) + { + case 6: // Luminance data + Format = IL_LUMINANCE; + NumChans = 1; + break; + case 50: // RGB data + Format = IL_RGB; + NumChans = 3; + break; + case 51: // RGBA data + Format = IL_RGBA; + NumChans = 4; + break; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + // These are all on nice word boundaries. + switch (ImageInfo.ImageElement[CurElem].BitSize) + { + case 8: + case 16: + case 32: + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, NumChans, Format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + if (iread(iCurImage->Data, iCurImage->SizeOfData, 1) != 1) + return IL_FALSE; + goto finish; + } + + // The rest of these do not end on word boundaries. + if (ImageInfo.ImageElement[CurElem].Packing == 1) { + // Here we have it padded out to a word boundary, so the extra bits are filler. + switch (ImageInfo.ImageElement[CurElem].BitSize) + { + case 10: + //@TODO: Support other formats! + /*if (Format != IL_RGB) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + }*/ + switch (Format) + { + case IL_LUMINANCE: + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + + for (i = 0; i < NumElements;) { + iread(Data, 1, 2); + Val = ((Data[0] << 2) + ((Data[1] & 0xC0) >> 6)) << 6; // Use the first 10 bits of the word-aligned data. + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. + } + break; + + case IL_RGB: + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 3, IL_RGB, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + + for (i = 0; i < NumElements;) { + iread(Data, 1, 4); + Val = ((Data[0] << 2) + ((Data[1] & 0xC0) >> 6)) << 6; // Use the first 10 bits of the word-aligned data. + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. + Val = (((Data[1] & 0x3F) << 4) + ((Data[2] & 0xF0) >> 4)) << 6; // Use the next 10 bits. + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Same fill + Val = (((Data[2] & 0x0F) << 6) + ((Data[3] & 0xFC) >> 2)) << 6; // And finally use the last 10 bits (ignores the last 2 bits). + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Same fill + } + break; + + case IL_RGBA: // Is this even a possibility? There is a ton of wasted space here! + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 4, IL_RGBA, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + + for (i = 0; i < NumElements;) { + iread(Data, 1, 8); + Val = (Data[0] << 2) + ((Data[1] & 0xC0) >> 6); // Use the first 10 bits of the word-aligned data. + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. + Val = ((Data[1] & 0x3F) << 4) + ((Data[2] & 0xF0) >> 4); // Use the next 10 bits. + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Same fill + Val = ((Data[2] & 0x0F) << 6) + ((Data[3] & 0xFC) >> 2); // Use the next 10 bits. + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Same fill + Val = ((Data[3] & 0x03) << 8) + Data[4]; // And finally use the last 10 relevant bits (skips 3 whole bytes worth of padding!). + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Last fill + } + break; + } + break; + + //case 1: + //case 12: + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + } + else if (ImageInfo.ImageElement[0].Packing == 0) { + // Here we have the data packed so that it is never aligned on a word boundary. + /*File = bfile(iGetFile()); + if (File == NULL) + return IL_FALSE; //@TODO: Error? + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + for (i = 0; i < NumElements; i++) { + //bread(&Val, 1, 10, File); + Val = breadVal(10, File); + ShortData[i] = (Val << 6) | (Val >> 4); + } + bclose(File);*/ + + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + else { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; //@TODO: Take care of this in an iCheckDpx* function. + } + +finish: + return ilFixImage(); +} + +#endif//IL_NO_DPX + |