int cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) { int longsRead; int pixelIndex; int longIndex; int numPixels = cineon->width * cineon->depth; /* only seek if not reading consecutive lines */ if (y != cineon->fileYPos) { int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4; if (verbose) d_printf("Seek in getRowBytes\n"); if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) { if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset); return 1; } cineon->fileYPos = y; } longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon); if (longsRead != cineon->lineBufferLength) { if (verbose) { d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4); perror("cineonGetRowBytes"); } return 1; } /* remember where we left the car, honey */ ++cineon->fileYPos; /* convert longwords to pixels */ pixelIndex = 0; for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { unsigned int t = ntohl(cineon->lineBuffer[longIndex]); t = t >> 2; cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff; t = t >> 10; cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff; t = t >> 10; cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff; pixelIndex += 3; } /* extract required pixels */ for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { if (cineon->params.doLogarithm) row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]]; else row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6; } return 0; }
int dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) { /* Note: this code is bizarre because DPX files can wrap */ /* packed longwords across line boundaries!!!! */ size_t readLongs; unsigned int longIndex; int numPixels = dpx->width * dpx->depth; int pixelIndex; /* only seek if not reading consecutive lines */ /* this is not quite right yet, need to account for leftovers */ if (y != dpx->fileYPos) { int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4; if (verbose) d_printf("Seek in getRowBytes\n"); if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) { if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset); return 1; } dpx->fileYPos = y; } /* read enough longwords */ readLongs = pixelsToLongs(numPixels - dpx->pixelBufferUsed); if (logimage_fread(dpx->lineBuffer, 4, readLongs, dpx) != readLongs) { if (verbose) d_printf("Couldn't read line %d length %d\n", y, (int)readLongs * 4); return 1; } ++dpx->fileYPos; /* convert longwords to pixels */ pixelIndex = dpx->pixelBufferUsed; /* this is just strange */ if (dpx->depth == 1) { for (longIndex = 0; longIndex < readLongs; ++longIndex) { unsigned int t = ntohl(dpx->lineBuffer[longIndex]); dpx->pixelBuffer[pixelIndex] = t & 0x3ff; t = t >> 10; dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff; t = t >> 10; dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff; pixelIndex += 3; } } else /* if (dpx->depth == 3) */ { for (longIndex = 0; longIndex < readLongs; ++longIndex) {
int cineonGetRow(CineonFile* cineon, unsigned short* row, int y) { int longsRead; int pixelIndex; int longIndex; /* int numPixels = cineon->width * cineon->depth; */ /* only seek if not reading consecutive lines */ if (y != cineon->fileYPos) { int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4; if (verbose) d_printf("Seek in getRow\n"); if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) { if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset); return 1; } cineon->fileYPos = y; } longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon); if (longsRead != cineon->lineBufferLength) { if (verbose) d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4); return 1; } /* remember where we left the car, honey */ ++cineon->fileYPos; /* convert longwords to pixels */ pixelIndex = 0; for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { unsigned int t = ntohl(cineon->lineBuffer[longIndex]); t = t >> 2; row[pixelIndex+2] = (unsigned short) t & 0x3ff; t = t >> 10; row[pixelIndex+1] = (unsigned short) t & 0x3ff; t = t >> 10; row[pixelIndex] = (unsigned short) t & 0x3ff; pixelIndex += 3; } return 0; }
CineonFile* cineonOpenFromMem(unsigned char *mem, unsigned int size) { CineonGenericHeader header; int i; CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile)); if (cineon == 0) { if (verbose) d_printf("Failed to malloc cineon file structure.\n"); return 0; } /* for close routine */ cineon->file = 0; cineon->lineBuffer = 0; cineon->pixelBuffer = 0; cineon->membuffer = mem; cineon->membuffersize = size; cineon->memcursor = mem; cineon->file = 0; cineon->reading = 1; verbose = 0; if (size < sizeof(CineonGenericHeader)) { if (verbose) d_printf("Not enough data for header!\n"); cineonClose(cineon); return 0; } logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon); /* let's assume cineon files are always network order */ if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) { if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num)); cineonClose(cineon); return 0; } if (header.formatInfo.packing != 5) { if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing); cineonClose(cineon); return 0; } cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line); cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image); cineon->depth = header.imageInfo.channels_per_image; /* cineon->bitsPerPixel = 10; */ cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; cineon->imageOffset = ntohl(header.fileInfo.image_offset); cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth); cineon->lineBuffer = malloc(cineon->lineBufferLength * 4); if (cineon->lineBuffer == 0) { if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4); cineonClose(cineon); return 0; } cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short)); if (cineon->pixelBuffer == 0) { if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", (cineon->width * cineon->depth) * (int)sizeof(unsigned short)); cineonClose(cineon); return 0; } cineon->pixelBufferUsed = 0; i = cineon->imageOffset; if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) { if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset); cineonClose(cineon); return 0; } cineon->fileYPos = 0; logImageGetByteConversionDefaults(&cineon->params); setupLut(cineon); cineon->getRow = &cineonGetRowBytes; cineon->setRow = 0; cineon->close = &cineonClose; if (verbose) { verboseMe(cineon); } return cineon; }
LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) { CineonMainHeader header; LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); const char *filename = (const char *)byteStuff; int i; unsigned int dataOffset; if (cineon == NULL) { if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n"); return NULL; } /* zero the header */ memset(&header, 0, sizeof(CineonMainHeader)); /* for close routine */ cineon->file = NULL; if (fromMemory == 0) { /* byteStuff is then the filename */ cineon->file = BLI_fopen(filename, "rb"); if (cineon->file == NULL) { if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename); logImageClose(cineon); return NULL; } /* not used in this case */ cineon->memBuffer = NULL; cineon->memCursor = NULL; cineon->memBufferSize = 0; } else { cineon->memBuffer = (unsigned char *)byteStuff; cineon->memCursor = (unsigned char *)byteStuff; cineon->memBufferSize = bufferSize; } if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) { if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff); logImageClose(cineon); return NULL; } /* endianness determination */ if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) { cineon->isMSB = 1; if (verbose) printf("Cineon: File is MSB.\n"); } else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) { cineon->isMSB = 0; if (verbose) printf("Cineon: File is LSB.\n"); } else { if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n", (unsigned long)header.fileHeader.magic_num, byteStuff); logImageClose(cineon); return NULL; } cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB); cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB); if (cineon->width == 0 || cineon->height == 0) { if (verbose) printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height); logImageClose(cineon); return NULL; } cineon->depth = header.imageHeader.elements_per_image; cineon->srcFormat = format_Cineon; if (header.imageHeader.interleave == 0) cineon->numElements = 1; else if (header.imageHeader.interleave == 2) cineon->numElements = header.imageHeader.elements_per_image; else { if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave); logImageClose(cineon); return NULL; } if (cineon->depth == 1) { /* Grayscale image */ cineon->element[0].descriptor = descriptor_Luminance; cineon->element[0].transfer = transfer_Linear; cineon->element[0].depth = 1; } else if (cineon->depth == 3) { /* RGB image */ if (cineon->numElements == 1) { cineon->element[0].descriptor = descriptor_RGB; cineon->element[0].transfer = transfer_PrintingDensity; cineon->element[0].depth = 3; } else if (cineon->numElements == 3) { cineon->element[0].descriptor = descriptor_Red; cineon->element[0].transfer = transfer_PrintingDensity; cineon->element[0].depth = 1; cineon->element[1].descriptor = descriptor_Green; cineon->element[1].transfer = transfer_PrintingDensity; cineon->element[1].depth = 1; cineon->element[2].descriptor = descriptor_Blue; cineon->element[2].transfer = transfer_PrintingDensity; cineon->element[2].depth = 1; } } else { if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth); logImageClose(cineon); return NULL; } dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB); for (i = 0; i < cineon->numElements; i++) { cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f; cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, cineon->isMSB); cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, cineon->isMSB); cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, cineon->isMSB); cineon->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, cineon->isMSB); switch (header.imageHeader.packing) { case 0: cineon->element[i].packing = 0; break; case 5: cineon->element[i].packing = 1; break; case 6: cineon->element[i].packing = 2; break; default: /* Not supported */ if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing); logImageClose(cineon); return NULL; } if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32) cineon->element[i].refLowData = 0; if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32) cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue; if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity)) cineon->element[i].refLowQuantity = 0.0f; if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refHighQuantity)) { if (cineon->element[i].transfer == transfer_PrintingDensity) cineon->element[i].refHighQuantity = 2.048f; else cineon->element[i].refHighQuantity = cineon->element[i].maxValue; } cineon->element[i].dataOffset = dataOffset; dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]); } cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue; cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue; cineon->gamma = 1.7f; if (verbose) { printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements); for (i = 0; i < cineon->numElements; i++) { printf(" Element %d:\n", i); printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample); printf(" Depth: %d\n", cineon->element[i].depth); printf(" Transfer characteristics: %d\n", cineon->element[i].transfer); printf(" Packing: %d\n", cineon->element[i].packing); printf(" Descriptor: %d\n", cineon->element[i].descriptor); printf(" Data offset: %u\n", cineon->element[i].dataOffset); printf(" Reference low data: %u\n", cineon->element[i].refLowData); printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity); printf(" Reference high data: %u\n", cineon->element[i].refHighData); printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity); printf("\n"); } printf("Gamma: %f\n", cineon->gamma); printf("Reference black: %f\n", cineon->referenceBlack); printf("Reference white: %f\n", cineon->referenceWhite); printf("----------------------------\n"); } return cineon; }
LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) { DpxMainHeader header; LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); const char *filename = (const char *)byteStuff; int i; if (dpx == NULL) { if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); return NULL; } /* zero the header */ memset(&header, 0, sizeof(DpxMainHeader)); /* for close routine */ dpx->file = NULL; if (fromMemory == 0) { /* byteStuff is then the filename */ dpx->file = BLI_fopen(filename, "rb"); if (dpx->file == NULL) { if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename); logImageClose(dpx); return NULL; } /* not used in this case */ dpx->memBuffer = NULL; dpx->memCursor = NULL; dpx->memBufferSize = 0; } else { dpx->memBuffer = (unsigned char *)byteStuff; dpx->memCursor = (unsigned char *)byteStuff; dpx->memBufferSize = bufferSize; } if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) { if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff); logImageClose(dpx); return NULL; } /* endianness determination */ if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) { dpx->isMSB = 1; if (verbose) printf("DPX: File is MSB.\n"); } else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) { dpx->isMSB = 0; if (verbose) printf("DPX: File is LSB.\n"); } else { if (verbose) { printf("DPX: Bad magic number %u in \"%s\".\n", header.fileHeader.magic_num, byteStuff); } logImageClose(dpx); return NULL; } dpx->srcFormat = format_DPX; dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB); if (dpx->numElements == 0) { if (verbose) printf("DPX: Wrong number of elements: %d\n", dpx->numElements); logImageClose(dpx); return NULL; } dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB); dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB); if (dpx->width == 0 || dpx->height == 0) { if (verbose) printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height); logImageClose(dpx); return NULL; } dpx->depth = 0; for (i = 0; i < dpx->numElements; i++) { dpx->element[i].descriptor = header.imageHeader.element[i].descriptor; switch (dpx->element[i].descriptor) { case descriptor_Red: case descriptor_Green: case descriptor_Blue: case descriptor_Alpha: case descriptor_Luminance: case descriptor_Chrominance: dpx->depth++; dpx->element[i].depth = 1; break; case descriptor_CbYCrY: dpx->depth += 2; dpx->element[i].depth = 2; break; case descriptor_RGB: case descriptor_CbYCr: case descriptor_CbYACrYA: dpx->depth += 3; dpx->element[i].depth = 3; break; case descriptor_RGBA: case descriptor_ABGR: case descriptor_CbYCrA: dpx->depth += 4; dpx->element[i].depth = 4; break; case descriptor_Depth: case descriptor_Composite: /* unsupported */ break; } if (dpx->depth == 0 || dpx->depth > 4) { if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth); logImageClose(dpx); return NULL; } dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; if (dpx->element[i].bitsPerSample != 1 && dpx->element[i].bitsPerSample != 8 && dpx->element[i].bitsPerSample != 10 && dpx->element[i].bitsPerSample != 12 && dpx->element[i].bitsPerSample != 16) { if (verbose) printf("DPX: Unsupported bitsPerSample for elements %d: %d\n", i, dpx->element[i].bitsPerSample); logImageClose(dpx); return NULL; } dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f; dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB); if (dpx->element[i].packing > 2) { if (verbose) printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing); logImageClose(dpx); return NULL; } /* Sometimes, the offset is not set correctly in the header */ dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB); if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1) dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB); if (dpx->element[i].dataOffset == 0) { if (verbose) printf("DPX: Image header is corrupted.\n"); logImageClose(dpx); return NULL; } dpx->element[i].transfer = header.imageHeader.element[i].transfer; /* if undefined, assign default */ dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB); dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, dpx->isMSB); dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, dpx->isMSB); dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, dpx->isMSB); switch (dpx->element[i].descriptor) { case descriptor_Red: case descriptor_Green: case descriptor_Blue: case descriptor_Alpha: case descriptor_RGB: case descriptor_RGBA: case descriptor_ABGR: if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) dpx->element[i].refLowData = 0; if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue; if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity)) dpx->element[i].refLowQuantity = 0.0f; if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) { if (dpx->element[i].transfer == transfer_PrintingDensity || dpx->element[i].transfer == transfer_Logarithmic) dpx->element[i].refHighQuantity = 2.048f; else dpx->element[i].refHighQuantity = dpx->element[i].maxValue; } break; case descriptor_Luminance: case descriptor_Chrominance: case descriptor_CbYCrY: case descriptor_CbYCr: case descriptor_CbYACrYA: case descriptor_CbYCrA: if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue; if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue; if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity)) dpx->element[i].refLowQuantity = 0.0f; if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) dpx->element[i].refHighQuantity = 0.7f; break; default: break; } } dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB); dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB); dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB); if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) || (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) || (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma))) { dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; dpx->gamma = 1.7f; } if (verbose) { printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements); for (i = 0; i < dpx->numElements; i++) { printf(" Element %d:\n", i); printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample); printf(" Depth: %d\n", dpx->element[i].depth); printf(" Transfer characteristics: %d\n", dpx->element[i].transfer); printf(" Packing: %d\n", dpx->element[i].packing); printf(" Descriptor: %d\n", dpx->element[i].descriptor); printf(" Data offset: %d\n", dpx->element[i].dataOffset); printf(" Reference low data: %u\n", dpx->element[i].refLowData); printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity); printf(" Reference high data: %u\n", dpx->element[i].refHighData); printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity); printf("\n"); } printf("Gamma: %f\n", dpx->gamma); printf("Reference black: %f\n", dpx->referenceBlack); printf("Reference white: %f\n", dpx->referenceWhite); printf("----------------------------\n"); } return dpx; }