summaryrefslogtreecommitdiff
path: root/DevIL/src-IL/src/il_dpx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'DevIL/src-IL/src/il_dpx.cpp')
-rw-r--r--DevIL/src-IL/src/il_dpx.cpp325
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
+