Blender V2.61 - r43446

dpxlib.c

Go to the documentation of this file.
00001 
00004 /*
00005  *   Dpx image file format library routines.
00006  *
00007  *   Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
00008  *
00009  *   This program is free software; you can redistribute it and/or modify it
00010  *   under the terms of the GNU General Public License as published by the Free
00011  *   Software Foundation; either version 2 of the License, or (at your option)
00012  *   any later version.
00013  *
00014  *   This program is distributed in the hope that it will be useful, but
00015  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00016  *   or FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
00017  *   for more details.
00018  *
00019  *   You should have received a copy of the GNU General Public License
00020  *   along with this program; if not, write to the Free Software
00021  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  */
00024 
00025 #include "dpxfile.h"
00026 #include "dpxlib.h"
00027 
00028 #include <stdio.h>
00029 #include <math.h>
00030 #include <stdlib.h>
00031 #include <time.h>                /* strftime() */
00032 #include <sys/types.h>
00033 #ifdef WIN32
00034 #include <winsock.h>
00035 #else
00036 #include <netinet/in.h>  /* htonl() */
00037 #endif
00038 #include <string.h>          /* memset */
00039 #include "cin_debug_stuff.h"
00040 #include "logmemfile.h"
00041 
00042 static void
00043 fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) {
00044 
00045     (void)dpx; /* unused */
00046     
00047     chan->signage = 0;
00048     chan->ref_low_data = htonl(0);
00049     chan->ref_low_quantity = htonf(0.0);
00050     chan->ref_high_data = htonl(1023);
00051     chan->ref_high_quantity = htonf(2.046);
00052     chan->designator1 = des;
00053     chan->transfer_characteristics = 0;
00054     chan->colourimetry = 0;
00055     chan->bits_per_pixel = 10;
00056     chan->packing = htons(1);
00057     chan->encoding = 0;
00058     chan->data_offset = 0;
00059     chan->line_padding = htonl(0);
00060     chan->channel_padding = htonl(0);
00061     chan->description[0] = 0;
00062 }
00063 
00064 static void
00065 dumpDpxChannelInfo(DpxChannelInformation* chan) {
00066     d_printf("  Signage %ld", (intptr_t)ntohl(chan->signage));
00067     d_printf("  Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
00068     d_printf("  Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
00069     d_printf("  Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
00070     d_printf("  Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
00071     d_printf("  Designator1: %d,", chan->designator1);
00072     d_printf("  Bits per pixel %d\n", chan->bits_per_pixel);
00073     d_printf("  Packing: %d,", ntohs(chan->packing));
00074     d_printf("  Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset));
00075 }
00076 
00077 static void
00078 fillDpxFileInfo(
00079     DpxFile* dpx, DpxFileInformation* fileInfo, const char* filename) {
00080 
00081     time_t fileClock;
00082     struct tm* fileTime;
00083 
00084     /* Note: always write files in network order */
00085     /* By the spec, it shouldn't matter, but ... */
00086 
00087     fileInfo->magic_num = htonl(DPX_FILE_MAGIC);
00088     fileInfo->offset = htonl(dpx->imageOffset);
00089     strcpy(fileInfo->vers, "v1.0");
00090     fileInfo->file_size = htonl(dpx->imageOffset +
00091         pixelsToLongs(dpx->height * dpx->width * dpx->depth) * 4);
00092     fileInfo->ditto_key = 0;
00093     fileInfo->gen_hdr_size = htonl(
00094         sizeof(DpxFileInformation) +
00095         sizeof(DpxImageInformation) +
00096         sizeof(DpxOriginationInformation));
00097     fileInfo->ind_hdr_size = htonl(sizeof(DpxMPIInformation));
00098     fileInfo->user_data_size = 0;
00099     strncpy(fileInfo->file_name, filename, 99);
00100     fileInfo->file_name[99] = 0;
00101 
00102     fileClock = time(0);
00103     fileTime = localtime(&fileClock);
00104     strftime(fileInfo->create_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
00105     /* Question: is %Z in strftime guaranteed to return 3 chars? */
00106     fileInfo->create_date[23] = 0;
00107 
00108     strcpy(fileInfo->creator, "David's DPX writer");
00109     fileInfo->project[0] = 0;
00110     fileInfo->copyright[0] = 0;
00111     fileInfo->key = 0xFFFFFFFF; /* same in any byte order */
00112 }
00113 
00114 static void
00115 dumpDpxFileInfo(DpxFileInformation* fileInfo) {
00116     d_printf("\n--File Information--\n");
00117     d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num));
00118     d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset));
00119     d_printf("Version \"%s\"\n", fileInfo->vers);
00120     d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
00121     d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key));
00122     d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
00123     d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
00124     d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
00125     d_printf("File name \"%s\"\n", fileInfo->file_name);
00126     d_printf("Creation date \"%s\"\n", fileInfo->create_date);
00127     d_printf("Creator \"%s\"\n", fileInfo->creator);
00128     d_printf("Project \"%s\"\n", fileInfo->project);
00129     d_printf("Copyright \"%s\"\n", fileInfo->copyright);
00130     d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key));
00131 }
00132 
00133 static void
00134 fillDpxImageInfo(
00135     DpxFile* dpx, DpxImageInformation* imageInfo) {
00136     imageInfo->orientation = 0;
00137     imageInfo->channels_per_image = htons(1);
00138     imageInfo->pixels_per_line = htonl(dpx->width);
00139     imageInfo->lines_per_image = htonl(dpx->height);
00140 
00141     if (dpx->depth == 1) {
00142         fillDpxChannelInfo(dpx, &imageInfo->channel[0], 0);
00143 
00144     } else if (dpx->depth == 3) {
00145         fillDpxChannelInfo(dpx, &imageInfo->channel[0], 50);
00146     }
00147 }
00148 
00149 static void
00150 dumpDpxImageInfo(DpxImageInformation* imageInfo) {
00151 
00152     int n;
00153     int i;
00154     d_printf("\n--Image Information--\n");
00155     d_printf("Image orientation %d,", ntohs(imageInfo->orientation));
00156     n = ntohs(imageInfo->channels_per_image);
00157     d_printf("Channels %d\n", n);
00158     d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line));
00159     d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image));
00160     for (i = 0; i < n; ++i) {
00161         d_printf("  --Channel %d--\n", i);
00162         dumpDpxChannelInfo(&imageInfo->channel[i]);
00163     }
00164 }
00165 
00166 static void
00167 fillDpxOriginationInfo(
00168     DpxFile* dpx, DpxOriginationInformation* originInfo, DpxFileInformation* fileInfo)
00169 {
00170     /* unused */
00171     (void)dpx;
00172     (void)originInfo;
00173     (void)fileInfo;
00174 }
00175 
00176 static void
00177 dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) {
00178     d_printf("\n--Origination Information--\n");
00179     d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
00180     d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
00181     d_printf("X centre %f\n", ntohf(originInfo->x_centre));
00182     d_printf("Y centre %f\n", ntohf(originInfo->y_centre));
00183     d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size));
00184     d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size));
00185     d_printf("File name \"%s\"\n", originInfo->file_name);
00186     d_printf("Creation time \"%s\"\n", originInfo->creation_time);
00187     d_printf("Input device \"%s\"\n", originInfo->input_device);
00188     d_printf("Serial number \"%s\"\n", originInfo->input_serial_number);
00189 }
00190 
00191 static void
00192 initDpxMainHeader(DpxFile* dpx, DpxMainHeader* header, const char* shortFilename) {
00193     memset(header, 0, sizeof(DpxMainHeader));
00194     fillDpxFileInfo(dpx, &header->fileInfo, shortFilename);
00195     fillDpxImageInfo(dpx, &header->imageInfo);
00196     fillDpxOriginationInfo(dpx, &header->originInfo, &header->fileInfo);
00197 #if 0
00198     fillDpxMPIInfo(dpx, &header->filmHeader);
00199 #endif
00200 }
00201 
00202 static void
00203 dumpDpxMainHeader(DpxMainHeader* header) {
00204     dumpDpxFileInfo(&header->fileInfo);
00205     dumpDpxImageInfo(&header->imageInfo);
00206     dumpDpxOriginationInfo(&header->originInfo);
00207 #if 0
00208     dumpDpxMPIInformation(&header->filmHeader);
00209 #endif
00210 }
00211 
00212 static int verbose = 0;
00213 void
00214 dpxSetVerbose(int verbosity) {
00215     verbose = verbosity;
00216 }
00217 
00218 static void
00219 verboseMe(DpxFile* dpx) {
00220 
00221     d_printf("size %d x %d x %d\n", dpx->width, dpx->height, dpx->depth);
00222     d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
00223         dpx->imageOffset, dpx->lineBufferLength * 4,
00224         dpx->imageOffset + pixelsToLongs(dpx->width * dpx->depth * dpx->height) * 4);
00225 }
00226 
00227 int
00228 dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) {
00229 
00230     /* Note: this code is bizarre because DPX files can wrap */
00231     /* packed longwords across line boundaries!!!! */
00232 
00233     size_t readLongs;
00234     unsigned int longIndex;
00235     int numPixels = dpx->width * dpx->depth;
00236     int pixelIndex;
00237 
00238     /* only seek if not reading consecutive lines */
00239     /* this is not quite right yet, need to account for leftovers */
00240     if (y != dpx->fileYPos) {
00241         int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
00242         if (verbose) d_printf("Seek in getRowBytes\n");
00243         if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
00244             if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
00245             return 1;
00246         }
00247         dpx->fileYPos = y;
00248     }
00249 
00250     /* read enough longwords */
00251     readLongs = pixelsToLongs(numPixels - dpx->pixelBufferUsed);
00252     if (logimage_fread(dpx->lineBuffer, 4, readLongs, dpx) != readLongs) {
00253         if (verbose) d_printf("Couldn't read line %d length %d\n", y, (int)readLongs * 4);
00254         return 1;
00255     }
00256     ++dpx->fileYPos;
00257 
00258     /* convert longwords to pixels */
00259     pixelIndex = dpx->pixelBufferUsed;
00260 
00261     /* this is just strange */
00262     if (dpx->depth == 1) {
00263         for (longIndex = 0; longIndex < readLongs; ++longIndex) {
00264             unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
00265             dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
00266             t = t >> 10;
00267             dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
00268             t = t >> 10;
00269             dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
00270             pixelIndex += 3;
00271         }
00272     } else /* if (dpx->depth == 3) */ {
00273         for (longIndex = 0; longIndex < readLongs; ++longIndex) {
00274             unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
00275             t = t >> 2;
00276             dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
00277             t = t >> 10;
00278             dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
00279             t = t >> 10;
00280             dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
00281             pixelIndex += 3;
00282         }
00283     }
00284     dpx->pixelBufferUsed = pixelIndex;
00285 
00286     /* extract required pixels */
00287     for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
00288         if(dpx->params.doLogarithm)
00289             row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]];
00290         else
00291             row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6;
00292     }
00293 
00294     /* save remaining pixels */
00295     while (pixelIndex < dpx->pixelBufferUsed) {
00296         dpx->pixelBuffer[pixelIndex - numPixels] = dpx->pixelBuffer[pixelIndex];
00297         ++pixelIndex;
00298     }
00299     dpx->pixelBufferUsed -= numPixels;
00300 
00301     /* done! */
00302     return 0;
00303 }
00304 
00305 int
00306 dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) {
00307 
00308     /* Note: this code is bizarre because DPX files can wrap */
00309     /* packed longwords across line boundaries!!!! */
00310 
00311     size_t writeLongs;
00312     int longIndex;
00313     int numPixels = dpx->width * dpx->depth;
00314     int pixelIndex;
00315     int pixelIndex2;
00316 
00317     /* only seek if not reading consecutive lines */
00318     /* this is not quite right yet */
00319     if (y != dpx->fileYPos) {
00320         int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
00321         if (verbose) d_printf("Seek in getRowBytes\n");
00322         if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
00323             if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
00324             return 1;
00325         }
00326         dpx->fileYPos = y;
00327     }
00328 
00329     /* put new pixels into pixelBuffer */
00330     for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
00331         if(dpx->params.doLogarithm)
00332             dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]];
00333         else
00334             dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6;
00335     }
00336     dpx->pixelBufferUsed += numPixels;
00337 
00338     /* pack into longwords */
00339     writeLongs = dpx->pixelBufferUsed / 3;
00340     /* process whole line at image end */
00341     if (dpx->fileYPos == (dpx->height - 1)) {
00342         writeLongs = pixelsToLongs(dpx->pixelBufferUsed);
00343     }
00344     pixelIndex = 0;
00345     if (dpx->depth == 1) {
00346         for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
00347             unsigned int t = dpx->pixelBuffer[pixelIndex] |
00348                     (dpx->pixelBuffer[pixelIndex+1] << 10) |
00349                     (dpx->pixelBuffer[pixelIndex+2] << 20);
00350             dpx->lineBuffer[longIndex] = htonl(t);
00351             pixelIndex += 3;
00352         }
00353     } else {
00354         for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
00355             unsigned int t = dpx->pixelBuffer[pixelIndex+2] << 2 |
00356                     (dpx->pixelBuffer[pixelIndex+1] << 12) |
00357                     (dpx->pixelBuffer[pixelIndex] << 22);
00358             dpx->lineBuffer[longIndex] = htonl(t);
00359             pixelIndex += 3;
00360         }
00361     }
00362 
00363     /* write them */
00364     if (fwrite(dpx->lineBuffer, 4, writeLongs, dpx->file) != writeLongs) {
00365         if (verbose) d_printf("Couldn't write line %d length %d\n", y, (int)writeLongs * 4);
00366         return 1;
00367     }
00368     ++dpx->fileYPos;
00369 
00370     /* save remaining pixels */
00371     pixelIndex2 = 0;
00372     while (pixelIndex < dpx->pixelBufferUsed) {
00373         dpx->pixelBuffer[pixelIndex2] = dpx->pixelBuffer[pixelIndex];
00374         ++pixelIndex;
00375         ++pixelIndex2;
00376     }
00377     dpx->pixelBufferUsed = pixelIndex2;
00378 
00379     return 0;
00380 }
00381 
00382 #define LFMEMFILE   0
00383 #define LFREALFILE  1
00384 
00385 static DpxFile* 
00386 intern_dpxOpen(int mode, const char* bytestuff, int bufsize) {
00387 
00388     DpxMainHeader header;
00389     const char *filename = bytestuff;
00390     DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
00391     
00392     if (dpx == 0) {
00393         if (verbose) d_printf("Failed to malloc dpx file structure.\n");
00394         return 0;
00395     }
00396 
00397     /* for close routine */
00398     dpx->file = 0;
00399     dpx->lineBuffer = 0;
00400     dpx->pixelBuffer = 0;
00401 
00402     if (mode == LFREALFILE) {
00403         filename = bytestuff;
00404         dpx->file = fopen(filename, "rb");
00405         if (dpx->file == 0) {   
00406             if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
00407             dpxClose(dpx);
00408             return 0;
00409         }
00410         dpx->membuffer = 0;
00411         dpx->memcursor = 0;
00412         dpx->membuffersize = 0;
00413     } else if (mode == LFMEMFILE) {
00414         dpx->membuffer = (unsigned char *)bytestuff;
00415         dpx->memcursor = (unsigned char *)bytestuff;
00416         dpx->membuffersize = bufsize;
00417     }
00418     
00419     dpx->reading = 1;
00420 
00421     if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
00422         if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
00423         dpxClose(dpx);
00424         return 0;
00425     }
00426 
00427     /* let's assume dpx files are always network order */
00428     if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) {
00429         if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
00430             (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
00431         dpxClose(dpx);
00432         return 0;
00433     }
00434 
00435     if (ntohs(header.imageInfo.channel[0].packing) != 1) {
00436         if (verbose) d_printf("Unknown packing %d\n", header.imageInfo.channel[0].packing);
00437         dpxClose(dpx);
00438         return 0;
00439     }
00440 
00441 
00442     dpx->width = ntohl(header.imageInfo.pixels_per_line);
00443     dpx->height = ntohl(header.imageInfo.lines_per_image);
00444     dpx->depth = ntohs(header.imageInfo.channels_per_image);
00445     /* Another DPX vs Cineon wierdness */
00446     if (dpx->depth == 1) {
00447         switch (header.imageInfo.channel[0].designator1) {
00448         case 50: dpx->depth = 3; break;
00449         case 51: dpx->depth = 4; break;
00450         case 52: dpx->depth = 4; break;
00451         default: break;
00452         }
00453     }
00454     /* dpx->bitsPerPixel = 10; */
00455     dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
00456     if (dpx->bitsPerPixel != 10) {
00457         if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel);
00458         dpxClose(dpx);
00459         return 0;
00460     }
00461 
00462     dpx->imageOffset = ntohl(header.fileInfo.offset);
00463     dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
00464     dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
00465     if (dpx->lineBuffer == 0) {
00466         if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
00467         dpxClose(dpx);
00468         return 0;
00469     }
00470 
00471     /* could have 2 pixels left over */
00472     dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
00473     if (dpx->pixelBuffer == 0) {
00474         if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
00475                 (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
00476         dpxClose(dpx);
00477         return 0;
00478     }
00479     dpx->pixelBufferUsed = 0;
00480 
00481     if (logimage_fseek(dpx, dpx->imageOffset, SEEK_SET) != 0) {
00482         if (verbose) d_printf("Couldn't seek to image data start at %d\n", dpx->imageOffset);
00483         dpxClose(dpx);
00484         return 0;
00485     }
00486     dpx->fileYPos = 0;
00487 
00488     logImageGetByteConversionDefaults(&dpx->params);
00489     /* The SMPTE define this code:
00490      *  0 - User-defined
00491      *  1 - Printing density
00492      *  2 - Linear
00493      *  3 - Logarithmic
00494      *  4 - Unspecified video
00495      *  5 - SMPTE 240M
00496      *  6 - CCIR 709-1
00497      *  7 - CCIR 601-2 system B or G
00498      *  8 - CCIR 601-2 system M
00499      *  9 - NTSC composite video
00500      *  10 - PAL composite video
00501      *  11 - Z linear
00502      *  12 - homogeneous
00503      *
00504      * Note that transfer_characteristics is U8, don't need
00505      * check the byte order.
00506      */
00507     
00508     switch (header.imageInfo.channel[0].transfer_characteristics) {
00509         case 1:
00510         case 2: /* linear */
00511             dpx->params.doLogarithm= 0;
00512             break;
00513         
00514         case 3:
00515             dpx->params.doLogarithm= 1;
00516             break;
00517         
00518         /* TODO - Unsupported, but for now just load them,
00519          * colors may look wrong, but can solve color conversion later
00520          */
00521         case 4: 
00522         case 5:
00523         case 6:
00524         case 7:
00525         case 8:
00526         case 9:
00527         case 10:
00528         case 11:
00529         case 12:
00530             if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics);
00531             dpx->params.doLogarithm= 0;
00532             break;
00533         default:
00534             if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics);
00535             dpxClose(dpx);
00536             return 0;
00537             break;
00538     }
00539     setupLut(dpx);
00540 
00541     dpx->getRow = &dpxGetRowBytes;
00542     dpx->setRow = 0;
00543     dpx->close = &dpxClose;
00544 
00545     if (verbose) {
00546         verboseMe(dpx);
00547     }
00548 
00549     return dpx;
00550 }
00551 
00552 DpxFile* 
00553 dpxOpen(const char *filename) {
00554     return intern_dpxOpen(LFREALFILE, filename, 0);
00555 }
00556 
00557 DpxFile* 
00558 dpxOpenFromMem(unsigned char *buffer, unsigned int size) {
00559     return intern_dpxOpen(LFMEMFILE, (const char *) buffer, size);
00560 }
00561 
00562 int 
00563 dpxIsMemFileCineon(void *buffer) {
00564     int magicnum = 0;
00565     magicnum = *((int*)buffer);
00566     if (magicnum == ntohl(DPX_FILE_MAGIC)) return 1;
00567     else return 0;
00568 }
00569 
00570 DpxFile*
00571 dpxCreate(const char* filename, int width, int height, int depth) {
00572 
00573     /* Note: always write files in network order */
00574     /* By the spec, it shouldn't matter, but ... */
00575 
00576     DpxMainHeader header;
00577     const char* shortFilename = 0;
00578 
00579     DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
00580     if (dpx == 0) {
00581         if (verbose) d_printf("Failed to malloc dpx file structure.\n");
00582         return 0;
00583     }
00584 
00585     memset(&header, 0, sizeof(header));
00586 
00587     /* for close routine */
00588     dpx->file = 0;
00589     dpx->lineBuffer = 0;
00590     dpx->pixelBuffer = 0;
00591 
00592     dpx->file = fopen(filename, "wb");
00593     if (dpx->file == 0) {
00594         if (verbose) d_printf("Couldn't open file %s\n", filename);
00595         dpxClose(dpx);
00596         return 0;
00597     }
00598     dpx->reading = 0;
00599 
00600     dpx->width = width;
00601     dpx->height = height;
00602     dpx->depth = depth;
00603     dpx->bitsPerPixel = 10;
00604     dpx->imageOffset = sizeof(DpxMainHeader);
00605 
00606     dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
00607     dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
00608     if (dpx->lineBuffer == 0) {
00609         if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
00610         dpxClose(dpx);
00611         return 0;
00612     }
00613 
00614     dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
00615     if (dpx->pixelBuffer == 0) {
00616         if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
00617                 (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
00618         dpxClose(dpx);
00619         return 0;
00620     }
00621     dpx->pixelBufferUsed = 0;
00622 
00623     /* find trailing part of filename */
00624     shortFilename = strrchr(filename, '/');
00625     if (shortFilename == 0) {
00626         shortFilename = filename;
00627     } else {
00628         ++shortFilename;
00629     }
00630     initDpxMainHeader(dpx, &header, shortFilename);
00631     logImageGetByteConversionDefaults(&dpx->params);
00632     /* Need set the file type before write the header!
00633      *  2 - Linear
00634      *  3 - Logarithmic
00635      *
00636      * Note that transfer characteristics is U8, don't need
00637      * check the byte order.
00638      */
00639     if (dpx->params.doLogarithm == 0)
00640         header.imageInfo.channel[0].transfer_characteristics= 2;
00641     else
00642         header.imageInfo.channel[0].transfer_characteristics= 3;
00643 
00644     if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
00645         if (verbose) d_printf("Couldn't write image header\n");
00646         dpxClose(dpx);
00647         return 0;
00648     }
00649     dpx->fileYPos = 0;
00650     setupLut(dpx);
00651 
00652     dpx->getRow = 0;
00653     dpx->setRow = &dpxSetRowBytes;
00654     dpx->close = &dpxClose;
00655 
00656     return dpx;
00657 }
00658 
00659 void
00660 dpxClose(DpxFile* dpx) {
00661 
00662     if (dpx == 0) {
00663         return;
00664     }
00665 
00666     if (dpx->file) {
00667         fclose(dpx->file);
00668         dpx->file = 0;
00669     }
00670 
00671     if (dpx->lineBuffer) {
00672         free(dpx->lineBuffer);
00673         dpx->lineBuffer = 0;
00674     }
00675 
00676     if (dpx->pixelBuffer) {
00677         free(dpx->pixelBuffer);
00678         dpx->pixelBuffer = 0;
00679     }
00680 
00681     free(dpx);
00682 }
00683 
00684 void
00685 dpxDump(const char* filename) {
00686 
00687     DpxMainHeader header;
00688     FILE* file;
00689 
00690     file = fopen(filename, "rb");
00691     if (file == 0) {
00692         d_printf("Failed to open file \"%s\".\n", filename);
00693         return;
00694     }
00695 
00696     if (fread(&header, sizeof(header), 1, file) == 0) {
00697         d_printf("Not enough data for header in \"%s\".\n", filename);
00698         fclose(file);
00699         return;
00700     }
00701 
00702     fclose(file);
00703     dumpDpxMainHeader(&header);
00704 }