Blender  V2.59
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 }