static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags) { ImBuf *ibuf; LogImageFile *image; int x, y; unsigned short *row, *upix; int width, height, depth; float *frow; logImageSetVerbose((G.f & G_DEBUG) ? 1:0); image = logImageOpenFromMem(mem, size, use_cineon); if (!image) { printf("no image!\n"); return NULL; } logImageGetSize(image, &width, &height, &depth); if (depth != 3) { /*need to do greyscale loading eventually.*/ logImageClose(image); return NULL; } if (width == 0 && height == 0) { logImageClose(image); return NULL; } ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c"); frow = ibuf->rect_float+width*height*4; for (y = 0; y < height; y++) { logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */ upix = row; frow -= width*4; for (x=0; x<width; x++) { *(frow++) = ((float)*(upix++)) / 65535.0f; *(frow++) = ((float)*(upix++)) / 65535.0f; *(frow++) = ((float)*(upix++)) / 65535.0f; *(frow++) = 1.0f; } frow -= width*4; } MEM_freeN(row); logImageClose(image); if (flags & IB_rect) { IMB_rect_from_float(ibuf); } return ibuf; }
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; LogImageFile *image; int width, height, depth; colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); image = logImageOpenFromMemory(mem, size); if (image == 0) { printf("DPX/Cineon: error opening image.\n"); return 0; } logImageGetSize(image, &width, &height, &depth); if (width == 0 || height == 0) { logImageClose(image); return 0; } ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); if (ibuf == 0) { logImageClose(image); return 0; } if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { /* Conversion not possible (probably because the format is unsupported) */ logImageClose(image); MEM_freeN(ibuf); return 0; } logImageClose(image); ibuf->ftype = use_cineon ? CINEON : DPX; IMB_flipy(ibuf); if (flags & IB_rect) IMB_rect_from_float(ibuf); if (flags & IB_alphamode_detect) ibuf->flags |= IB_alphamode_premul; return ibuf; }
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; LogImageFile *image; int width, height, depth; colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); image = logImageOpenFromMemory(mem, size); if (image == NULL) { printf("DPX/Cineon: error opening image.\n"); return NULL; } logImageGetSize(image, &width, &height, &depth); ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); if (ibuf == NULL) { logImageClose(image); return NULL; } if (!(flags & IB_test)) { if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { logImageClose(image); IMB_freeImBuf(ibuf); return NULL; } IMB_flipy(ibuf); } logImageClose(image); ibuf->ftype = use_cineon ? CINEON : DPX; if (flags & IB_alphamode_detect) ibuf->flags |= IB_alphamode_premul; return ibuf; }
static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags) { LogImageByteConversionParameters conversion; const int width= ibuf->x; const int height= ibuf->y; const int depth= 3; LogImageFile* logImage; unsigned short* line, *pixel; int i, j; float *fline; float *fbuf; int is_alloc= 0; (void)flags; /* unused */ // cineon_conversion_parameters(&conversion); logImageGetByteConversionDefaults(&conversion); /* * Get the drawable for the current image... */ fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc); if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */ return 0; } logImageSetVerbose((G.f & G_DEBUG) ? 1:0); logImage = logImageCreate(filename, use_cineon, width, height, depth); if (!logImage) return 0; if(logImageSetByteConversion(logImage, &conversion)==0) { printf("error setting args\n"); } line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line"); /*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/ for (j = 0; j < height; ++j) { fline = &fbuf[width*j*4]; for (i=0; i<width; i++) { float *fpix, fpix2[3]; /*we have to convert to cinepaint's 16-bit-per-channel here*/ pixel = &line[i*depth]; fpix = &fline[i*4]; memcpy(fpix2, fpix, sizeof(float)*3); if (fpix2[0]>=1.0f) fpix2[0] = 1.0f; else if (fpix2[0]<0.0f) fpix2[0]= 0.0f; if (fpix2[1]>=1.0f) fpix2[1] = 1.0f; else if (fpix2[1]<0.0f) fpix2[1]= 0.0f; if (fpix2[2]>=1.0f) fpix2[2] = 1.0f; else if (fpix2[2]<0.0f) fpix2[2]= 0.0f; pixel[0] = (unsigned short)(fpix2[0] * 65535.0f); /*float-float math is faster*/ pixel[1] = (unsigned short)(fpix2[1] * 65535.0f); pixel[2] = (unsigned short)(fpix2[2] * 65535.0f); } logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j); } logImageClose(logImage); MEM_freeN(line); if(is_alloc) { MEM_freeN(fbuf); } return 1; }
LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator) { CineonMainHeader header; const char *shortFilename = NULL; /* unsigned char pad[6044]; */ LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); if (cineon == NULL) { if (verbose) printf("cineon: Failed to malloc cineon file structure.\n"); return NULL; } /* Only 10 bits Cineon are supported */ if (bitsPerSample != 10) { if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n"); logImageClose(cineon); return NULL; } cineon->width = width; cineon->height = height; cineon->element[0].bitsPerSample = 10; cineon->element[0].dataOffset = sizeof(CineonMainHeader); cineon->element[0].maxValue = 1023; cineon->isMSB = 1; cineon->numElements = 1; cineon->element[0].packing = 1; cineon->depth = 3; cineon->element[0].depth = 3; cineon->element[0].descriptor = descriptor_RGB; cineon->element[0].transfer = transfer_PrintingDensity; cineon->element[0].refHighQuantity = 2.048f; cineon->element[0].refLowQuantity = 0; cineon->element[0].refLowData = 0; cineon->element[0].refHighData = cineon->element[0].maxValue; cineon->referenceWhite = 685.0f; cineon->referenceBlack = 95.0f; cineon->gamma = 1.7f; shortFilename = strrchr(filename, '/'); if (shortFilename == NULL) shortFilename = filename; else shortFilename++; cineon->file = BLI_fopen(filename, "wb"); if (cineon->file == NULL) { if (verbose) printf("cineon: Couldn't open file %s\n", filename); logImageClose(cineon); return NULL; } fillCineonMainHeader(cineon, &header, shortFilename, creator); if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) { if (verbose) printf("cineon: Couldn't write image header\n"); logImageClose(cineon); return NULL; } 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; }
static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags) { LogImageFile *logImage; float *fbuf; float *fbuf_ptr; unsigned char *rect_ptr; int x, y, depth, bitspersample, rvalue; if (flags & IB_mem) { printf("DPX/Cineon: saving in memory is not supported.\n"); return 0; } logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); depth = (ibuf->planes + 7) >> 3; if (depth > 4 || depth < 3) { printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename); return 0; } if (ibuf->ftype & CINEON_10BIT) bitspersample = 10; else if (ibuf->ftype & CINEON_12BIT) bitspersample = 12; else if (ibuf->ftype & CINEON_16BIT) bitspersample = 16; else bitspersample = 8; logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4), (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender"); if (logImage == NULL) { printf("DPX/Cineon: error creating file.\n"); return 0; } if (ibuf->rect_float != NULL && bitspersample != 8) { /* don't use the float buffer to save 8 bpp picture to prevent color banding * (there's no dithering algorithm behing the logImageSetDataRGBA function) */ fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); for (y = 0; y < ibuf->y; y++) { float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x); float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x); memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float)); } rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0); MEM_freeN(fbuf); } else { if (ibuf->rect == NULL) IMB_rect_from_float(ibuf); fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); if (fbuf == NULL) { printf("DPX/Cineon: error allocating memory.\n"); logImageClose(logImage); return 0; } for (y = 0; y < ibuf->y; y++) { for (x = 0; x < ibuf->x; x++) { fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x); rect_ptr = (unsigned char *)ibuf->rect + 4 * (y * ibuf->x + x); fbuf_ptr[0] = (float)rect_ptr[0] / 255.0f; fbuf_ptr[1] = (float)rect_ptr[1] / 255.0f; fbuf_ptr[2] = (float)rect_ptr[2] / 255.0f; fbuf_ptr[3] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f; } } rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0); MEM_freeN(fbuf); } logImageClose(logImage); return rvalue; }
LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha, int isLogarithmic, int referenceWhite, int referenceBlack, float gamma, const char *creator) { DpxMainHeader header; const char *shortFilename = NULL; unsigned char pad[6044]; LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); if (dpx == NULL) { if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); return NULL; } dpx->width = width; dpx->height = height; dpx->element[0].bitsPerSample = bitsPerSample; dpx->element[0].dataOffset = 8092; dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f; dpx->isMSB = 1; dpx->numElements = 1; switch (bitsPerSample) { case 8: case 16: dpx->element[0].packing = 0; break; case 10: case 12: /* Packed Type A padding is the most common 10/12 bits format */ dpx->element[0].packing = 1; break; default: if (verbose) printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample); logImageClose(dpx); return NULL; } if (hasAlpha == 0) { dpx->depth = 3; dpx->element[0].depth = 3; dpx->element[0].descriptor = descriptor_RGB; } else { dpx->depth = 4; dpx->element[0].depth = 4; dpx->element[0].descriptor = descriptor_RGBA; } if (isLogarithmic == 0) { dpx->element[0].transfer = transfer_Linear; dpx->element[0].refHighQuantity = dpx->element[0].maxValue; } else { dpx->element[0].transfer = transfer_PrintingDensity; dpx->element[0].refHighQuantity = 2.048f; } dpx->element[0].refLowQuantity = 0; dpx->element[0].refLowData = 0; dpx->element[0].refHighData = dpx->element[0].maxValue; if (referenceWhite > 0) dpx->referenceWhite = referenceWhite; else dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; if (referenceBlack > 0) dpx->referenceBlack = referenceBlack; else dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; if (gamma > 0.0f) dpx->gamma = gamma; else dpx->gamma = 1.7f; shortFilename = strrchr(filename, '/'); if (shortFilename == NULL) shortFilename = filename; else shortFilename++; dpx->file = BLI_fopen(filename, "wb"); if (dpx->file == NULL) { if (verbose) printf("DPX: Couldn't open file %s\n", filename); logImageClose(dpx); return NULL; } fillDpxMainHeader(dpx, &header, shortFilename, creator); if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { if (verbose) printf("DPX: Couldn't write image header\n"); logImageClose(dpx); return NULL; } /* Header should be rounded to next 8k block * 6044 = 8092 - sizeof(DpxMainHeader) */ memset(&pad, 0, 6044); if (fwrite(&pad, 6044, 1, dpx->file) == 0) { if (verbose) printf("DPX: Couldn't write image header\n"); logImageClose(dpx); return NULL; } return dpx; }
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; }