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