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