Blender V2.61 - r43446

cineonlib.c

Go to the documentation of this file.
00001 
00004 /*
00005  *   Cineon image file format library routines.
00006  *
00007  *   Copyright 1999,2000,2001 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 "cineonlib.h"
00026 #include "cineonfile.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 
00040 #include "BLI_utildefines.h"
00041 
00042 #include "cin_debug_stuff.h"
00043 #include "logmemfile.h"
00044 
00045 static void
00046 fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) {
00047 
00048     time_t fileClock;
00049     struct tm* fileTime;
00050 
00051     fileInfo->magic_num = htonl(CINEON_FILE_MAGIC);
00052     fileInfo->image_offset = htonl(cineon->imageOffset);
00053     fileInfo->gen_hdr_size = htonl(
00054         sizeof(CineonFileInformation) +
00055         sizeof(CineonImageInformation) +
00056         sizeof(CineonFormatInformation) +
00057         sizeof(CineonOriginationInformation));
00058     fileInfo->ind_hdr_size = 0;
00059     fileInfo->user_data_size = 0;
00060     fileInfo->file_size = htonl(cineon->imageOffset + cineon->height * cineon->lineBufferLength);
00061     strcpy(fileInfo->vers, "V4.5");
00062     strncpy(fileInfo->file_name, filename, 99);
00063     fileInfo->file_name[99] = 0;
00064 
00065     fileClock = time(0);
00066     fileTime = localtime(&fileClock);
00067     strftime(fileInfo->create_date, 12, "%Y:%m:%d", fileTime);
00068     /* Question: is %Z in strftime guaranteed to return 3 chars? */
00069     strftime(fileInfo->create_time, 12, "%H:%M:%S%Z", fileTime);
00070     fileInfo->create_time[11] = 0;
00071 }
00072 
00073 static void
00074 dumpCineonFileInfo(CineonFileInformation* fileInfo) {
00075     d_printf("\n--File Information--\n");
00076     d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num));
00077     d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset));
00078     d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
00079     d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
00080     d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
00081     d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
00082     d_printf("Version \"%s\"\n", fileInfo->vers);
00083     d_printf("File name \"%s\"\n", fileInfo->file_name);
00084     d_printf("Creation date \"%s\"\n", fileInfo->create_date);
00085     d_printf("Creation time \"%s\"\n", fileInfo->create_time);
00086 }
00087 
00088 static void
00089 fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) {
00090 
00091     chan->designator1 = 0;
00092     chan->designator2 = des;
00093     chan->bits_per_pixel = 10;
00094     chan->pixels_per_line = htonl(cineon->width);
00095     chan->lines_per_image = htonl(cineon->height);
00096     chan->ref_low_data = htonl(0);
00097     chan->ref_low_quantity = htonf(0.0);
00098     chan->ref_high_data = htonl(1023);
00099     chan->ref_high_quantity = htonf(2.046);
00100 }
00101 
00102 static void
00103 dumpCineonChannelInfo(CineonChannelInformation* chan) {
00104     d_printf("  Metric selector: %d", chan->designator1);
00105     switch (chan->designator1) {
00106         case 0: d_printf(" (Universal)\n"); break;
00107         default: d_printf(" (Vendor specific)\n"); break;
00108     }
00109     d_printf("  Metric: %d,", chan->designator2);
00110     switch (chan->designator2) {
00111         case 0: d_printf(" B&W (printing density?)\n"); break;
00112         case 1: d_printf(" Red printing density\n"); break;
00113         case 2: d_printf(" Green printing density\n"); break;
00114         case 3: d_printf(" Blue printing density\n"); break;
00115         case 4: d_printf(" Red CCIR XA/11\n"); break;
00116         case 5: d_printf(" Green CCIR XA/11\n"); break;
00117         case 6: d_printf(" Blue CCIR XA/11\n"); break;
00118         default: d_printf(" (unknown)\n"); break;
00119     }
00120     d_printf("  Bits per pixel %d\n", chan->bits_per_pixel);
00121     d_printf("  Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line));
00122     d_printf("  Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image));
00123     d_printf("  Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
00124     d_printf("  Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
00125     d_printf("  Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
00126     d_printf("  Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
00127 }
00128 
00129 static void
00130 fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) {
00131 
00132     imageInfo->orientation = 0;
00133     imageInfo->channels_per_image = cineon->depth;
00134 
00135     if (cineon->depth == 1) {
00136         fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0);
00137 
00138     } else if (cineon->depth == 3) {
00139         fillCineonChannelInfo(cineon, &imageInfo->channel[0], 1);
00140         fillCineonChannelInfo(cineon, &imageInfo->channel[1], 2);
00141         fillCineonChannelInfo(cineon, &imageInfo->channel[2], 3);
00142     }
00143 
00144     imageInfo->white_point_x = htonf(undefined());
00145     imageInfo->white_point_y = htonf(undefined());
00146     imageInfo->red_primary_x = htonf(undefined());
00147     imageInfo->red_primary_y = htonf(undefined());
00148     imageInfo->green_primary_x = htonf(undefined());
00149     imageInfo->green_primary_y = htonf(undefined());
00150     imageInfo->blue_primary_x = htonf(undefined());
00151     imageInfo->blue_primary_y = htonf(undefined());
00152 
00153     strcpy(imageInfo->label, "David's Cineon writer.");
00154 
00155 }
00156 
00157 static void
00158 dumpCineonImageInfo(CineonImageInformation* imageInfo) {
00159 
00160     int i;
00161     d_printf("\n--Image Information--\n");
00162     d_printf("Image orientation %d,", imageInfo->orientation);
00163     switch (imageInfo->orientation) {
00164         case 0: d_printf(" LRTB\n"); break;
00165         case 1: d_printf(" LRBT\n"); break;
00166         case 2: d_printf(" RLTB\n"); break;
00167         case 3: d_printf(" RLBT\n"); break;
00168         case 4: d_printf(" TBLR\n"); break;
00169         case 5: d_printf(" TBRL\n"); break;
00170         case 6: d_printf(" BTLR\n"); break;
00171         case 7: d_printf(" BTRL\n"); break;
00172         default: d_printf(" (unknown)\n"); break;
00173     }
00174     d_printf("Channels %d\n", imageInfo->channels_per_image);
00175     for (i = 0; i < imageInfo->channels_per_image; ++i) {
00176         d_printf("  --Channel %d--\n", i);
00177         dumpCineonChannelInfo(&imageInfo->channel[i]);
00178     }
00179 
00180     d_printf("White point x %f\n", ntohf(imageInfo->white_point_x));
00181     d_printf("White point y %f\n", ntohf(imageInfo->white_point_y));
00182     d_printf("Red primary x %f\n", ntohf(imageInfo->red_primary_x));
00183     d_printf("Red primary y %f\n", ntohf(imageInfo->red_primary_y));
00184     d_printf("Green primary x %f\n", ntohf(imageInfo->green_primary_x));
00185     d_printf("Green primary y %f\n", ntohf(imageInfo->green_primary_y));
00186     d_printf("Blue primary x %f\n", ntohf(imageInfo->blue_primary_x));
00187     d_printf("Blue primary y %f\n", ntohf(imageInfo->blue_primary_y));
00188     d_printf("Label \"%s\"\n", imageInfo->label);
00189 }
00190 
00191 static void
00192 fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) {
00193 
00194     (void)cineon; /* unused */
00195     
00196     formatInfo->interleave = 0;
00197     formatInfo->packing = 5;
00198     formatInfo->signage = 0;
00199     formatInfo->sense = 0;
00200     formatInfo->line_padding = htonl(0);
00201     formatInfo->channel_padding = htonl(0);
00202 }
00203 
00204 static void
00205 dumpCineonFormatInfo(CineonFormatInformation* formatInfo) {
00206     d_printf("\n--Format Information--\n");
00207     d_printf("Interleave %d,", formatInfo->interleave);
00208     switch (formatInfo->interleave) {
00209         case 0: d_printf(" pixel interleave\n"); break;
00210         case 1: d_printf(" line interleave\n"); break;
00211         case 2: d_printf(" channel interleave\n"); break;
00212         default: d_printf(" (unknown)\n"); break;
00213     }
00214     d_printf("Packing %d,", formatInfo->packing);
00215     if (formatInfo->packing & 0x80) { 
00216         d_printf(" multi pixel,");
00217     } else {
00218         d_printf(" single pixel,");
00219     }
00220     switch (formatInfo->packing & 0x7F) {
00221         case 0: d_printf(" tight\n"); break;
00222         case 1: d_printf(" byte packed left\n"); break;
00223         case 2: d_printf(" byte packed right\n"); break;
00224         case 3: d_printf(" word packed left\n"); break;
00225         case 4: d_printf(" word packed right\n"); break;
00226         case 5: d_printf(" long packed left\n"); break;
00227         case 6: d_printf(" long packed right\n"); break;
00228         default: d_printf(" (unknown)\n"); break;
00229     }
00230     d_printf("Sign %d,", formatInfo->signage);
00231     if (formatInfo->signage) { 
00232         d_printf(" signed\n");
00233     } else {
00234         d_printf(" unsigned\n");
00235     }
00236     d_printf("Sense %d,", formatInfo->signage);
00237     if (formatInfo->signage) { 
00238         d_printf(" negative\n");
00239     } else {
00240         d_printf(" positive\n");
00241     }
00242     d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding));
00243     d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding));
00244 }
00245 
00246 static void
00247 fillCineonOriginationInfo(CineonFile* cineon,
00248     CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) {
00249     
00250     (void)cineon; /* unused */
00251 
00252     originInfo->x_offset = htonl(0);
00253     originInfo->y_offset = htonl(0);
00254     strcpy(originInfo->file_name, fileInfo->file_name);
00255     strcpy(originInfo->create_date, fileInfo->create_date);
00256     strcpy(originInfo->create_time, fileInfo->create_time);
00257     strncpy(originInfo->input_device, "David's Cineon writer", 64);
00258     strncpy(originInfo->model_number, "Software", 32);
00259     strncpy(originInfo->serial_number, "001", 32);
00260     originInfo->x_input_samples_per_mm = htonf(undefined());
00261     originInfo->y_input_samples_per_mm =    htonf(undefined());
00262     /* this should probably be undefined, too */
00263     originInfo->input_device_gamma = htonf(1.0);
00264 }
00265 
00266 static void
00267 dumpCineonOriginationInfo(CineonOriginationInformation* originInfo) {
00268     d_printf("\n--Origination Information--\n");
00269     d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
00270     d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
00271     d_printf("File name \"%s\"\n", originInfo->file_name);
00272     d_printf("Creation date \"%s\"\n", originInfo->create_date);
00273     d_printf("Creation time \"%s\"\n", originInfo->create_time);
00274     d_printf("Input device \"%s\"\n", originInfo->input_device);
00275     d_printf("Model number \"%s\"\n", originInfo->model_number);
00276     d_printf("Serial number \"%s\"\n", originInfo->serial_number);
00277     d_printf("Samples per mm in x %f\n", ntohf(originInfo->x_input_samples_per_mm));
00278     d_printf("Samples per mm in y %f\n", ntohf(originInfo->y_input_samples_per_mm));
00279     d_printf("Input device gamma %f\n", ntohf(originInfo->input_device_gamma));
00280 }
00281 
00282 static int
00283 initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) {
00284 
00285     fillCineonFileInfo(cineon, &header->fileInfo, imagename);
00286     fillCineonImageInfo(cineon, &header->imageInfo);
00287     fillCineonFormatInfo(cineon, &header->formatInfo);
00288     fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo);
00289 
00290     return 0;
00291 }
00292 
00293 static void
00294 UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) {
00295     dumpCineonFileInfo(&header->fileInfo);
00296     dumpCineonImageInfo(&header->imageInfo);
00297     dumpCineonFormatInfo(&header->formatInfo);
00298     dumpCineonOriginationInfo(&header->originInfo);
00299 }
00300 
00301 static int verbose = 0;
00302 void
00303 cineonSetVerbose(int verbosity) {
00304     verbose = verbosity;
00305 }
00306 
00307 static void
00308 verboseMe(CineonFile* cineon) {
00309 
00310     d_printf("size %d x %d x %d\n", cineon->width, cineon->height, cineon->depth);
00311     d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
00312         cineon->imageOffset, cineon->lineBufferLength * 4,
00313         cineon->imageOffset + cineon->lineBufferLength * 4 * cineon->height);
00314 }
00315 
00316 int
00317 cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) {
00318 
00319     int longsRead;
00320     int pixelIndex;
00321     int longIndex;
00322     int numPixels = cineon->width * cineon->depth;
00323 
00324 
00325     /* only seek if not reading consecutive lines */
00326     if (y != cineon->fileYPos) {
00327         int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
00328         if (verbose) d_printf("Seek in getRowBytes\n");
00329         if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
00330             if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
00331             return 1;
00332         }
00333         cineon->fileYPos = y;
00334     }
00335 
00336     longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
00337     if (longsRead != cineon->lineBufferLength) {
00338         if (verbose) 
00339     {   d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
00340         perror("cineonGetRowBytes");
00341     }
00342         return 1;
00343     }
00344 
00345     /* remember where we left the car, honey */
00346     ++cineon->fileYPos;
00347 
00348     /* convert longwords to pixels */
00349     pixelIndex = 0;
00350     for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
00351         unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
00352         t = t >> 2;
00353         cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff;
00354         t = t >> 10;
00355         cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff;
00356         t = t >> 10;
00357         cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff;
00358         pixelIndex += 3;
00359     }
00360 
00361     /* extract required pixels */
00362     for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
00363         if(cineon->params.doLogarithm)
00364             row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]];
00365         else
00366             row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
00367     }
00368 
00369     return 0;
00370 }
00371 
00372 int
00373 cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) {
00374 
00375     int pixelIndex;
00376     int numPixels = cineon->width * cineon->depth;
00377     int longIndex;
00378     int longsWritten;
00379 
00380     /* put new pixels into pixelBuffer */
00381     for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
00382         if(cineon->params.doLogarithm)
00383             cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]];
00384         else
00385             cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
00386     }
00387 
00388     /* pack into longwords */
00389     pixelIndex = 0;
00390     for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
00391         unsigned int t =
00392                 (cineon->pixelBuffer[pixelIndex] << 22) |
00393                 (cineon->pixelBuffer[pixelIndex+1] << 12) |
00394                 (cineon->pixelBuffer[pixelIndex+2] << 2);
00395         cineon->lineBuffer[longIndex] = htonl(t);
00396         pixelIndex += 3;
00397     }
00398 
00399     /* only seek if not reading consecutive lines */
00400     if (y != cineon->fileYPos) {
00401         int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
00402         if (verbose) d_printf("Seek in setRowBytes\n");
00403         if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
00404             if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
00405             return 1;
00406         }
00407         cineon->fileYPos = y;
00408     }
00409 
00410     longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
00411     if (longsWritten != cineon->lineBufferLength) {
00412         if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
00413         return 1;
00414     }
00415 
00416     ++cineon->fileYPos;
00417 
00418     return 0;
00419 }
00420 
00421 int
00422 cineonGetRow(CineonFile* cineon, unsigned short* row, int y) {
00423 
00424     int longsRead;
00425     int pixelIndex;
00426     int longIndex;
00427 /*  int numPixels = cineon->width * cineon->depth;
00428 */
00429     /* only seek if not reading consecutive lines */
00430     if (y != cineon->fileYPos) {
00431         int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
00432         if (verbose) d_printf("Seek in getRow\n");
00433         if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
00434             if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
00435             return 1;
00436         }
00437         cineon->fileYPos = y;
00438     }
00439 
00440     longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
00441     if (longsRead != cineon->lineBufferLength) {
00442         if (verbose) d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
00443         return 1;
00444     }
00445 
00446     /* remember where we left the car, honey */
00447     ++cineon->fileYPos;
00448 
00449     /* convert longwords to pixels */
00450     pixelIndex = 0;
00451     for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
00452         unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
00453         t = t >> 2;
00454         row[pixelIndex+2] = (unsigned short) t & 0x3ff;
00455         t = t >> 10;
00456         row[pixelIndex+1] = (unsigned short) t & 0x3ff;
00457         t = t >> 10;
00458         row[pixelIndex] = (unsigned short) t & 0x3ff;
00459         pixelIndex += 3;
00460     }
00461 
00462     return 0;
00463 }
00464 
00465 int
00466 cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) {
00467 
00468     int pixelIndex;
00469 /*  int numPixels = cineon->width * cineon->depth;
00470 */  int longIndex;
00471     int longsWritten;
00472 
00473     /* pack into longwords */
00474     pixelIndex = 0;
00475     for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
00476         unsigned int t =
00477                 (row[pixelIndex] << 22) |
00478                 (row[pixelIndex+1] << 12) |
00479                 (row[pixelIndex+2] << 2);
00480         cineon->lineBuffer[longIndex] = htonl(t);
00481         pixelIndex += 3;
00482     }
00483 
00484     /* only seek if not reading consecutive lines */
00485     if (y != cineon->fileYPos) {
00486         int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
00487         if (verbose) d_printf("Seek in setRowBytes\n");
00488         if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
00489             if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
00490             return 1;
00491         }
00492         cineon->fileYPos = y;
00493     }
00494 
00495     longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
00496     if (longsWritten != cineon->lineBufferLength) {
00497         if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
00498         return 1;
00499     }
00500 
00501     ++cineon->fileYPos;
00502 
00503     return 0;
00504 }
00505 
00506 CineonFile* 
00507 cineonOpen(const char* filename) {
00508 
00509     CineonGenericHeader header;
00510 
00511     CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
00512     if (cineon == 0) {
00513         if (verbose) d_printf("Failed to malloc cineon file structure.\n");
00514         return 0;
00515     }
00516 
00517     /* for close routine */
00518     cineon->file = 0;
00519     cineon->lineBuffer = 0;
00520     cineon->pixelBuffer = 0;
00521     cineon->membuffer = 0;
00522     cineon->memcursor = 0;
00523     cineon->membuffersize = 0;
00524     
00525     cineon->file = fopen(filename, "rb");
00526     if (cineon->file == 0) {
00527         if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
00528         cineonClose(cineon);
00529         return 0;
00530     }
00531     cineon->reading = 1;
00532 
00533     if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) {
00534         if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
00535         cineonClose(cineon);
00536         return 0;
00537     }
00538 
00539     /* let's assume cineon files are always network order */
00540     if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
00541         if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
00542             (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
00543         cineonClose(cineon);
00544         return 0;
00545     }
00546 
00547     if (header.formatInfo.packing != 5) {
00548         if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
00549         cineonClose(cineon);
00550         return 0;
00551     }
00552 
00553     cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
00554     cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
00555     cineon->depth = header.imageInfo.channels_per_image;
00556     /* cineon->bitsPerPixel = 10; */
00557     cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
00558     cineon->imageOffset = ntohl(header.fileInfo.image_offset);
00559 
00560     cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
00561     cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
00562     if (cineon->lineBuffer == 0) {
00563         if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
00564         cineonClose(cineon);
00565         return 0;
00566     }
00567 
00568     cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
00569     if (cineon->pixelBuffer == 0) {
00570         if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
00571                 (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
00572         cineonClose(cineon);
00573         return 0;
00574     }
00575     cineon->pixelBufferUsed = 0;
00576 
00577     if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
00578         if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
00579         cineonClose(cineon);
00580         return 0;
00581     }
00582     cineon->fileYPos = 0;
00583 
00584     logImageGetByteConversionDefaults(&cineon->params);
00585     setupLut(cineon);
00586 
00587     cineon->getRow = &cineonGetRowBytes;
00588     cineon->setRow = 0;
00589     cineon->close = &cineonClose;
00590 
00591     if (verbose) {
00592         verboseMe(cineon);
00593     }
00594 
00595     return cineon;
00596 }
00597 
00598 int cineonIsMemFileCineon(unsigned char *mem)
00599 {
00600     unsigned int num;
00601     memcpy(&num, mem, sizeof(unsigned int));
00602     
00603     if (num != ntohl(CINEON_FILE_MAGIC)) {
00604         return 0;
00605     } else return 1;
00606 }
00607 
00608 CineonFile* 
00609 cineonOpenFromMem(unsigned char *mem, unsigned int size) {
00610 
00611     CineonGenericHeader header;
00612     
00613     CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
00614     if (cineon == 0) {
00615         if (verbose) d_printf("Failed to malloc cineon file structure.\n");
00616         return 0;
00617     }
00618 
00619     /* for close routine */
00620     cineon->file = 0;
00621     cineon->lineBuffer = 0;
00622     cineon->pixelBuffer = 0;
00623     cineon->membuffer = mem;
00624     cineon->membuffersize = size;
00625     cineon->memcursor = mem;
00626     
00627     cineon->file = 0;
00628     cineon->reading = 1;
00629     verbose = 0;
00630     if (size < sizeof(CineonGenericHeader)) {
00631         if (verbose) d_printf("Not enough data for header!\n");
00632         cineonClose(cineon);
00633         return 0;
00634     }
00635 
00636     logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon);
00637 
00638     /* let's assume cineon files are always network order */
00639     if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
00640         if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num));
00641 
00642         cineonClose(cineon);
00643         return 0;
00644     }
00645 
00646     if (header.formatInfo.packing != 5) {
00647         if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
00648         cineonClose(cineon);
00649         return 0;
00650     }
00651 
00652     cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
00653     cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
00654     cineon->depth = header.imageInfo.channels_per_image;
00655     /* cineon->bitsPerPixel = 10; */
00656     cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
00657     cineon->imageOffset = ntohl(header.fileInfo.image_offset);
00658 
00659     cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
00660     cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
00661     if (cineon->lineBuffer == 0) {
00662         if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
00663         cineonClose(cineon);
00664         return 0;
00665     }
00666 
00667     cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
00668     if (cineon->pixelBuffer == 0) {
00669         if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
00670                 (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
00671         cineonClose(cineon);
00672         return 0;
00673     }
00674     cineon->pixelBufferUsed = 0;
00675     
00676     if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
00677         if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
00678         cineonClose(cineon);
00679         return 0;
00680     }
00681     
00682     cineon->fileYPos = 0;
00683 
00684     logImageGetByteConversionDefaults(&cineon->params);
00685     setupLut(cineon);
00686 
00687     cineon->getRow = &cineonGetRowBytes;
00688     cineon->setRow = 0;
00689     cineon->close = &cineonClose;
00690 
00691     if (verbose) {
00692         verboseMe(cineon);
00693     }
00694 
00695     return cineon;
00696 }
00697 
00698 
00699 int
00700 cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) {
00701     *width = cineon->width;
00702     *height = cineon->height;
00703     *depth = cineon->depth;
00704     return 0;
00705 }
00706 
00707 CineonFile*
00708 cineonCreate(const char* filename, int width, int height, int depth) {
00709 
00710     /* Note: always write files in network order */
00711     /* By the spec, it shouldn't matter, but ... */
00712 
00713     CineonGenericHeader header;
00714     const char* shortFilename = 0;
00715 
00716     CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile));
00717     if (cineon == 0) {
00718         if (verbose) d_printf("Failed to malloc cineon file structure.\n");
00719         return 0;
00720     }
00721 
00722     memset(&header, 0, sizeof(header));
00723 
00724     /* for close routine */
00725     cineon->file = 0;
00726     cineon->lineBuffer = 0;
00727     cineon->pixelBuffer = 0;
00728 
00729     cineon->file = fopen(filename, "wb");
00730     if (cineon->file == 0) {
00731         if (verbose) d_printf("Couldn't open file %s\n", filename);
00732         cineonClose(cineon);
00733         return 0;
00734     }
00735     cineon->reading = 0;
00736 
00737     cineon->width = width;
00738     cineon->height = height;
00739     cineon->depth = depth;
00740     cineon->bitsPerPixel = 10;
00741     cineon->imageOffset = sizeof(CineonGenericHeader);
00742 
00743     cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
00744     cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
00745     if (cineon->lineBuffer == 0) {
00746         if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
00747         cineonClose(cineon);
00748         return 0;
00749     }
00750 
00751     cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
00752     if (cineon->pixelBuffer == 0) {
00753         if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
00754                 (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
00755         cineonClose(cineon);
00756         return 0;
00757     }
00758     cineon->pixelBufferUsed = 0;
00759 
00760     /* find trailing part of filename */
00761     shortFilename = strrchr(filename, '/');
00762     if (shortFilename == 0) {
00763         shortFilename = filename;
00764     } else {
00765         ++shortFilename;
00766     }
00767 
00768     if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) {
00769         cineonClose(cineon);
00770         return 0;
00771     }
00772 
00773     if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
00774         if (verbose) d_printf("Couldn't write image header\n");
00775         cineonClose(cineon);
00776         return 0;
00777     }
00778     cineon->fileYPos = 0;
00779 
00780     logImageGetByteConversionDefaults(&cineon->params);
00781     setupLut(cineon);
00782 
00783     cineon->getRow = 0;
00784     cineon->setRow = &cineonSetRowBytes;
00785     cineon->close = &cineonClose;
00786 
00787     return cineon;
00788 }
00789 
00790 void
00791 cineonClose(CineonFile* cineon) {
00792 
00793     if (cineon == 0) {
00794         return;
00795     }
00796 
00797     if (cineon->file) {
00798         fclose(cineon->file);
00799         cineon->file = 0;
00800     }
00801 
00802     if (cineon->lineBuffer) {
00803         free(cineon->lineBuffer);
00804         cineon->lineBuffer = 0;
00805     }
00806 
00807     if (cineon->pixelBuffer) {
00808         free(cineon->pixelBuffer);
00809         cineon->pixelBuffer = 0;
00810     }
00811 
00812     free(cineon);
00813 }