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