diff options
Diffstat (limited to 'source/blender/imbuf')
62 files changed, 3460 insertions, 2754 deletions
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index bbe70a7d73f..29ed8c95fc6 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -25,7 +25,6 @@ set(INC . - ../avi ../blenkernel ../blenlib ../blenloader @@ -82,25 +81,6 @@ set(SRC intern/IMB_indexer.h intern/IMB_metadata.h intern/imbuf.h - intern/cineon/cin_debug_stuff.h - intern/cineon/cineonfile.h - intern/cineon/cineonlib.h - intern/cineon/dpxfile.h - intern/cineon/dpxlib.h - intern/cineon/logImageCore.h - intern/cineon/logImageLib.h - intern/cineon/logmemfile.h - intern/dds/BlockDXT.h - intern/dds/Color.h - intern/dds/ColorBlock.h - intern/dds/Common.h - intern/dds/DirectDrawSurface.h - intern/dds/Image.h - intern/dds/PixelFormat.h - intern/dds/Stream.h - intern/dds/dds_api.h - intern/openexr/openexr_api.h - intern/openexr/openexr_multi.h # orphan include ../../../intern/ffmpeg/ffmpeg_compat.h @@ -143,6 +123,13 @@ if(WITH_IMAGE_REDCODE) add_definitions(-DWITH_REDCODE) endif() +if(WITH_CODEC_AVI) + list(APPEND INC + ../avi + ) + add_definitions(-DWITH_AVI) +endif() + if(WITH_CODEC_QUICKTIME) list(APPEND INC ../quicktime diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index e2604241caf..0653956e113 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -130,7 +130,8 @@ void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, i void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, const unsigned char *buffer_byte, int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax); + int xmin, int ymin, int xmax, int ymax, + int update_orig_byte_buffer); /* ** Pixel processor functions ** */ struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings, diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 28dbe110528..d0ac71a7131 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -103,7 +103,7 @@ struct ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, * * \attention Defined in readimage.c */ -struct ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *IMB_testiffname(const char *filepath, int flags); /** * @@ -371,7 +371,7 @@ void IMB_interlace(struct ImBuf *ibuf); void IMB_rect_from_float(struct ImBuf *ibuf); /* Create char buffer for part of the image, color corrected if necessary, * Changed part will be stored in buffer. This is expected to be used for texture painting updates */ -void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h); +void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data); void IMB_float_from_rect(struct ImBuf *ibuf); void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */ /* note, check that the conversion exists, only some are supported */ diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index f03f709f13f..28e62d496b2 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -93,7 +93,7 @@ typedef struct ImBuf { /* tiled pixel storage */ int tilex, tiley; int xtiles, ytiles; - unsigned int **tiles; + unsigned int **tiles; /* zbuffer */ int *zbuf; /* z buffer data, original zbuffer */ @@ -200,6 +200,10 @@ typedef struct ImBuf { #ifdef WITH_CINEON #define CINEON (1 << 21) #define DPX (1 << 20) +#define CINEON_LOG (1 << 8) +#define CINEON_16BIT (1 << 7) +#define CINEON_12BIT (1 << 6) +#define CINEON_10BIT (1 << 5) #endif #ifdef WITH_DDS @@ -242,7 +246,7 @@ typedef struct ImBuf { ((unsigned long)(unsigned char)(ch1) << 8) | \ ((unsigned long)(unsigned char)(ch2) << 16) | \ ((unsigned long)(unsigned char)(ch3) << 24)) -#endif //MAKEFOURCC +#endif /* MAKEFOURCC */ /* * FOURCC codes for DX compressed-texture pixel formats @@ -255,7 +259,7 @@ typedef struct ImBuf { #define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4')) #define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5')) -#endif // DDS +#endif /* DDS */ extern const char *imb_ext_image[]; extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index d5cc4929aed..ed349e8f7eb 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -62,7 +62,9 @@ #include "imbuf.h" -#include "AVI_avi.h" +#ifdef WITH_AVI +# include "AVI_avi.h" +#endif #ifdef WITH_QUICKTIME # if defined(_WIN32) || defined(__APPLE__) diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 56a03121409..68ad4808c80 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -97,13 +97,13 @@ struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, cha short imb_cocoaSaveImage(struct ImBuf *ibuf, const char *name, int flags); /* cineon */ -int imb_savecineon(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +int imb_save_cineon(struct ImBuf *buf, const char *name, int flags); +struct ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_is_cineon(unsigned char *buf); /* dpx */ int imb_save_dpx(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_is_dpx(unsigned char *buf); /* hdr */ diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h index 18816924a9b..9c95531e90d 100644 --- a/source/blender/imbuf/intern/IMB_indexer.h +++ b/source/blender/imbuf/intern/IMB_indexer.h @@ -72,7 +72,7 @@ typedef struct anim_index_builder { char name[FILE_MAX]; char temp_name[FILE_MAX]; - void * private_data; + void *private_data; void (*delete_priv_data)(struct anim_index_builder * idx); void (*proc_frame)(struct anim_index_builder * idx, diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 69048274104..1b3a6d4a4cd 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -357,7 +357,7 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int ibuf->planes = planes; ibuf->ftype = TGA; ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ - ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254; /* IMB_DPI_DEFAULT -> pixels-per-meter */ + ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */ if (flags & IB_rect) { if (imb_addrectImBuf(ibuf) == FALSE) { diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 394f5169046..5b64416c309 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -78,7 +78,9 @@ #include "imbuf.h" -#include "AVI_avi.h" +#ifdef WITH_AVI +# include "AVI_avi.h" +#endif #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined(__APPLE__) @@ -185,6 +187,7 @@ static void an_stringenc(char *string, const char *head, const char *tail, unsig BLI_stringenc(string, head, tail, numlen, pic); } +#ifdef WITH_AVI static void free_anim_avi(struct anim *anim) { #if defined(_WIN32) && !defined(FREE_WINDOWS) @@ -219,6 +222,7 @@ static void free_anim_avi(struct anim *anim) anim->duration = 0; } +#endif /* WITH_AVI */ #ifdef WITH_FFMPEG static void free_anim_ffmpeg(struct anim *anim); @@ -235,7 +239,10 @@ void IMB_free_anim(struct anim *anim) } free_anim_movie(anim); + +#ifdef WITH_AVI free_anim_avi(anim); +#endif #ifdef WITH_QUICKTIME free_anim_quicktime(anim); @@ -287,7 +294,7 @@ struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char return(anim); } - +#ifdef WITH_AVI static int startavi(struct anim *anim) { @@ -397,7 +404,9 @@ static int startavi(struct anim *anim) return 0; } +#endif /* WITH_AVI */ +#ifdef WITH_AVI static ImBuf *avi_fetchibuf(struct anim *anim, int position) { ImBuf *ibuf = NULL; @@ -447,6 +456,7 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position) return ibuf; } +#endif /* WITH_AVI */ #ifdef WITH_FFMPEG @@ -1206,7 +1216,11 @@ static ImBuf *anim_getnew(struct anim *anim) if (anim == NULL) return(NULL); free_anim_movie(anim); + +#ifdef WITH_AVI free_anim_avi(anim); +#endif + #ifdef WITH_QUICKTIME free_anim_quicktime(anim); #endif @@ -1219,7 +1233,7 @@ static ImBuf *anim_getnew(struct anim *anim) if (anim->curtype != 0) return (NULL); - anim->curtype = imb_get_anim_type(anim->name); + anim->curtype = imb_get_anim_type(anim->name); switch (anim->curtype) { case ANIM_SEQUENCE: @@ -1233,6 +1247,7 @@ static ImBuf *anim_getnew(struct anim *anim) if (startmovie(anim)) return (NULL); ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); /* fake */ break; +#ifdef WITH_AVI case ANIM_AVI: if (startavi(anim)) { printf("couldnt start avi\n"); @@ -1240,6 +1255,7 @@ static ImBuf *anim_getnew(struct anim *anim) } ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); break; +#endif #ifdef WITH_QUICKTIME case ANIM_QTIME: if (startquicktime(anim)) return (0); @@ -1331,11 +1347,13 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, IMB_convert_rgba_to_abgr(ibuf); } break; +#ifdef WITH_AVI case ANIM_AVI: ibuf = avi_fetchibuf(anim, position); if (ibuf) anim->curposition = position; break; +#endif #ifdef WITH_QUICKTIME case ANIM_QTIME: ibuf = qtime_fetchibuf(anim, position); diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index df12f0b703e..32733668052 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -184,7 +184,7 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co rect += 4; bmp += 3; } /* for 24-bit images, rows are padded to multiples of 4 */ - bmp += x % 4; + bmp += x % 4; } } else if (depth == 32) { diff --git a/source/blender/imbuf/intern/cineon/CMakeLists.txt b/source/blender/imbuf/intern/cineon/CMakeLists.txt index fdf4f5409a5..b94cfd22058 100644 --- a/source/blender/imbuf/intern/cineon/CMakeLists.txt +++ b/source/blender/imbuf/intern/cineon/CMakeLists.txt @@ -39,12 +39,24 @@ set(INC_SYS ) set(SRC + cin_debug_stuff.h + cineonfile.h + cineonlib.h + dpxfile.h + dpxlib.h + logImageCore.h + logImageLib.h + logmemfile.h + cineon_dpx.c cineonlib.c dpxlib.c logImageCore.c - logImageLib.c logmemfile.c ) +if(WITH_IMAGE_CINEON) + add_definitions(-DWITH_CINEON) +endif() + blender_add_lib(bf_imbuf_cineon "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/cineon/SConscript b/source/blender/imbuf/intern/cineon/SConscript index e1afb5ebd2d..a07334632d7 100644 --- a/source/blender/imbuf/intern/cineon/SConscript +++ b/source/blender/imbuf/intern/cineon/SConscript @@ -15,4 +15,7 @@ incs = ['.', defs = [] +if env['WITH_BF_CINEON']: + defs.append('WITH_CINEON') + env.BlenderLib ('bf_imbuf_cineon', source_files, incs, defs, libtype=['core','player'], priority = [220,175]) diff --git a/source/blender/imbuf/intern/cineon/cin_debug_stuff.h b/source/blender/imbuf/intern/cineon/cin_debug_stuff.h index a97499fb1ae..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/cin_debug_stuff.h +++ b/source/blender/imbuf/intern/cineon/cin_debug_stuff.h @@ -1,4 +0,0 @@ -/** \file blender/imbuf/intern/cineon/cin_debug_stuff.h - * \ingroup imbcineon - */ -#define d_printf printf diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 7705af13b1e..d20c6dec9d3 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -4,11 +4,11 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License @@ -20,25 +20,24 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Julien Enche. * * ***** END GPL LICENSE BLOCK ***** * cineon.c - * contributors: joeedh + * contributors: joeedh, Julien Enche * I hearby donate this code and all rights to the Blender Foundation. + * $Id$ */ /** \file blender/imbuf/intern/cineon/cineon_dpx.c * \ingroup imbcineon */ - -#include <stdio.h> -#include <string.h> /*for memcpy*/ -#include "logImageLib.h" -#include "cineonlib.h" -#include "dpxlib.h" +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "logImageCore.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -51,167 +50,142 @@ #include "MEM_guardedalloc.h" -#if 0 -static void cineon_conversion_parameters(LogImageByteConversionParameters *params) -{ -// params->blackPoint = scene?scene->r.cineonblack:95; -// params->whitePoint = scene?scene->r.cineonwhite:685; -// params->gamma = scene?scene->r.cineongamma:1.7f; -// params->doLogarithm = scene?scene->r.subimtype & R_CINEON_LOG:0; - - params->blackPoint = 95; - params->whitePoint = 685; - params->gamma = 1.0f; - params->doLogarithm = 0; -} -#endif - -static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags, char colorspace[IM_MAX_SPACE]) +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 x, y; - unsigned short *row, *upix; int width, height, depth; - float *frow; colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); - logImageSetVerbose((G.debug & G_DEBUG) ? 1:0); - - image = logImageOpenFromMem(mem, size, use_cineon); - - if (!image) { - printf("no image!\n"); - return NULL; + 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 (depth != 3) { /*need to do grayscale loading eventually.*/ + + if (width == 0 || height == 0) { logImageClose(image); - return NULL; + return 0; } - - if (width == 0 && height == 0) { + + ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); + if (ibuf == 0) { logImageClose(image); - return NULL; + return 0; } - - 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; + if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { + /* Conversion not possible (probably because the format is unsupported) */ + logImageClose(image); + MEM_freeN(ibuf); + return 0; } - MEM_freeN(row); logImageClose(image); - - if (flags & IB_rect) { + ibuf->ftype = use_cineon ? CINEON : DPX; + IMB_flipy(ibuf); + + if (flags & IB_rect) IMB_rect_from_float(ibuf); - } + 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; + LogImageFile *logImage; float *fbuf; - int is_alloc= 0; + 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; + } - (void)flags; /* unused */ + logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); - // cineon_conversion_parameters(&conversion); - logImageGetByteConversionDefaults(&conversion); + depth = (ibuf->planes + 7) >> 3; + if (depth > 4 || depth < 3) { + printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename); + return 0; + } - /* - * Get the drawable for the current image... - */ + 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; - fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc); + logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4), + (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender"); - if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */ + if (logImage == 0) { + printf("DPX/Cineon: error creating file.\n"); return 0; } - - logImageSetVerbose((G.debug & 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"); + if (ibuf->rect_float != 0 && 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) */ + IMB_flipy(ibuf); + rvalue = (logImageSetDataRGBA(logImage, ibuf->rect_float, 1) == 0); + IMB_flipy(ibuf); } - - 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); + else { + if (ibuf->rect == 0) + IMB_rect_from_float(ibuf); + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); + if (fbuf == 0) { + printf("DPX/Cineon: error allocating memory.\n"); + logImageClose(logImage); + return 0; } - logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j); - } - logImageClose(logImage); - - MEM_freeN(line); - - if (is_alloc) { + 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); } - - return 1; + + logImageClose(logImage); + return rvalue; } -int imb_savecineon(struct ImBuf *buf, const char *myfile, int flags) +int imb_save_cineon(struct ImBuf *buf, const char *myfile, int flags) { return imb_save_dpx_cineon(buf, myfile, 1, flags); } - int imb_is_cineon(unsigned char *buf) { - return cineonIsMemFileCineon(buf); + return logImageIsCineon(buf); } -ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { if (imb_is_cineon(mem)) - return imb_load_dpx_cineon(mem, 1, size, flags, colorspace); - return NULL; + return imb_load_dpx_cineon(mem, size, 1, flags, colorspace); + return 0; } int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags) @@ -221,12 +195,12 @@ int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags) int imb_is_dpx(unsigned char *buf) { - return dpxIsMemFileCineon(buf); + return logImageIsDpx(buf); } -ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { if (imb_is_dpx(mem)) - return imb_load_dpx_cineon(mem, 0, size, flags, colorspace); - return NULL; + return imb_load_dpx_cineon(mem, size, 0, flags, colorspace); + return 0; } diff --git a/source/blender/imbuf/intern/cineon/cineonfile.h b/source/blender/imbuf/intern/cineon/cineonfile.h index e681153aa6e..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/cineonfile.h +++ b/source/blender/imbuf/intern/cineon/cineonfile.h @@ -1,134 +0,0 @@ -/* - * Cineon image file format library definitions. - * Cineon file format structures. - * - * This header file contains private details. - * User code should generally use cineonlib.h only. - * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef __CINEONFILE_H__ -#define __CINEONFILE_H__ - -/** \file blender/imbuf/intern/cineon/cineonfile.h - * \ingroup imbcineon - */ - -#include "logImageCore.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - U32 magic_num; /* magic number */ - U32 image_offset; /* offset to image data in bytes */ - U32 gen_hdr_size; /* generic header length in bytes */ - U32 ind_hdr_size; /* industry header length in bytes */ - U32 user_data_size; /* user-defined data length in bytes */ - U32 file_size; /* file size in bytes */ - ASCII vers[8]; /* which header format version is being used (v4.5) */ - ASCII file_name[100]; /* image file name */ - ASCII create_date[12]; /* file creation date */ - ASCII create_time[12]; /* file creation time */ - ASCII Reserved[36]; /* reserved field TBD (need to pad) */ -} CineonFileInformation; - -typedef struct { - U8 designator1; - U8 designator2; - U8 bits_per_pixel; - U8 filler; - U32 pixels_per_line; - U32 lines_per_image; - U32 ref_low_data; /* reference low data code value */ - R32 ref_low_quantity; /* reference low quantity represented */ - U32 ref_high_data; /* reference high data code value */ - R32 ref_high_quantity;/* reference high quantity represented */ -} CineonChannelInformation; - -typedef struct { - U8 orientation; /* image orientation */ - U8 channels_per_image; - U16 filler; - CineonChannelInformation channel[8]; - R32 white_point_x; - R32 white_point_y; - R32 red_primary_x; - R32 red_primary_y; - R32 green_primary_x; - R32 green_primary_y; - R32 blue_primary_x; - R32 blue_primary_y; - ASCII label[200]; - ASCII reserved[28]; -} CineonImageInformation; - -typedef struct { - U8 interleave; - U8 packing; - U8 signage; - U8 sense; - U32 line_padding; - U32 channel_padding; - ASCII reserved[20]; -} CineonFormatInformation; - -typedef struct { - S32 x_offset; - S32 y_offset; - ASCII file_name[100]; - ASCII create_date[12]; /* file creation date */ - ASCII create_time[12]; /* file creation time */ - ASCII input_device[64]; - ASCII model_number[32]; - ASCII serial_number[32]; - R32 x_input_samples_per_mm; - R32 y_input_samples_per_mm; - R32 input_device_gamma; - ASCII reserved[40]; -} CineonOriginationInformation; - -typedef struct { - CineonFileInformation fileInfo; - CineonImageInformation imageInfo; - CineonFormatInformation formatInfo; - CineonOriginationInformation originInfo; -} CineonGenericHeader; - -typedef struct { - U8 filmCode; - U8 filmType; - U8 perfOffset; - U8 filler; - U32 keycodePrefix; - U32 keycodeCount; - ASCII format[32]; - U32 framePosition; /* in sequence */ - R32 frameRate; /* frames per second */ - ASCII attribute[32]; - ASCII slate[200]; - ASCII reserved[740]; -} CineonMPISpecificInformation; - -#ifdef __cplusplus -} -#endif - -#endif /* __CINEONFILE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index a9001303679..9926d8c8562 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -1,21 +1,23 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> + * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ @@ -23,800 +25,355 @@ * \ingroup imbcineon */ + #include "cineonlib.h" -#include "cineonfile.h" +#include "logmemfile.h" #include <stdio.h> #include <math.h> #include <stdlib.h> -#include <time.h> /* strftime() */ +#include <time.h> #include <sys/types.h> -#ifdef WIN32 -#include <winsock.h> -#else -#include <netinet/in.h> /* htonl() */ -#endif -#include <string.h> /* memset */ +#include <string.h> -#include "BLI_utildefines.h" #include "BLI_fileops.h" +#include "BLI_math_base.h" +#include "BLI_utildefines.h" -#include "cin_debug_stuff.h" -#include "logmemfile.h" - -static void -fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) { - - time_t fileClock; - struct tm* fileTime; - - fileInfo->magic_num = htonl(CINEON_FILE_MAGIC); - fileInfo->image_offset = htonl(cineon->imageOffset); - fileInfo->gen_hdr_size = htonl( - sizeof(CineonFileInformation) + - sizeof(CineonImageInformation) + - sizeof(CineonFormatInformation) + - sizeof(CineonOriginationInformation)); - fileInfo->ind_hdr_size = 0; - fileInfo->user_data_size = 0; - fileInfo->file_size = htonl(cineon->imageOffset + cineon->height * cineon->lineBufferLength); - strcpy(fileInfo->vers, "V4.5"); - strncpy(fileInfo->file_name, filename, 99); - fileInfo->file_name[99] = 0; - - fileClock = time(0); - fileTime = localtime(&fileClock); - strftime(fileInfo->create_date, 12, "%Y:%m:%d", fileTime); - /* Question: is %Z in strftime guaranteed to return 3 chars? */ - strftime(fileInfo->create_time, 12, "%H:%M:%S%Z", fileTime); - fileInfo->create_time[11] = 0; -} - -static void -dumpCineonFileInfo(CineonFileInformation* fileInfo) { - d_printf("\n--File Information--\n"); - d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num)); - d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset)); - d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size)); - d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size)); - d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size)); - d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size)); - d_printf("Version \"%s\"\n", fileInfo->vers); - d_printf("File name \"%s\"\n", fileInfo->file_name); - d_printf("Creation date \"%s\"\n", fileInfo->create_date); - d_printf("Creation time \"%s\"\n", fileInfo->create_time); -} - -static void -fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) { - - chan->designator1 = 0; - chan->designator2 = des; - chan->bits_per_pixel = 10; - chan->pixels_per_line = htonl(cineon->width); - chan->lines_per_image = htonl(cineon->height); - chan->ref_low_data = htonl(0); - chan->ref_low_quantity = htonf(0.0); - chan->ref_high_data = htonl(1023); - chan->ref_high_quantity = htonf(2.046); -} - -static void -dumpCineonChannelInfo(CineonChannelInformation* chan) { - d_printf(" Metric selector: %d", chan->designator1); - switch (chan->designator1) { - case 0: d_printf(" (Universal)\n"); break; - default: d_printf(" (Vendor specific)\n"); break; - } - d_printf(" Metric: %d,", chan->designator2); - switch (chan->designator2) { - case 0: d_printf(" B&W (printing density?)\n"); break; - case 1: d_printf(" Red printing density\n"); break; - case 2: d_printf(" Green printing density\n"); break; - case 3: d_printf(" Blue printing density\n"); break; - case 4: d_printf(" Red CCIR XA/11\n"); break; - case 5: d_printf(" Green CCIR XA/11\n"); break; - case 6: d_printf(" Blue CCIR XA/11\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf(" Bits per pixel %d\n", chan->bits_per_pixel); - d_printf(" Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line)); - d_printf(" Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image)); - d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data)); - d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity)); - d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data)); - d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity)); -} - -static void -fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) { - - imageInfo->orientation = 0; - imageInfo->channels_per_image = cineon->depth; - - if (cineon->depth == 1) { - fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0); - - } - else if (cineon->depth == 3) { - fillCineonChannelInfo(cineon, &imageInfo->channel[0], 1); - fillCineonChannelInfo(cineon, &imageInfo->channel[1], 2); - fillCineonChannelInfo(cineon, &imageInfo->channel[2], 3); - } - - imageInfo->white_point_x = htonf(undefined()); - imageInfo->white_point_y = htonf(undefined()); - imageInfo->red_primary_x = htonf(undefined()); - imageInfo->red_primary_y = htonf(undefined()); - imageInfo->green_primary_x = htonf(undefined()); - imageInfo->green_primary_y = htonf(undefined()); - imageInfo->blue_primary_x = htonf(undefined()); - imageInfo->blue_primary_y = htonf(undefined()); - - strcpy(imageInfo->label, "David's Cineon writer."); - -} - -static void -dumpCineonImageInfo(CineonImageInformation* imageInfo) { - - int i; - d_printf("\n--Image Information--\n"); - d_printf("Image orientation %d,", imageInfo->orientation); - switch (imageInfo->orientation) { - case 0: d_printf(" LRTB\n"); break; - case 1: d_printf(" LRBT\n"); break; - case 2: d_printf(" RLTB\n"); break; - case 3: d_printf(" RLBT\n"); break; - case 4: d_printf(" TBLR\n"); break; - case 5: d_printf(" TBRL\n"); break; - case 6: d_printf(" BTLR\n"); break; - case 7: d_printf(" BTRL\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf("Channels %d\n", imageInfo->channels_per_image); - for (i = 0; i < imageInfo->channels_per_image; ++i) { - d_printf(" --Channel %d--\n", i); - dumpCineonChannelInfo(&imageInfo->channel[i]); - } - - d_printf("White point x %f\n", ntohf(imageInfo->white_point_x)); - d_printf("White point y %f\n", ntohf(imageInfo->white_point_y)); - d_printf("Red primary x %f\n", ntohf(imageInfo->red_primary_x)); - d_printf("Red primary y %f\n", ntohf(imageInfo->red_primary_y)); - d_printf("Green primary x %f\n", ntohf(imageInfo->green_primary_x)); - d_printf("Green primary y %f\n", ntohf(imageInfo->green_primary_y)); - d_printf("Blue primary x %f\n", ntohf(imageInfo->blue_primary_x)); - d_printf("Blue primary y %f\n", ntohf(imageInfo->blue_primary_y)); - d_printf("Label \"%s\"\n", imageInfo->label); -} - -static void -fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) { - - (void)cineon; /* unused */ - - formatInfo->interleave = 0; - formatInfo->packing = 5; - formatInfo->signage = 0; - formatInfo->sense = 0; - formatInfo->line_padding = htonl(0); - formatInfo->channel_padding = htonl(0); -} - -static void -dumpCineonFormatInfo(CineonFormatInformation* formatInfo) { - d_printf("\n--Format Information--\n"); - d_printf("Interleave %d,", formatInfo->interleave); - switch (formatInfo->interleave) { - case 0: d_printf(" pixel interleave\n"); break; - case 1: d_printf(" line interleave\n"); break; - case 2: d_printf(" channel interleave\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf("Packing %d,", formatInfo->packing); - if (formatInfo->packing & 0x80) { - d_printf(" multi pixel,"); - } - else { - d_printf(" single pixel,"); - } - switch (formatInfo->packing & 0x7F) { - case 0: d_printf(" tight\n"); break; - case 1: d_printf(" byte packed left\n"); break; - case 2: d_printf(" byte packed right\n"); break; - case 3: d_printf(" word packed left\n"); break; - case 4: d_printf(" word packed right\n"); break; - case 5: d_printf(" long packed left\n"); break; - case 6: d_printf(" long packed right\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf("Sign %d,", formatInfo->signage); - if (formatInfo->signage) { - d_printf(" signed\n"); - } - else { - d_printf(" unsigned\n"); - } - d_printf("Sense %d,", formatInfo->signage); - if (formatInfo->signage) { - d_printf(" negative\n"); - } - else { - d_printf(" positive\n"); - } - d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding)); - d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding)); -} - -static void -fillCineonOriginationInfo(CineonFile* cineon, - CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) { - - (void)cineon; /* unused */ - - originInfo->x_offset = htonl(0); - originInfo->y_offset = htonl(0); - strcpy(originInfo->file_name, fileInfo->file_name); - strcpy(originInfo->create_date, fileInfo->create_date); - strcpy(originInfo->create_time, fileInfo->create_time); - strncpy(originInfo->input_device, "David's Cineon writer", 64); - strncpy(originInfo->model_number, "Software", 32); - strncpy(originInfo->serial_number, "001", 32); - originInfo->x_input_samples_per_mm = htonf(undefined()); - originInfo->y_input_samples_per_mm = htonf(undefined()); - /* this should probably be undefined, too */ - originInfo->input_device_gamma = htonf(1.0); -} - -static void -dumpCineonOriginationInfo(CineonOriginationInformation* originInfo) { - d_printf("\n--Origination Information--\n"); - d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset)); - d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset)); - d_printf("File name \"%s\"\n", originInfo->file_name); - d_printf("Creation date \"%s\"\n", originInfo->create_date); - d_printf("Creation time \"%s\"\n", originInfo->create_time); - d_printf("Input device \"%s\"\n", originInfo->input_device); - d_printf("Model number \"%s\"\n", originInfo->model_number); - d_printf("Serial number \"%s\"\n", originInfo->serial_number); - d_printf("Samples per mm in x %f\n", ntohf(originInfo->x_input_samples_per_mm)); - d_printf("Samples per mm in y %f\n", ntohf(originInfo->y_input_samples_per_mm)); - d_printf("Input device gamma %f\n", ntohf(originInfo->input_device_gamma)); -} - -static int -initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) { - - fillCineonFileInfo(cineon, &header->fileInfo, imagename); - fillCineonImageInfo(cineon, &header->imageInfo); - fillCineonFormatInfo(cineon, &header->formatInfo); - fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo); +#include "logImageLib.h" - return 0; -} +#include "MEM_guardedalloc.h" -static void -UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) { - dumpCineonFileInfo(&header->fileInfo); - dumpCineonImageInfo(&header->imageInfo); - dumpCineonFormatInfo(&header->formatInfo); - dumpCineonOriginationInfo(&header->originInfo); -} +/* + * For debug purpose + */ static int verbose = 0; -void -cineonSetVerbose(int verbosity) { - verbose = verbosity; -} - -static void -verboseMe(CineonFile* cineon) { - - d_printf("size %d x %d x %d\n", cineon->width, cineon->height, cineon->depth); - d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n", - cineon->imageOffset, cineon->lineBufferLength * 4, - cineon->imageOffset + cineon->lineBufferLength * 4 * cineon->height); -} - -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; +void cineonSetVerbose(int verbosity) { + verbose = verbosity; } -int -cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) { - - int pixelIndex; - int numPixels = cineon->width * cineon->depth; - int longIndex; - int longsWritten; - - /* put new pixels into pixelBuffer */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (cineon->params.doLogarithm) - cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]]; - else - cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6; - } - - /* pack into longwords */ - pixelIndex = 0; - for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { - unsigned int t = - (cineon->pixelBuffer[pixelIndex] << 22) | - (cineon->pixelBuffer[pixelIndex+1] << 12) | - (cineon->pixelBuffer[pixelIndex+2] << 2); - cineon->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - - /* 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 setRowBytes\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; - } - - longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file); - if (longsWritten != cineon->lineBufferLength) { - if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4); - return 1; - } - - ++cineon->fileYPos; +static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, + const char *filename, const char *creator) +{ + time_t fileClock; + struct tm *fileTime; + int i; - return 0; + memset(header, 0, sizeof(CineonMainHeader)); + + /* --- File header --- */ + header->fileHeader.magic_num = swap_uint(CINEON_FILE_MAGIC, cineon->isMSB); + header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB); + header->fileHeader.gen_hdr_size = swap_uint(sizeof(CineonFileHeader) + sizeof(CineonImageHeader) + + sizeof(CineonOriginationHeader), cineon->isMSB); + header->fileHeader.ind_hdr_size = 0; + header->fileHeader.user_data_size = 0; + header->fileHeader.file_size = swap_uint(cineon->element[0].dataOffset + cineon->height * getRowLength(cineon->width, cineon->element[0]), cineon->isMSB); + strcpy(header->fileHeader.version, "v4.5"); + strncpy(header->fileHeader.file_name, filename, 99); + header->fileHeader.file_name[99] = 0; + fileClock = time(0); + fileTime = localtime(&fileClock); + strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime); + strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime); + header->fileHeader.creation_time[11] = 0; + + /* --- Image header --- */ + header->imageHeader.orientation = 0; + header->imageHeader.elements_per_image = cineon->depth; + + for (i = 0; i < 3; i++) { + header->imageHeader.element[i].descriptor1 = 0; + header->imageHeader.element[i].descriptor2 = i; + header->imageHeader.element[i].bits_per_sample = cineon->element[0].bitsPerSample; + header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB); + header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB); + header->imageHeader.element[i].ref_low_data = swap_uint(cineon->element[0].refLowData, cineon->isMSB); + header->imageHeader.element[i].ref_low_quantity = swap_float(cineon->element[0].refLowQuantity, cineon->isMSB); + header->imageHeader.element[i].ref_high_data = swap_uint(cineon->element[0].refHighData, cineon->isMSB); + header->imageHeader.element[i].ref_high_quantity = swap_float(cineon->element[0].refHighQuantity, cineon->isMSB); + } + + header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB); + header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB); + header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB); + header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB); + strncpy(header->imageHeader.label, creator, 199); + header->imageHeader.label[199] = 0; + header->imageHeader.interleave = 0; + header->imageHeader.data_sign = 0; + header->imageHeader.sense = 0; + header->imageHeader.line_padding = swap_uint(0, cineon->isMSB); + header->imageHeader.element_padding = swap_uint(0, cineon->isMSB); + + switch (cineon->element[0].packing) { + case 0: + header->imageHeader.packing = 0; + break; + + case 1: + header->imageHeader.packing = 5; + break; + + case 2: + header->imageHeader.packing = 6; + break; + } + + /* --- Origination header --- */ + /* we leave it blank */ + + /* --- Film header --- */ + /* we leave it blank */ } -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; - } +LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) +{ + CineonMainHeader header; + LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + char *filename = (char *)byteStuff; + int i; + unsigned int dataOffset; - /* 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; + if (cineon == 0) { + if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n"); + return 0; } - return 0; -} + /* zero the header */ + memset(&header, 0, sizeof(CineonMainHeader)); -int -cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) { - - int pixelIndex; -/* int numPixels = cineon->width * cineon->depth; -*/ int longIndex; - int longsWritten; - - /* pack into longwords */ - pixelIndex = 0; - for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { - unsigned int t = - (row[pixelIndex] << 22) | - (row[pixelIndex+1] << 12) | - (row[pixelIndex+2] << 2); - cineon->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } + /* for close routine */ + cineon->file = 0; - /* 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 setRowBytes\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; + if (fromMemory == 0) { + /* byteStuff is then the filename */ + cineon->file = BLI_fopen(filename, "rb"); + if (cineon->file == 0) { + if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename); + logImageClose(cineon); + return 0; } - cineon->fileYPos = y; + /* not used in this case */ + cineon->memBuffer = 0; + cineon->memCursor = 0; + cineon->memBufferSize = 0; } - - longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file); - if (longsWritten != cineon->lineBufferLength) { - if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4); - return 1; + else { + cineon->memBuffer = (unsigned char *)byteStuff; + cineon->memCursor = (unsigned char *)byteStuff; + cineon->memBufferSize = bufferSize; } - ++cineon->fileYPos; - - return 0; -} - -CineonFile* -cineonOpen(const char* filename) { - - CineonGenericHeader header; - - CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile)); - if (cineon == 0) { - if (verbose) d_printf("Failed to malloc cineon file structure.\n"); + 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 0; } - /* for close routine */ - cineon->file = 0; - cineon->lineBuffer = 0; - cineon->pixelBuffer = 0; - cineon->membuffer = 0; - cineon->memcursor = 0; - cineon->membuffersize = 0; - - cineon->file = BLI_fopen(filename, "rb"); - if (cineon->file == 0) { - if (verbose) d_printf("Failed to open file \"%s\".\n", filename); - cineonClose(cineon); - return 0; + /* endianness determination */ + if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) { + cineon->isMSB = 1; + if (verbose) printf("Cineon: File is MSB.\n"); } - cineon->reading = 1; - - if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) { - if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename); - cineonClose(cineon); - return 0; + else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) { + cineon->isMSB = 0; + if (verbose) printf("Cineon: File is LSB.\n"); } - - /* 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 \"%s\".\n", - (uintptr_t)ntohl(header.fileInfo.magic_num), filename); - cineonClose(cineon); + else { + if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n", + (uintptr_t)header.fileHeader.magic_num, byteStuff); + logImageClose(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 = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB); + cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB); + cineon->depth = header.imageHeader.elements_per_image; + cineon->srcFormat = format_Cineon; - 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); + 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); 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; + if (cineon->depth == 1) { + /* Grayscale image */ + cineon->element[0].descriptor = descriptor_Luminance; + cineon->element[0].transfer = transfer_Linear; + cineon->element[0].depth = 1; } - cineon->pixelBufferUsed = 0; - - 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; + 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; + } } - cineon->fileYPos = 0; - - logImageGetByteConversionDefaults(&cineon->params); - setupLut(cineon); - - cineon->getRow = &cineonGetRowBytes; - cineon->setRow = 0; - cineon->close = &cineonClose; - - if (verbose) { - verboseMe(cineon); + else { + if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth); + return 0; } - return cineon; -} + dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB); -int cineonIsMemFileCineon(unsigned char *mem) -{ - unsigned int num; - memcpy(&num, mem, sizeof(unsigned int)); - - if (num != ntohl(CINEON_FILE_MAGIC)) { - return 0; - } - else return 1; -} + 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); -CineonFile* -cineonOpenFromMem(unsigned char *mem, unsigned int size) { + switch (header.imageHeader.packing) { + case 0: + cineon->element[i].packing = 0; + break; - CineonGenericHeader header; - - CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile)); - if (cineon == 0) { - if (verbose) d_printf("Failed to malloc cineon file structure.\n"); - return 0; - } + case 5: + cineon->element[i].packing = 1; + break; - /* 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; - } + case 6: + cineon->element[i].packing = 2; + break; - logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon); + default: + /* Not supported */ + if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing); + return 0; + } - /* 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)); + if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData)) + cineon->element[i].refLowData = 0; - cineonClose(cineon); - return 0; - } + if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refHighData)) + cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue; - if (header.formatInfo.packing != 5) { - if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing); - cineonClose(cineon); - return 0; - } + if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity)) + cineon->element[i].refLowQuantity = 0.0f; - 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; - } + 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->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; - - 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->element[i].dataOffset = dataOffset; + dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]); } - - cineon->fileYPos = 0; - - logImageGetByteConversionDefaults(&cineon->params); - setupLut(cineon); - cineon->getRow = &cineonGetRowBytes; - cineon->setRow = 0; - cineon->close = &cineonClose; + 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) { - verboseMe(cineon); - } + 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 *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator) +{ + CineonMainHeader header; + const char *shortFilename = 0; + /* unsigned char pad[6044]; */ -int -cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) { - *width = cineon->width; - *height = cineon->height; - *depth = cineon->depth; - return 0; -} - -CineonFile* -cineonCreate(const char* filename, int width, int height, int depth) { - - /* Note: always write files in network order */ - /* By the spec, it shouldn't matter, but ... */ - - CineonGenericHeader header; - const char* shortFilename = 0; - - CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile)); + LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); if (cineon == 0) { - if (verbose) d_printf("Failed to malloc cineon file structure.\n"); + if (verbose) printf("cineon: Failed to malloc cineon file structure.\n"); return 0; } - memset(&header, 0, sizeof(header)); - - /* for close routine */ - cineon->file = 0; - cineon->lineBuffer = 0; - cineon->pixelBuffer = 0; - - cineon->file = BLI_fopen(filename, "wb"); - if (cineon->file == 0) { - if (verbose) d_printf("Couldn't open file %s\n", filename); - cineonClose(cineon); + /* Only 10 bits Cineon are supported */ + if (bitsPerSample != 10) { + if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n"); + logImageClose(cineon); return 0; } - cineon->reading = 0; cineon->width = width; cineon->height = height; - cineon->depth = depth; - cineon->bitsPerPixel = 10; - cineon->imageOffset = sizeof(CineonGenericHeader); - - 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->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; - 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; - - /* find trailing part of filename */ shortFilename = strrchr(filename, '/'); - if (shortFilename == 0) { + if (shortFilename == 0) shortFilename = filename; - } - else { - ++shortFilename; - } + else + shortFilename++; - if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) { - cineonClose(cineon); + cineon->file = BLI_fopen(filename, "wb"); + if (cineon->file == 0) { + if (verbose) printf("cineon: Couldn't open file %s\n", filename); + logImageClose(cineon); return 0; } + fillCineonMainHeader(cineon, &header, shortFilename, creator); + if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) { - if (verbose) d_printf("Couldn't write image header\n"); - cineonClose(cineon); + if (verbose) printf("cineon: Couldn't write image header\n"); + logImageClose(cineon); return 0; } - cineon->fileYPos = 0; - - logImageGetByteConversionDefaults(&cineon->params); - setupLut(cineon); - - cineon->getRow = 0; - cineon->setRow = &cineonSetRowBytes; - cineon->close = &cineonClose; return cineon; } - -void -cineonClose(CineonFile* cineon) { - - if (cineon == 0) { - return; - } - - if (cineon->file) { - fclose(cineon->file); - cineon->file = 0; - } - - if (cineon->lineBuffer) { - free(cineon->lineBuffer); - cineon->lineBuffer = 0; - } - - if (cineon->pixelBuffer) { - free(cineon->pixelBuffer); - cineon->pixelBuffer = 0; - } - - free(cineon); -} diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h index ef992c527b0..9333743a1bf 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.h +++ b/source/blender/imbuf/intern/cineon/cineonlib.h @@ -1,68 +1,142 @@ /* - * Cineon image file format library definitions. - * Also handles DPX files (almost) + * Cineon image file format library definitions. + * Also handles DPX files (almost) * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> + * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ -#ifndef __CINEONLIB_H__ -#define __CINEONLIB_H__ - /** \file blender/imbuf/intern/cineon/cineonlib.h * \ingroup imbcineon */ -#include "logImageCore.h" + +#ifndef __CINEON_LIB_H__ +#define __CINEON_LIB_H__ #ifdef __cplusplus extern "C" { #endif -/* - * Cineon image structure. You don't care what this is. - */ +#include "logImageCore.h" -typedef struct _Log_Image_File_t_ CineonFile; +#define CINEON_FILE_MAGIC 0x802A5FD7 +#define CINEON_UNDEFINED_U8 0xFF +#define CINEON_UNDEFINED_U16 0xFFFF +#define CINEON_UNDEFINED_U32 0xFFFFFFFF +#define CINEON_UNDEFINED_R32 0x7F800000 +#define CINEON_UNDEFINED_CHAR 0 -/* int functions return 0 for OK */ +typedef struct { + unsigned int magic_num; + unsigned int offset; + unsigned int gen_hdr_size; + unsigned int ind_hdr_size; + unsigned int user_data_size; + unsigned int file_size; + char version[8]; + char file_name[100]; + char creation_date[12]; + char creation_time[12]; + char reserved[36]; +} CineonFileHeader; -void cineonSetVerbose(int); +typedef struct { + unsigned char descriptor1; + unsigned char descriptor2; + unsigned char bits_per_sample; + unsigned char filler; + unsigned int pixels_per_line; + unsigned int lines_per_image; + unsigned int ref_low_data; + float ref_low_quantity; + unsigned int ref_high_data; + float ref_high_quantity; +} CineonElementHeader; -CineonFile* cineonOpenFromMem(unsigned char *mem, unsigned int size); +typedef struct { + unsigned char orientation; + unsigned char elements_per_image; + unsigned short filler; + CineonElementHeader element[8]; + float white_point_x; + float white_point_y; + float red_primary_x; + float red_primary_y; + float green_primary_x; + float green_primary_y; + float blue_primary_x; + float blue_primary_y; + char label[200]; + char reserved[28]; + unsigned char interleave; + unsigned char packing; + unsigned char data_sign; + unsigned char sense; + unsigned int line_padding; + unsigned int element_padding; + char reserved2[20]; +} CineonImageHeader; -CineonFile* cineonOpen(const char* filename); -int cineonGetSize(const CineonFile* cineon, int* xsize, int* ysize, int* channels); -CineonFile* cineonCreate(const char* filename, int xsize, int ysize, int channels); -int cineonIsMemFileCineon(unsigned char *mem); +typedef struct { + int x_offset; + int y_offset; + char file_name[100]; + char creation_date[12]; + char creation_time[12]; + char input_device[64]; + char model_number[32]; + char input_serial_number[32]; + float x_input_samples_per_mm; + float y_input_samples_per_mm; + float input_device_gamma; + char reserved[40]; +} CineonOriginationHeader; -/* get/set scanline of converted bytes */ -int cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y); -int cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y); +typedef struct { + unsigned char film_code; + unsigned char film_type; + unsigned char edge_code_perforation_offset; + unsigned char filler; + unsigned int prefix; + unsigned int count; + char format[32]; + unsigned int frame_position; + float frame_rate; + char attribute[32]; + char slate[200]; + char reserved[740]; +} CineonFilmHeader; -/* get/set scanline of unconverted shorts */ -int cineonGetRow(CineonFile* cineon, unsigned short* row, int y); -int cineonSetRow(CineonFile* cineon, const unsigned short* row, int y); +typedef struct { + CineonFileHeader fileHeader; + CineonImageHeader imageHeader; + CineonOriginationHeader originationHeader; + CineonFilmHeader filmHeader; +} CineonMainHeader; -/* closes file and deletes data */ -void cineonClose(CineonFile* cineon); +void cineonSetVerbose(int); +LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize); +LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator); #ifdef __cplusplus } #endif -#endif /* __CINEONLIB_H__ */ +#endif /* __CINEON_LIB_H__ */ diff --git a/source/blender/imbuf/intern/cineon/dpxfile.h b/source/blender/imbuf/intern/cineon/dpxfile.h index e1d95268a80..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/dpxfile.h +++ b/source/blender/imbuf/intern/cineon/dpxfile.h @@ -1,128 +0,0 @@ -/* - * Cineon image file format library definitions. - * Dpx file format structures. - * - * This header file contains private details. - * User code should generally use cineonlib.h only. - * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef __DPXFILE_H__ -#define __DPXFILE_H__ - -/** \file blender/imbuf/intern/cineon/dpxfile.h - * \ingroup imbcineon - */ - -#include "logImageCore.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - U32 magic_num; /* magic number */ - U32 offset; /* offset to image data in bytes */ - ASCII vers[8]; /* which header format version is being used (v1.0) */ - U32 file_size; /* file size in bytes */ - U32 ditto_key; /* I bet some people use this */ - U32 gen_hdr_size; /* generic header length in bytes */ - U32 ind_hdr_size; /* industry header length in bytes */ - U32 user_data_size; /* user-defined data length in bytes */ - ASCII file_name[100]; /* image file name */ - ASCII create_date[24]; /* file creation date, yyyy:mm:dd:hh:mm:ss:LTZ */ - ASCII creator[100]; - ASCII project[200]; - ASCII copyright[200]; - U32 key; /* encryption key, FFFFFFF = unencrypted */ - ASCII Reserved[104]; /* reserved field TBD (need to pad) */ -} DpxFileInformation; - -typedef struct { - U32 signage; - U32 ref_low_data; /* reference low data code value */ - R32 ref_low_quantity; /* reference low quantity represented */ - U32 ref_high_data; /* reference high data code value */ - R32 ref_high_quantity;/* reference high quantity represented */ - U8 designator1; - U8 transfer_characteristics; - U8 colorimetry; - U8 bits_per_pixel; - U16 packing; - U16 encoding; - U32 data_offset; - U32 line_padding; - U32 channel_padding; - ASCII description[32]; -} DpxChannelInformation; - -typedef struct { - U16 orientation; - U16 channels_per_image; - U32 pixels_per_line; - U32 lines_per_image; - DpxChannelInformation channel[8]; - ASCII reserved[52]; -} DpxImageInformation; - -typedef struct { - U32 x_offset; - U32 y_offset; - R32 x_centre; - R32 y_centre; - U32 x_original_size; - U32 y_original_size; - ASCII file_name[100]; - ASCII creation_time[24]; - ASCII input_device[32]; - ASCII input_serial_number[32]; - U16 border_validity[4]; - U32 pixel_aspect_ratio[2]; /* h:v */ - ASCII reserved[28]; -} DpxOriginationInformation; - -typedef struct { - ASCII film_manufacturer_id[2]; - ASCII film_type[2]; - ASCII edge_code_perforation_offset[2]; - ASCII edge_code_prefix[6]; - ASCII edge_code_count[4]; - ASCII film_format[32]; - U32 frame_position; - U32 sequence_length; - U32 held_count; - R32 frame_rate; - R32 shutter_angle; - ASCII frame_identification[32]; - ASCII slate_info[100]; - ASCII reserved[56]; -} DpxMPIInformation; - -typedef struct { - DpxFileInformation fileInfo; - DpxImageInformation imageInfo; - DpxOriginationInformation originInfo; - DpxMPIInformation filmHeader; -} DpxMainHeader; - -#ifdef __cplusplus -} -#endif - -#endif /* __DPXFILE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index c1138225e93..aedce52a7bf 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -1,21 +1,23 @@ /* - * Dpx image file format library routines. + * Dpx image file format library routines. * - * Copyright 1999 - 2002 David Hodson <hodsond@acm.org> + * Copyright 1999 - 2002 David Hodson <hodsond@acm.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ @@ -23,689 +25,445 @@ * \ingroup imbcineon */ -#include "dpxfile.h" + #include "dpxlib.h" +#include "logmemfile.h" #include <stdio.h> #include <math.h> #include <stdlib.h> -#include <time.h> /* strftime() */ +#include <time.h> #include <sys/types.h> -#ifdef WIN32 -#include <winsock.h> -#else -#include <netinet/in.h> /* htonl() */ -#endif -#include <string.h> /* memset */ -#include "cin_debug_stuff.h" -#include "logmemfile.h" -#include "BLI_fileops.h" - -static void -fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) { - - (void)dpx; /* unused */ - - chan->signage = 0; - chan->ref_low_data = htonl(0); - chan->ref_low_quantity = htonf(0.0); - chan->ref_high_data = htonl(1023); - chan->ref_high_quantity = htonf(2.046); - chan->designator1 = des; - chan->transfer_characteristics = 0; - chan->colorimetry = 0; - chan->bits_per_pixel = 10; - chan->packing = htons(1); - chan->encoding = 0; - chan->data_offset = 0; - chan->line_padding = htonl(0); - chan->channel_padding = htonl(0); - chan->description[0] = 0; -} - -static void -dumpDpxChannelInfo(DpxChannelInformation* chan) { - d_printf(" Signage %ld", (intptr_t)ntohl(chan->signage)); - d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data)); - d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity)); - d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data)); - d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity)); - d_printf(" Designator1: %d,", chan->designator1); - d_printf(" Bits per pixel %d\n", chan->bits_per_pixel); - d_printf(" Packing: %d,", ntohs(chan->packing)); - d_printf(" Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset)); -} - -static void -fillDpxFileInfo( - DpxFile* dpx, DpxFileInformation* fileInfo, const char* filename) { - - time_t fileClock; - struct tm* fileTime; - - /* Note: always write files in network order */ - /* By the spec, it shouldn't matter, but ... */ - - fileInfo->magic_num = htonl(DPX_FILE_MAGIC); - fileInfo->offset = htonl(dpx->imageOffset); - strcpy(fileInfo->vers, "v1.0"); - fileInfo->file_size = htonl(dpx->imageOffset + - pixelsToLongs(dpx->height * dpx->width * dpx->depth) * 4); - fileInfo->ditto_key = 0; - fileInfo->gen_hdr_size = htonl( - sizeof(DpxFileInformation) + - sizeof(DpxImageInformation) + - sizeof(DpxOriginationInformation)); - fileInfo->ind_hdr_size = htonl(sizeof(DpxMPIInformation)); - fileInfo->user_data_size = 0; - strncpy(fileInfo->file_name, filename, 99); - fileInfo->file_name[99] = 0; +#include <string.h> - fileClock = time(0); - fileTime = localtime(&fileClock); - strftime(fileInfo->create_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime); - /* Question: is %Z in strftime guaranteed to return 3 chars? */ - fileInfo->create_date[23] = 0; - - strcpy(fileInfo->creator, "David's DPX writer"); - fileInfo->project[0] = 0; - fileInfo->copyright[0] = 0; - fileInfo->key = 0xFFFFFFFF; /* same in any byte order */ -} +#include "BLI_fileops.h" +#include "BLI_math_base.h" +#include "BLI_utildefines.h" -static void -dumpDpxFileInfo(DpxFileInformation* fileInfo) { - d_printf("\n--File Information--\n"); - d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num)); - d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset)); - d_printf("Version \"%s\"\n", fileInfo->vers); - d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size)); - d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key)); - d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size)); - d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size)); - d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size)); - d_printf("File name \"%s\"\n", fileInfo->file_name); - d_printf("Creation date \"%s\"\n", fileInfo->create_date); - d_printf("Creator \"%s\"\n", fileInfo->creator); - d_printf("Project \"%s\"\n", fileInfo->project); - d_printf("Copyright \"%s\"\n", fileInfo->copyright); - d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key)); -} +#include "MEM_guardedalloc.h" -static void -fillDpxImageInfo( - DpxFile* dpx, DpxImageInformation* imageInfo) { - imageInfo->orientation = 0; - imageInfo->channels_per_image = htons(1); - imageInfo->pixels_per_line = htonl(dpx->width); - imageInfo->lines_per_image = htonl(dpx->height); +/* + * For debug purpose + */ - if (dpx->depth == 1) { - fillDpxChannelInfo(dpx, &imageInfo->channel[0], 0); +static int verbose = 0; - } - else if (dpx->depth == 3) { - fillDpxChannelInfo(dpx, &imageInfo->channel[0], 50); - } +void dpxSetVerbose(int verbosity) { + verbose = verbosity; } -static void -dumpDpxImageInfo(DpxImageInformation* imageInfo) { - int n; - int i; - d_printf("\n--Image Information--\n"); - d_printf("Image orientation %d,", ntohs(imageInfo->orientation)); - n = ntohs(imageInfo->channels_per_image); - d_printf("Channels %d\n", n); - d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line)); - d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image)); - for (i = 0; i < n; ++i) { - d_printf(" --Channel %d--\n", i); - dumpDpxChannelInfo(&imageInfo->channel[i]); - } -} +/* + * Headers + */ -static void -fillDpxOriginationInfo( - DpxFile* dpx, DpxOriginationInformation* originInfo, DpxFileInformation* fileInfo) +static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const char *filename, const char *creator) { - /* unused */ - (void)dpx; - (void)originInfo; - (void)fileInfo; -} - -static void -dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) { - d_printf("\n--Origination Information--\n"); - d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset)); - d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset)); - d_printf("X centre %f\n", ntohf(originInfo->x_centre)); - d_printf("Y centre %f\n", ntohf(originInfo->y_centre)); - d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size)); - d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size)); - d_printf("File name \"%s\"\n", originInfo->file_name); - d_printf("Creation time \"%s\"\n", originInfo->creation_time); - d_printf("Input device \"%s\"\n", originInfo->input_device); - d_printf("Serial number \"%s\"\n", originInfo->input_serial_number); -} + time_t fileClock; + struct tm *fileTime; -static void -initDpxMainHeader(DpxFile* dpx, DpxMainHeader* header, const char* shortFilename) { memset(header, 0, sizeof(DpxMainHeader)); - fillDpxFileInfo(dpx, &header->fileInfo, shortFilename); - fillDpxImageInfo(dpx, &header->imageInfo); - fillDpxOriginationInfo(dpx, &header->originInfo, &header->fileInfo); -#if 0 - fillDpxMPIInfo(dpx, &header->filmHeader); -#endif -} - -static void -dumpDpxMainHeader(DpxMainHeader* header) { - dumpDpxFileInfo(&header->fileInfo); - dumpDpxImageInfo(&header->imageInfo); - dumpDpxOriginationInfo(&header->originInfo); -#if 0 - dumpDpxMPIInformation(&header->filmHeader); -#endif -} - -static int verbose = 0; -void -dpxSetVerbose(int verbosity) { - verbose = verbosity; -} - -static void -verboseMe(DpxFile* dpx) { - - d_printf("size %d x %d x %d\n", dpx->width, dpx->height, dpx->depth); - d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n", - dpx->imageOffset, dpx->lineBufferLength * 4, - dpx->imageOffset + pixelsToLongs(dpx->width * dpx->depth * dpx->height) * 4); -} - -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) { - unsigned int t = ntohl(dpx->lineBuffer[longIndex]); - t = t >> 2; - dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff; - t = t >> 10; - dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff; - t = t >> 10; - dpx->pixelBuffer[pixelIndex] = t & 0x3ff; - pixelIndex += 3; - } - } - dpx->pixelBufferUsed = pixelIndex; - - /* extract required pixels */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (dpx->params.doLogarithm) - row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]]; - else - row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6; - } - - /* save remaining pixels */ - while (pixelIndex < dpx->pixelBufferUsed) { - dpx->pixelBuffer[pixelIndex - numPixels] = dpx->pixelBuffer[pixelIndex]; - ++pixelIndex; - } - dpx->pixelBufferUsed -= numPixels; - /* done! */ - return 0; -} - -int -dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) { - - /* Note: this code is bizarre because DPX files can wrap */ - /* packed longwords across line boundaries!!!! */ - - size_t writeLongs; - int longIndex; - int numPixels = dpx->width * dpx->depth; - int pixelIndex; - int pixelIndex2; - - /* only seek if not reading consecutive lines */ - /* this is not quite right yet */ - 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; - } - - /* put new pixels into pixelBuffer */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (dpx->params.doLogarithm) - dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]]; - else - dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6; - } - dpx->pixelBufferUsed += numPixels; - - /* pack into longwords */ - writeLongs = dpx->pixelBufferUsed / 3; - /* process whole line at image end */ - if (dpx->fileYPos == (dpx->height - 1)) { - writeLongs = pixelsToLongs(dpx->pixelBufferUsed); - } - pixelIndex = 0; - if (dpx->depth == 1) { - for (longIndex = 0; longIndex < writeLongs; ++longIndex) { - unsigned int t = dpx->pixelBuffer[pixelIndex] | - (dpx->pixelBuffer[pixelIndex+1] << 10) | - (dpx->pixelBuffer[pixelIndex+2] << 20); - dpx->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - } - else { - for (longIndex = 0; longIndex < writeLongs; ++longIndex) { - unsigned int t = dpx->pixelBuffer[pixelIndex+2] << 2 | - (dpx->pixelBuffer[pixelIndex+1] << 12) | - (dpx->pixelBuffer[pixelIndex] << 22); - dpx->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - } - - /* write them */ - if (fwrite(dpx->lineBuffer, 4, writeLongs, dpx->file) != writeLongs) { - if (verbose) d_printf("Couldn't write line %d length %d\n", y, (int)writeLongs * 4); - return 1; - } - ++dpx->fileYPos; - - /* save remaining pixels */ - pixelIndex2 = 0; - while (pixelIndex < dpx->pixelBufferUsed) { - dpx->pixelBuffer[pixelIndex2] = dpx->pixelBuffer[pixelIndex]; - ++pixelIndex; - ++pixelIndex2; - } - dpx->pixelBufferUsed = pixelIndex2; - - return 0; + /* --- File header --- */ + header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB); + header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB); + strcpy(header->fileHeader.version, "v2.0"); + header->fileHeader.file_size = swap_uint(dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, dpx->element[0]), dpx->isMSB); + header->fileHeader.ditto_key = 0; + header->fileHeader.gen_hdr_size = swap_uint(sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB); + header->fileHeader.ind_hdr_size = swap_uint(sizeof(DpxFilmHeader) + sizeof(DpxTelevisionHeader), dpx->isMSB); + header->fileHeader.user_data_size = DPX_UNDEFINED_U32; + strncpy(header->fileHeader.file_name, filename, 99); + header->fileHeader.file_name[99] = 0; + fileClock = time(0); + fileTime = localtime(&fileClock); + strftime(header->fileHeader.creation_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime); + header->fileHeader.creation_date[23] = 0; + strncpy(header->fileHeader.creator, creator, 99); + header->fileHeader.creator[99] = 0; + header->fileHeader.project[0] = 0; + header->fileHeader.copyright[0] = 0; + header->fileHeader.key = 0xFFFFFFFF; + + /* --- Image header --- */ + header->imageHeader.orientation = 0; + header->imageHeader.elements_per_image = swap_ushort(1, dpx->isMSB); + header->imageHeader.pixels_per_line = swap_uint(dpx->width, dpx->isMSB); + header->imageHeader.lines_per_element = swap_uint(dpx->height, dpx->isMSB); + + /* Fills element */ + header->imageHeader.element[0].data_sign = 0; + header->imageHeader.element[0].ref_low_data = swap_uint(dpx->element[0].refLowData, dpx->isMSB); + header->imageHeader.element[0].ref_low_quantity = swap_float(dpx->element[0].refLowQuantity, dpx->isMSB); + header->imageHeader.element[0].ref_high_data = swap_uint(dpx->element[0].refHighData, dpx->isMSB); + header->imageHeader.element[0].ref_high_quantity = swap_float(dpx->element[0].refHighQuantity, dpx->isMSB); + header->imageHeader.element[0].descriptor = dpx->element[0].descriptor; + header->imageHeader.element[0].transfer = dpx->element[0].transfer; + header->imageHeader.element[0].colorimetric = 0; + header->imageHeader.element[0].bits_per_sample = dpx->element[0].bitsPerSample; + header->imageHeader.element[0].packing = swap_ushort(dpx->element[0].packing, dpx->isMSB); + header->imageHeader.element[0].encoding = 0; + header->imageHeader.element[0].data_offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB); + header->imageHeader.element[0].line_padding = 0; + header->imageHeader.element[0].element_padding = 0; + header->imageHeader.element[0].description[0] = 0; + + /* --- Orientation header --- */ + /* we leave it blank */ + + /* --- Television header --- */ + header->televisionHeader.time_code = DPX_UNDEFINED_U32; + header->televisionHeader.user_bits = DPX_UNDEFINED_U32; + header->televisionHeader.interlace = DPX_UNDEFINED_U8; + header->televisionHeader.field_number = DPX_UNDEFINED_U8; + header->televisionHeader.video_signal = DPX_UNDEFINED_U8; + header->televisionHeader.padding = DPX_UNDEFINED_U8; + header->televisionHeader.horizontal_sample_rate = DPX_UNDEFINED_R32; + header->televisionHeader.vertical_sample_rate = DPX_UNDEFINED_R32; + header->televisionHeader.frame_rate = DPX_UNDEFINED_R32; + header->televisionHeader.time_offset = DPX_UNDEFINED_R32; + header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB); + header->televisionHeader.black_level = swap_float(dpx->referenceBlack, dpx->isMSB); + header->televisionHeader.black_gain = DPX_UNDEFINED_R32; + header->televisionHeader.breakpoint = DPX_UNDEFINED_R32; + header->televisionHeader.white_level = swap_float(dpx->referenceWhite, dpx->isMSB); + header->televisionHeader.integration_times = DPX_UNDEFINED_R32; } -#define LFMEMFILE 0 -#define LFREALFILE 1 - -static DpxFile* -intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { - +LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) +{ DpxMainHeader header; - const char *filename = bytestuff; - DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile)); - + LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + char *filename = (char *)byteStuff; + int i; + if (dpx == 0) { - if (verbose) d_printf("Failed to malloc dpx file structure.\n"); + if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); return 0; } + /* zero the header */ + memset(&header, 0, sizeof(DpxMainHeader)); + /* for close routine */ dpx->file = 0; - dpx->lineBuffer = 0; - dpx->pixelBuffer = 0; - if (mode == LFREALFILE) { - filename = bytestuff; + if (fromMemory == 0) { + /* byteStuff is then the filename */ dpx->file = BLI_fopen(filename, "rb"); - if (dpx->file == 0) { - if (verbose) d_printf("Failed to open file \"%s\".\n", filename); - dpxClose(dpx); + if (dpx->file == 0) { + if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename); + logImageClose(dpx); return 0; } - dpx->membuffer = 0; - dpx->memcursor = 0; - dpx->membuffersize = 0; + /* not used in this case */ + dpx->memBuffer = 0; + dpx->memCursor = 0; + dpx->memBufferSize = 0; } - else if (mode == LFMEMFILE) { - dpx->membuffer = (unsigned char *)bytestuff; - dpx->memcursor = (unsigned char *)bytestuff; - dpx->membuffersize = bufsize; + else { + dpx->memBuffer = (unsigned char *)byteStuff; + dpx->memCursor = (unsigned char *)byteStuff; + dpx->memBufferSize = bufferSize; } - - dpx->reading = 1; if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) { - if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename); - dpxClose(dpx); + if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff); + logImageClose(dpx); return 0; } - /* let's assume dpx files are always network order */ - if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) { - if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n", - (uintptr_t)ntohl(header.fileInfo.magic_num), filename); - dpxClose(dpx); - return 0; + /* endianness determination */ + if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) { + dpx->isMSB = 1; + if (verbose) printf("DPX: File is MSB.\n"); } - - if (ntohs(header.imageInfo.channel[0].packing) != 1) { - if (verbose) d_printf("Unknown packing %d\n", header.imageInfo.channel[0].packing); - dpxClose(dpx); + 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 %lu in \"%s\".\n", + (uintptr_t)header.fileHeader.magic_num, byteStuff); + logImageClose(dpx); return 0; } + dpx->srcFormat = format_DPX; + dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB); + dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB); + dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB); + 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; + } - dpx->width = ntohl(header.imageInfo.pixels_per_line); - dpx->height = ntohl(header.imageInfo.lines_per_image); - dpx->depth = ntohs(header.imageInfo.channels_per_image); - /* Another DPX vs Cineon wierdness */ - if (dpx->depth == 1) { - switch (header.imageInfo.channel[0].designator1) { - case 50: dpx->depth = 3; break; - case 51: dpx->depth = 4; break; - case 52: dpx->depth = 4; break; - default: break; + if (dpx->depth == 0 || dpx->depth > 4) { + if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth); + logImageClose(dpx); + return 0; } - } - /* dpx->bitsPerPixel = 10; */ - dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; - if (dpx->bitsPerPixel != 10) { - if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel); - dpxClose(dpx); - return 0; - } - dpx->imageOffset = ntohl(header.fileInfo.offset); - dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth); - dpx->lineBuffer = malloc(dpx->lineBufferLength * 4); - if (dpx->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4); - dpxClose(dpx); - return 0; - } + dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; + 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); - /* could have 2 pixels left over */ - dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short)); - if (dpx->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short)); - dpxClose(dpx); - return 0; - } - dpx->pixelBufferUsed = 0; + /* 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 (logimage_fseek(dpx, dpx->imageOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to image data start at %d\n", dpx->imageOffset); - dpxClose(dpx); - return 0; - } - dpx->fileYPos = 0; - - logImageGetByteConversionDefaults(&dpx->params); - /* The SMPTE define this code: - * 0 - User-defined - * 1 - Printing density - * 2 - Linear - * 3 - Logarithmic - * 4 - Unspecified video - * 5 - SMPTE 240M - * 6 - CCIR 709-1 - * 7 - CCIR 601-2 system B or G - * 8 - CCIR 601-2 system M - * 9 - NTSC composite video - * 10 - PAL composite video - * 11 - Z linear - * 12 - homogeneous - * - * Note that transfer_characteristics is U8, don't need - * check the byte order. - */ - - switch (header.imageInfo.channel[0].transfer_characteristics) { - case 1: - case 2: /* linear */ - dpx->params.doLogarithm= 0; - break; - - case 3: - dpx->params.doLogarithm= 1; - break; - - /* TODO - Unsupported, but for now just load them, - * colors may look wrong, but can solve color conversion later - */ - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics); - dpx->params.doLogarithm= 0; - break; - default: - if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics); - dpxClose(dpx); + if (dpx->element[i].dataOffset == 0) { + if (verbose) printf("DPX: Image header is corrupted.\n"); + logImageClose(dpx); return 0; - break; - } - setupLut(dpx); - - dpx->getRow = &dpxGetRowBytes; - dpx->setRow = 0; - dpx->close = &dpxClose; + } - if (verbose) { - verboseMe(dpx); + 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 || isnan(dpx->element[i].refLowData)) + dpx->element[i].refLowData = 0; + + if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData)) + 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 || isnan(dpx->element[i].refLowData)) + dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue; + + if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData)) + 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; + } } - return dpx; -} - -DpxFile* -dpxOpen(const char *filename) { - return intern_dpxOpen(LFREALFILE, filename, 0); -} + 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); -DpxFile* -dpxOpenFromMem(unsigned char *buffer, unsigned int size) { - return intern_dpxOpen(LFMEMFILE, (const char *) buffer, size); -} + 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))) + { -int -dpxIsMemFileCineon(void *buffer) { - int magicnum = 0; - magicnum = *((int*)buffer); - if (magicnum == ntohl(DPX_FILE_MAGIC)) return 1; - else return 0; -} + dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; + dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; + dpx->gamma = 1.7f; + } -DpxFile* -dpxCreate(const char* filename, int width, int height, int depth) { + 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: %u\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"); + } - /* Note: always write files in network order */ - /* By the spec, it shouldn't matter, but ... */ + printf("Gamma: %f\n", dpx->gamma); + printf("Reference black: %f\n", dpx->referenceBlack); + printf("Reference white: %f\n", dpx->referenceWhite); + printf("----------------------------\n"); + } + return dpx; +} +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 = 0; + const char *shortFilename = 0; + unsigned char pad[6044]; - DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile)); + LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); if (dpx == 0) { - if (verbose) d_printf("Failed to malloc dpx file structure.\n"); - return 0; - } - - memset(&header, 0, sizeof(header)); - - /* for close routine */ - dpx->file = 0; - dpx->lineBuffer = 0; - dpx->pixelBuffer = 0; - - dpx->file = BLI_fopen(filename, "wb"); - if (dpx->file == 0) { - if (verbose) d_printf("Couldn't open file %s\n", filename); - dpxClose(dpx); + if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); return 0; } - dpx->reading = 0; dpx->width = width; dpx->height = height; - dpx->depth = depth; - dpx->bitsPerPixel = 10; - dpx->imageOffset = sizeof(DpxMainHeader); - - dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth); - dpx->lineBuffer = malloc(dpx->lineBufferLength * 4); - if (dpx->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4); - dpxClose(dpx); - return 0; - } + 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; - dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short)); - if (dpx->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short)); - dpxClose(dpx); - return 0; + 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 0; } - dpx->pixelBufferUsed = 0; - /* find trailing part of filename */ - shortFilename = strrchr(filename, '/'); - if (shortFilename == 0) { - shortFilename = filename; + if (hasAlpha == 0) { + dpx->depth = 3; + dpx->element[0].depth = 3; + dpx->element[0].descriptor = descriptor_RGB; } else { - ++shortFilename; + dpx->depth = 4; + dpx->element[0].depth = 4; + dpx->element[0].descriptor = descriptor_RGBA; } - initDpxMainHeader(dpx, &header, shortFilename); - logImageGetByteConversionDefaults(&dpx->params); - /* Need set the file type before write the header! - * 2 - Linear - * 3 - Logarithmic - * - * Note that transfer characteristics is U8, don't need - * check the byte order. - */ - if (dpx->params.doLogarithm == 0) - header.imageInfo.channel[0].transfer_characteristics= 2; - else - header.imageInfo.channel[0].transfer_characteristics= 3; - if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { - if (verbose) d_printf("Couldn't write image header\n"); - dpxClose(dpx); - return 0; + if (isLogarithmic == 0) { + dpx->element[0].transfer = transfer_Linear; + dpx->element[0].refHighQuantity = dpx->element[0].maxValue; } - dpx->fileYPos = 0; - setupLut(dpx); + else { + dpx->element[0].transfer = transfer_PrintingDensity; + dpx->element[0].refHighQuantity = 2.048f; - dpx->getRow = 0; - dpx->setRow = &dpxSetRowBytes; - dpx->close = &dpxClose; + } - return dpx; -} + dpx->element[0].refLowQuantity = 0; + dpx->element[0].refLowData = 0; + dpx->element[0].refHighData = dpx->element[0].maxValue; -void -dpxClose(DpxFile* dpx) { + if (referenceWhite > 0) + dpx->referenceWhite = referenceWhite; + else + dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; - if (dpx == 0) { - return; - } + if (referenceBlack > 0) + dpx->referenceBlack = referenceBlack; + else + dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; - if (dpx->file) { - fclose(dpx->file); - dpx->file = 0; - } + if (gamma > 0.0f) + dpx->gamma = gamma; + else + dpx->gamma = 1.7f; - if (dpx->lineBuffer) { - free(dpx->lineBuffer); - dpx->lineBuffer = 0; - } - if (dpx->pixelBuffer) { - free(dpx->pixelBuffer); - dpx->pixelBuffer = 0; - } + shortFilename = strrchr(filename, '/'); + if (shortFilename == 0) + shortFilename = filename; + else + shortFilename++; - free(dpx); -} + dpx->file = BLI_fopen(filename, "wb"); -void -dpxDump(const char* filename) { + if (dpx->file == 0) { + if (verbose) printf("DPX: Couldn't open file %s\n", filename); + logImageClose(dpx); + return 0; + } - DpxMainHeader header; - FILE* file; + fillDpxMainHeader(dpx, &header, shortFilename, creator); - file = BLI_fopen(filename, "rb"); - if (file == 0) { - d_printf("Failed to open file \"%s\".\n", filename); - return; + if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { + if (verbose) printf("DPX: Couldn't write image header\n"); + logImageClose(dpx); + return 0; } - if (fread(&header, sizeof(header), 1, file) == 0) { - d_printf("Not enough data for header in \"%s\".\n", filename); - fclose(file); - return; + /* 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 0; } - fclose(file); - dumpDpxMainHeader(&header); + return dpx; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index eb3937f2bf7..e910aaa61e1 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -1,60 +1,160 @@ /* - * DPX image file format library definitions. + * DPX image file format library definitions. * - * Copyright 1999 - 2002 David Hodson <hodsond@acm.org> + * Copyright 1999 - 2002 David Hodson <hodsond@acm.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ -#ifndef __DPXLIB_H__ -#define __DPXLIB_H__ - /** \file blender/imbuf/intern/cineon/dpxlib.h * \ingroup imbcineon */ + +#ifndef __DPX_LIB_H__ +#define __DPX_LIB_H__ + #ifdef __cplusplus extern "C" { #endif #include "logImageCore.h" -typedef struct _Log_Image_File_t_ DpxFile; +#define DPX_FILE_MAGIC 0x53445058 +#define DPX_UNDEFINED_U8 0xFF +#define DPX_UNDEFINED_U16 0xFFFF +#define DPX_UNDEFINED_U32 0xFFFFFFFF +#define DPX_UNDEFINED_R32 0xFFFFFFFF +#define DPX_UNDEFINED_CHAR 0 -/* int functions return 0 for OK */ +typedef struct { + unsigned int magic_num; + unsigned int offset; + char version[8]; + unsigned int file_size; + unsigned int ditto_key; + unsigned int gen_hdr_size; + unsigned int ind_hdr_size; + unsigned int user_data_size; + char file_name[100]; + char creation_date[24]; + char creator[100]; + char project[200]; + char copyright[200]; + unsigned int key; + char reserved[104]; +} DpxFileHeader; -void dpxSetVerbose(int); +typedef struct { + unsigned int data_sign; + unsigned int ref_low_data; + float ref_low_quantity; + unsigned int ref_high_data; + float ref_high_quantity; + unsigned char descriptor; + unsigned char transfer; + unsigned char colorimetric; + unsigned char bits_per_sample; + unsigned short packing; + unsigned short encoding; + unsigned int data_offset; + unsigned int line_padding; + unsigned int element_padding; + char description[32]; +} DpxElementHeader; -DpxFile* dpxOpen(const char* filename); -DpxFile* dpxCreate(const char* filename, int xsize, int ysize, int channels); -DpxFile* dpxOpenFromMem(unsigned char *buffer, unsigned int size); -int dpxIsMemFileCineon(void *buffer); +typedef struct { + unsigned short orientation; + unsigned short elements_per_image; + unsigned int pixels_per_line; + unsigned int lines_per_element; + DpxElementHeader element[8]; + char reserved[52]; +} DpxImageHeader; -/* get/set scanline of converted bytes */ -int dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y); -int dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y); +typedef struct { + unsigned int x_offset; + unsigned int y_offset; + float x_center; + float y_center; + unsigned int x_original_size; + unsigned int y_original_size; + char file_name[100]; + char creation_time[24]; + char input_device[32]; + char input_serial_number[32]; + unsigned short border_validity[4]; + unsigned int pixel_aspect_ratio[2]; + char reserved[28]; +} DpxOrientationHeader; -/* closes file and deletes data */ -void dpxClose(DpxFile* dpx); +typedef struct { + char film_manufacturer_id[2]; + char film_type[2]; + char edge_code_perforation_offset[2]; + char edge_code_prefix[6]; + char edge_code_count[4]; + char film_format[32]; + unsigned int frame_position; + unsigned int sequence_length; + unsigned int held_count; + float frame_rate; + float shutter_angle; + char frame_identification[32]; + char slate_info[100]; + char reserved[56]; +} DpxFilmHeader; -/* dumps file to stdout */ -void dpxDump(const char* filename); +typedef struct { + unsigned int time_code; + unsigned int user_bits; + unsigned char interlace; + unsigned char field_number; + unsigned char video_signal; + unsigned char padding; + float horizontal_sample_rate; + float vertical_sample_rate; + float frame_rate; + float time_offset; + float gamma; + float black_level; + float black_gain; + float breakpoint; + float white_level; + float integration_times; + unsigned char reserved[76]; +} DpxTelevisionHeader; + + +typedef struct { + DpxFileHeader fileHeader; + DpxImageHeader imageHeader; + DpxOrientationHeader orientationHeader; + DpxFilmHeader filmHeader; + DpxTelevisionHeader televisionHeader; +} DpxMainHeader; + +void dpxSetVerbose(int verbosity); +LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize); +LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha, int isLogarithmic, int referenceWhite, int referenceBlack, float gamma, const char *creator); #ifdef __cplusplus } #endif -#endif /* __DPXLIB_H__ */ +#endif diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index f772cc7d477..3911e5c2ef3 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -1,21 +1,23 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> + * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ @@ -23,223 +25,1407 @@ * \ingroup imbcineon */ + +#include "logmemfile.h" #include "logImageCore.h" +#include "dpxlib.h" +#include "cineonlib.h" -#include <time.h> /* strftime() */ +#include <stdlib.h> +#include <string.h> #include <math.h> -/* Makes rint consistent in Windows and Linux: */ -#define rint(x) floor(x+0.5) -#ifdef WIN32 -#include <winsock.h> -#else -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <sys/param.h> -#endif +#include "BLI_fileops.h" +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +/* + * Declaration of static functions + */ + +static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageElementGetData(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData1(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData8(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData10(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData10Packed(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData12(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData12Packed(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData16(LogImageFile *dpx, LogImageElement logElement, float *data); +static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int dstIsLinearRGB); +static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int srcIsLinearRGB); + + +/* + * For debug purpose + */ + +static int verbose = 0; + +void logImageSetVerbose(int verbosity) +{ + verbose = verbosity; + cineonSetVerbose(verbosity); + dpxSetVerbose(verbosity); +} + + +/* + * IO stuff + */ + +int logImageIsDpx(const void *buffer) +{ + unsigned int magicNum = *(unsigned int *)buffer; + return (magicNum == DPX_FILE_MAGIC || magicNum == swap_uint(DPX_FILE_MAGIC, 1)); +} -#if defined(__hpux) -/* These are macros in hpux */ -#ifdef htonl -#undef htonl -#undef htons -#undef ntohl -#undef ntohs -#endif -unsigned int htonl(h) unsigned int h; { return(h); } -unsigned short htons(h) unsigned short h; { return(h); } -unsigned int ntohl(n) unsigned int n; { return(n); } -unsigned short ntohs(n) unsigned short n; { return(n); } -#endif - - -/* obscure LogImage conversion */ -/* from 10 bit int to 0.0 - 1.0 */ -/* magic numbers left intact */ -static double -convertTo(int inp, int white, float gamma) { - /* return pow(pow(10.0, ((inp - white) * 0.002 / 0.6)), gamma); */ - return pow(10.0, (inp - white) * gamma * 0.002 / 0.6); +int logImageIsCineon(const void *buffer) +{ + unsigned int magicNum = *(unsigned int *)buffer; + return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1)); } -static double -convertFrom(double inp, int white, float gamma) { - return white + log10(inp) / (gamma * 0.002 / 0.6); +LogImageFile *logImageOpenFromFile(const char *filename, int cineon) +{ + unsigned int magicNum; + FILE *f = BLI_fopen(filename, "rb"); + + (void)cineon; + + if (f == 0) + return 0; + + if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) { + fclose(f); + return 0; + } + + fclose(f); + + if (logImageIsDpx(&magicNum)) + return dpxOpen((const unsigned char *)filename, 0, 0); + else if (logImageIsCineon(&magicNum)) + return cineonOpen((const unsigned char *)filename, 0, 0); + + return 0; } -/* set up the 10 bit to 8 bit and 8 bit to 10 bit tables */ -void -setupLut(LogImageFile *logImage) { +LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size) +{ + if (logImageIsDpx(buffer)) + return dpxOpen(buffer, 1, size); + else if (logImageIsCineon(buffer)) + return cineonOpen(buffer, 1, size); - int i; - double f_black; - double scale; + return 0; +} + +LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample, + int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack, + float gamma, const char *creator) +{ + /* referenceWhite, referenceBlack and gamma values are only supported for DPX file */ + if (cineon) + return cineonCreate(filename, width, height, bitsPerSample, creator); + else + return dpxCreate(filename, width, height, bitsPerSample, isLogarithmic, hasAlpha, + referenceWhite, referenceBlack, gamma, creator); - f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma); - scale = 255.0 / (1.0 - f_black); + return 0; +} - for (i = 0; i <= logImage->params.blackPoint; ++i) { - logImage->lut10[i] = 0; +void logImageClose(LogImageFile *logImage) +{ + if (logImage != 0) { + if (logImage->file) { + fclose(logImage->file); + logImage->file = 0; + } + MEM_freeN(logImage); } - for (; i < logImage->params.whitePoint; ++i) { - double f_i; - f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma); - logImage->lut10[i] = (int)rint(scale * (f_i - f_black)); +} + +void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth) +{ + *width = logImage->width; + *height = logImage->height; + *depth = logImage->depth; +} + + +/* + * Helper + */ + +unsigned int getRowLength(int width, LogImageElement logElement) +{ + /* return the row length in bytes according to width and packing method */ + switch (logElement.bitsPerSample) { + case 1: + return ((width * logElement.depth - 1) / 32 + 1) * 4; + + case 8: + return ((width * logElement.depth - 1) / 4 + 1) * 4; + + case 10: + if (logElement.packing == 0) + return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4; + else if (logElement.packing == 1 || logElement.packing == 2) + return ((width * logElement.depth - 1) / 3 + 1) * 4; + + case 12: + if (logElement.packing == 0) + return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4; + else if (logElement.packing == 1 || logElement.packing == 2) + return width * logElement.depth * 2; + + case 16: + return width * logElement.depth * 2; + + default: + return 0; } - for (; i < 1024; ++i) { - logImage->lut10[i] = 255; +} + + +/* + * Data writing + */ + +int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB) +{ + float *elementData; + int returnValue; + + elementData = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->depth * sizeof(float), __func__); + if (elementData == 0) + return 1; + + if (convertRGBAToLogElement(data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) { + MEM_freeN(elementData); + return 1; } - for (i = 0; i < 256; ++i) { - double f_i = f_black + (i / 255.0) * (1.0 - f_black); - logImage->lut8[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma); - } -} - -/* set up the 10 bit to 16 bit and 16 bit to 10 bit tables */ -void -setupLut16(LogImageFile *logImage) { + switch (logImage->element[0].bitsPerSample) { + case 8: + returnValue = logImageSetData8(logImage, logImage->element[0], elementData); + break; + + case 10: + returnValue = logImageSetData10(logImage, logImage->element[0], elementData); + break; - int i; - double f_black; - double scale; + case 12: + returnValue = logImageSetData12(logImage, logImage->element[0], elementData); + break; - f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma); - scale = 65535.0 / (1.0 - f_black); - - for (i = 0; i <= logImage->params.blackPoint; ++i) { - logImage->lut10_16[i] = 0; - } - for (; i < logImage->params.whitePoint; ++i) { - double f_i; - f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma); - logImage->lut10_16[i] = (int)rint(scale * (f_i - f_black)); - } - for (; i < 1024; ++i) { - logImage->lut10_16[i] = 65535; - } - - for (i = 0; i < 65536; ++i) { - double f_i = f_black + (i / 65535.0) * (1.0 - f_black); - logImage->lut16_16[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma); - } -} - -/* how many longwords to hold this many pixels? */ -int -pixelsToLongs(int numPixels) { - return (numPixels + 2) / 3; -} - -/* byte reversed float */ + case 16: + returnValue = logImageSetData16(logImage, logImage->element[0], elementData); + break; -typedef union { - U32 i; - R32 f; -} Hack; + default: + returnValue = 1; + break; + } -R32 -htonf(R32 f) { - Hack hack; - hack.f = f; - hack.i = htonl(hack.i); - return hack.f; + MEM_freeN(elementData); + return returnValue; } -R32 -ntohf(R32 f) { - Hack hack; - hack.f = f; - hack.i = ntohl(hack.i); - return hack.f; +static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned char *row; + int x, y; + + row = (unsigned char *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + memset(row, 0, rowLength); + + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logImage->depth; x++) + row[x] = (unsigned char)float_uint(data[y * logImage->width * logImage->depth + x], 255); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); + MEM_freeN(row); + return 1; + } + } + MEM_freeN(row); + return 0; } -#define UNDEF_FLOAT 0x7F800000 +static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, index; + unsigned int *row; + int x, y, offset; -R32 -undefined(void) { - Hack hack; - hack.i = UNDEF_FLOAT; - return hack.f; + row = (unsigned int *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (y = 0; y < logImage->height; y++) { + offset = 22; + index = 0; + pixel = 0; + + for (x = 0; x < logImage->width * logImage->depth; x++) { + pixel |= (unsigned int)float_uint(data[y * logImage->width * logImage->depth + x], 1023) << offset; + offset -= 10; + if (offset < 0) { + row[index] = swap_uint(pixel, logImage->isMSB); + index++; + pixel = 0; + offset = 22; + } + } + if (pixel != 0) + row[index] = swap_uint(pixel, logImage->isMSB); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); { + MEM_freeN(row); + return 1; + } + } + } + MEM_freeN(row); + return 0; } -/* reverse an endian-swapped U16 */ -U16 -reverseU16(U16 value) { +static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned short *row; + int x, y; - union { - U16 whole; - char part[2]; - } buff; - char temp; - buff.whole = value; - temp = buff.part[0]; - buff.part[0] = buff.part[1]; - buff.part[1] = temp; - return buff.whole; + row = (unsigned short *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logImage->depth; x++) + row[x] = swap_ushort(((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 4095)) << 4, logImage->isMSB); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); + MEM_freeN(row); + return 1; + } + } + MEM_freeN(row); + return 0; } -/* reverse an endian-swapped U32 */ -U32 -reverseU32(U32 value) { +static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned short *row; + int x, y; - union { - U32 whole; - char part[4]; - } buff; - char temp; - buff.whole = value; - temp = buff.part[0]; - buff.part[0] = buff.part[3]; - buff.part[3] = temp; - temp = buff.part[1]; - buff.part[1] = buff.part[2]; - buff.part[2] = temp; - return buff.whole; + row = (unsigned short *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logImage->depth; x++) + row[x] = swap_ushort((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 65535), logImage->isMSB); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); + MEM_freeN(row); + return 1; + } + } + MEM_freeN(row); + return 0; } -/* reverse an endian-swapped R32 */ -R32 -reverseR32(R32 value) { - union { - R32 whole; - char part[4]; - } buff; - char temp; - buff.whole = value; - temp = buff.part[0]; - buff.part[0] = buff.part[3]; - buff.part[3] = temp; - temp = buff.part[1]; - buff.part[1] = buff.part[2]; - buff.part[2] = temp; - return buff.whole; +/* + * Data reading + */ + +int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB) +{ + /* Fills data with 32 bits float RGBA values */ + int i, j, returnValue, sortedElementData[8], hasAlpha; + float *elementData[8]; + float *elementData_ptr[8]; + float *mergedData; + unsigned int sampleIndex; + LogImageElement mergedElement; + + /* Determine the depth of the picture and if there's a separate alpha element. + If the element is supported, load it into an unsigned ints array. */ + memset(&elementData, 0, 8 * sizeof(float *)); + hasAlpha = 0; + + for (i = 0; i < logImage->numElements; i++) { + /* descriptor_Depth and descriptor_Composite are not supported */ + if (logImage->element[i].descriptor != descriptor_Depth && logImage->element[i].descriptor != descriptor_Composite) { + /* Allocate memory */ + elementData[i] = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->element[i].depth * sizeof(float), __func__); + if (elementData[i] == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i); + for (j = 0; j < i; j++) + if (elementData[j] != 0) + MEM_freeN(elementData[j]); + return 1; + } + elementData_ptr[i] = elementData[i]; + + /* Load data */ + if (logImageElementGetData(logImage, logImage->element[i], elementData[i]) != 0) { + if (verbose) printf("DPX/Cineon: Cannot read elementData[%d]\n.", i); + for (j = 0; j < i; j++) + if (elementData[j] != 0) + MEM_freeN(elementData[j]); + return 1; + } + } + + if (logImage->element[i].descriptor == descriptor_Alpha) + hasAlpha = 1; + } + + /* only one element, easy case, no need to do anything */ + if (logImage->numElements == 1) { + returnValue = convertLogElementToRGBA(elementData[0], data, logImage, logImage->element[0], dataIsLinearRGB); + MEM_freeN(elementData[0]); + } + else { + /* The goal here is to merge every elements into only one + * to recreate a classic 16 bits RGB, RGBA or YCbCr element. + * Unsupported elements are skipped (depth, composite) */ + + memcpy(&mergedElement, &logImage->element[0], sizeof(LogImageElement)); + mergedElement.descriptor = -1; + mergedElement.depth = logImage->depth; + memset(&sortedElementData, -1, 8 * sizeof(int)); + + /* Try to know how to assemble the elements */ + for (i = 0; i < logImage->numElements; i++) { + switch (logImage->element[i].descriptor) { + case descriptor_Red: + case descriptor_RGB: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_RGB; + else + mergedElement.descriptor = descriptor_RGBA; + + sortedElementData[0] = i; + break; + + case descriptor_Green: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_RGB; + else + mergedElement.descriptor = descriptor_RGBA; + + sortedElementData[1] = i; + break; + + case descriptor_Blue: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_RGB; + else + mergedElement.descriptor = descriptor_RGBA; + + sortedElementData[2] = i; + break; + + case descriptor_Alpha: + /* Alpha component is always the last one */ + sortedElementData[mergedElement.depth - 1] = i; + break; + + case descriptor_Luminance: + if (mergedElement.descriptor == -1) + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_Luminance; + else + mergedElement.descriptor = descriptor_YA; + else if (mergedElement.descriptor == descriptor_Chrominance) { + if (mergedElement.depth == 2) + mergedElement.descriptor = descriptor_CbYCrY; + else if (mergedElement.depth == 3) + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_CbYCr; + else + mergedElement.descriptor = descriptor_CbYACrYA; + else if (mergedElement.depth == 4) + mergedElement.descriptor = descriptor_CbYCrA; + } + + /* Y component always in 1 except if it's alone or with alpha */ + if (mergedElement.depth == 1 || (mergedElement.depth == 2 && hasAlpha == 1)) + sortedElementData[0] = i; + else + sortedElementData[1] = i; + break; + + case descriptor_Chrominance: + if (mergedElement.descriptor == -1) + mergedElement.descriptor = descriptor_Chrominance; + else if (mergedElement.descriptor == descriptor_Luminance) { + if (mergedElement.depth == 2) + mergedElement.descriptor = descriptor_CbYCrY; + else if (mergedElement.depth == 3) + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_CbYCr; + else + mergedElement.descriptor = descriptor_CbYACrYA; + else if (mergedElement.depth == 4) + mergedElement.descriptor = descriptor_CbYCrA; + } + + /* Cb and Cr always in 0 or 2 */ + if (sortedElementData[0] == -1) + sortedElementData[0] = i; + else + sortedElementData[2] = i; + break; + + case descriptor_CbYCr: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_CbYCr; + else + mergedElement.descriptor = descriptor_CbYCrA; + + sortedElementData[0] = i; + break; + + case descriptor_RGBA: + case descriptor_ABGR: + case descriptor_CbYACrYA: + case descriptor_CbYCrY: + case descriptor_CbYCrA: + /* I don't think these ones can be seen in a planar image */ + mergedElement.descriptor = logImage->element[i].descriptor; + sortedElementData[0] = i; + break; + + case descriptor_Depth: + case descriptor_Composite: + /* Not supported */ + break; + } + } + + mergedData = (float *)MEM_mallocN(logImage->width * logImage->height * mergedElement.depth * sizeof(float), __func__); + if (mergedData == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n"); + for (i = 0; i < logImage->numElements; i++) + if (elementData[i] != 0) + MEM_freeN(elementData[i]); + return 1; + } + + sampleIndex = 0; + while (sampleIndex < logImage->width * logImage->height * mergedElement.depth) { + for (i = 0; i < logImage->numElements; i++) + for (j = 0; j < logImage->element[sortedElementData[i]].depth; j++) + mergedData[sampleIndex++] = *(elementData_ptr[sortedElementData[i]]++); + } + + /* Done with elements data, clean-up */ + for (i = 0; i < logImage->numElements; i++) + if (elementData[i] != 0) + MEM_freeN(elementData[i]); + + returnValue = convertLogElementToRGBA(mergedData, data, logImage, mergedElement, dataIsLinearRGB); + MEM_freeN(mergedData); + } + return returnValue; } -#if 0 -/* bytes per line for images packed 3 10 bit pixels to 32 bits, 32 bit aligned */ -int -bytesPerLine_10_4(int numPixels) { - return ((numPixels + 2) / 3) * 4; +static int logImageElementGetData(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + switch (logElement.bitsPerSample) { + case 1: + return logImageElementGetData1(logImage, logElement, data); + + case 8: + return logImageElementGetData8(logImage, logElement, data); + + case 10: + if (logElement.packing == 0) + return logImageElementGetData10Packed(logImage, logElement, data); + else if (logElement.packing == 1 || logElement.packing == 2) + return logImageElementGetData10(logImage, logElement, data); + + case 12: + if (logElement.packing == 0) + return logImageElementGetData12Packed(logImage, logElement, data); + else if (logElement.packing == 1 || logElement.packing == 2) + return logImageElementGetData12(logImage, logElement, data); + + case 16: + return logImageElementGetData16(logImage, logElement, data); + + default: + /* format not supported */ + return 1; + } } -void -seekLine_noPadding(LogImageFile* logImage, int lineNumber) { - int fileOffset = bytesPerLine_10_4(lineNumber * logImage->width * logImage->depth); - int filePos = logImage->imageOffset + fileOffset; - if (fseek(logImage->file, filePos, SEEK_SET) != 0) { - /* complain? */ - } -} - -void -seekLine_padding(LogImageFile* logImage, int lineNumber) { - int fileOffset = lineNumber * bytesPerLine_10_4(logImage->width * logImage->depth); - int filePos = logImage->imageOffset + fileOffset; - if (fseek(logImage->file, filePos, SEEK_SET) != 0) { - /* complain? */ - } -} -#endif +static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int pixel; + int x, y, offset; + + /* seek at the right place */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + /* read 1 bit data padded to 32 bits */ + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logElement.depth; x += 32) { + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + for (offset = 0; offset < 32 && x + offset < logImage->width; offset++) + data[y * logImage->width * logElement.depth + x + offset] = (float)((pixel >> offset) & 0x01); + } + } + return 0; +} + +static int logImageElementGetData8(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned char pixel; + int x, y; + + /* extract required pixels */ + for (y = 0; y < logImage->height; y++) { + /* 8 bits are 32-bits padded so we need to seek at each row */ + if (logimage_fseek(logImage, logElement.dataOffset + y * rowLength, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset + y * rowLength); + return 1; + } + + for (x = 0; x < logImage->width * logElement.depth; x++) { + if (logimage_read_uchar(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + data[y * logImage->width * logElement.depth + x] = (float)pixel / 255.0f; + } + } + return 0; +} + +static int logImageElementGetData10(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int pixel; + int x, y, offset; + + /* seek to data */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + if (logImage->depth == 1 && logImage->srcFormat == format_DPX) { + for (y = 0; y < logImage->height; y++) { + offset = 32; + for (x = 0; x < logImage->width * logElement.depth; x++) { + /* we need to read the next long */ + if (offset >= 30) { + if (logElement.packing == 1) + offset = 2; + else if (logElement.packing == 2) + offset = 0; + + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f; + offset += 10; + } + } + } + else { + for (y = 0; y < logImage->height; y++) { + offset = -1; + for (x = 0; x < logImage->width * logElement.depth; x++) { + /* we need to read the next long */ + if (offset < 0) { + if (logElement.packing == 1) + offset = 22; + else if (logElement.packing == 2) + offset = 20; + + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f; + offset -= 10; + } + } + } + + return 0; +} + +static int logImageElementGetData10Packed(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, oldPixel; + int offset, offset2, x, y; + + /* converting bytes to pixels */ + for (y = 0; y < logImage->height; y++) { + /* seek to data */ + if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset); + return 1; + } + + oldPixel = 0; + offset = 0; + offset2 = 0; + + for (x = 0; x < logImage->width * logElement.depth; x++) { + if (offset2 != 0) { + offset = 10 - offset2; + offset2 = 0; + oldPixel = 0; + } + else if (offset == 32) { + offset = 0; + } + else if (offset + 10 > 32) { + /* next pixel is on two different longs */ + oldPixel = (pixel >> offset); + offset2 = 32 - offset; + offset = 0; + } + + if (offset == 0) { + /* we need to read the next long */ + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0x3ff) | oldPixel) / 1023.0f; + offset += 10; + } + } + return 0; +} + +static int logImageElementGetData12(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int sampleIndex; + unsigned int numSamples = logImage->width * logImage->height * logElement.depth; + unsigned short pixel; + + /* seek to data */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + /* convert bytes to pixels */ + sampleIndex = 0; + + for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) { + if (logimage_read_ushort(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_ushort(pixel, logImage->isMSB); + + if (logElement.packing == 1) /* padded to the right */ + data[sampleIndex] = (float)(pixel >> 4) / 4095.0f; + else if (logElement.packing == 2) /* padded to the left */ + data[sampleIndex] = (float)pixel / 4095.0f; + } + return 0; +} + +static int logImageElementGetData12Packed(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, oldPixel; + int offset, offset2, x, y; + + /* converting bytes to pixels */ + for (y = 0; y < logImage->height; y++) { + /* seek to data */ + if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset); + return 1; + } + + oldPixel = 0; + offset = 0; + offset2 = 0; + + for (x = 0; x < logImage->width * logElement.depth; x++) { + if (offset2 != 0) { + offset = 12 - offset2; + offset2 = 0; + oldPixel = 0; + } + else if (offset == 32) { + offset = 0; + } + else if (offset + 12 > 32) { + /* next pixel is on two different longs */ + oldPixel = (pixel >> offset); + offset2 = 32 - offset; + offset = 0; + } + + if (offset == 0) { + /* we need to read the next long */ + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0xfff) | oldPixel) / 4095.0f; + offset += 12; + } + } + return 0; +} + +static int logImageElementGetData16(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int numSamples = logImage->width * logImage->height * logElement.depth; + unsigned int sampleIndex; + unsigned short pixel; + + /* seek to data */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) { + if (logimage_read_ushort(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_ushort(pixel, logImage->isMSB); + data[sampleIndex] = (float)pixel / 65535.0f; + } + + return 0; +} + + +/* + * Color conversion + */ + +static int getYUVtoRGBMatrix(float *matrix, LogImageElement logElement) +{ + float scaleY, scaleCbCr; + float refHighData = (float)logElement.refHighData / logElement.maxValue; + float refLowData = (float)logElement.refLowData / logElement.maxValue; + + scaleY = 1.0f / (refHighData - refLowData); + scaleCbCr = scaleY * ((940.0f - 64.0f) / (960.0f - 64.0f)); + + switch (logElement.transfer) { + case 2: /* linear */ + matrix[0] = 1.0f * scaleY; + matrix[1] = 1.0f * scaleCbCr; + matrix[2] = 1.0f * scaleCbCr; + matrix[3] = 1.0f * scaleY; + matrix[4] = 1.0f * scaleCbCr; + matrix[5] = 1.0f * scaleCbCr; + matrix[6] = 1.0f * scaleY; + matrix[7] = 1.0f * scaleCbCr; + matrix[8] = 1.0f * scaleCbCr; + return 0; + + case 5: /* SMPTE 240M */ + matrix[0] = 1.0000f * scaleY; + matrix[1] = 0.0000f * scaleCbCr; + matrix[2] = 1.5756f * scaleCbCr; + matrix[3] = 1.0000f * scaleY; + matrix[4] = -0.2253f * scaleCbCr; + matrix[5] = -0.5000f * scaleCbCr; + matrix[6] = 1.0000f * scaleY; + matrix[7] = 1.8270f * scaleCbCr; + matrix[8] = 0.0000f * scaleCbCr; + return 0; + + case 6: /* CCIR 709-1 */ + matrix[0] = 1.000000f * scaleY; + matrix[1] = 0.000000f * scaleCbCr; + matrix[2] = 1.574800f * scaleCbCr; + matrix[3] = 1.000000f * scaleY; + matrix[4] = -0.187324f * scaleCbCr; + matrix[5] = -0.468124f * scaleCbCr; + matrix[6] = 1.000000f * scaleY; + matrix[7] = 1.855600f * scaleCbCr; + matrix[8] = 0.000000f * scaleCbCr; + return 0; + + case 7: /* CCIR 601 */ + case 8: /* I'm not sure 7 and 8 should share the same matrix */ + matrix[0] = 1.000000f * scaleY; + matrix[1] = 0.000000f * scaleCbCr; + matrix[2] = 1.402000f * scaleCbCr; + matrix[3] = 1.000000f * scaleY; + matrix[4] = -0.344136f * scaleCbCr; + matrix[5] = -0.714136f * scaleCbCr; + matrix[6] = 1.000000f * scaleY; + matrix[7] = 1.772000f * scaleCbCr; + matrix[8] = 0.000000f * scaleCbCr; + return 0; + + default: + return 1; + } +} + +static void getLinToLogLut(float *lut, LogImageFile *logImage, LogImageElement logElement) +{ + float gain, negativeFilmGamma, offset, step; + unsigned int i; + + negativeFilmGamma = 0.6; + step = logElement.refHighQuantity / logElement.maxValue; + gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f)); + offset = gain - logElement.maxValue; + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) + lut[i] = (logImage->referenceWhite + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / (step / negativeFilmGamma)) / logElement.maxValue; +} + +static void getLogToLinLut(float *lut, LogImageFile *logImage, LogImageElement logElement) +{ + float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip; + /* float filmGamma; unused */ + unsigned int i; + + /* Building the Log -> Lin LUT */ + step = logElement.refHighQuantity / logElement.maxValue; + negativeFilmGamma = 0.6; + + /* these are default values */ + /* filmGamma = 2.2f; unused */ + softClip = 0; + + breakPoint = logImage->referenceWhite - softClip; + gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f)); + offset = gain - logElement.maxValue; + kneeOffset = powf(10, (breakPoint - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset; + kneeGain = (logElement.maxValue - kneeOffset) / powf(5 * softClip, softClip / 100); + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) { + if (i < logImage->referenceBlack) + lut[i] = 0.0f; + else if (i > breakPoint) + lut[i] = (powf(i - breakPoint, softClip / 100) * kneeGain + kneeOffset) / logElement.maxValue; + else + lut[i] = (powf(10, ((float)i - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset) / logElement.maxValue; + } +} + +static void getLinToSrgbLut(float *lut, LogImageElement logElement) +{ + unsigned int i; + float col; + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) { + col = (float)i / logElement.maxValue; + if (col < 0.0031308f) + lut[i] = (col < 0.0f) ? 0.0f : col * 12.92f; + else + lut[i] = 1.055f * powf(col, 1.0f / 2.4f) - 0.055f; + } +} + +static void getSrgbToLinLut(float *lut, LogImageElement logElement) +{ + unsigned int i; + float col; + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) { + col = (float)i / logElement.maxValue; + if (col < 0.04045f) + lut[i] = (col < 0.0f) ? 0.0f : col * (1.0f / 12.92f); + else + lut[i] = powf((col + 0.055f) * (1.0f / 1.055f), 2.4f); + } +} + +static int convertRGBA_RGB(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + src_ptr++; + } + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + src_ptr++; + } + return 0; + + default: + return 1; + } +} + +static int convertRGB_RGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = 1.0f; + } + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = 1.0f; + } + return 0; + + default: + return 1; + } +} + +static int convertRGBA_RGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + memcpy(dst, src, 4 * logImage->width * logImage->height * sizeof(float)); + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = *(src_ptr++); + } + return 0; + + default: + return 1; + } +} + +static int convertABGR_RGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + for (i = 0; i < logImage->width * logImage->height; i++) { + src_ptr += 4; + *(dst_ptr++) = *(src_ptr--); + *(dst_ptr++) = *(src_ptr--); + *(dst_ptr++) = *(src_ptr--); + *(dst_ptr++) = *(src_ptr--); + src_ptr += 4; + } + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + src_ptr += 4; + *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)]; + *(dst_ptr++) = *(src_ptr--); + src_ptr += 4; + } + return 0; + + default: + return 1; + } +} + +static int convertCbYCr_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y, cb, cr; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + cb = *(src_ptr++) - 0.5f; + y = *(src_ptr++) - refLowData; + cr = *(src_ptr++) - 0.5f; + + *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = 1.0f; + } + return 0; +} + +static int convertCbYCrA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y, cb, cr, a; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + cb = *(src_ptr++) - 0.5f; + y = *(src_ptr++) - refLowData; + cr = *(src_ptr++) - 0.5f; + a = *(src_ptr++); + + *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = a; + } + return 0; +} + +static int convertCbYCrY_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y1, y2, cb, cr; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height / 2; i++) { + cb = *(src_ptr++) - 0.5f; + y1 = *(src_ptr++) - refLowData; + cr = *(src_ptr++) - 0.5f; + y2 = *(src_ptr++) - refLowData; + + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = 1.0f; + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = 1.0f; + } + return 0; +} + +static int convertCbYACrYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y1, y2, cb, cr, a1, a2; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height / 2; i++) { + cb = *(src_ptr++) - 0.5f; + y1 = *(src_ptr++) - refLowData; + a1 = *(src_ptr++); + cr = *(src_ptr++) - 0.5f; + y2 = *(src_ptr++) - refLowData; + a2 = *(src_ptr++); + + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = a1; + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = a2; + } + return 0; +} + +static int convertLuminance_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], value, refLowData; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f); + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = 1.0f; + } + return 0; +} + +static int convertYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], value, refLowData; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f); + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = *(src_ptr++); + } + return 0; +} + +static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int dstIsLinearRGB) +{ + int rvalue; + unsigned int i; + float *src_ptr; + float *dst_ptr; + float lut[65536]; + + /* Convert data in src to linear RGBA in dst */ + switch (logElement.descriptor) { + case descriptor_RGB: + rvalue = convertRGB_RGBA(src, dst, logImage, logElement, 1); + break; + + case descriptor_RGBA: + rvalue = convertRGBA_RGBA(src, dst, logImage, logElement, 1); + break; + + case descriptor_ABGR: + rvalue = convertABGR_RGBA(src, dst, logImage, logElement, 1); + break; + + case descriptor_Luminance: + rvalue = convertLuminance_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYCr: + rvalue = convertCbYCr_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYCrY: + rvalue = convertCbYCrY_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYACrYA: + rvalue = convertCbYACrYA_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYCrA: + rvalue = convertCbYCrA_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_YA: /* this descriptor is for internal use only */ + rvalue = convertYA_RGBA(src, dst, logImage, logElement); + break; + + default: + return 1; + } + + if (rvalue == 1) + return 1; + else if (dstIsLinearRGB) { + /* convert data from sRGB to Linear RGB via lut */ + getSrgbToLinLut((float *)&lut, logElement); + src_ptr = dst; // no error here + dst_ptr = dst; + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + dst_ptr++; src_ptr++; + } + } + return 0; +} + +static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int srcIsLinearRGB) +{ + unsigned int i; + int rvalue; + float *srgbSrc; + float *srgbSrc_ptr; + float *src_ptr = src; + float lut[65536]; + + if (srcIsLinearRGB != 0) { + /* we need to convert src to sRGB */ + srgbSrc = (float *)MEM_mallocN(4 * logImage->width * logImage->height * sizeof(float), __func__); + if (srgbSrc == 0) + return 1; + + memcpy(srgbSrc, src, 4 * logImage->width * logImage->height * sizeof(float)); + srgbSrc_ptr = srgbSrc; + + /* convert data from Linear RGB to sRGB via lut */ + getLinToSrgbLut((float *)&lut, logElement); + for (i = 0; i < logImage->width * logImage->height; i++) { + *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + srgbSrc_ptr++; src_ptr++; + } + } + else + srgbSrc = src; + + /* Convert linear RGBA data in src to format described by logElement in dst */ + switch (logElement.descriptor) { + case descriptor_RGB: + rvalue = convertRGBA_RGB(srgbSrc, dst, logImage, logElement, 0); + break; + + case descriptor_RGBA: + rvalue = convertRGBA_RGBA(srgbSrc, dst, logImage, logElement, 0); + break; + + /* these ones are not supported for the moment */ + case descriptor_ABGR: + case descriptor_Luminance: + case descriptor_CbYCr: + case descriptor_CbYCrY: + case descriptor_CbYACrYA: + case descriptor_CbYCrA: + case descriptor_YA: /* this descriptor is for internal use only */ + default: + rvalue = 1; + } + + if (srcIsLinearRGB != 0) { + MEM_freeN(srgbSrc); + } + + return rvalue; +} diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h index 7d88c10c2d6..7c75f8b730b 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -1,123 +1,283 @@ /* - * Cineon image file format library definitions. - * Cineon and DPX common structures. + * Cineon image file format library definitions. + * Cineon and DPX common structures. * - * This header file contains private details. - * User code should generally use cineonlib.h and dpxlib.h only. - * Hmm. I thought the two formats would have more in common! + * This header file contains private details. + * User code should generally use cineonlib.h and dpxlib.h only. + * Hmm. I thought the two formats would have more in common! * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> + * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ -#ifndef __LOGIMAGECORE_H__ -#define __LOGIMAGECORE_H__ - /** \file blender/imbuf/intern/cineon/logImageCore.h * \ingroup imbcineon */ +#ifndef __LOG_IMAGE_CORE_H__ +#define __LOG_IMAGE_CORE_H__ + #include <stdio.h> -#include "logImageLib.h" + +#include "BLO_sys_types.h" +#include "BLI_utildefines.h" #ifdef __cplusplus extern "C" { #endif -#include "BLO_sys_types.h" // for intptr_t support +/* + * Image structure + */ -#ifdef _MSC_VER -#undef ntohl -#undef htonl -#endif +/* There are some differences between DPX and Cineon so we need to know from what type of file the datas come from */ +enum format { + format_DPX, + format_Cineon +}; -typedef int (GetRowFn)(LogImageFile* logImage, unsigned short* row, int lineNum); -typedef int (SetRowFn)(LogImageFile* logImage, const unsigned short* row, int lineNum); -typedef void (CloseFn)(LogImageFile* logImage); +typedef struct LogImageElement +{ + int depth; + int bitsPerSample; + int dataOffset; + int packing; + int transfer; + int descriptor; + unsigned int refLowData; + unsigned int refHighData; + float refLowQuantity; + float refHighQuantity; + float maxValue; /* = 2^bitsPerSample - 1 (used internally, doesn't come from the file header) */ +} LogImageElement; -struct _Log_Image_File_t_ +typedef struct LogImageFile { /* specified in header */ int width; int height; + int numElements; int depth; - int bitsPerPixel; - int imageOffset; + LogImageElement element[8]; - /* file buffer, measured in longwords (4 byte) */ - int lineBufferLength; - unsigned int* lineBuffer; - - /* pixel buffer, holds 10 bit pixel values */ - unsigned short* pixelBuffer; - int pixelBufferUsed; + /* used for log <-> lin conversion */ + float referenceBlack; + float referenceWhite; + float gamma; /* io stuff */ - FILE* file; - int reading; - int fileYPos; + FILE *file; + unsigned char *memBuffer; + uintptr_t memBufferSize; + unsigned char *memCursor; - /* byte conversion stuff */ - LogImageByteConversionParameters params; -#if 0 - float gamma; - int blackPoint; - int whitePoint; -#endif - unsigned char lut10[1024]; - unsigned short lut8[256]; - - unsigned short lut10_16[1024]; - unsigned short lut16_16[65536]; - - /* pixel access functions */ - GetRowFn* getRow; - SetRowFn* setRow; - CloseFn* close; - - unsigned char *membuffer; - uintptr_t membuffersize; - unsigned char *memcursor; + /* is the file LSB or MSB ? */ + int isMSB; + + /* DPX or Cineon ? */ + int srcFormat; +} LogImageFile; + + +/* The SMPTE defines this code: + * 0 - User-defined + * 1 - Printing density + * 2 - Linear + * 3 - Logarithmic + * 4 - Unspecified video + * 5 - SMPTE 240M + * 6 - CCIR 709-1 + * 7 - CCIR 601-2 system B or G + * 8 - CCIR 601-2 system M + * 9 - NTSC composite video + * 10 - PAL composite video + * 11 - Z linear + * 12 - homogeneous + * + * Note that transfer_characteristics is U8, don't need + * check the byte order. + */ + +enum transfer { + transfer_UserDefined, + transfer_PrintingDensity, + transfer_Linear, + transfer_Logarithmic, + transfer_Unspecified, + transfer_Smpte240M, + transfer_Ccir7091, + transfer_Ccir6012BG, + transfer_Ccir6012M, + transfer_NTSC, + transfer_PAL, + transfer_ZLinear, + transfer_Homogeneous +}; + +/* The SMPTE defines this code: + * 0 - User-defined + * 1 - Red + * 2 - Green + * 3 - Blue + * 4 - Alpha + * 6 - Luminance + * 7 - Chrominance + * 8 - Depth + * 9 - Composite video + * 50 - RGB + * 51 - RGBA + * 52 - ABGR + * 100 - CbYCrY + * 101 - CbYACrYA + * 102 - CbYCr + * 103 - CbYCrA + * 150 - User-defined 2-component element + * 151 - User-defined 3-component element + * 152 - User-defined 4-component element + * 153 - User-defined 5-component element + * 154 - User-defined 6-component element + * 155 - User-defined 7-component element + * 156 - User-defined 8-component element + */ + +enum descriptor { + descriptor_UserDefined, + descriptor_Red, + descriptor_Green, + descriptor_Blue, + descriptor_Alpha, + descriptor_Luminance = 6, /* don't ask me why there's no 5 */ + descriptor_Chrominance, + descriptor_Depth, + descriptor_Composite, + descriptor_RGB = 50, + descriptor_RGBA, + descriptor_ABGR, + descriptor_CbYCrY = 100, + descriptor_CbYACrYA, + descriptor_CbYCr, + descriptor_CbYCrA, + descriptor_UserDefined2Elt = 150, + descriptor_UserDefined3Elt, + descriptor_UserDefined4Elt, + descriptor_UserDefined5Elt, + descriptor_UserDefined6Elt, + descriptor_UserDefined7Elt, + descriptor_UserDefined8Elt, + /* following descriptors are for internal use only */ + descriptor_YA }; -void setupLut(LogImageFile*); -void setupLut16(LogImageFile*); +/* int functions return 0 for OK */ -int pixelsToLongs(int numPixels); +void logImageSetVerbose(int verbosity); +int logImageIsDpx(const void *buffer); +int logImageIsCineon(const void *buffer); +LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size); +LogImageFile *logImageOpenFromFile(const char *filename, int cineon); +void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth); +LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample, + int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack, + float gamma, const char *creator); +void logImageClose(LogImageFile *logImage); -/* typedefs used in original docs */ -/* note size assumptions! */ +/* Data handling */ +unsigned int getRowLength(int width, LogImageElement logElement); +int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB); +int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB); -typedef unsigned int U32; -typedef unsigned short U16; -typedef unsigned char U8; -typedef signed int S32; -typedef float R32; -typedef char ASCII; +/* + * Inline routines + */ + +/* Endianness swapping */ + +BLI_INLINE unsigned short swap_ushort(unsigned short x, int swap) +{ + if (swap != 0) + return (x >> 8) | (x << 8); + else + return x; +} + +BLI_INLINE unsigned int swap_uint(unsigned int x, int swap) +{ + if (swap != 0) + return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24); + else + return x; +} + +BLI_INLINE float swap_float(float x, int swap) +{ + if (swap != 0) { + union { + float f; + unsigned char b[4]; + } dat1, dat2; + + dat1.f = x; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; + } + else + return x; +} + +/* Other */ + +BLI_INLINE unsigned int clamp_uint(unsigned int x, unsigned int low, unsigned int high) +{ + if (x > high) + return high; + else if (x < low) + return low; + else + return x; +} + +BLI_INLINE float clamp_float(float x, float low, float high) +{ + if (x > high) + return high; + else if (x < low) + return low; + else + return x; +} + +BLI_INLINE unsigned int float_uint(float value, unsigned int max) +{ + if (value < 0.0f) + return 0; + else if (value > (1.0f - 0.5f / (float)max)) + return max; + else + return (unsigned int)(((float)max * value) + 0.5f); +} -R32 htonf(R32 f); -R32 ntohf(R32 f); -R32 undefined(void); -U16 reverseU16(U16 value); -U32 reverseU32(U32 value); -R32 reverseR32(R32 value); #ifdef __cplusplus } #endif -#endif /* __LOGIMAGECORE_H__ */ +#endif /* __LOG_IMAGE_CORE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/logImageLib.c b/source/blender/imbuf/intern/cineon/logImageLib.c deleted file mode 100644 index ccc6045e6e5..00000000000 --- a/source/blender/imbuf/intern/cineon/logImageLib.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Cineon and DPX image file format library routines. - * - * Copyright 1999 - 2002 David Hodson <hodsond@acm.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/** \file blender/imbuf/intern/cineon/logImageLib.c - * \ingroup imbcineon - */ - -#include "cineonlib.h" -#include "dpxlib.h" - -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <time.h> /* strftime() */ -#include <sys/types.h> -#ifdef WIN32 -#include <winsock.h> -#else -#include <netinet/in.h> /* htonl() */ -#endif -#include <string.h> /* memset */ -#include "BLI_fileops.h" - -#define MIN_GAMMA 0.01 -#define MAX_GAMMA 99.9 -#define DEFAULT_GAMMA 1.0 -#define DEFAULT_BLACK_POINT 95 -#define DEFAULT_WHITE_POINT 685 - -void -logImageSetVerbose(int verbosity) -{ - cineonSetVerbose(verbosity); - dpxSetVerbose(verbosity); -} - -LogImageFile* -logImageOpen(const char* filename, int cineon) -{ - if (cineon) { - return cineonOpen(filename); - } - else { - return dpxOpen(filename); - } - return 0; -} - -LogImageFile* -logImageOpenFromMem(unsigned char *buffer, unsigned int size, int cineon) -{ - if (cineon) { - return cineonOpenFromMem(buffer, size); - } - else { - return dpxOpenFromMem(buffer, size); - } - return 0; -} - -LogImageFile* -logImageCreate(const char* filename, int cineon, int width, int height, int depth) -{ - if (cineon) { - return cineonCreate(filename, width, height, depth); - } - else { - return dpxCreate(filename, width, height, depth); - } - return 0; -} - -int -logImageGetSize(const LogImageFile* logImage, int* width, int* height, int* depth) -{ - *width = logImage->width; - *height = logImage->height; - *depth = logImage->depth; - return 0; -} - -int -logImageGetByteConversionDefaults(LogImageByteConversionParameters* params) -{ - params->gamma = DEFAULT_GAMMA; - params->blackPoint = DEFAULT_BLACK_POINT; - params->whitePoint = DEFAULT_WHITE_POINT; - params->doLogarithm = 0; - return 0; -} - -int -logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionParameters* params) -{ - params->gamma = logImage->params.gamma; - params->blackPoint = logImage->params.blackPoint; - params->whitePoint = logImage->params.whitePoint; - params->doLogarithm = 0; - return 0; -} - -int -logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionParameters* params) -{ - if ((params->gamma >= MIN_GAMMA) && - (params->gamma <= MAX_GAMMA) && - (params->blackPoint >= 0) && - (params->blackPoint < params->whitePoint) && - (params->whitePoint <= 1023)) - { - logImage->params.gamma = params->gamma; - logImage->params.blackPoint = params->blackPoint; - logImage->params.whitePoint = params->whitePoint; - logImage->params.doLogarithm = params->doLogarithm; - setupLut16(logImage); - return 0; - } - return 1; -} - -int -logImageGetRowBytes(LogImageFile* logImage, unsigned short* row, int y) -{ - return logImage->getRow(logImage, row, y); -} - -int -logImageSetRowBytes(LogImageFile* logImage, const unsigned short* row, int y) -{ - return logImage->setRow(logImage, row, y); -} - -void -logImageClose(LogImageFile* logImage) -{ - logImage->close(logImage); -} - -void -logImageDump(const char* filename) -{ - - U32 magic; - - FILE* foo = BLI_fopen(filename, "rb"); - if (foo == 0) { - return; - } - - if (fread(&magic, sizeof(magic), 1, foo) == 0) { - fclose(foo); - return; - } - - fclose(foo); - - if (magic == ntohl(CINEON_FILE_MAGIC)) { -#if 0 - cineonDump(filename); -#endif - } - else if (magic == ntohl(DPX_FILE_MAGIC)) { - dpxDump(filename); - } -} diff --git a/source/blender/imbuf/intern/cineon/logImageLib.h b/source/blender/imbuf/intern/cineon/logImageLib.h index 1c24358e4ef..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/logImageLib.h +++ b/source/blender/imbuf/intern/cineon/logImageLib.h @@ -1,87 +0,0 @@ -/* - * Common library definitions for Cineon and DPX image files. - * - * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef __LOGIMAGELIB_H__ -#define __LOGIMAGELIB_H__ - -/** \file blender/imbuf/intern/cineon/logImageLib.h - * \ingroup imbcineon - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Image structure. You don't care what this is. - */ - -typedef struct _Log_Image_File_t_ LogImageFile; - -/* - * Magic numbers for normal and byte-swapped Cineon and Dpx files - */ - -#define CINEON_FILE_MAGIC 0x802A5FD7 -#define DPX_FILE_MAGIC 0x53445058 - -/* - * Image 8 bit <-> 10 bit conversion parameters. - */ - -typedef struct { - float gamma; - int blackPoint; - int whitePoint; - int doLogarithm; -} LogImageByteConversionParameters; - -/* int functions return 0 for OK */ - -void logImageSetVerbose(int); - -LogImageFile* logImageOpenFromMem(unsigned char *buffer, unsigned int size, int cineon); -LogImageFile* logImageOpen(const char* filename, int cineon); -int logImageGetSize(const LogImageFile* logImage, int* xsize, int* ysize, int* channels); -LogImageFile* logImageCreate(const char* filename, int cineon, int xsize, int ysize, int channels); - -/* byte conversion routines for mapping logImage (usually) 10 bit values to 8 bit */ -/* see Kodak docs for details... */ - -int logImageGetByteConversionDefaults(LogImageByteConversionParameters* params); -int logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionParameters* params); -int logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionParameters* params); - -/* get/set scanline of converted bytes */ -int logImageGetRowBytes(LogImageFile* logImage, unsigned short* row, int y); -int logImageSetRowBytes(LogImageFile* logImage, const unsigned short* row, int y); - -/* closes file and deletes data */ -void logImageClose(LogImageFile* logImage); - -/* read file and dump header info */ -void logImageDump(const char* filename); - -#ifdef __cplusplus -} -#endif - -#endif /* __LOGIMAGELIB_H__ */ diff --git a/source/blender/imbuf/intern/cineon/logmemfile.c b/source/blender/imbuf/intern/cineon/logmemfile.c index a9938582f2a..3914f6dc633 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.c +++ b/source/blender/imbuf/intern/cineon/logmemfile.c @@ -1,21 +1,23 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 2006 Joseph Eagar (joeedh@gmail.com) + * Copyright 2006 Joseph Eagar (joeedh@gmail.com) * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ @@ -23,64 +25,102 @@ * \ingroup imbcineon */ + #include <stdio.h> #include <stdlib.h> #include <string.h> #include "logImageCore.h" +#include "logmemfile.h" -#include "logmemfile.h" /* own include */ - -int logimage_fseek(void* logfile, intptr_t offsett, int origin) -{ - struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - intptr_t offset = offsett; - - if (file->file) fseek(file->file, offset, origin); - else { /*we're seeking in memory*/ - if (origin==SEEK_SET) { - if (offset > file->membuffersize) return 1; - file->memcursor = file->membuffer + offset; +int logimage_fseek(LogImageFile *logFile, intptr_t offset, int origin) +{ + if (logFile->file) + fseek(logFile->file, offset, origin); + else { /* we're seeking in memory */ + if (origin == SEEK_SET) { + if (offset > logFile->memBufferSize) + return 1; + logFile->memCursor = logFile->memBuffer + offset; } - else if (origin==SEEK_END) { - if (offset > file->membuffersize) return 1; - file->memcursor = (file->membuffer + file->membuffersize) - offset; + else if (origin == SEEK_END) { + if (offset > logFile->memBufferSize) + return 1; + logFile->memCursor = (logFile->memBuffer + logFile->memBufferSize) - offset; } - else if (origin==SEEK_CUR) { - uintptr_t pos = (uintptr_t)file->membuffer - (uintptr_t)file->memcursor; - if (pos + offset > file->membuffersize) return 1; - if (pos < 0) return 1; - file->memcursor += offset; + else if (origin == SEEK_CUR) { + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + offset > logFile->memBufferSize || pos < 0) + return 1; + + logFile->memCursor += offset; } } return 0; } -int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile) +int logimage_fwrite(void *buffer, size_t size, unsigned int count, LogImageFile *logFile) { - struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - if (file->file) return fwrite(buffer, size, count, file->file); - else { /*we're writing to memory*/ - /*do nothing as this isn't supported yet*/ + if (logFile->file) + return fwrite(buffer, size, count, logFile->file); + else { /* we're writing to memory */ + /* do nothing as this isn't supported yet */ return count; } } -int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile) +int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile) { - struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - if (file->file) return fread(buffer, size, count, file->file); - else { /*we're reading from memory*/ - int i; - /* we convert ot uchar just on the off chance some platform can't handle - * pointer arithmetic with type (void*). */ - unsigned char *buf = (unsigned char *) buffer; - - for (i=0; i<count; i++) { - memcpy(buf, file->memcursor, size); - file->memcursor += size; - buf += size; + if (logFile->file) { + return fread(buffer, size, count, logFile->file); + } + else { /* we're reading from memory */ + unsigned char *buf = (unsigned char *)buffer; + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + size_t total_size = size * count; + if (pos + total_size > logFile->memBufferSize) { + /* how many elements can we read without overflow ? */ + count = (logFile->memBufferSize - pos) / size; + /* recompute the size */ + total_size = size * count; } + + if (total_size != 0) + memcpy(buf, logFile->memCursor, total_size); + return count; } } + +int logimage_read_uchar(unsigned char *x, LogImageFile *logFile) +{ + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + sizeof(unsigned char) > logFile->memBufferSize) + return 1; + + *x = *(unsigned char *)logFile->memCursor; + logFile->memCursor += sizeof(unsigned char); + return 0; +} + +int logimage_read_ushort(unsigned short *x, LogImageFile *logFile) +{ + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + sizeof(unsigned short) > logFile->memBufferSize) + return 1; + + *x = *(unsigned short *)logFile->memCursor; + logFile->memCursor += sizeof(unsigned short); + return 0; +} + +int logimage_read_uint(unsigned int *x, LogImageFile *logFile) +{ + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + sizeof(unsigned int) > logFile->memBufferSize) + return 1; + + *x = *(unsigned int *)logFile->memCursor; + logFile->memCursor += sizeof(unsigned int); + return 0; +} diff --git a/source/blender/imbuf/intern/cineon/logmemfile.h b/source/blender/imbuf/intern/cineon/logmemfile.h index df3589a70d3..068a53e641b 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.h +++ b/source/blender/imbuf/intern/cineon/logmemfile.h @@ -1,33 +1,43 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 2006 Joseph Eagar (joeedh@gmail.com) + * Copyright 2006 Joseph Eagar (joeedh@gmail.com) * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Julien Enche. * */ - -#ifndef __LOGMEMFILE_H__ -#define __LOGMEMFILE_H__ /** \file blender/imbuf/intern/cineon/logmemfile.h * \ingroup imbcineon */ -int logimage_fseek(void* logfile, intptr_t offsett, int origin); -int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile); -int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile); -#endif /* __LOGMEMFILE_H__ */ +#ifndef __LOGMEMFILE_H__ +#define __LOGMEMFILE_H__ + +#include "logImageCore.h" + +#include <stdlib.h> + +int logimage_fseek(LogImageFile *logFile, intptr_t offset, int origin); +int logimage_fwrite(void *buffer, size_t size, unsigned int count, LogImageFile *logFile); +int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile); +int logimage_read_uchar(unsigned char *x, LogImageFile *logFile); +int logimage_read_ushort(unsigned short *x, LogImageFile *logFile); +int logimage_read_uint(unsigned int *x, LogImageFile *logFile); + +#endif /* __LOGMEMFILE_H__ */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 37510c10e9a..b9774a9f7b0 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -99,6 +99,7 @@ static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER; typedef struct ColormanageProcessor { OCIO_ConstProcessorRcPtr *processor; CurveMapping *curve_mapping; + int is_data_result; } ColormanageProcessor; /*********************** Color managed cache *************************/ @@ -889,7 +890,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); - if (colorspace->is_data) { + if (colorspace && colorspace->is_data) { ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; return; } @@ -1082,7 +1083,7 @@ void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) { ColorSpace *colorspace = colormanage_colorspace_get_named(name); - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1094,7 +1095,7 @@ void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) ibuf->float_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1106,7 +1107,7 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) ibuf->rect_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1207,6 +1208,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) int predivide = handle->predivide; int is_data = handle->is_data; + int is_data_display = handle->cm_processor->is_data_result; linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); @@ -1223,12 +1225,12 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) /* first convert byte buffer to float, keep in image space */ for (i = 0, fp = linear_buffer, cp = byte_buffer; i < channels * width * height; - i++, fp++, cp++) + i++, fp++, cp++) { *fp = (float)(*cp) / 255.0f; } - if (!is_data) { + if (!is_data && !is_data_display) { /* convert float buffer to scene linear space */ IMB_colormanagement_transform(linear_buffer, width, height, channels, from_colorspace, to_colorspace, predivide); @@ -1822,7 +1824,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet if (global_tot_display) ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags"); } - else if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { + else if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { /* all display buffers were marked as invalid from other areas, * now propagate this flag to internal color management routines */ @@ -2347,7 +2349,6 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe } else if (byte_buffer) { rgba_uchar_to_float(pixel, byte_buffer + linear_index); - IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); } @@ -2382,9 +2383,9 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax) + int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer) { - if (ibuf->rect && ibuf->rect_float) { + if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { /* update byte buffer created by legacy color management */ unsigned char *rect = (unsigned char *) ibuf->rect; @@ -2449,28 +2450,29 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag const ColorManagedDisplaySettings *display_settings) { ColormanageProcessor *cm_processor; + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; + ColorSpace *display_space; cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); - { - ColorManagedViewSettings default_view_settings; - const ColorManagedViewSettings *applied_view_settings; + if (view_settings) { + applied_view_settings = view_settings; + } + else { + init_default_view_settings(display_settings, &default_view_settings); + applied_view_settings = &default_view_settings; + } - if (view_settings) { - applied_view_settings = view_settings; - } - else { - init_default_view_settings(display_settings, &default_view_settings); - applied_view_settings = &default_view_settings; - } + display_space = display_transform_get_colorspace(applied_view_settings, display_settings); + cm_processor->is_data_result = display_space->is_data; - cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, - applied_view_settings->exposure, applied_view_settings->gamma); + cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, + applied_view_settings->exposure, applied_view_settings->gamma); - if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { - cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); - curvemapping_premultiply(cm_processor->curve_mapping, FALSE); - } + if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { + cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); + curvemapping_premultiply(cm_processor->curve_mapping, FALSE); } return cm_processor; @@ -2479,9 +2481,13 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace) { ColormanageProcessor *cm_processor; + ColorSpace *color_space; cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); + color_space = colormanage_colorspace_get_named(to_colorspace); + cm_processor->is_data_result = color_space->is_data; + cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); return cm_processor; diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index f5e9e536e41..db2ca5969ec 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -232,7 +232,7 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const uint idx = (row[j] >> (2 * i)) & 3; block->color(i, j) = color_array[idx]; } - } + } } void BlockDXT1::decodeBlockNV5x(ColorBlock * block) const @@ -592,7 +592,7 @@ void BlockCTX1::decodeBlock(ColorBlock * block) const uint idx = (row[j] >> (2 * i)) & 3; block->color(i, j) = color_array[idx]; } - } + } } void BlockCTX1::setIndices(int * idx) diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index c6712f4f058..0291816cd03 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -173,24 +173,24 @@ struct AlphaBlockDXT5 }; */ uint64 u; - uint8 alpha0() const { return u & 0xffLL; }; - uint8 alpha1() const { return (u >> 8) & 0xffLL; }; - uint8 bits0() const { return (u >> 16) & 0x7LL; }; - uint8 bits1() const { return (u >> 19) & 0x7LL; }; - uint8 bits2() const { return (u >> 22) & 0x7LL; }; - uint8 bits3() const { return (u >> 25) & 0x7LL; }; - uint8 bits4() const { return (u >> 28) & 0x7LL; }; - uint8 bits5() const { return (u >> 31) & 0x7LL; }; - uint8 bits6() const { return (u >> 34) & 0x7LL; }; - uint8 bits7() const { return (u >> 37) & 0x7LL; }; - uint8 bits8() const { return (u >> 40) & 0x7LL; }; - uint8 bits9() const { return (u >> 43) & 0x7LL; }; - uint8 bitsA() const { return (u >> 46) & 0x7LL; }; - uint8 bitsB() const { return (u >> 49) & 0x7LL; }; - uint8 bitsC() const { return (u >> 52) & 0x7LL; }; - uint8 bitsD() const { return (u >> 55) & 0x7LL; }; - uint8 bitsE() const { return (u >> 58) & 0x7LL; }; - uint8 bitsF() const { return (u >> 61) & 0x7LL; }; + uint8 alpha0() const { return u & 0xffLL; } + uint8 alpha1() const { return (u >> 8) & 0xffLL; } + uint8 bits0() const { return (u >> 16) & 0x7LL; } + uint8 bits1() const { return (u >> 19) & 0x7LL; } + uint8 bits2() const { return (u >> 22) & 0x7LL; } + uint8 bits3() const { return (u >> 25) & 0x7LL; } + uint8 bits4() const { return (u >> 28) & 0x7LL; } + uint8 bits5() const { return (u >> 31) & 0x7LL; } + uint8 bits6() const { return (u >> 34) & 0x7LL; } + uint8 bits7() const { return (u >> 37) & 0x7LL; } + uint8 bits8() const { return (u >> 40) & 0x7LL; } + uint8 bits9() const { return (u >> 43) & 0x7LL; } + uint8 bitsA() const { return (u >> 46) & 0x7LL; } + uint8 bitsB() const { return (u >> 49) & 0x7LL; } + uint8 bitsC() const { return (u >> 52) & 0x7LL; } + uint8 bitsD() const { return (u >> 55) & 0x7LL; } + uint8 bitsE() const { return (u >> 58) & 0x7LL; } + uint8 bitsF() const { return (u >> 61) & 0x7LL; } void evaluatePalette(uint8 alpha[8]) const; void evaluatePalette8(uint8 alpha[8]) const; @@ -271,4 +271,4 @@ void mem_read(Stream & mem, BlockATI1 & block); void mem_read(Stream & mem, BlockATI2 & block); void mem_read(Stream & mem, BlockCTX1 & block); -#endif // __BLOCKDXT_H__ +#endif /* __BLOCKDXT_H__ */ diff --git a/source/blender/imbuf/intern/dds/CMakeLists.txt b/source/blender/imbuf/intern/dds/CMakeLists.txt index e514b7ab6f9..57603725ce1 100644 --- a/source/blender/imbuf/intern/dds/CMakeLists.txt +++ b/source/blender/imbuf/intern/dds/CMakeLists.txt @@ -39,9 +39,21 @@ set(INC_SYS ) set(SRC + BlockDXT.h + Color.h + ColorBlock.h + Common.h + DirectDrawSurface.h + FlipDXT.h + Image.h + PixelFormat.h + Stream.h + dds_api.h + BlockDXT.cpp ColorBlock.cpp DirectDrawSurface.cpp + FlipDXT.cpp Image.cpp Stream.cpp dds_api.cpp @@ -51,4 +63,4 @@ if(WITH_IMAGE_DDS) add_definitions(-DWITH_DDS) endif() -blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}") +blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h index 17de0a596c6..6676057d710 100644 --- a/source/blender/imbuf/intern/dds/Color.h +++ b/source/blender/imbuf/intern/dds/Color.h @@ -96,4 +96,4 @@ public: }; }; -#endif // __COLOR_H__ +#endif /* __COLOR_H__ */ diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 0b9f5c163fb..dbd87bf1426 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -393,7 +393,7 @@ void ColorBlock::computeRange(Vector3::Arg axis, Color32 * start, Color32 * end) int mini, maxi; mini = maxi = 0; - float min, max; + float min, max; min = max = dot(Vector3(m_color[0].r, m_color[0].g, m_color[0].b), axis); for (uint i = 1; i < 16; i++) diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 2bf362f2780..f0864f06e6f 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -104,4 +104,4 @@ inline Color32 & ColorBlock::color(uint x, uint y) return m_color[y * 4 + x]; } -#endif // __COLORBLOCK_H__ +#endif /* __COLORBLOCK_H__ */ diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h index 4e3e3e024f7..ab929b82264 100644 --- a/source/blender/imbuf/intern/dds/Common.h +++ b/source/blender/imbuf/intern/dds/Common.h @@ -42,9 +42,9 @@ template<typename T> inline void swap(T & a, T & b) { - T tmp = a; - a = b; - b = tmp; + T tmp = a; + a = b; + b = tmp; } typedef unsigned char uint8; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index d9d0cb86ee0..ccf72f9af86 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -280,19 +280,19 @@ static const uint DDPF_SRGB = 0x40000000U; DXGI_FORMAT_B8G8R8A8_UNORM = 87, DXGI_FORMAT_B8G8R8X8_UNORM = 88, - DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, - DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, - DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, - DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, - - DXGI_FORMAT_BC6H_TYPELESS = 94, - DXGI_FORMAT_BC6H_UF16 = 95, - DXGI_FORMAT_BC6H_SF16 = 96, - - DXGI_FORMAT_BC7_TYPELESS = 97, - DXGI_FORMAT_BC7_UNORM = 98, - DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, }; enum D3D10_RESOURCE_DIMENSION @@ -496,60 +496,60 @@ void mem_read(Stream & mem, DDSHeader & header) namespace { - struct FormatDescriptor - { - uint format; - uint bitcount; - uint rmask; - uint gmask; - uint bmask; - uint amask; - }; - - static const FormatDescriptor s_d3dFormats[] = - { - { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 }, - { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM - { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM - { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM - { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 }, - { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM - { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 }, - { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 }, - { D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM - { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 }, - { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 }, - { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2 - { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM - { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 }, - { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM - { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 }, - { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, - - { D3DFMT_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM - { D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM - }; - - static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]); +struct FormatDescriptor +{ + uint format; + uint bitcount; + uint rmask; + uint gmask; + uint bmask; + uint amask; +}; + +static const FormatDescriptor s_d3dFormats[] = +{ + { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 }, + { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, /* DXGI_FORMAT_B8G8R8A8_UNORM */ + { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, /* DXGI_FORMAT_B8G8R8X8_UNORM */ + { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, /* DXGI_FORMAT_B5G6R5_UNORM */ + { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 }, + { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, /* DXGI_FORMAT_B5G5R5A1_UNORM */ + { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 }, + { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 }, + { D3DFMT_A8, 8, 0, 0, 0, 8 }, /* DXGI_FORMAT_A8_UNORM */ + { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 }, + { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 }, + { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, /* DXGI_FORMAT_R10G10B10A2 */ + { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, /* DXGI_FORMAT_R8G8B8A8_UNORM */ + { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 }, + { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, /* DXGI_FORMAT_R16G16_UNORM */ + { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 }, + { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, + + { D3DFMT_L8, 8, 8, 0, 0, 0 }, /* DXGI_FORMAT_R8_UNORM */ + { D3DFMT_L16, 16, 16, 0, 0, 0 }, /* DXGI_FORMAT_R16_UNORM */ +}; + +static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]); } // namespace static uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { - for (int i = 0; i < s_d3dFormatCount; i++) - { - if (s_d3dFormats[i].bitcount == bitcount && - s_d3dFormats[i].rmask == rmask && - s_d3dFormats[i].gmask == gmask && - s_d3dFormats[i].bmask == bmask && - s_d3dFormats[i].amask == amask) - { - return s_d3dFormats[i].format; - } - } + for (int i = 0; i < s_d3dFormatCount; i++) + { + if (s_d3dFormats[i].bitcount == bitcount && + s_d3dFormats[i].rmask == rmask && + s_d3dFormats[i].gmask == gmask && + s_d3dFormats[i].bmask == bmask && + s_d3dFormats[i].amask == amask) + { + return s_d3dFormats[i].format; + } + } - return 0; - } + return 0; +} @@ -566,7 +566,7 @@ DDSHeader::DDSHeader() for (uint i = 0; i < 11; i++) this->reserved[i] = 0; // Store version information on the reserved header attributes. - this->reserved[9] = FOURCC_NVTT; + this->reserved[9] = FOURCC_NVTT; this->reserved[10] = (2 << 16) | (1 << 8) | (0); // major.minor.revision this->pf.size = 32; @@ -613,7 +613,7 @@ void DDSHeader::setMipmapCount(uint count) if (count == 0 || count == 1) { this->flags &= ~DDSD_MIPMAPCOUNT; - this->mipmapcount = 1; + this->mipmapcount = 1; if (this->caps.caps2 == 0) { this->caps.caps1 = DDSCAPS_TEXTURE; @@ -715,14 +715,14 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask if (rmask != 0 || gmask != 0 || bmask != 0) { - if (gmask == 0 && bmask == 0) - { - this->pf.flags = DDPF_LUMINANCE; - } - else - { - this->pf.flags = DDPF_RGB; - } + if (gmask == 0 && bmask == 0) + { + this->pf.flags = DDPF_LUMINANCE; + } + else + { + this->pf.flags = DDPF_RGB; + } if (amask != 0) { this->pf.flags |= DDPF_ALPHAPIXELS; @@ -737,17 +737,17 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask { // Compute bit count from the masks. uint total = rmask | gmask | bmask | amask; - while(total != 0) { + while (total != 0) { bitcount++; total >>= 1; } } - // D3DX functions do not like this: + // D3DX functions do not like this: this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask); - /*if (this->pf.fourcc) { - this->pf.flags |= DDPF_FOURCC; - }*/ + /*if (this->pf.fourcc) { + this->pf.flags |= DDPF_FOURCC; + }*/ if (!(bitcount > 0 && bitcount <= 32)) { printf("DDS: bad bit count, pixel format not set\n"); @@ -775,8 +775,8 @@ void DDSHeader::setNormalFlag(bool b) void DDSHeader::setSrgbFlag(bool b) { - if (b) this->pf.flags |= DDPF_SRGB; - else this->pf.flags &= ~DDPF_SRGB; + if (b) this->pf.flags |= DDPF_SRGB; + else this->pf.flags &= ~DDPF_SRGB; } void DDSHeader::setHasAlphaFlag(bool b) @@ -787,8 +787,8 @@ void DDSHeader::setHasAlphaFlag(bool b) void DDSHeader::setUserVersion(int version) { - this->reserved[7] = FOURCC_UVER; - this->reserved[8] = version; + this->reserved[7] = FOURCC_UVER; + this->reserved[8] = version; } /* @@ -836,45 +836,45 @@ bool DDSHeader::hasDX10Header() const uint DDSHeader::signature() const { - return this->reserved[9]; + return this->reserved[9]; } uint DDSHeader::toolVersion() const { - return this->reserved[10]; + return this->reserved[10]; } uint DDSHeader::userVersion() const { - if (this->reserved[7] == FOURCC_UVER) { - return this->reserved[8]; - } - return 0; + if (this->reserved[7] == FOURCC_UVER) { + return this->reserved[8]; + } + return 0; } bool DDSHeader::isNormalMap() const { - return (pf.flags & DDPF_NORMAL) != 0; + return (pf.flags & DDPF_NORMAL) != 0; } bool DDSHeader::isSrgb() const { - return (pf.flags & DDPF_SRGB) != 0; + return (pf.flags & DDPF_SRGB) != 0; } bool DDSHeader::hasAlpha() const { - return (pf.flags & DDPF_ALPHAPIXELS) != 0; + return (pf.flags & DDPF_ALPHAPIXELS) != 0; } uint DDSHeader::d3d9Format() const { - if (pf.flags & DDPF_FOURCC) { - return pf.fourcc; - } - else { - return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask); - } + if (pf.flags & DDPF_FOURCC) { + return pf.fourcc; + } + else { + return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask); + } } DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() @@ -949,9 +949,9 @@ bool DirectDrawSurface::isSupported() const return false; } } - else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)) - { - // All RGB and luminance formats are supported now. + else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)) + { + // All RGB and luminance formats are supported now. } else { @@ -1001,7 +1001,7 @@ bool DirectDrawSurface::hasAlpha() const } else { - // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) + // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) return true; } } @@ -1089,7 +1089,7 @@ void DirectDrawSurface::setHasAlphaFlag(bool b) void DirectDrawSurface::setUserVersion(int version) { - header.setUserVersion(version); + header.setUserVersion(version); } void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) @@ -1268,15 +1268,15 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba) block.decodeBlock(rgba); } else if (fourcc == FOURCC_DXT2 || - header.pf.fourcc == FOURCC_DXT3) + header.pf.fourcc == FOURCC_DXT3) { BlockDXT3 block; mem_read(stream, block); block.decodeBlock(rgba); } else if (fourcc == FOURCC_DXT4 || - header.pf.fourcc == FOURCC_DXT5 || - header.pf.fourcc == FOURCC_RXGB) + header.pf.fourcc == FOURCC_DXT5 || + header.pf.fourcc == FOURCC_RXGB) { BlockDXT5 block; mem_read(stream, block); @@ -1393,8 +1393,8 @@ uint DirectDrawSurface::mipmapSize(uint mipmap) const } else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE)) { - uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects. - + uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects. + return pitch * h * d; } else { @@ -1461,7 +1461,7 @@ void DirectDrawSurface::printInfo() const printf("Pixel Format:\n"); printf("\tFlags: 0x%.8X\n", header.pf.flags); if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n"); - if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n"); + if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n"); if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n"); if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n"); if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n"); @@ -1472,24 +1472,24 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - if (header.pf.fourcc != 0) { - // Display fourcc code even when DDPF_FOURCC flag not set. - printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n", - ((header.pf.fourcc >> 0) & 0xFF), - ((header.pf.fourcc >> 8) & 0xFF), - ((header.pf.fourcc >> 16) & 0xFF), - ((header.pf.fourcc >> 24) & 0xFF), - header.pf.fourcc); - } - - if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0)) + if (header.pf.fourcc != 0) { + // Display fourcc code even when DDPF_FOURCC flag not set. + printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF), + header.pf.fourcc); + } + + if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0)) { - printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", - (header.pf.bitcount >> 0) & 0xFF, - (header.pf.bitcount >> 8) & 0xFF, - (header.pf.bitcount >> 16) & 0xFF, - (header.pf.bitcount >> 24) & 0xFF, - header.pf.bitcount); + printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF, + header.pf.bitcount); } else { @@ -1535,7 +1535,7 @@ void DirectDrawSurface::printInfo() const printf("\tArray size: %u\n", header.header10.arraySize); } - if (header.reserved[9] == FOURCC_NVTT) + if (header.reserved[9] == FOURCC_NVTT) { int major = (header.reserved[10] >> 16) & 0xFF; int minor = (header.reserved[10] >> 8) & 0xFF; @@ -1545,9 +1545,9 @@ void DirectDrawSurface::printInfo() const printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision); } - if (header.reserved[7] == FOURCC_UVER) - { - printf("User Version: %u\n", header.reserved[8]); - } + if (header.reserved[7] == FOURCC_UVER) + { + printf("User Version: %u\n", header.reserved[8]); + } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index a851533b1f3..72a524daba2 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -169,7 +169,7 @@ public: void setNormalFlag(bool b); void setHasAlphaFlag(bool b); - void setUserVersion(int version); + void setUserVersion(int version); void mipmap(Image * img, uint f, uint m); void* readData(uint &size); @@ -200,4 +200,4 @@ void mem_read(Stream & mem, DDSCaps & caps); void mem_read(Stream & mem, DDSHeader & header); void mem_read(Stream & mem, DDSHeader10 & header); -#endif // __DIRECTDRAWSURFACE_H__ +#endif /* __DIRECTDRAWSURFACE_H__ */ diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp new file mode 100644 index 00000000000..05821b27ca6 --- /dev/null +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -0,0 +1,255 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This file comes from the chromium project, adapted to Blender to add DDS +// flipping to OpenGL convention for Blender + +#include "IMB_imbuf_types.h" + +#include <string.h> + +#include <Common.h> +#include <Stream.h> +#include <ColorBlock.h> +#include <BlockDXT.h> +#include <FlipDXT.h> + +// A function that flips a DXTC block. +typedef void (*FlipBlockFunction)(uint8_t *block); + +// Flips a full DXT1 block in the y direction. +static void FlipDXT1BlockFull(uint8_t *block) +{ + // A DXT1 block layout is: + // [0-1] color0. + // [2-3] color1. + // [4-7] color bitmap, 2 bits per pixel. + // So each of the 4-7 bytes represents one line, flipping a block is just + // flipping those bytes. + uint8_t tmp = block[4]; + block[4] = block[7]; + block[7] = tmp; + tmp = block[5]; + block[5] = block[6]; + block[6] = tmp; +} + +// Flips the first 2 lines of a DXT1 block in the y direction. +static void FlipDXT1BlockHalf(uint8_t *block) +{ + // See layout above. + uint8_t tmp = block[4]; + block[4] = block[5]; + block[5] = tmp; +} + +// Flips a full DXT3 block in the y direction. +static void FlipDXT3BlockFull(uint8_t *block) +{ + // A DXT3 block layout is: + // [0-7] alpha bitmap, 4 bits per pixel. + // [8-15] a DXT1 block. + + // We can flip the alpha bits at the byte level (2 bytes per line). + uint8_t tmp = block[0]; + + block[0] = block[6]; + block[6] = tmp; + tmp = block[1]; + block[1] = block[7]; + block[7] = tmp; + tmp = block[2]; + block[2] = block[4]; + block[4] = tmp; + tmp = block[3]; + block[3] = block[5]; + block[5] = tmp; + + // And flip the DXT1 block using the above function. + FlipDXT1BlockFull(block + 8); +} + +// Flips the first 2 lines of a DXT3 block in the y direction. +static void FlipDXT3BlockHalf(uint8_t *block) +{ + // See layout above. + uint8_t tmp = block[0]; + + block[0] = block[2]; + block[2] = tmp; + tmp = block[1]; + block[1] = block[3]; + block[3] = tmp; + FlipDXT1BlockHalf(block + 8); +} + +// Flips a full DXT5 block in the y direction. +static void FlipDXT5BlockFull(uint8_t *block) +{ + // A DXT5 block layout is: + // [0] alpha0. + // [1] alpha1. + // [2-7] alpha bitmap, 3 bits per pixel. + // [8-15] a DXT1 block. + + // The alpha bitmap doesn't easily map lines to bytes, so we have to + // interpret it correctly. Extracted from + // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt : + // + // The 6 "bits" bytes of the block are decoded into one 48-bit integer: + // + // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 + + // 256 * (bits_4 + 256 * bits_5)))) + // + // bits is a 48-bit unsigned integer, from which a three-bit control code + // is extracted for a texel at location (x,y) in the block using: + // + // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0] + // + // where bit 47 is the most significant and bit 0 is the least + // significant bit. + unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); + unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); + // swap lines 0 and 1 in line_0_1. + unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | + ((line_0_1 & 0xfff000) >> 12); + // swap lines 2 and 3 in line_2_3. + unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | + ((line_2_3 & 0xfff000) >> 12); + + block[2] = line_3_2 & 0xff; + block[3] = (line_3_2 & 0xff00) >> 8; + block[4] = (line_3_2 & 0xff0000) >> 8; + block[5] = line_1_0 & 0xff; + block[6] = (line_1_0 & 0xff00) >> 8; + block[7] = (line_1_0 & 0xff0000) >> 8; + + // And flip the DXT1 block using the above function. + FlipDXT1BlockFull(block + 8); +} + +// Flips the first 2 lines of a DXT5 block in the y direction. +static void FlipDXT5BlockHalf(uint8_t *block) +{ + // See layout above. + unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); + unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | + ((line_0_1 & 0xfff000) >> 12); + block[2] = line_1_0 & 0xff; + block[3] = (line_1_0 & 0xff00) >> 8; + block[4] = (line_1_0 & 0xff0000) >> 8; + FlipDXT1BlockHalf(block + 8); +} + +// Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate. +int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data) +{ + // must have valid dimensions + if (width == 0 || height == 0) + return 0; + // height must be a power-of-two + if ((height & (height - 1)) != 0) + return 0; + + FlipBlockFunction full_block_function; + FlipBlockFunction half_block_function; + unsigned int block_bytes = 0; + + switch (fourcc) { + case FOURCC_DXT1: + full_block_function = FlipDXT1BlockFull; + half_block_function = FlipDXT1BlockHalf; + block_bytes = 8; + break; + case FOURCC_DXT3: + full_block_function = FlipDXT3BlockFull; + half_block_function = FlipDXT3BlockHalf; + block_bytes = 16; + break; + case FOURCC_DXT5: + full_block_function = FlipDXT5BlockFull; + half_block_function = FlipDXT5BlockHalf; + block_bytes = 16; + break; + default: + return 0; + } + + unsigned int mip_width = width; + unsigned int mip_height = height; + + for (unsigned int i = 0; i < levels; ++i) { + unsigned int blocks_per_row = (mip_width + 3) / 4; + unsigned int blocks_per_col = (mip_height + 3) / 4; + unsigned int blocks = blocks_per_row * blocks_per_col; + + if (mip_height == 1) { + // no flip to do, and we're done. + break; + } + else if (mip_height == 2) { + // flip the first 2 lines in each block. + for (unsigned int i = 0; i < blocks_per_row; ++i) { + half_block_function(data + i * block_bytes); + } + } + else { + // flip each block. + for (unsigned int i = 0; i < blocks; ++i) + full_block_function(data + i * block_bytes); + + // swap each block line in the first half of the image with the + // corresponding one in the second half. + // note that this is a no-op if mip_height is 4. + unsigned int row_bytes = block_bytes * blocks_per_row; + uint8_t *temp_line = new uint8_t[row_bytes]; + + for (unsigned int y = 0; y < blocks_per_col / 2; ++y) { + uint8_t *line1 = data + y * row_bytes; + uint8_t *line2 = data + (blocks_per_col - y - 1) * row_bytes; + + memcpy(temp_line, line1, row_bytes); + memcpy(line1, line2, row_bytes); + memcpy(line2, temp_line, row_bytes); + } + + delete temp_line; + } + + // mip levels are contiguous. + data += block_bytes * blocks; + mip_width = max(1U, mip_width >> 1); + mip_height = max(1U, mip_height >> 1); + } + + return 1; +} + diff --git a/source/blender/imbuf/intern/dds/FlipDXT.h b/source/blender/imbuf/intern/dds/FlipDXT.h new file mode 100644 index 00000000000..8d0ae8139a1 --- /dev/null +++ b/source/blender/imbuf/intern/dds/FlipDXT.h @@ -0,0 +1,32 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: Amorilia (amorilia@users.sourceforge.net) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FLIPDXT_H__ +#define __FLIPDXT_H__ + +#include "MEM_sys_types.h" + +/* flip compressed DXT image vertically to fit OpenGL convention */ +int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data); + +#endif + diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h index 5dcf3011c76..81074fba6b7 100644 --- a/source/blender/imbuf/intern/dds/Image.h +++ b/source/blender/imbuf/intern/dds/Image.h @@ -101,4 +101,4 @@ inline Color32 & Image::pixel(uint x, uint y) return pixel(y * width() + x); } -#endif // __IMAGE_H__ +#endif /* __IMAGE_H__ */ diff --git a/source/blender/imbuf/intern/dds/PixelFormat.h b/source/blender/imbuf/intern/dds/PixelFormat.h index 308ea810f03..2bb1864e49d 100644 --- a/source/blender/imbuf/intern/dds/PixelFormat.h +++ b/source/blender/imbuf/intern/dds/PixelFormat.h @@ -101,38 +101,38 @@ } } - inline float quantizeCeil(float f, int inbits, int outbits) - { - //uint i = f * (float(1 << inbits) - 1); - //i = convert(i, inbits, outbits); - //float result = float(i) / (float(1 << outbits) - 1); - //nvCheck(result >= f); - float result; - int offset = 0; - do { - uint i = offset + uint(f * (float(1 << inbits) - 1)); - i = convert(i, inbits, outbits); - result = float(i) / (float(1 << outbits) - 1); - offset++; - } while (result < f); - - return result; - } - - /* - inline float quantizeRound(float f, int bits) - { - float scale = float(1 << bits); - return fround(f * scale) / scale; - } - - inline float quantizeFloor(float f, int bits) - { - float scale = float(1 << bits); - return floor(f * scale) / scale; - } - */ + inline float quantizeCeil(float f, int inbits, int outbits) + { + //uint i = f * (float(1 << inbits) - 1); + //i = convert(i, inbits, outbits); + //float result = float(i) / (float(1 << outbits) - 1); + //nvCheck(result >= f); + float result; + int offset = 0; + do { + uint i = offset + uint(f * (float(1 << inbits) - 1)); + i = convert(i, inbits, outbits); + result = float(i) / (float(1 << outbits) - 1); + offset++; + } while (result < f); + + return result; + } + +#if 0 + inline float quantizeRound(float f, int bits) + { + float scale = float(1 << bits); + return fround(f * scale) / scale; + } + + inline float quantizeFloor(float f, int bits) + { + float scale = float(1 << bits); + return floor(f * scale) / scale; + } +#endif } // PixelFormat namespace -#endif // _DDS_IMAGE_PIXELFORMAT_H +#endif /* __PIXELFORMAT_H__ */ diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript index 4245f5001b9..d5a613f5981 100644 --- a/source/blender/imbuf/intern/dds/SConscript +++ b/source/blender/imbuf/intern/dds/SConscript @@ -1,7 +1,7 @@ #!/usr/bin/python Import ('env') -source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp'] +source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp', 'FlipDXT.cpp'] incs = ['.', '../../', diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index 9f513ca8aba..a1ac49b58da 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -35,7 +35,7 @@ struct Stream unsigned char *mem; // location in memory unsigned int size; // size unsigned int pos; // current position - Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {}; + Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {} unsigned int seek(unsigned int p); }; @@ -45,5 +45,4 @@ unsigned int mem_read(Stream & mem, unsigned short & i); unsigned int mem_read(Stream & mem, unsigned char & i); unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt); -#endif // __STREAM_H__ - +#endif /* __STREAM_H__ */ diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 7aacbf20bae..5459cffe590 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -29,6 +29,7 @@ #include <dds_api.h> #include <Stream.h> #include <DirectDrawSurface.h> +#include <FlipDXT.h> #include <stdio.h> // printf #include <fstream> @@ -162,13 +163,18 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo rect[i] = col; } - if (ibuf->dds_data.fourcc != FOURCC_DDS) + if (ibuf->dds_data.fourcc != FOURCC_DDS) { ibuf->dds_data.data = (unsigned char*)dds.readData(ibuf->dds_data.size); + + /* flip compressed texture */ + FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data); + } else { ibuf->dds_data.data = NULL; ibuf->dds_data.size = 0; } + /* flip uncompressed texture */ IMB_flipy(ibuf); } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index aa236af3507..8d289de9970 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -62,7 +62,7 @@ void IMB_de_interlace(ImBuf *ibuf) tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect); tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect); - ibuf->x *= 2; + ibuf->x *= 2; IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); @@ -561,7 +561,7 @@ void IMB_rect_from_float(ImBuf *ibuf) } /* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */ -void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h) +void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data) { float *rect_float; uchar *rect_byte; @@ -580,14 +580,27 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels; rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4; - IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, - w, h, w, ibuf->x); + if (is_data) { + /* exception for non-color data, just copy float */ + IMB_buffer_float_from_float(buffer, rect_float, + ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, + w, h, w, ibuf->x); - /* XXX: need to convert to image buffer's rect space */ - IMB_buffer_byte_from_float(rect_byte, buffer, - 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, - w, h, ibuf->x, w); + /* and do color space conversion to byte */ + IMB_buffer_byte_from_float(rect_byte, rect_float, + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + w, h, ibuf->x, w); + } + else { + IMB_buffer_float_from_float(buffer, rect_float, + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); + + /* XXX: need to convert to image buffer's rect space */ + IMB_buffer_byte_from_float(rect_byte, buffer, + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); + } /* ensure user flag is reset */ ibuf->userflags &= ~IB_RECT_INVALID; @@ -710,7 +723,7 @@ void IMB_buffer_float_clamp(float *buf, int width, int height) { int i, total = width * height * 4; for (i = 0; i < total; i++) { - buf[i] = minf(1.0, buf[i]); + buf[i] = min_ff(1.0, buf[i]); } } diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index ed4db50035d..5c2dc0c7df9 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -74,8 +74,8 @@ ImFileType IMB_FILE_TYPES[] = { {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, #ifdef WITH_CINEON - {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, - {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_load_dpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_load_cineon, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_TIFF {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 863b8424cc2..57fbce710a1 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -444,7 +444,7 @@ void neareast_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[2] = dataF[2]; outF[3] = dataF[3]; } - } + } } void neareast_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, int yout) diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index f35a4345366..38bd28452f3 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -36,18 +36,19 @@ #include "IMB_indexer.h" #include "IMB_anim.h" -#include "AVI_avi.h" #include "imbuf.h" #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" #include "BKE_global.h" -#ifdef WITH_FFMPEG - -#include "ffmpeg_compat.h" +#ifdef WITH_AVI +# include "AVI_avi.h" +#endif -#endif //WITH_FFMPEG +#ifdef WITH_FFMPEG +# include "ffmpeg_compat.h" +#endif static char magic[] = "BlenMIdx"; @@ -869,9 +870,9 @@ static void index_rebuild_ffmpeg_proc_decoded_frame( context->start_pts_set = TRUE; } - context->frameno = floor((pts - context->start_pts) - * context->pts_time_base - * context->frame_rate + 0.5f); + context->frameno = floor((pts - context->start_pts) * + context->pts_time_base * + context->frame_rate + 0.5); /* decoding starts *always* on I-Frames, * so: P-Frames won't work, even if all the @@ -989,6 +990,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, * - internal AVI (fallback) rebuilder * ---------------------------------------------------------------------- */ +#ifdef WITH_AVI typedef struct FallbackIndexBuilderContext { int anim_type; @@ -1149,6 +1151,8 @@ static void index_rebuild_fallback(FallbackIndexBuilderContext *context, } } +#endif /* WITH_AVI */ + /* ---------------------------------------------------------------------- * - public API * ---------------------------------------------------------------------- */ @@ -1164,15 +1168,19 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecod context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality); break; #endif +#ifdef WITH_AVI default: context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality); break; +#endif } if (context) context->anim_type = anim->curtype; return context; + + (void)tcs_in_use, (void)proxy_sizes_in_use, (void)quality; } void IMB_anim_index_rebuild(struct IndexBuildContext *context, @@ -1184,10 +1192,14 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context, index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress); break; #endif +#ifdef WITH_AVI default: index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress); break; +#endif } + + (void)stop, (void)do_update, (void)progress; } void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop) @@ -1198,10 +1210,15 @@ void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop) index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop); break; #endif +#ifdef WITH_AVI default: index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop); break; +#endif } + + (void)stop; + (void)proxy_sizes; /* static defined at top of the file */ } diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 549a28a0453..dec5f6fb39e 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -408,7 +408,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo } MEM_freeN(starttab); - MEM_freeN(lengthtab); + MEM_freeN(lengthtab); } else { @@ -613,7 +613,7 @@ static void expandrow2(float *optr, unsigned char *iptr, int z) optr += 4; } } - } + } } static void expandrow(unsigned char *optr, unsigned char *iptr, int z) diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index 01523463712..d94f6368298 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -41,7 +41,7 @@ #include "openjpeg.h" -#define JP2_FILEHEADER_SIZE 14 +// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */ static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00}; @@ -436,7 +436,7 @@ static void cinema_parameters(opj_cparameters_t *parameters) parameters->image_offset_y0 = 0; /*Codeblock size = 32 * 32*/ - parameters->cblockw_init = 32; + parameters->cblockw_init = 32; parameters->cblockh_init = 32; parameters->csty |= 0x01; @@ -602,7 +602,7 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) prec = 12; numcomps = 3; } - else { + else { /* Get settings from the imbuf */ color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB; diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 61275a8937c..d96a01d7093 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -235,19 +235,19 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t */ #define INPUT_BYTE(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo, action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo, action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) static boolean diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index a5afc1abdc6..d5cb8e8a3b6 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -39,6 +39,9 @@ set(INC_SYS ) set(SRC + openexr_api.h + openexr_multi.h + openexr_api.cpp ) @@ -49,4 +52,4 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() -blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}") +blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 066d07a36c5..60c6e184070 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -238,19 +238,19 @@ public: Iex::throwErrnoExc(); } - virtual void write(const char c[], int n) + virtual void write(const char c[], int n) { errno = 0; ofs.write(c, n); check_error(); } - virtual Int64 tellp() + virtual Int64 tellp() { return std::streamoff(ofs.tellp()); } - virtual void seekp(Int64 pos) + virtual void seekp(Int64 pos) { ofs.seekp(pos); check_error(); diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 7262656d4e8..21fa878c08a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -33,25 +33,25 @@ #include "openexr_multi.h" -void * IMB_exr_get_handle (void) {return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void *IMB_exr_get_handle (void) {return NULL;} +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} -int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} -void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } +int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} +int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} +void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } -void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -void IMB_exr_read_channels (void *handle) { (void)handle; } -void IMB_exr_write_channels (void *handle) { (void)handle; } -void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } -void IMB_exrtile_clear_channels (void *handle) { (void)handle; } +void IMB_exr_read_channels (void *handle) { (void)handle; } +void IMB_exr_write_channels (void *handle) { (void)handle; } +void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } +void IMB_exrtile_clear_channels (void *handle) { (void)handle; } -void IMB_exr_multilayer_convert (void *handle, void *base, - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) - { - (void)handle; (void)base; (void)addlayer; (void)addpass; - } +void IMB_exr_multilayer_convert (void *handle, void *base, + void * (*addlayer)(void *base, const char *str), + void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) +{ + (void)handle; (void)base; (void)addlayer; (void)addpass; +} -void IMB_exr_close (void *handle) { (void)handle; } +void IMB_exr_close (void *handle) { (void)handle; } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 6310d8e105f..dcfebb95b87 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -558,7 +558,8 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); - MEM_freeN(row_pointers); + if (row_pointers) + MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 53b00f441c8..03ed1bb8008 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -65,7 +65,6 @@ #define BLU 2 #define EXP 3 #define COLXS 128 -#define STR_MAX 540 typedef unsigned char RGBE[4]; typedef float fCOLOR[3]; @@ -154,7 +153,7 @@ static void FLOAT2RGBE(fCOLOR fcol, RGBE rgbe) if (d <= 1e-32f) rgbe[RED] = rgbe[GRN] = rgbe[BLU] = rgbe[EXP] = 0; else { - d = frexp(d, &e) * 256.f / d; + d = (float)frexp(d, &e) * 256.0f / d; rgbe[RED] = (unsigned char)(fcol[RED] * d); rgbe[GRN] = (unsigned char)(fcol[GRN] * d); rgbe[BLU] = (unsigned char)(fcol[BLU] * d); diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index a1fa05d1098..be20c80bdec 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -100,7 +100,8 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co } } - fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); + if ((flags & IB_test) == 0) + fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); return NULL; } @@ -170,11 +171,12 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_S return ibuf; } -ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *IMB_testiffname(const char *filepath, int flags) { ImBuf *ibuf; int file; char filepath_tx[IB_FILENAME_SIZE]; + char colorspace[IM_MAX_SPACE] = "\0"; imb_cache_filename(filepath_tx, filepath, flags); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index a11f16d5669..d2b0645cf93 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -447,7 +447,7 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, drectf += destskip * 4; srectf += srcskip * 4; - } + } } } } @@ -482,13 +482,13 @@ void IMB_rectfill(struct ImBuf *drect, const float col[4]) *rrectf++ = col[2]; *rrectf++ = col[3]; } - } + } } void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, - const float col[4], struct ColorManagedDisplay *display, - int x1, int y1, int x2, int y2) + const float col[4], struct ColorManagedDisplay *display, + int x1, int y1, int x2, int y2) { int i, j; float a; /* alpha */ @@ -587,7 +587,7 @@ void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, i { if (!ibuf) return; buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display, - x1, y1, x2, y2); + x1, y1, x2, y2); } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 527f334d6a4..b9525ccccf1 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -331,13 +331,13 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) for (y = ibuf2->y; y > 0; y--) { p2f = p1f + (ibuf1->x << 2); for (x = ibuf2->x; x > 0; x--) { - destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); - destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); - destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); - destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); - p1f += 8; - p2f += 8; - destf += 4; + destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); + destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); + destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); + destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); + p1f += 8; + p2f += 8; + destf += 4; } p1f = p2f; if (ibuf1->x & 1) p1f += 4; diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index 253680e4bea..eaad77f1ff9 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -55,9 +55,9 @@ /***/ typedef struct TARGA { - unsigned char numid; + unsigned char numid; unsigned char maptyp; - unsigned char imgtyp; + unsigned char imgtyp; short maporig; short mapsize; unsigned char mapbits; diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index ff7218d649c..94bb85b49ea 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -175,7 +175,7 @@ static void to_hex_char(char *hexbytes, const unsigned char *bytes, int len) static int uri_from_filename(const char *path, char *uri) { - char orig_uri[URI_MAX]; + char orig_uri[URI_MAX]; const char *dirstart = path; #ifdef WIN32 @@ -265,7 +265,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im char thumb[40]; short tsize = 128; short ex, ey; - float scaledx, scaledy; + float scaledx, scaledy; struct stat info; switch (size) { @@ -334,7 +334,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } else { IMB_freeImBuf(img); - img = IMB_anim_previewframe(anim); + img = IMB_anim_previewframe(anim); } IMB_free_anim(anim); } @@ -401,7 +401,7 @@ ImBuf *IMB_thumb_read(const char *path, ThumbSize size) if (!uri_from_filename(path, uri)) { return NULL; } - if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { + if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); } @@ -436,9 +436,9 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) struct stat st; ImBuf *img = NULL; - if (stat(path, &st)) { + if (BLI_stat(path, &st)) { return NULL; - } + } if (!uri_from_filename(path, uri)) { return NULL; } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index cfc49d8cef5..73ced4095f9 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -166,7 +166,7 @@ void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float as margin_t = height - margin_b; } - { + { int x, y; int stride_x = (margin_r - margin_l) - 2; diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 833671e3f2f..fe138a71a4a 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -211,7 +211,12 @@ int IMB_ispic(const char *filename) static int isavi(const char *name) { +#ifdef WITH_AVI return AVI_is_avi(name); +#else + (void)name; + return FALSE; +#endif } #ifdef WITH_QUICKTIME @@ -223,6 +228,10 @@ static int isqtime(const char *name) #ifdef WITH_FFMPEG +/* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-format-attribute" + static char ffmpeg_last_error[1024]; static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) @@ -240,6 +249,8 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis } } +#pragma GCC diagnostic pop + void IMB_ffmpeg_init(void) { av_register_all(); @@ -405,7 +416,7 @@ int IMB_isanim(const char *filename) type = imb_get_anim_type(filename); } else { - return(FALSE); + return(FALSE); } } else { /* no quicktime */ |