Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-10-22 16:49:00 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-10-22 16:49:00 +0400
commit4e11fe6c5aec1d609e3ecc2218138b838d253ebf (patch)
treed57b4f18280c04e50ecb562135fed058cf11b82d /source/blender/imbuf/intern/cineon/dpxlib.c
parent655e24979bb37c97a34b328238233591cfd5c924 (diff)
Patch #27397: Improved DPX/Cineon code
Patch by Julien Enche, thanks! From the patch comment: It allows Blender to load: - 1, 8, 10, 12 and 16 bits files. For 10 and 12 bits files, packed or filled type A/B are supported. - RGB, Log, Luma and YCbCr colorspaces. - Big and little endian storage. - Multi-elements (planar) storage. It allows Blender to save : - 8, 10, 12 and 16 bits file. For 10 and 12 bits files, the most used type A padding is used. - RGB and Log colorspaces (Cineon can only be saved in Log colorspace). For Log colorspace, the common default values are used for gamma, reference black and reference white (respectively 1.7, 95 and 685 for 10 bits files). - Saved DPX/Cineon files now match the viewer. Some files won't load (mostly because I haven't seen any of them): - Compressed files - 32 and 64 bits files - Image orientation information are not taken in account. Here too, I haven't seen any file that was not top-bottom/left-right oriented.
Diffstat (limited to 'source/blender/imbuf/intern/cineon/dpxlib.c')
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c975
1 files changed, 364 insertions, 611 deletions
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 0a067af2cb9..dc5f42ecaad 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -1,21 +1,23 @@
/*
- * Dpx image file format library routines.
+ * Dpx image file format library routines.
*
- * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
+ * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
@@ -23,689 +25,440 @@
* \ingroup imbcineon
*/
-#include "dpxfile.h"
+
#include "dpxlib.h"
+#include "logmemfile.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
-#include <time.h> /* strftime() */
+#include <time.h>
#include <sys/types.h>
-#ifdef WIN32
-#include <winsock.h>
-#else
-#include <netinet/in.h> /* htonl() */
-#endif
-#include <string.h> /* memset */
-#include "cin_debug_stuff.h"
-#include "logmemfile.h"
-#include "BLI_fileops.h"
-
-static void
-fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) {
-
- (void)dpx; /* unused */
-
- chan->signage = 0;
- chan->ref_low_data = htonl(0);
- chan->ref_low_quantity = htonf(0.0);
- chan->ref_high_data = htonl(1023);
- chan->ref_high_quantity = htonf(2.046);
- chan->designator1 = des;
- chan->transfer_characteristics = 0;
- chan->colorimetry = 0;
- chan->bits_per_pixel = 10;
- chan->packing = htons(1);
- chan->encoding = 0;
- chan->data_offset = 0;
- chan->line_padding = htonl(0);
- chan->channel_padding = htonl(0);
- chan->description[0] = 0;
-}
-
-static void
-dumpDpxChannelInfo(DpxChannelInformation* chan) {
- d_printf(" Signage %ld", (intptr_t)ntohl(chan->signage));
- d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
- d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
- d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
- d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
- d_printf(" Designator1: %d,", chan->designator1);
- d_printf(" Bits per pixel %d\n", chan->bits_per_pixel);
- d_printf(" Packing: %d,", ntohs(chan->packing));
- d_printf(" Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset));
-}
-
-static void
-fillDpxFileInfo(
- DpxFile* dpx, DpxFileInformation* fileInfo, const char* filename) {
-
- time_t fileClock;
- struct tm* fileTime;
-
- /* Note: always write files in network order */
- /* By the spec, it shouldn't matter, but ... */
-
- fileInfo->magic_num = htonl(DPX_FILE_MAGIC);
- fileInfo->offset = htonl(dpx->imageOffset);
- strcpy(fileInfo->vers, "v1.0");
- fileInfo->file_size = htonl(dpx->imageOffset +
- pixelsToLongs(dpx->height * dpx->width * dpx->depth) * 4);
- fileInfo->ditto_key = 0;
- fileInfo->gen_hdr_size = htonl(
- sizeof(DpxFileInformation) +
- sizeof(DpxImageInformation) +
- sizeof(DpxOriginationInformation));
- fileInfo->ind_hdr_size = htonl(sizeof(DpxMPIInformation));
- fileInfo->user_data_size = 0;
- strncpy(fileInfo->file_name, filename, 99);
- fileInfo->file_name[99] = 0;
+#include <string.h>
- fileClock = time(0);
- fileTime = localtime(&fileClock);
- strftime(fileInfo->create_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
- /* Question: is %Z in strftime guaranteed to return 3 chars? */
- fileInfo->create_date[23] = 0;
-
- strcpy(fileInfo->creator, "David's DPX writer");
- fileInfo->project[0] = 0;
- fileInfo->copyright[0] = 0;
- fileInfo->key = 0xFFFFFFFF; /* same in any byte order */
-}
+#include "BLI_fileops.h"
-static void
-dumpDpxFileInfo(DpxFileInformation* fileInfo) {
- d_printf("\n--File Information--\n");
- d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num));
- d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset));
- d_printf("Version \"%s\"\n", fileInfo->vers);
- d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
- d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key));
- d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
- d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
- d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
- d_printf("File name \"%s\"\n", fileInfo->file_name);
- d_printf("Creation date \"%s\"\n", fileInfo->create_date);
- d_printf("Creator \"%s\"\n", fileInfo->creator);
- d_printf("Project \"%s\"\n", fileInfo->project);
- d_printf("Copyright \"%s\"\n", fileInfo->copyright);
- d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key));
-}
+#include "MEM_guardedalloc.h"
-static void
-fillDpxImageInfo(
- DpxFile* dpx, DpxImageInformation* imageInfo) {
- imageInfo->orientation = 0;
- imageInfo->channels_per_image = htons(1);
- imageInfo->pixels_per_line = htonl(dpx->width);
- imageInfo->lines_per_image = htonl(dpx->height);
+/*
+ * For debug purpose
+ */
- if (dpx->depth == 1) {
- fillDpxChannelInfo(dpx, &imageInfo->channel[0], 0);
+static int verbose = 0;
- }
- else if (dpx->depth == 3) {
- fillDpxChannelInfo(dpx, &imageInfo->channel[0], 50);
- }
+void dpxSetVerbose(int verbosity) {
+ verbose = verbosity;
}
-static void
-dumpDpxImageInfo(DpxImageInformation* imageInfo) {
- int n;
- int i;
- d_printf("\n--Image Information--\n");
- d_printf("Image orientation %d,", ntohs(imageInfo->orientation));
- n = ntohs(imageInfo->channels_per_image);
- d_printf("Channels %d\n", n);
- d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line));
- d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image));
- for (i = 0; i < n; ++i) {
- d_printf(" --Channel %d--\n", i);
- dumpDpxChannelInfo(&imageInfo->channel[i]);
- }
-}
+/*
+ * Headers
+ */
-static void
-fillDpxOriginationInfo(
- DpxFile* dpx, DpxOriginationInformation* originInfo, DpxFileInformation* fileInfo)
+static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const char *filename, const char *creator)
{
- /* unused */
- (void)dpx;
- (void)originInfo;
- (void)fileInfo;
-}
-
-static void
-dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) {
- d_printf("\n--Origination Information--\n");
- d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
- d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
- d_printf("X centre %f\n", ntohf(originInfo->x_centre));
- d_printf("Y centre %f\n", ntohf(originInfo->y_centre));
- d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size));
- d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size));
- d_printf("File name \"%s\"\n", originInfo->file_name);
- d_printf("Creation time \"%s\"\n", originInfo->creation_time);
- d_printf("Input device \"%s\"\n", originInfo->input_device);
- d_printf("Serial number \"%s\"\n", originInfo->input_serial_number);
-}
+ time_t fileClock;
+ struct tm *fileTime;
-static void
-initDpxMainHeader(DpxFile* dpx, DpxMainHeader* header, const char* shortFilename) {
memset(header, 0, sizeof(DpxMainHeader));
- fillDpxFileInfo(dpx, &header->fileInfo, shortFilename);
- fillDpxImageInfo(dpx, &header->imageInfo);
- fillDpxOriginationInfo(dpx, &header->originInfo, &header->fileInfo);
-#if 0
- fillDpxMPIInfo(dpx, &header->filmHeader);
-#endif
-}
-
-static void
-dumpDpxMainHeader(DpxMainHeader* header) {
- dumpDpxFileInfo(&header->fileInfo);
- dumpDpxImageInfo(&header->imageInfo);
- dumpDpxOriginationInfo(&header->originInfo);
-#if 0
- dumpDpxMPIInformation(&header->filmHeader);
-#endif
-}
-
-static int verbose = 0;
-void
-dpxSetVerbose(int verbosity) {
- verbose = verbosity;
-}
-
-static void
-verboseMe(DpxFile* dpx) {
-
- d_printf("size %d x %d x %d\n", dpx->width, dpx->height, dpx->depth);
- d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
- dpx->imageOffset, dpx->lineBufferLength * 4,
- dpx->imageOffset + pixelsToLongs(dpx->width * dpx->depth * dpx->height) * 4);
-}
-
-int
-dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) {
-
- /* Note: this code is bizarre because DPX files can wrap */
- /* packed longwords across line boundaries!!!! */
-
- size_t readLongs;
- unsigned int longIndex;
- int numPixels = dpx->width * dpx->depth;
- int pixelIndex;
-
- /* only seek if not reading consecutive lines */
- /* this is not quite right yet, need to account for leftovers */
- if (y != dpx->fileYPos) {
- int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
- if (verbose) d_printf("Seek in getRowBytes\n");
- if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
- return 1;
- }
- dpx->fileYPos = y;
- }
-
- /* read enough longwords */
- readLongs = pixelsToLongs(numPixels - dpx->pixelBufferUsed);
- if (logimage_fread(dpx->lineBuffer, 4, readLongs, dpx) != readLongs) {
- if (verbose) d_printf("Couldn't read line %d length %d\n", y, (int)readLongs * 4);
- return 1;
- }
- ++dpx->fileYPos;
-
- /* convert longwords to pixels */
- pixelIndex = dpx->pixelBufferUsed;
-
- /* this is just strange */
- if (dpx->depth == 1) {
- for (longIndex = 0; longIndex < readLongs; ++longIndex) {
- unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
- dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
- pixelIndex += 3;
- }
- }
- else /* if (dpx->depth == 3) */ {
- for (longIndex = 0; longIndex < readLongs; ++longIndex) {
- unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
- t = t >> 2;
- dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
- pixelIndex += 3;
- }
- }
- dpx->pixelBufferUsed = pixelIndex;
-
- /* extract required pixels */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (dpx->params.doLogarithm)
- row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]];
- else
- row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6;
- }
-
- /* save remaining pixels */
- while (pixelIndex < dpx->pixelBufferUsed) {
- dpx->pixelBuffer[pixelIndex - numPixels] = dpx->pixelBuffer[pixelIndex];
- ++pixelIndex;
- }
- dpx->pixelBufferUsed -= numPixels;
- /* done! */
- return 0;
-}
-
-int
-dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) {
-
- /* Note: this code is bizarre because DPX files can wrap */
- /* packed longwords across line boundaries!!!! */
-
- size_t writeLongs;
- int longIndex;
- int numPixels = dpx->width * dpx->depth;
- int pixelIndex;
- int pixelIndex2;
-
- /* only seek if not reading consecutive lines */
- /* this is not quite right yet */
- if (y != dpx->fileYPos) {
- int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
- if (verbose) d_printf("Seek in getRowBytes\n");
- if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
- return 1;
- }
- dpx->fileYPos = y;
- }
-
- /* put new pixels into pixelBuffer */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (dpx->params.doLogarithm)
- dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]];
- else
- dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6;
- }
- dpx->pixelBufferUsed += numPixels;
-
- /* pack into longwords */
- writeLongs = dpx->pixelBufferUsed / 3;
- /* process whole line at image end */
- if (dpx->fileYPos == (dpx->height - 1)) {
- writeLongs = pixelsToLongs(dpx->pixelBufferUsed);
- }
- pixelIndex = 0;
- if (dpx->depth == 1) {
- for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
- unsigned int t = dpx->pixelBuffer[pixelIndex] |
- (dpx->pixelBuffer[pixelIndex+1] << 10) |
- (dpx->pixelBuffer[pixelIndex+2] << 20);
- dpx->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
- }
- else {
- for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
- unsigned int t = dpx->pixelBuffer[pixelIndex+2] << 2 |
- (dpx->pixelBuffer[pixelIndex+1] << 12) |
- (dpx->pixelBuffer[pixelIndex] << 22);
- dpx->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
- }
-
- /* write them */
- if (fwrite(dpx->lineBuffer, 4, writeLongs, dpx->file) != writeLongs) {
- if (verbose) d_printf("Couldn't write line %d length %d\n", y, (int)writeLongs * 4);
- return 1;
- }
- ++dpx->fileYPos;
-
- /* save remaining pixels */
- pixelIndex2 = 0;
- while (pixelIndex < dpx->pixelBufferUsed) {
- dpx->pixelBuffer[pixelIndex2] = dpx->pixelBuffer[pixelIndex];
- ++pixelIndex;
- ++pixelIndex2;
- }
- dpx->pixelBufferUsed = pixelIndex2;
-
- return 0;
+ /* --- File header --- */
+ header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB);
+ header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
+ strcpy(header->fileHeader.version, "v2.0");
+ header->fileHeader.file_size = swap_uint(dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, dpx->element[0]), dpx->isMSB);
+ header->fileHeader.ditto_key = 0;
+ header->fileHeader.gen_hdr_size = swap_uint(sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB);
+ header->fileHeader.ind_hdr_size = swap_uint(sizeof(DpxFilmHeader) + sizeof(DpxTelevisionHeader), dpx->isMSB);
+ header->fileHeader.user_data_size = DPX_UNDEFINED_U32;
+ strncpy(header->fileHeader.file_name, filename, 99);
+ header->fileHeader.file_name[99] = 0;
+ fileClock = time(0);
+ fileTime = localtime(&fileClock);
+ strftime(header->fileHeader.creation_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
+ header->fileHeader.creation_date[23] = 0;
+ strncpy(header->fileHeader.creator, creator, 99);
+ header->fileHeader.creator[99] = 0;
+ header->fileHeader.project[0] = 0;
+ header->fileHeader.copyright[0] = 0;
+ header->fileHeader.key = 0xFFFFFFFF;
+
+ /* --- Image header --- */
+ header->imageHeader.orientation = 0;
+ header->imageHeader.elements_per_image = swap_ushort(1, dpx->isMSB);
+ header->imageHeader.pixels_per_line = swap_uint(dpx->width, dpx->isMSB);
+ header->imageHeader.lines_per_element = swap_uint(dpx->height, dpx->isMSB);
+
+ /* Fills element */
+ header->imageHeader.element[0].data_sign = 0;
+ header->imageHeader.element[0].ref_low_data = swap_uint(dpx->element[0].refLowData, dpx->isMSB);
+ header->imageHeader.element[0].ref_low_quantity = swap_float(dpx->element[0].refLowQuantity, dpx->isMSB);
+ header->imageHeader.element[0].ref_high_data = swap_uint(dpx->element[0].refHighData, dpx->isMSB);
+ header->imageHeader.element[0].ref_high_quantity = swap_float(dpx->element[0].refHighQuantity, dpx->isMSB);
+ header->imageHeader.element[0].descriptor = dpx->element[0].descriptor;
+ header->imageHeader.element[0].transfer = dpx->element[0].transfer;
+ header->imageHeader.element[0].colorimetric = 0;
+ header->imageHeader.element[0].bits_per_sample = dpx->element[0].bitsPerSample;
+ header->imageHeader.element[0].packing = swap_ushort(dpx->element[0].packing, dpx->isMSB);
+ header->imageHeader.element[0].encoding = 0;
+ header->imageHeader.element[0].data_offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
+ header->imageHeader.element[0].line_padding = 0;
+ header->imageHeader.element[0].element_padding = 0;
+ header->imageHeader.element[0].description[0] = 0;
+
+ /* --- Orientation header --- */
+ /* we leave it blank */
+
+ /* --- Television header --- */
+ header->televisionHeader.time_code = DPX_UNDEFINED_U32;
+ header->televisionHeader.user_bits = DPX_UNDEFINED_U32;
+ header->televisionHeader.interlace = DPX_UNDEFINED_U8;
+ header->televisionHeader.field_number = DPX_UNDEFINED_U8;
+ header->televisionHeader.video_signal = DPX_UNDEFINED_U8;
+ header->televisionHeader.padding = DPX_UNDEFINED_U8;
+ header->televisionHeader.horizontal_sample_rate = DPX_UNDEFINED_R32;
+ header->televisionHeader.vertical_sample_rate = DPX_UNDEFINED_R32;
+ header->televisionHeader.frame_rate = DPX_UNDEFINED_R32;
+ header->televisionHeader.time_offset = DPX_UNDEFINED_R32;
+ header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB);
+ header->televisionHeader.black_level = swap_float(dpx->referenceBlack, dpx->isMSB);
+ header->televisionHeader.black_gain = DPX_UNDEFINED_R32;
+ header->televisionHeader.breakpoint = DPX_UNDEFINED_R32;
+ header->televisionHeader.white_level = swap_float(dpx->referenceWhite, dpx->isMSB);
+ header->televisionHeader.integration_times = DPX_UNDEFINED_R32;
}
-#define LFMEMFILE 0
-#define LFREALFILE 1
-
-static DpxFile*
-intern_dpxOpen(int mode, const char* bytestuff, int bufsize) {
-
+LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
+{
DpxMainHeader header;
- const char *filename = bytestuff;
- DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
-
+ LogImageFile *dpx = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
+ char *filename = (char*)byteStuff;
+ int i;
+
if (dpx == 0) {
- if (verbose) d_printf("Failed to malloc dpx file structure.\n");
+ if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
return 0;
}
+ /* zero the header */
+ memset(&header, 0, sizeof(DpxMainHeader));
+
/* for close routine */
dpx->file = 0;
- dpx->lineBuffer = 0;
- dpx->pixelBuffer = 0;
- if (mode == LFREALFILE) {
- filename = bytestuff;
+ if (fromMemory == 0) {
+ /* byteStuff is then the filename */
dpx->file = BLI_fopen(filename, "rb");
if (dpx->file == 0) {
- if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
- dpxClose(dpx);
+ if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename);
+ logImageClose(dpx);
return 0;
}
- dpx->membuffer = 0;
- dpx->memcursor = 0;
- dpx->membuffersize = 0;
+ /* not used in this case */
+ dpx->memBuffer = 0;
+ dpx->memCursor = 0;
+ dpx->memBufferSize = 0;
+ } else {
+ dpx->memBuffer = (unsigned char*)byteStuff;
+ dpx->memCursor = (unsigned char*)byteStuff;
+ dpx->memBufferSize = bufferSize;
}
- else if (mode == LFMEMFILE) {
- dpx->membuffer = (unsigned char *)bytestuff;
- dpx->memcursor = (unsigned char *)bytestuff;
- dpx->membuffersize = bufsize;
- }
-
- dpx->reading = 1;
if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
- if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
- dpxClose(dpx);
- return 0;
- }
-
- /* let's assume dpx files are always network order */
- if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) {
- if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
- (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
- dpxClose(dpx);
+ if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff);
+ logImageClose(dpx);
return 0;
}
- if (ntohs(header.imageInfo.channel[0].packing) != 1) {
- if (verbose) d_printf("Unknown packing %d\n", header.imageInfo.channel[0].packing);
- dpxClose(dpx);
+ /* endianness determination */
+ if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) {
+ dpx->isMSB = 1;
+ if (verbose) printf("DPX: File is MSB.\n");
+ } else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) {
+ dpx->isMSB = 0;
+ if (verbose) printf("DPX: File is LSB.\n");
+ } else {
+ if (verbose) printf("DPX: Bad magic number %lu in \"%s\".\n",
+ (uintptr_t)header.fileHeader.magic_num, byteStuff);
+ logImageClose(dpx);
return 0;
}
+ dpx->srcFormat = format_DPX;
+ dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB);
+ dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB);
+ dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB);
+ dpx->depth = 0;
+
+ for (i = 0; i < dpx->numElements; i++) {
+ dpx->element[i].descriptor = header.imageHeader.element[i].descriptor;
+
+ switch (dpx->element[i].descriptor) {
+ case descriptor_Red:
+ case descriptor_Green:
+ case descriptor_Blue:
+ case descriptor_Alpha:
+ case descriptor_Luminance:
+ case descriptor_Chrominance:
+ dpx->depth++;
+ dpx->element[i].depth = 1;
+ break;
+
+ case descriptor_CbYCrY:
+ dpx->depth += 2;
+ dpx->element[i].depth = 2;
+ break;
+
+ case descriptor_RGB:
+ case descriptor_CbYCr:
+ case descriptor_CbYACrYA:
+ dpx->depth += 3;
+ dpx->element[i].depth = 3;
+ break;
+
+ case descriptor_RGBA:
+ case descriptor_ABGR:
+ case descriptor_CbYCrA:
+ dpx->depth += 4;
+ dpx->element[i].depth = 4;
+ break;
+
+ case descriptor_Depth:
+ case descriptor_Composite:
+ /* unsupported */
+ break;
+ }
- dpx->width = ntohl(header.imageInfo.pixels_per_line);
- dpx->height = ntohl(header.imageInfo.lines_per_image);
- dpx->depth = ntohs(header.imageInfo.channels_per_image);
- /* Another DPX vs Cineon wierdness */
- if (dpx->depth == 1) {
- switch (header.imageInfo.channel[0].designator1) {
- case 50: dpx->depth = 3; break;
- case 51: dpx->depth = 4; break;
- case 52: dpx->depth = 4; break;
- default: break;
+ if (dpx->depth == 0 || dpx->depth > 4) {
+ if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth);
+ logImageClose(dpx);
+ return 0;
}
- }
- /* dpx->bitsPerPixel = 10; */
- dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
- if (dpx->bitsPerPixel != 10) {
- if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel);
- dpxClose(dpx);
- return 0;
- }
- dpx->imageOffset = ntohl(header.fileInfo.offset);
- dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
- dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
- if (dpx->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
- dpxClose(dpx);
- return 0;
- }
+ dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
+ dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f;
+ dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB);
- /* could have 2 pixels left over */
- dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
- if (dpx->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
- dpxClose(dpx);
- return 0;
- }
- dpx->pixelBufferUsed = 0;
+ /* Sometimes, the offset is not set correctly in the header */
+ dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB);
+ if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1)
+ dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB);
- if (logimage_fseek(dpx, dpx->imageOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to image data start at %d\n", dpx->imageOffset);
- dpxClose(dpx);
- return 0;
- }
- dpx->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&dpx->params);
- /* The SMPTE define this code:
- * 0 - User-defined
- * 1 - Printing density
- * 2 - Linear
- * 3 - Logarithmic
- * 4 - Unspecified video
- * 5 - SMPTE 240M
- * 6 - CCIR 709-1
- * 7 - CCIR 601-2 system B or G
- * 8 - CCIR 601-2 system M
- * 9 - NTSC composite video
- * 10 - PAL composite video
- * 11 - Z linear
- * 12 - homogeneous
- *
- * Note that transfer_characteristics is U8, don't need
- * check the byte order.
- */
-
- switch (header.imageInfo.channel[0].transfer_characteristics) {
- case 1:
- case 2: /* linear */
- dpx->params.doLogarithm= 0;
- break;
-
- case 3:
- dpx->params.doLogarithm= 1;
- break;
-
- /* TODO - Unsupported, but for now just load them,
- * colors may look wrong, but can solve color conversion later
- */
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics);
- dpx->params.doLogarithm= 0;
- break;
- default:
- if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics);
- dpxClose(dpx);
+ if (dpx->element[i].dataOffset == 0) {
+ if (verbose) printf("DPX: Image header is corrupted.\n");
+ logImageClose(dpx);
return 0;
- break;
- }
- setupLut(dpx);
-
- dpx->getRow = &dpxGetRowBytes;
- dpx->setRow = 0;
- dpx->close = &dpxClose;
+ }
- if (verbose) {
- verboseMe(dpx);
+ dpx->element[i].transfer = header.imageHeader.element[i].transfer;
+
+ /* if undefined, assign default */
+ dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB);
+ dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, dpx->isMSB);
+ dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, dpx->isMSB);
+ dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, dpx->isMSB);
+
+ switch (dpx->element[i].descriptor) {
+ case descriptor_Red:
+ case descriptor_Green:
+ case descriptor_Blue:
+ case descriptor_Alpha:
+ case descriptor_RGB:
+ case descriptor_RGBA:
+ case descriptor_ABGR:
+ if (dpx->element[i].refLowData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refLowData))
+ dpx->element[i].refLowData = 0;
+
+ if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData))
+ dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue;
+
+ if(dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity))
+ dpx->element[i].refLowQuantity = 0.0f;
+
+ if(dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) {
+ if (dpx->element[i].transfer == transfer_PrintingDensity || dpx->element[i].transfer == transfer_Logarithmic)
+ dpx->element[i].refHighQuantity = 2.048f;
+ else
+ dpx->element[i].refHighQuantity = dpx->element[i].maxValue;
+ }
+
+ break;
+
+ case descriptor_Luminance:
+ case descriptor_Chrominance:
+ case descriptor_CbYCrY:
+ case descriptor_CbYCr:
+ case descriptor_CbYACrYA:
+ case descriptor_CbYCrA:
+ if (dpx->element[i].refLowData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refLowData))
+ dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue;
+
+ if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData))
+ dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue;
+
+ if(dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity))
+ dpx->element[i].refLowQuantity = 0.0f;
+
+ if(dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity))
+ dpx->element[i].refHighQuantity = 0.7f;
+
+ break;
+
+ default:
+ break;
+ }
}
- return dpx;
-}
-
-DpxFile*
-dpxOpen(const char *filename) {
- return intern_dpxOpen(LFREALFILE, filename, 0);
-}
+ dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB);
+ dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB);
+ dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB);
-DpxFile*
-dpxOpenFromMem(unsigned char *buffer, unsigned int size) {
- return intern_dpxOpen(LFMEMFILE, (const char *) buffer, size);
-}
+ if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) ||
+ (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) ||
+ (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma)))
+ {
-int
-dpxIsMemFileCineon(void *buffer) {
- int magicnum = 0;
- magicnum = *((int*)buffer);
- if (magicnum == ntohl(DPX_FILE_MAGIC)) return 1;
- else return 0;
-}
+ dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
+ dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
+ dpx->gamma = 1.7f;
+ }
-DpxFile*
-dpxCreate(const char* filename, int width, int height, int depth) {
+ if (verbose) {
+ printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements);
+ for (i = 0; i < dpx->numElements; i++) {
+ printf(" Element %d:\n", i);
+ printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample);
+ printf(" Depth: %d\n", dpx->element[i].depth);
+ printf(" Transfer characteristics: %d\n", dpx->element[i].transfer);
+ printf(" Packing: %d\n", dpx->element[i].packing);
+ printf(" Descriptor: %d\n", dpx->element[i].descriptor);
+ printf(" Data offset: %u\n", dpx->element[i].dataOffset);
+ printf(" Reference low data: %u\n", dpx->element[i].refLowData);
+ printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity);
+ printf(" Reference high data: %u\n", dpx->element[i].refHighData);
+ printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity);
+ printf("\n");
+ }
- /* Note: always write files in network order */
- /* By the spec, it shouldn't matter, but ... */
+ printf("Gamma: %f\n", dpx->gamma);
+ printf("Reference black: %f\n", dpx->referenceBlack);
+ printf("Reference white: %f\n", dpx->referenceWhite);
+ printf("----------------------------\n");
+ }
+ return dpx;
+}
+LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha,
+ int isLogarithmic, int referenceWhite, int referenceBlack, float gamma,
+ const char *creator)
+{
DpxMainHeader header;
- const char* shortFilename = 0;
+ const char *shortFilename = 0;
+ unsigned char pad[6044];
- DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
+ LogImageFile *dpx = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
if (dpx == 0) {
- if (verbose) d_printf("Failed to malloc dpx file structure.\n");
- return 0;
- }
-
- memset(&header, 0, sizeof(header));
-
- /* for close routine */
- dpx->file = 0;
- dpx->lineBuffer = 0;
- dpx->pixelBuffer = 0;
-
- dpx->file = BLI_fopen(filename, "wb");
- if (dpx->file == 0) {
- if (verbose) d_printf("Couldn't open file %s\n", filename);
- dpxClose(dpx);
+ if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
return 0;
}
- dpx->reading = 0;
dpx->width = width;
dpx->height = height;
- dpx->depth = depth;
- dpx->bitsPerPixel = 10;
- dpx->imageOffset = sizeof(DpxMainHeader);
-
- dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
- dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
- if (dpx->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
- dpxClose(dpx);
- return 0;
- }
+ dpx->element[0].bitsPerSample = bitsPerSample;
+ dpx->element[0].dataOffset = 8092;
+ dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f;
+ dpx->isMSB = 1;
+ dpx->numElements = 1;
- dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
- if (dpx->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
- dpxClose(dpx);
- return 0;
+ switch (bitsPerSample) {
+ case 8:
+ case 16:
+ dpx->element[0].packing = 0;
+ break;
+
+ case 10:
+ case 12:
+ /* Packed Type A padding is the most common 10/12 bits format */
+ dpx->element[0].packing = 1;
+ break;
+
+ default:
+ if (verbose) printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample);
+ logImageClose(dpx);
+ return 0;
}
- dpx->pixelBufferUsed = 0;
- /* find trailing part of filename */
- shortFilename = strrchr(filename, '/');
- if (shortFilename == 0) {
- shortFilename = filename;
+ if (hasAlpha == 0) {
+ dpx->depth = 3;
+ dpx->element[0].depth = 3;
+ dpx->element[0].descriptor = descriptor_RGB;
}
else {
- ++shortFilename;
+ dpx->depth = 4;
+ dpx->element[0].depth = 4;
+ dpx->element[0].descriptor = descriptor_RGBA;
}
- initDpxMainHeader(dpx, &header, shortFilename);
- logImageGetByteConversionDefaults(&dpx->params);
- /* Need set the file type before write the header!
- * 2 - Linear
- * 3 - Logarithmic
- *
- * Note that transfer characteristics is U8, don't need
- * check the byte order.
- */
- if (dpx->params.doLogarithm == 0)
- header.imageInfo.channel[0].transfer_characteristics= 2;
- else
- header.imageInfo.channel[0].transfer_characteristics= 3;
- if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
- if (verbose) d_printf("Couldn't write image header\n");
- dpxClose(dpx);
- return 0;
+ if (isLogarithmic == 0) {
+ dpx->element[0].transfer = transfer_Linear;
+ dpx->element[0].refHighQuantity = dpx->element[0].maxValue;
}
- dpx->fileYPos = 0;
- setupLut(dpx);
+ else {
+ dpx->element[0].transfer = transfer_PrintingDensity;
+ dpx->element[0].refHighQuantity = 2.048f;
- dpx->getRow = 0;
- dpx->setRow = &dpxSetRowBytes;
- dpx->close = &dpxClose;
+ }
- return dpx;
-}
+ dpx->element[0].refLowQuantity = 0;
+ dpx->element[0].refLowData = 0;
+ dpx->element[0].refHighData = dpx->element[0].maxValue;
-void
-dpxClose(DpxFile* dpx) {
+ if (referenceWhite > 0)
+ dpx->referenceWhite = referenceWhite;
+ else
+ dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
- if (dpx == 0) {
- return;
- }
+ if (referenceBlack > 0)
+ dpx->referenceBlack = referenceBlack;
+ else
+ dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
- if (dpx->file) {
- fclose(dpx->file);
- dpx->file = 0;
- }
+ if (gamma > 0.0f)
+ dpx->gamma = gamma;
+ else
+ dpx->gamma = 1.7f;
- if (dpx->lineBuffer) {
- free(dpx->lineBuffer);
- dpx->lineBuffer = 0;
- }
- if (dpx->pixelBuffer) {
- free(dpx->pixelBuffer);
- dpx->pixelBuffer = 0;
- }
+ shortFilename = strrchr(filename, '/');
+ if (shortFilename == 0)
+ shortFilename = filename;
+ else
+ shortFilename++;
- free(dpx);
-}
+ dpx->file = BLI_fopen(filename, "wb");
-void
-dpxDump(const char* filename) {
+ if (dpx->file == 0) {
+ if (verbose) printf("DPX: Couldn't open file %s\n", filename);
+ logImageClose(dpx);
+ return 0;
+ }
- DpxMainHeader header;
- FILE* file;
+ fillDpxMainHeader(dpx, &header, shortFilename, creator);
- file = BLI_fopen(filename, "rb");
- if (file == 0) {
- d_printf("Failed to open file \"%s\".\n", filename);
- return;
+ if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
+ if (verbose) printf("DPX: Couldn't write image header\n");
+ logImageClose(dpx);
+ return 0;
}
- if (fread(&header, sizeof(header), 1, file) == 0) {
- d_printf("Not enough data for header in \"%s\".\n", filename);
- fclose(file);
- return;
+ /* Header should be rounded to next 8k block
+ 6044 = 8092 - sizeof(DpxMainHeader) */
+ memset(&pad, 0, 6044);
+ if (fwrite(&pad, 6044, 1, dpx->file) == 0) {
+ if (verbose) printf("DPX: Couldn't write image header\n");
+ logImageClose(dpx);
+ return 0;
}
- fclose(file);
- dumpDpxMainHeader(&header);
+ return dpx;
}