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/cineonlib.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/cineonlib.c')
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c1010
1 files changed, 280 insertions, 730 deletions
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index 894e3a93b4b..92a984378db 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -1,21 +1,23 @@
/*
- * Cineon image file format library routines.
+ * Cineon image file format library routines.
*
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
+ * Copyright 1999,2000,2001 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,800 +25,348 @@
* \ingroup imbcineon
*/
+
#include "cineonlib.h"
-#include "cineonfile.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 "BLI_utildefines.h"
-#include "BLI_fileops.h"
-
-#include "cin_debug_stuff.h"
-#include "logmemfile.h"
-
-static void
-fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) {
+#include <string.h>
- time_t fileClock;
- struct tm* fileTime;
-
- fileInfo->magic_num = htonl(CINEON_FILE_MAGIC);
- fileInfo->image_offset = htonl(cineon->imageOffset);
- fileInfo->gen_hdr_size = htonl(
- sizeof(CineonFileInformation) +
- sizeof(CineonImageInformation) +
- sizeof(CineonFormatInformation) +
- sizeof(CineonOriginationInformation));
- fileInfo->ind_hdr_size = 0;
- fileInfo->user_data_size = 0;
- fileInfo->file_size = htonl(cineon->imageOffset + cineon->height * cineon->lineBufferLength);
- strcpy(fileInfo->vers, "V4.5");
- strncpy(fileInfo->file_name, filename, 99);
- fileInfo->file_name[99] = 0;
-
- fileClock = time(0);
- fileTime = localtime(&fileClock);
- strftime(fileInfo->create_date, 12, "%Y:%m:%d", fileTime);
- /* Question: is %Z in strftime guaranteed to return 3 chars? */
- strftime(fileInfo->create_time, 12, "%H:%M:%S%Z", fileTime);
- fileInfo->create_time[11] = 0;
-}
-
-static void
-dumpCineonFileInfo(CineonFileInformation* fileInfo) {
- d_printf("\n--File Information--\n");
- d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num));
- d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset));
- 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 size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
- d_printf("Version \"%s\"\n", fileInfo->vers);
- d_printf("File name \"%s\"\n", fileInfo->file_name);
- d_printf("Creation date \"%s\"\n", fileInfo->create_date);
- d_printf("Creation time \"%s\"\n", fileInfo->create_time);
-}
-
-static void
-fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) {
-
- chan->designator1 = 0;
- chan->designator2 = des;
- chan->bits_per_pixel = 10;
- chan->pixels_per_line = htonl(cineon->width);
- chan->lines_per_image = htonl(cineon->height);
- 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);
-}
-
-static void
-dumpCineonChannelInfo(CineonChannelInformation* chan) {
- d_printf(" Metric selector: %d", chan->designator1);
- switch (chan->designator1) {
- case 0: d_printf(" (Universal)\n"); break;
- default: d_printf(" (Vendor specific)\n"); break;
- }
- d_printf(" Metric: %d,", chan->designator2);
- switch (chan->designator2) {
- case 0: d_printf(" B&W (printing density?)\n"); break;
- case 1: d_printf(" Red printing density\n"); break;
- case 2: d_printf(" Green printing density\n"); break;
- case 3: d_printf(" Blue printing density\n"); break;
- case 4: d_printf(" Red CCIR XA/11\n"); break;
- case 5: d_printf(" Green CCIR XA/11\n"); break;
- case 6: d_printf(" Blue CCIR XA/11\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf(" Bits per pixel %d\n", chan->bits_per_pixel);
- d_printf(" Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line));
- d_printf(" Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image));
- 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));
-}
-
-static void
-fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) {
-
- imageInfo->orientation = 0;
- imageInfo->channels_per_image = cineon->depth;
-
- if (cineon->depth == 1) {
- fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0);
-
- }
- else if (cineon->depth == 3) {
- fillCineonChannelInfo(cineon, &imageInfo->channel[0], 1);
- fillCineonChannelInfo(cineon, &imageInfo->channel[1], 2);
- fillCineonChannelInfo(cineon, &imageInfo->channel[2], 3);
- }
-
- imageInfo->white_point_x = htonf(undefined());
- imageInfo->white_point_y = htonf(undefined());
- imageInfo->red_primary_x = htonf(undefined());
- imageInfo->red_primary_y = htonf(undefined());
- imageInfo->green_primary_x = htonf(undefined());
- imageInfo->green_primary_y = htonf(undefined());
- imageInfo->blue_primary_x = htonf(undefined());
- imageInfo->blue_primary_y = htonf(undefined());
-
- strcpy(imageInfo->label, "David's Cineon writer.");
-
-}
-
-static void
-dumpCineonImageInfo(CineonImageInformation* imageInfo) {
-
- int i;
- d_printf("\n--Image Information--\n");
- d_printf("Image orientation %d,", imageInfo->orientation);
- switch (imageInfo->orientation) {
- case 0: d_printf(" LRTB\n"); break;
- case 1: d_printf(" LRBT\n"); break;
- case 2: d_printf(" RLTB\n"); break;
- case 3: d_printf(" RLBT\n"); break;
- case 4: d_printf(" TBLR\n"); break;
- case 5: d_printf(" TBRL\n"); break;
- case 6: d_printf(" BTLR\n"); break;
- case 7: d_printf(" BTRL\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf("Channels %d\n", imageInfo->channels_per_image);
- for (i = 0; i < imageInfo->channels_per_image; ++i) {
- d_printf(" --Channel %d--\n", i);
- dumpCineonChannelInfo(&imageInfo->channel[i]);
- }
-
- d_printf("White point x %f\n", ntohf(imageInfo->white_point_x));
- d_printf("White point y %f\n", ntohf(imageInfo->white_point_y));
- d_printf("Red primary x %f\n", ntohf(imageInfo->red_primary_x));
- d_printf("Red primary y %f\n", ntohf(imageInfo->red_primary_y));
- d_printf("Green primary x %f\n", ntohf(imageInfo->green_primary_x));
- d_printf("Green primary y %f\n", ntohf(imageInfo->green_primary_y));
- d_printf("Blue primary x %f\n", ntohf(imageInfo->blue_primary_x));
- d_printf("Blue primary y %f\n", ntohf(imageInfo->blue_primary_y));
- d_printf("Label \"%s\"\n", imageInfo->label);
-}
-
-static void
-fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) {
-
- (void)cineon; /* unused */
-
- formatInfo->interleave = 0;
- formatInfo->packing = 5;
- formatInfo->signage = 0;
- formatInfo->sense = 0;
- formatInfo->line_padding = htonl(0);
- formatInfo->channel_padding = htonl(0);
-}
-
-static void
-dumpCineonFormatInfo(CineonFormatInformation* formatInfo) {
- d_printf("\n--Format Information--\n");
- d_printf("Interleave %d,", formatInfo->interleave);
- switch (formatInfo->interleave) {
- case 0: d_printf(" pixel interleave\n"); break;
- case 1: d_printf(" line interleave\n"); break;
- case 2: d_printf(" channel interleave\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf("Packing %d,", formatInfo->packing);
- if (formatInfo->packing & 0x80) {
- d_printf(" multi pixel,");
- }
- else {
- d_printf(" single pixel,");
- }
- switch (formatInfo->packing & 0x7F) {
- case 0: d_printf(" tight\n"); break;
- case 1: d_printf(" byte packed left\n"); break;
- case 2: d_printf(" byte packed right\n"); break;
- case 3: d_printf(" word packed left\n"); break;
- case 4: d_printf(" word packed right\n"); break;
- case 5: d_printf(" long packed left\n"); break;
- case 6: d_printf(" long packed right\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf("Sign %d,", formatInfo->signage);
- if (formatInfo->signage) {
- d_printf(" signed\n");
- }
- else {
- d_printf(" unsigned\n");
- }
- d_printf("Sense %d,", formatInfo->signage);
- if (formatInfo->signage) {
- d_printf(" negative\n");
- }
- else {
- d_printf(" positive\n");
- }
- d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding));
- d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding));
-}
-
-static void
-fillCineonOriginationInfo(CineonFile* cineon,
- CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) {
-
- (void)cineon; /* unused */
-
- originInfo->x_offset = htonl(0);
- originInfo->y_offset = htonl(0);
- strcpy(originInfo->file_name, fileInfo->file_name);
- strcpy(originInfo->create_date, fileInfo->create_date);
- strcpy(originInfo->create_time, fileInfo->create_time);
- strncpy(originInfo->input_device, "David's Cineon writer", 64);
- strncpy(originInfo->model_number, "Software", 32);
- strncpy(originInfo->serial_number, "001", 32);
- originInfo->x_input_samples_per_mm = htonf(undefined());
- originInfo->y_input_samples_per_mm = htonf(undefined());
- /* this should probably be undefined, too */
- originInfo->input_device_gamma = htonf(1.0);
-}
-
-static void
-dumpCineonOriginationInfo(CineonOriginationInformation* 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("File name \"%s\"\n", originInfo->file_name);
- d_printf("Creation date \"%s\"\n", originInfo->create_date);
- d_printf("Creation time \"%s\"\n", originInfo->create_time);
- d_printf("Input device \"%s\"\n", originInfo->input_device);
- d_printf("Model number \"%s\"\n", originInfo->model_number);
- d_printf("Serial number \"%s\"\n", originInfo->serial_number);
- d_printf("Samples per mm in x %f\n", ntohf(originInfo->x_input_samples_per_mm));
- d_printf("Samples per mm in y %f\n", ntohf(originInfo->y_input_samples_per_mm));
- d_printf("Input device gamma %f\n", ntohf(originInfo->input_device_gamma));
-}
-
-static int
-initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) {
-
- fillCineonFileInfo(cineon, &header->fileInfo, imagename);
- fillCineonImageInfo(cineon, &header->imageInfo);
- fillCineonFormatInfo(cineon, &header->formatInfo);
- fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo);
+#include "BLI_fileops.h"
- return 0;
-}
+#include "MEM_guardedalloc.h"
-static void
-UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) {
- dumpCineonFileInfo(&header->fileInfo);
- dumpCineonImageInfo(&header->imageInfo);
- dumpCineonFormatInfo(&header->formatInfo);
- dumpCineonOriginationInfo(&header->originInfo);
-}
+/*
+ * For debug purpose
+ */
static int verbose = 0;
-void
-cineonSetVerbose(int verbosity) {
- verbose = verbosity;
-}
-
-static void
-verboseMe(CineonFile* cineon) {
-
- d_printf("size %d x %d x %d\n", cineon->width, cineon->height, cineon->depth);
- d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
- cineon->imageOffset, cineon->lineBufferLength * 4,
- cineon->imageOffset + cineon->lineBufferLength * 4 * cineon->height);
-}
-
-int
-cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) {
-
- int longsRead;
- int pixelIndex;
- int longIndex;
- int numPixels = cineon->width * cineon->depth;
-
-
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in getRowBytes\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
- if (longsRead != cineon->lineBufferLength) {
- if (verbose) {
- d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
- perror("cineonGetRowBytes");
- }
-
- return 1;
- }
-
- /* remember where we left the car, honey */
- ++cineon->fileYPos;
-
- /* convert longwords to pixels */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
- t = t >> 2;
- cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff;
- pixelIndex += 3;
- }
-
- /* extract required pixels */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (cineon->params.doLogarithm)
- row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]];
- else
- row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
- }
-
- return 0;
-}
-
-int
-cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) {
-
- int pixelIndex;
- int numPixels = cineon->width * cineon->depth;
- int longIndex;
- int longsWritten;
-
- /* put new pixels into pixelBuffer */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (cineon->params.doLogarithm)
- cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]];
- else
- cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
- }
-
- /* pack into longwords */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t =
- (cineon->pixelBuffer[pixelIndex] << 22) |
- (cineon->pixelBuffer[pixelIndex+1] << 12) |
- (cineon->pixelBuffer[pixelIndex+2] << 2);
- cineon->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
-
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in setRowBytes\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
- if (longsWritten != cineon->lineBufferLength) {
- if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
- return 1;
- }
-
- ++cineon->fileYPos;
-
- return 0;
-}
-
-int
-cineonGetRow(CineonFile* cineon, unsigned short* row, int y) {
-
- int longsRead;
- int pixelIndex;
- int longIndex;
-/* int numPixels = cineon->width * cineon->depth;
-*/
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in getRow\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
- if (longsRead != cineon->lineBufferLength) {
- if (verbose) d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
- return 1;
- }
- /* remember where we left the car, honey */
- ++cineon->fileYPos;
-
- /* convert longwords to pixels */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
- t = t >> 2;
- row[pixelIndex+2] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- row[pixelIndex+1] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- row[pixelIndex] = (unsigned short) t & 0x3ff;
- pixelIndex += 3;
- }
-
- return 0;
+void cineonSetVerbose(int verbosity) {
+ verbose = verbosity;
}
-int
-cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) {
-
- int pixelIndex;
-/* int numPixels = cineon->width * cineon->depth;
-*/ int longIndex;
- int longsWritten;
-
- /* pack into longwords */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t =
- (row[pixelIndex] << 22) |
- (row[pixelIndex+1] << 12) |
- (row[pixelIndex+2] << 2);
- cineon->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
-
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in setRowBytes\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
- if (longsWritten != cineon->lineBufferLength) {
- if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
- return 1;
- }
-
- ++cineon->fileYPos;
+static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header,
+ const char *filename, const char *creator)
+{
+ time_t fileClock;
+ struct tm *fileTime;
+ int i;
- return 0;
+ memset(header, 0, sizeof(CineonMainHeader));
+
+ /* --- File header --- */
+ header->fileHeader.magic_num = swap_uint(CINEON_FILE_MAGIC, cineon->isMSB);
+ header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB);
+ header->fileHeader.gen_hdr_size = swap_uint(sizeof(CineonFileHeader) + sizeof(CineonImageHeader) +
+ sizeof(CineonOriginationHeader), cineon->isMSB);
+ header->fileHeader.ind_hdr_size = 0;
+ header->fileHeader.user_data_size = 0;
+ header->fileHeader.file_size = swap_uint(cineon->element[0].dataOffset + cineon->height * getRowLength(cineon->width, cineon->element[0]), cineon->isMSB);
+ strcpy(header->fileHeader.version, "v4.5");
+ strncpy(header->fileHeader.file_name, filename, 99);
+ header->fileHeader.file_name[99] = 0;
+ fileClock = time(0);
+ fileTime = localtime(&fileClock);
+ strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime);
+ strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime);
+ header->fileHeader.creation_time[11] = 0;
+
+ /* --- Image header --- */
+ header->imageHeader.orientation = 0;
+ header->imageHeader.elements_per_image = cineon->depth;
+
+ for (i = 0; i < 3; i++) {
+ header->imageHeader.element[i].descriptor1 = 0;
+ header->imageHeader.element[i].descriptor2 = i;
+ header->imageHeader.element[i].bits_per_sample = cineon->element[0].bitsPerSample;
+ header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB);
+ header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB);
+ header->imageHeader.element[i].ref_low_data = swap_uint(cineon->element[0].refLowData, cineon->isMSB);
+ header->imageHeader.element[i].ref_low_quantity = swap_float(cineon->element[0].refLowQuantity, cineon->isMSB);
+ header->imageHeader.element[i].ref_high_data = swap_uint(cineon->element[0].refHighData, cineon->isMSB);
+ header->imageHeader.element[i].ref_high_quantity = swap_float(cineon->element[0].refHighQuantity, cineon->isMSB);
+ }
+
+ header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB);
+ header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB);
+ strncpy(header->imageHeader.label, creator, 199);
+ header->imageHeader.label[199] = 0;
+ header->imageHeader.interleave = 0;
+ header->imageHeader.data_sign = 0;
+ header->imageHeader.sense = 0;
+ header->imageHeader.line_padding = swap_uint(0, cineon->isMSB);
+ header->imageHeader.element_padding = swap_uint(0, cineon->isMSB);
+
+ switch (cineon->element[0].packing) {
+ case 0:
+ header->imageHeader.packing = 0;
+ break;
+
+ case 1:
+ header->imageHeader.packing = 5;
+ break;
+
+ case 2:
+ header->imageHeader.packing = 6;
+ break;
+ }
+
+ /* --- Origination header --- */
+ /* we leave it blank */
+
+ /* --- Film header --- */
+ /* we leave it blank */
}
-CineonFile*
-cineonOpen(const char* filename) {
-
- CineonGenericHeader header;
+LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
+{
+ CineonMainHeader header;
+ LogImageFile *cineon = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
+ char *filename = (char*)byteStuff;
+ int i;
+ unsigned int dataOffset;
- CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
if (cineon == 0) {
- if (verbose) d_printf("Failed to malloc cineon file structure.\n");
+ if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n");
return 0;
}
+ /* zero the header */
+ memset(&header, 0, sizeof(CineonMainHeader));
+
/* for close routine */
cineon->file = 0;
- cineon->lineBuffer = 0;
- cineon->pixelBuffer = 0;
- cineon->membuffer = 0;
- cineon->memcursor = 0;
- cineon->membuffersize = 0;
-
- cineon->file = BLI_fopen(filename, "rb");
- if (cineon->file == 0) {
- if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
- cineonClose(cineon);
- return 0;
- }
- cineon->reading = 1;
- if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) {
- if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
- cineonClose(cineon);
+ if (fromMemory == 0) {
+ /* byteStuff is then the filename */
+ cineon->file = BLI_fopen(filename, "rb");
+ if (cineon->file == 0) {
+ if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename);
+ logImageClose(cineon);
+ return 0;
+ }
+ /* not used in this case */
+ cineon->memBuffer = 0;
+ cineon->memCursor = 0;
+ cineon->memBufferSize = 0;
+ } else {
+ cineon->memBuffer = (unsigned char*)byteStuff;
+ cineon->memCursor = (unsigned char*)byteStuff;
+ cineon->memBufferSize = bufferSize;
+ }
+
+ if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
+ if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
+ logImageClose(cineon);
return 0;
}
- /* let's assume cineon files are always network order */
- if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
- if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
- (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
- cineonClose(cineon);
+ /* endianness determination */
+ if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
+ cineon->isMSB = 1;
+ if (verbose) printf("Cineon: File is MSB.\n");
+ } else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
+ cineon->isMSB = 0;
+ if (verbose) printf("Cineon: File is LSB.\n");
+ } else {
+ if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n",
+ (uintptr_t)header.fileHeader.magic_num, byteStuff);
+ logImageClose(cineon);
return 0;
}
- if (header.formatInfo.packing != 5) {
- if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
- cineonClose(cineon);
- return 0;
- }
+ cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
+ cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);
+ cineon->depth = header.imageHeader.elements_per_image;
+ cineon->srcFormat = format_Cineon;
- cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
- cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
- cineon->depth = header.imageInfo.channels_per_image;
- /* cineon->bitsPerPixel = 10; */
- cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
- cineon->imageOffset = ntohl(header.fileInfo.image_offset);
-
- cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
- cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
- if (cineon->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
- cineonClose(cineon);
+ if (header.imageHeader.interleave == 0)
+ cineon->numElements = 1;
+ else if (header.imageHeader.interleave == 2)
+ cineon->numElements = header.imageHeader.elements_per_image;
+ else {
+ if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
return 0;
}
- cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
- if (cineon->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
- cineonClose(cineon);
- return 0;
+ if (cineon->depth == 1) {
+ /* Grayscale image */
+ cineon->element[0].descriptor = descriptor_Luminance;
+ cineon->element[0].transfer = transfer_Linear;
+ cineon->element[0].depth = 1;
}
- cineon->pixelBufferUsed = 0;
-
- if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
- cineonClose(cineon);
- return 0;
+ else if (cineon->depth == 3) {
+ /* RGB image */
+ if (cineon->numElements == 1) {
+ cineon->element[0].descriptor = descriptor_RGB;
+ cineon->element[0].transfer = transfer_PrintingDensity;
+ cineon->element[0].depth = 3;
+ }
+ else if (cineon->numElements == 3) {
+ cineon->element[0].descriptor = descriptor_Red;
+ cineon->element[0].transfer = transfer_PrintingDensity;
+ cineon->element[0].depth = 1;
+ cineon->element[1].descriptor = descriptor_Green;
+ cineon->element[1].transfer = transfer_PrintingDensity;
+ cineon->element[1].depth = 1;
+ cineon->element[2].descriptor = descriptor_Blue;
+ cineon->element[2].transfer = transfer_PrintingDensity;
+ cineon->element[2].depth = 1;
+ }
}
- cineon->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&cineon->params);
- setupLut(cineon);
-
- cineon->getRow = &cineonGetRowBytes;
- cineon->setRow = 0;
- cineon->close = &cineonClose;
-
- if (verbose) {
- verboseMe(cineon);
+ else {
+ if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
+ return 0;
}
- return cineon;
-}
+ dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
-int cineonIsMemFileCineon(unsigned char *mem)
-{
- unsigned int num;
- memcpy(&num, mem, sizeof(unsigned int));
-
- if (num != ntohl(CINEON_FILE_MAGIC)) {
- return 0;
- }
- else return 1;
-}
+ for (i = 0; i < cineon->numElements; i++) {
+ cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
+ cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f;
+ cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, cineon->isMSB);
+ cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, cineon->isMSB);
+ cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, cineon->isMSB);
+ cineon->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, cineon->isMSB);
-CineonFile*
-cineonOpenFromMem(unsigned char *mem, unsigned int size) {
+ switch (header.imageHeader.packing) {
+ case 0:
+ cineon->element[i].packing = 0;
+ break;
- CineonGenericHeader header;
-
- CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
- if (cineon == 0) {
- if (verbose) d_printf("Failed to malloc cineon file structure.\n");
- return 0;
- }
+ case 5:
+ cineon->element[i].packing = 1;
+ break;
- /* for close routine */
- cineon->file = 0;
- cineon->lineBuffer = 0;
- cineon->pixelBuffer = 0;
- cineon->membuffer = mem;
- cineon->membuffersize = size;
- cineon->memcursor = mem;
-
- cineon->file = 0;
- cineon->reading = 1;
- verbose = 0;
- if (size < sizeof(CineonGenericHeader)) {
- if (verbose) d_printf("Not enough data for header!\n");
- cineonClose(cineon);
- return 0;
- }
+ case 6:
+ cineon->element[i].packing = 2;
+ break;
- logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon);
+ default:
+ /* Not supported */
+ if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
+ return 0;
+ }
- /* let's assume cineon files are always network order */
- if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
- if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num));
+ if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData))
+ cineon->element[i].refLowData = 0;
- cineonClose(cineon);
- return 0;
- }
+ if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refHighData))
+ cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue;
- if (header.formatInfo.packing != 5) {
- if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
- cineonClose(cineon);
- return 0;
- }
+ if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity))
+ cineon->element[i].refLowQuantity = 0.0f;
- cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
- cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
- cineon->depth = header.imageInfo.channels_per_image;
- /* cineon->bitsPerPixel = 10; */
- cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
- cineon->imageOffset = ntohl(header.fileInfo.image_offset);
-
- cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
- cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
- if (cineon->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
- cineonClose(cineon);
- return 0;
- }
+ if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refHighQuantity)) {
+ if (cineon->element[i].transfer == transfer_PrintingDensity)
+ cineon->element[i].refHighQuantity = 2.048f;
+ else
+ cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
+ }
- cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
- if (cineon->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
- cineonClose(cineon);
- return 0;
- }
- cineon->pixelBufferUsed = 0;
-
- if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
- cineonClose(cineon);
- return 0;
+ cineon->element[i].dataOffset = dataOffset;
+ dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
}
-
- cineon->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&cineon->params);
- setupLut(cineon);
- cineon->getRow = &cineonGetRowBytes;
- cineon->setRow = 0;
- cineon->close = &cineonClose;
+ cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
+ cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
+ cineon->gamma = 1.7f;
if (verbose) {
- verboseMe(cineon);
- }
+ printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
+ for (i = 0; i < cineon->numElements; i++) {
+ printf(" Element %d:\n", i);
+ printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample);
+ printf(" Depth: %d\n", cineon->element[i].depth);
+ printf(" Transfer characteristics: %d\n", cineon->element[i].transfer);
+ printf(" Packing: %d\n", cineon->element[i].packing);
+ printf(" Descriptor: %d\n", cineon->element[i].descriptor);
+ printf(" Data offset: %u\n", cineon->element[i].dataOffset);
+ printf(" Reference low data: %u\n", cineon->element[i].refLowData);
+ printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
+ printf(" Reference high data: %u\n", cineon->element[i].refHighData);
+ printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
+ printf("\n");
+ }
+ printf("Gamma: %f\n", cineon->gamma);
+ printf("Reference black: %f\n", cineon->referenceBlack);
+ printf("Reference white: %f\n", cineon->referenceWhite);
+ printf("----------------------------\n");
+ }
return cineon;
}
+LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
+{
+ CineonMainHeader header;
+ const char *shortFilename = 0;
+ /* unsigned char pad[6044]; */
-int
-cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) {
- *width = cineon->width;
- *height = cineon->height;
- *depth = cineon->depth;
- return 0;
-}
-
-CineonFile*
-cineonCreate(const char* filename, int width, int height, int depth) {
-
- /* Note: always write files in network order */
- /* By the spec, it shouldn't matter, but ... */
-
- CineonGenericHeader header;
- const char* shortFilename = 0;
-
- CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile));
+ LogImageFile *cineon = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
if (cineon == 0) {
- if (verbose) d_printf("Failed to malloc cineon file structure.\n");
+ if (verbose) printf("cineon: Failed to malloc cineon file structure.\n");
return 0;
}
- memset(&header, 0, sizeof(header));
-
- /* for close routine */
- cineon->file = 0;
- cineon->lineBuffer = 0;
- cineon->pixelBuffer = 0;
-
- cineon->file = BLI_fopen(filename, "wb");
- if (cineon->file == 0) {
- if (verbose) d_printf("Couldn't open file %s\n", filename);
- cineonClose(cineon);
+ /* Only 10 bits Cineon are supported */
+ if (bitsPerSample != 10) {
+ if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n");
+ logImageClose(cineon);
return 0;
}
- cineon->reading = 0;
cineon->width = width;
cineon->height = height;
- cineon->depth = depth;
- cineon->bitsPerPixel = 10;
- cineon->imageOffset = sizeof(CineonGenericHeader);
-
- cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
- cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
- if (cineon->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
- cineonClose(cineon);
- return 0;
- }
+ cineon->element[0].bitsPerSample = 10;
+ cineon->element[0].dataOffset = sizeof(CineonMainHeader);
+ cineon->element[0].maxValue = 1023;
+ cineon->isMSB = 1;
+ cineon->numElements = 1;
+ cineon->element[0].packing = 1;
+ cineon->depth = 3;
+ cineon->element[0].depth = 3;
+ cineon->element[0].descriptor = descriptor_RGB;
+ cineon->element[0].transfer = transfer_PrintingDensity;
+ cineon->element[0].refHighQuantity = 2.048f;
+ cineon->element[0].refLowQuantity = 0;
+ cineon->element[0].refLowData = 0;
+ cineon->element[0].refHighData = cineon->element[0].maxValue;
+ cineon->referenceWhite = 685.0f;
+ cineon->referenceBlack = 95.0f;
+ cineon->gamma = 1.7f;
- cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
- if (cineon->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
- cineonClose(cineon);
- return 0;
- }
- cineon->pixelBufferUsed = 0;
-
- /* find trailing part of filename */
shortFilename = strrchr(filename, '/');
- if (shortFilename == 0) {
+ if (shortFilename == 0)
shortFilename = filename;
- }
- else {
- ++shortFilename;
- }
+ else
+ shortFilename++;
- if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) {
- cineonClose(cineon);
+ cineon->file = BLI_fopen(filename, "wb");
+ if (cineon->file == 0) {
+ if (verbose) printf("cineon: Couldn't open file %s\n", filename);
+ logImageClose(cineon);
return 0;
}
+ fillCineonMainHeader(cineon, &header, shortFilename, creator);
+
if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
- if (verbose) d_printf("Couldn't write image header\n");
- cineonClose(cineon);
+ if (verbose) printf("cineon: Couldn't write image header\n");
+ logImageClose(cineon);
return 0;
}
- cineon->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&cineon->params);
- setupLut(cineon);
-
- cineon->getRow = 0;
- cineon->setRow = &cineonSetRowBytes;
- cineon->close = &cineonClose;
return cineon;
}
-
-void
-cineonClose(CineonFile* cineon) {
-
- if (cineon == 0) {
- return;
- }
-
- if (cineon->file) {
- fclose(cineon->file);
- cineon->file = 0;
- }
-
- if (cineon->lineBuffer) {
- free(cineon->lineBuffer);
- cineon->lineBuffer = 0;
- }
-
- if (cineon->pixelBuffer) {
- free(cineon->pixelBuffer);
- cineon->pixelBuffer = 0;
- }
-
- free(cineon);
-}