From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- source/blender/imbuf/CMakeLists.txt | 252 +- source/blender/imbuf/IMB_colormanagement.h | 321 +- source/blender/imbuf/IMB_imbuf.h | 450 +- source/blender/imbuf/IMB_imbuf_types.h | 401 +- source/blender/imbuf/IMB_metadata.h | 6 +- source/blender/imbuf/IMB_moviecache.h | 26 +- source/blender/imbuf/IMB_thumbs.h | 20 +- source/blender/imbuf/intern/IMB_anim.h | 127 +- .../imbuf/intern/IMB_colormanagement_intern.h | 67 +- source/blender/imbuf/intern/IMB_filetype.h | 95 +- source/blender/imbuf/intern/IMB_indexer.h | 77 +- source/blender/imbuf/intern/allocimbuf.c | 746 +-- source/blender/imbuf/intern/anim_movie.c | 2342 +++++---- source/blender/imbuf/intern/bmp.c | 535 +- source/blender/imbuf/intern/cache.c | 559 +-- source/blender/imbuf/intern/cineon/CMakeLists.txt | 36 +- source/blender/imbuf/intern/cineon/cineon_dpx.c | 266 +- source/blender/imbuf/intern/cineon/cineonlib.c | 688 +-- source/blender/imbuf/intern/cineon/cineonlib.h | 158 +- source/blender/imbuf/intern/cineon/dpxlib.c | 905 ++-- source/blender/imbuf/intern/cineon/dpxlib.h | 197 +- source/blender/imbuf/intern/cineon/logImageCore.c | 2650 +++++----- source/blender/imbuf/intern/cineon/logImageCore.h | 248 +- source/blender/imbuf/intern/cineon/logmemfile.c | 131 +- source/blender/imbuf/intern/cineon/logmemfile.h | 3 +- source/blender/imbuf/intern/colormanagement.c | 5103 ++++++++++---------- .../blender/imbuf/intern/colormanagement_inline.c | 18 +- source/blender/imbuf/intern/dds/BlockDXT.cpp | 729 ++- source/blender/imbuf/intern/dds/BlockDXT.h | 339 +- source/blender/imbuf/intern/dds/CMakeLists.txt | 52 +- source/blender/imbuf/intern/dds/Color.h | 116 +- source/blender/imbuf/intern/dds/ColorBlock.cpp | 592 +-- source/blender/imbuf/intern/dds/ColorBlock.h | 59 +- source/blender/imbuf/intern/dds/Common.h | 27 +- .../blender/imbuf/intern/dds/DirectDrawSurface.cpp | 2186 +++++---- .../blender/imbuf/intern/dds/DirectDrawSurface.h | 229 +- source/blender/imbuf/intern/dds/FlipDXT.cpp | 346 +- source/blender/imbuf/intern/dds/FlipDXT.h | 3 +- source/blender/imbuf/intern/dds/Image.cpp | 78 +- source/blender/imbuf/intern/dds/Image.h | 77 +- source/blender/imbuf/intern/dds/PixelFormat.h | 142 +- source/blender/imbuf/intern/dds/Stream.cpp | 107 +- source/blender/imbuf/intern/dds/Stream.h | 29 +- source/blender/imbuf/intern/dds/dds_api.cpp | 258 +- source/blender/imbuf/intern/dds/dds_api.h | 10 +- source/blender/imbuf/intern/divers.c | 1515 +++--- source/blender/imbuf/intern/filetype.c | 203 +- source/blender/imbuf/intern/filter.c | 1116 ++--- source/blender/imbuf/intern/imageprocess.c | 663 +-- source/blender/imbuf/intern/imbuf.h | 5 +- source/blender/imbuf/intern/indexer.c | 2015 ++++---- source/blender/imbuf/intern/iris.c | 1451 +++--- source/blender/imbuf/intern/jp2.c | 2008 ++++---- source/blender/imbuf/intern/jpeg.c | 895 ++-- source/blender/imbuf/intern/metadata.c | 91 +- source/blender/imbuf/intern/module.c | 21 +- source/blender/imbuf/intern/moviecache.c | 696 +-- source/blender/imbuf/intern/oiio/CMakeLists.txt | 40 +- .../blender/imbuf/intern/oiio/openimageio_api.cpp | 404 +- source/blender/imbuf/intern/oiio/openimageio_api.h | 9 +- source/blender/imbuf/intern/openexr/CMakeLists.txt | 30 +- .../blender/imbuf/intern/openexr/openexr_api.cpp | 3108 ++++++------ source/blender/imbuf/intern/openexr/openexr_api.h | 13 +- .../blender/imbuf/intern/openexr/openexr_multi.h | 93 +- .../blender/imbuf/intern/openexr/openexr_stub.cpp | 119 +- source/blender/imbuf/intern/png.c | 1357 +++--- source/blender/imbuf/intern/radiance_hdr.c | 639 +-- source/blender/imbuf/intern/readimage.c | 382 +- source/blender/imbuf/intern/rectop.c | 1845 +++---- source/blender/imbuf/intern/rotate.c | 126 +- source/blender/imbuf/intern/scaling.c | 3106 ++++++------ source/blender/imbuf/intern/stereoimbuf.c | 2331 ++++----- source/blender/imbuf/intern/targa.c | 1240 ++--- source/blender/imbuf/intern/thumbs.c | 1129 +++-- source/blender/imbuf/intern/thumbs_blend.c | 234 +- source/blender/imbuf/intern/thumbs_font.c | 67 +- source/blender/imbuf/intern/tiff.c | 1315 +++-- source/blender/imbuf/intern/util.c | 458 +- source/blender/imbuf/intern/writeimage.c | 66 +- 79 files changed, 26198 insertions(+), 24398 deletions(-) (limited to 'source/blender/imbuf') diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index a52c72f8ecd..b8d43b8e9c2 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -19,180 +19,180 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - ../blenkernel - ../blenlib - ../blenloader - ../makesdna - ../makesrna - ../../../intern/guardedalloc - ../../../intern/memutil + . + ../blenkernel + ../blenlib + ../blenloader + ../makesdna + ../makesrna + ../../../intern/guardedalloc + ../../../intern/memutil ) set(INC_SYS - ${JPEG_INCLUDE_DIR} - ${PNG_INCLUDE_DIRS} - ${ZLIB_INCLUDE_DIRS} + ${JPEG_INCLUDE_DIR} + ${PNG_INCLUDE_DIRS} + ${ZLIB_INCLUDE_DIRS} ) set(SRC - intern/allocimbuf.c - intern/anim_movie.c - intern/bmp.c - intern/cache.c - intern/colormanagement.c - intern/colormanagement_inline.c - intern/divers.c - intern/filetype.c - intern/filter.c - intern/imageprocess.c - intern/indexer.c - intern/iris.c - intern/jpeg.c - intern/metadata.c - intern/module.c - intern/moviecache.c - intern/png.c - intern/readimage.c - intern/rectop.c - intern/rotate.c - intern/scaling.c - intern/stereoimbuf.c - intern/targa.c - intern/thumbs.c - intern/thumbs_blend.c - intern/thumbs_font.c - intern/util.c - intern/writeimage.c - - IMB_colormanagement.h - IMB_imbuf.h - IMB_imbuf_types.h - IMB_metadata.h - IMB_moviecache.h - IMB_thumbs.h - intern/IMB_allocimbuf.h - intern/IMB_anim.h - intern/IMB_colormanagement_intern.h - intern/IMB_filetype.h - intern/IMB_filter.h - intern/IMB_indexer.h - intern/imbuf.h - - # orphan include - ../../../intern/ffmpeg/ffmpeg_compat.h + intern/allocimbuf.c + intern/anim_movie.c + intern/bmp.c + intern/cache.c + intern/colormanagement.c + intern/colormanagement_inline.c + intern/divers.c + intern/filetype.c + intern/filter.c + intern/imageprocess.c + intern/indexer.c + intern/iris.c + intern/jpeg.c + intern/metadata.c + intern/module.c + intern/moviecache.c + intern/png.c + intern/readimage.c + intern/rectop.c + intern/rotate.c + intern/scaling.c + intern/stereoimbuf.c + intern/targa.c + intern/thumbs.c + intern/thumbs_blend.c + intern/thumbs_font.c + intern/util.c + intern/writeimage.c + + IMB_colormanagement.h + IMB_imbuf.h + IMB_imbuf_types.h + IMB_metadata.h + IMB_moviecache.h + IMB_thumbs.h + intern/IMB_allocimbuf.h + intern/IMB_anim.h + intern/IMB_colormanagement_intern.h + intern/IMB_filetype.h + intern/IMB_filter.h + intern/IMB_indexer.h + intern/imbuf.h + + # orphan include + ../../../intern/ffmpeg/ffmpeg_compat.h ) set(LIB - bf_blenkernel - bf_blenlib - bf_blenloader - bf_intern_guardedalloc - bf_intern_memutil - bf_intern_opencolorio + bf_blenkernel + bf_blenlib + bf_blenloader + bf_intern_guardedalloc + bf_intern_memutil + bf_intern_opencolorio ) if(WITH_IMAGE_OPENEXR) - list(APPEND LIB - bf_imbuf_openexr - ) - add_definitions(-DWITH_OPENEXR) + list(APPEND LIB + bf_imbuf_openexr + ) + add_definitions(-DWITH_OPENEXR) else() - list(APPEND SRC - intern/openexr/openexr_stub.cpp - ) + list(APPEND SRC + intern/openexr/openexr_stub.cpp + ) endif() if(WITH_IMAGE_TIFF) - list(APPEND INC_SYS - ${TIFF_INCLUDE_DIR} - ) - list(APPEND SRC - intern/tiff.c - ) - add_definitions(-DWITH_TIFF) + list(APPEND INC_SYS + ${TIFF_INCLUDE_DIR} + ) + list(APPEND SRC + intern/tiff.c + ) + add_definitions(-DWITH_TIFF) endif() if(WITH_OPENIMAGEIO) - list(APPEND LIB - bf_imbuf_openimageio - ) - add_definitions(-DWITH_OPENIMAGEIO) + list(APPEND LIB + bf_imbuf_openimageio + ) + add_definitions(-DWITH_OPENIMAGEIO) endif() if(WITH_IMAGE_OPENJPEG) - list(APPEND INC_SYS - ${OPENJPEG_INCLUDE_DIRS} - ) - list(APPEND SRC - intern/jp2.c - ) - - add_definitions(-DWITH_OPENJPEG ${OPENJPEG_DEFINES}) + list(APPEND INC_SYS + ${OPENJPEG_INCLUDE_DIRS} + ) + list(APPEND SRC + intern/jp2.c + ) + + add_definitions(-DWITH_OPENJPEG ${OPENJPEG_DEFINES}) endif() if(WITH_CODEC_AVI) - list(APPEND INC - ../avi - ) - list(APPEND LIB - bf_avi - ) - add_definitions(-DWITH_AVI) + list(APPEND INC + ../avi + ) + list(APPEND LIB + bf_avi + ) + add_definitions(-DWITH_AVI) endif() if(WITH_CODEC_FFMPEG) - list(APPEND INC - ../../../intern/ffmpeg - ) - list(APPEND INC_SYS - ${FFMPEG_INCLUDE_DIRS} - ) - add_definitions(-DWITH_FFMPEG) - - remove_strict_c_flags_file( - intern/anim_movie.c - intern/indexer.c - intern/util.c - ) + list(APPEND INC + ../../../intern/ffmpeg + ) + list(APPEND INC_SYS + ${FFMPEG_INCLUDE_DIRS} + ) + add_definitions(-DWITH_FFMPEG) + + remove_strict_c_flags_file( + intern/anim_movie.c + intern/indexer.c + intern/util.c + ) endif() if(WITH_IMAGE_DDS) - list(APPEND LIB - bf_imbuf_dds - ) - add_definitions(-DWITH_DDS) + list(APPEND LIB + bf_imbuf_dds + ) + add_definitions(-DWITH_DDS) endif() if(WITH_IMAGE_CINEON) - list(APPEND LIB - bf_imbuf_cineon - ) - add_definitions(-DWITH_CINEON) + list(APPEND LIB + bf_imbuf_cineon + ) + add_definitions(-DWITH_CINEON) endif() if(WITH_IMAGE_HDR) - list(APPEND SRC - intern/radiance_hdr.c - ) - add_definitions(-DWITH_HDR) + list(APPEND SRC + intern/radiance_hdr.c + ) + add_definitions(-DWITH_HDR) endif() list(APPEND INC - ../../../intern/opencolorio + ../../../intern/opencolorio ) if(WIN32) - list(APPEND INC - ../../../intern/utfconv - ) + list(APPEND INC + ../../../intern/utfconv + ) endif() # no need to compile object files for inline headers. set_source_files_properties( - intern/colormanagement_inline.c - PROPERTIES HEADER_FILE_ONLY TRUE + intern/colormanagement_inline.c + PROPERTIES HEADER_FILE_ONLY TRUE ) blender_add_lib(bf_imbuf "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index c042e17cf80..5978066f4a8 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -29,7 +29,6 @@ #define BCM_CONFIG_FILE "config.ocio" - struct ColorManagedColorspaceSettings; struct ColorManagedDisplaySettings; struct ColorManagedViewSettings; @@ -47,8 +46,9 @@ struct ColorSpace; void IMB_colormanagement_check_file_config(struct Main *bmain); -void IMB_colormanagement_validate_settings(const struct ColorManagedDisplaySettings *display_settings, - struct ColorManagedViewSettings *view_settings); +void IMB_colormanagement_validate_settings( + const struct ColorManagedDisplaySettings *display_settings, + struct ColorManagedViewSettings *view_settings); const char *IMB_colormanagement_role_colorspace_name_get(int role); void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name); @@ -64,28 +64,65 @@ BLI_INLINE void IMB_colormangement_xyz_to_rgb(float rgb[3], const float xyz[3]); BLI_INLINE void IMB_colormangement_rgb_to_xyz(float xyz[3], const float rgb[3]); /* ** Color space transformation functions ** */ -void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, bool predivide); -void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, bool predivide); -void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace); -void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace); -void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, - int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace); -void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, - int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace); -void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace); - -void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace); -void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], bool predivide, struct ColorSpace *colorspace); - -void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct ColorSpace *colorspace); - -void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide); +void IMB_colormanagement_transform(float *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace, + bool predivide); +void IMB_colormanagement_transform_threaded(float *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace, + bool predivide); +void IMB_colormanagement_transform_byte(unsigned char *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace); +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace); +void IMB_colormanagement_transform_from_byte(float *float_buffer, + unsigned char *byte_buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace); +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, + unsigned char *byte_buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace); +void IMB_colormanagement_transform_v4(float pixel[4], + const char *from_colorspace, + const char *to_colorspace); + +void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], + struct ColorSpace *colorspace); +void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], + bool predivide, + struct ColorSpace *colorspace); + +void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], + struct ColorSpace *colorspace); + +void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, + int width, + int height, + int channels, + struct ColorSpace *colorspace, + bool predivide); void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]); void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]); @@ -93,44 +130,74 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]); void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3]); void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]); -void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display); -void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], struct ColorManagedDisplay *display); - -void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4], const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - -void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - -void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - -struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, bool save_as_render, bool allocate_result, - const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, - struct ImageFormatData *image_format_data); - -void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char *display_buffer, - int width, int height, int channels, float dither, - const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); +void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], + struct ColorManagedDisplay *display); +void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], + struct ColorManagedDisplay *display); + +void IMB_colormanagement_pixel_to_display_space_v4( + float result[4], + const float pixel[4], + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + +void IMB_colormanagement_pixel_to_display_space_v3( + float result[3], + const float pixel[3], + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + +void IMB_colormanagement_imbuf_make_display_space( + struct ImBuf *ibuf, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + +struct ImBuf *IMB_colormanagement_imbuf_for_write( + struct ImBuf *ibuf, + bool save_as_render, + bool allocate_result, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + struct ImageFormatData *image_format_data); + +void IMB_colormanagement_buffer_make_display_space( + float *buffer, + unsigned char *display_buffer, + int width, + int height, + int channels, + float dither, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); /* ** Public display buffers interfaces ** */ -void IMB_colormanagement_display_settings_from_ctx(const struct bContext *C, - struct ColorManagedViewSettings **view_settings_r, - struct ColorManagedDisplaySettings **display_settings_r); - -const char *IMB_colormanagement_get_display_colorspace_name(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - -unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, void **cache_handle); -unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct ImBuf *ibuf, void **cache_handle); - -void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, - int channels, const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, bool predivide); +void IMB_colormanagement_display_settings_from_ctx( + const struct bContext *C, + struct ColorManagedViewSettings **view_settings_r, + struct ColorManagedDisplaySettings **display_settings_r); + +const char *IMB_colormanagement_get_display_colorspace_name( + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + +unsigned char *IMB_display_buffer_acquire( + struct ImBuf *ibuf, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + void **cache_handle); +unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, + struct ImBuf *ibuf, + void **cache_handle); + +void IMB_display_buffer_transform_apply(unsigned char *display_buffer, + float *linear_buffer, + int width, + int height, + int channels, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + bool predivide); void IMB_display_buffer_release(void *cache_handle); @@ -141,7 +208,7 @@ const char *IMB_colormanagement_display_get_default_name(void); struct ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name); const char *IMB_colormanagement_display_get_none_name(void); const char *IMB_colormanagement_display_get_default_view_transform_name( - struct ColorManagedDisplay *display); + struct ColorManagedDisplay *display); /* ** View functions ** */ int IMB_colormanagement_view_get_named_index(const char *name); @@ -156,46 +223,78 @@ int IMB_colormanagement_colorspace_get_named_index(const char *name); const char *IMB_colormanagement_colorspace_get_indexed_name(int index); const char *IMB_colormanagement_view_get_default_name(const char *display_name); -void IMB_colormanagement_colorspace_from_ibuf_ftype(struct ColorManagedColorspaceSettings *colorspace_settings, struct ImBuf *ibuf); +void IMB_colormanagement_colorspace_from_ibuf_ftype( + struct ColorManagedColorspaceSettings *colorspace_settings, struct ImBuf *ibuf); /* ** RNA helper functions ** */ void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem); -void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name); -void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem, const char *view_name); +void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, + int *totitem, + const char *display_name); +void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, + int *totitem, + const char *view_name); void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem); /* ** Tile-based buffer management ** */ -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, +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, bool copy_display_to_byte_buffer); -void IMB_partial_display_buffer_update_threaded(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, - bool copy_display_to_byte_buffer); - -void IMB_partial_display_buffer_update_delayed(struct ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax); +void IMB_partial_display_buffer_update_threaded( + 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, + bool copy_display_to_byte_buffer); + +void IMB_partial_display_buffer_update_delayed( + struct ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax); /* ** Pixel processor functions ** */ -struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); -struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace); -void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4]); -void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, float pixel[4]); -void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]); -void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, float *pixel, int channels); -void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height, - int channels, bool predivide); +struct ColormanageProcessor *IMB_colormanagement_display_processor_new( + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); +struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new( + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, + float pixel[4]); +void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, + float pixel[4]); +void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, + float pixel[3]); +void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, + float *pixel, + int channels); +void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, + float *buffer, + int width, + int height, + int channels, + bool predivide); void IMB_colormanagement_processor_apply_byte(struct ColormanageProcessor *cm_processor, - unsigned char *buffer, int width, int height, int channels); + unsigned char *buffer, + int width, + int height, + int channels); void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor); /* ** OpenGL drawing routines using GLSL for color space transform ** */ @@ -203,37 +302,45 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo /* Test if GLSL drawing is supported for combination of graphics card and this configuration */ bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings); /* Configures GLSL shader for conversion from scene linear to display space */ -bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, - float dither, bool predivide); +bool IMB_colormanagement_setup_glsl_draw( + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + float dither, + bool predivide); /* Same as above, but display space conversion happens from a specified space */ -bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, - struct ColorSpace *colorspace, - float dither, bool predivide); +bool IMB_colormanagement_setup_glsl_draw_from_space( + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + struct ColorSpace *colorspace, + float dither, + bool predivide); /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, float dither, bool predivide); +bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, + float dither, + bool predivide); /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, - float dither, bool predivide); +bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, + struct ColorSpace *colorspace, + float dither, + bool predivide); /* Finish GLSL-based display space conversion */ void IMB_colormanagement_finish_glsl_draw(void); /* ** View transform ** */ void IMB_colormanagement_init_default_view_settings( - struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); + struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); /* Roles */ enum { - COLOR_ROLE_SCENE_LINEAR = 0, - COLOR_ROLE_COLOR_PICKING, - COLOR_ROLE_TEXTURE_PAINTING, - COLOR_ROLE_DEFAULT_SEQUENCER, - COLOR_ROLE_DEFAULT_BYTE, - COLOR_ROLE_DEFAULT_FLOAT, + COLOR_ROLE_SCENE_LINEAR = 0, + COLOR_ROLE_COLOR_PICKING, + COLOR_ROLE_TEXTURE_PAINTING, + COLOR_ROLE_DEFAULT_SEQUENCER, + COLOR_ROLE_DEFAULT_BYTE, + COLOR_ROLE_DEFAULT_FLOAT, }; #include "intern/colormanagement_inline.c" -#endif /* __IMB_COLORMANAGEMENT_H__ */ +#endif /* __IMB_COLORMANAGEMENT_H__ */ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 03d07844ec8..27eb6a5eee5 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -95,9 +95,11 @@ void IMB_exit(void); * * \attention Defined in readimage.c */ -struct ImBuf *IMB_ibImageFromMemory( - const unsigned char *mem, size_t size, int flags, - char colorspace[IM_MAX_SPACE], const char *descr); +struct ImBuf *IMB_ibImageFromMemory(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE], + const char *descr); /** * @@ -121,8 +123,10 @@ void IMB_freeImBuf(struct ImBuf *ibuf); * * \attention Defined in allocimbuf.c */ -struct ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, - unsigned char planes, unsigned int flags); +struct ImBuf *IMB_allocImBuf(unsigned int x, + unsigned int y, + unsigned char planes, + unsigned int flags); /** * Initialize given ImBuf. @@ -131,16 +135,17 @@ struct ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, * * \attention Defined in allocimbuf.c */ -bool IMB_initImBuf(struct ImBuf *ibuf, - unsigned int x, unsigned int y, - unsigned char planes, unsigned int flags); +bool IMB_initImBuf( + struct ImBuf *ibuf, unsigned int x, unsigned int y, unsigned char planes, unsigned int flags); /** * Create a copy of a pixel buffer and wrap it to a new ImBuf * \attention Defined in allocimbuf.c */ -struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, - unsigned int w, unsigned int h); +struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, + const float *rectf, + unsigned int w, + unsigned int h); /** * @@ -173,54 +178,93 @@ bool addzbuffloatImBuf(struct ImBuf *ibuf); */ typedef enum IMB_BlendMode { - IMB_BLEND_MIX = 0, - IMB_BLEND_ADD = 1, - IMB_BLEND_SUB = 2, - IMB_BLEND_MUL = 3, - IMB_BLEND_LIGHTEN = 4, - IMB_BLEND_DARKEN = 5, - IMB_BLEND_ERASE_ALPHA = 6, - IMB_BLEND_ADD_ALPHA = 7, - IMB_BLEND_OVERLAY = 8, - IMB_BLEND_HARDLIGHT = 9, - IMB_BLEND_COLORBURN = 10, - IMB_BLEND_LINEARBURN = 11, - IMB_BLEND_COLORDODGE = 12, - IMB_BLEND_SCREEN = 13, - IMB_BLEND_SOFTLIGHT = 14, - IMB_BLEND_PINLIGHT = 15, - IMB_BLEND_VIVIDLIGHT = 16, - IMB_BLEND_LINEARLIGHT = 17, - IMB_BLEND_DIFFERENCE = 18, - IMB_BLEND_EXCLUSION = 19, - IMB_BLEND_HUE = 20, - IMB_BLEND_SATURATION = 21, - IMB_BLEND_LUMINOSITY = 22, - IMB_BLEND_COLOR = 23, - IMB_BLEND_INTERPOLATE = 24, - - IMB_BLEND_COPY = 1000, - IMB_BLEND_COPY_RGB = 1001, - IMB_BLEND_COPY_ALPHA = 1002, + IMB_BLEND_MIX = 0, + IMB_BLEND_ADD = 1, + IMB_BLEND_SUB = 2, + IMB_BLEND_MUL = 3, + IMB_BLEND_LIGHTEN = 4, + IMB_BLEND_DARKEN = 5, + IMB_BLEND_ERASE_ALPHA = 6, + IMB_BLEND_ADD_ALPHA = 7, + IMB_BLEND_OVERLAY = 8, + IMB_BLEND_HARDLIGHT = 9, + IMB_BLEND_COLORBURN = 10, + IMB_BLEND_LINEARBURN = 11, + IMB_BLEND_COLORDODGE = 12, + IMB_BLEND_SCREEN = 13, + IMB_BLEND_SOFTLIGHT = 14, + IMB_BLEND_PINLIGHT = 15, + IMB_BLEND_VIVIDLIGHT = 16, + IMB_BLEND_LINEARLIGHT = 17, + IMB_BLEND_DIFFERENCE = 18, + IMB_BLEND_EXCLUSION = 19, + IMB_BLEND_HUE = 20, + IMB_BLEND_SATURATION = 21, + IMB_BLEND_LUMINOSITY = 22, + IMB_BLEND_COLOR = 23, + IMB_BLEND_INTERPOLATE = 24, + + IMB_BLEND_COPY = 1000, + IMB_BLEND_COPY_RGB = 1001, + IMB_BLEND_COPY_ALPHA = 1002, } IMB_BlendMode; -void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], - unsigned char src2[4], IMB_BlendMode mode); -void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], - IMB_BlendMode mode); - -void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx, - int *desty, int *srcx, int *srcy, int *width, int *height); -void IMB_rectcpy(struct ImBuf *drect, struct ImBuf *srect, int destx, - int desty, int srcx, int srcy, int width, int height); -void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf, - unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max, - int destx, int desty, int origx, int origy, int srcx, int srcy, - int width, int height, IMB_BlendMode mode, bool accumulate); -void IMB_rectblend_threaded(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf, - unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max, - int destx, int desty, int origx, int origy, int srcx, int srcy, - int width, int height, IMB_BlendMode mode, bool accumulate); +void IMB_blend_color_byte(unsigned char dst[4], + unsigned char src1[4], + unsigned char src2[4], + IMB_BlendMode mode); +void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_BlendMode mode); + +void IMB_rectclip(struct ImBuf *dbuf, + struct ImBuf *sbuf, + int *destx, + int *desty, + int *srcx, + int *srcy, + int *width, + int *height); +void IMB_rectcpy(struct ImBuf *drect, + struct ImBuf *srect, + int destx, + int desty, + int srcx, + int srcy, + int width, + int height); +void IMB_rectblend(struct ImBuf *dbuf, + struct ImBuf *obuf, + struct ImBuf *sbuf, + unsigned short *dmask, + unsigned short *curvemask, + unsigned short *mmask, + float mask_max, + int destx, + int desty, + int origx, + int origy, + int srcx, + int srcy, + int width, + int height, + IMB_BlendMode mode, + bool accumulate); +void IMB_rectblend_threaded(struct ImBuf *dbuf, + struct ImBuf *obuf, + struct ImBuf *sbuf, + unsigned short *dmask, + unsigned short *curvemask, + unsigned short *mmask, + float mask_max, + int destx, + int desty, + int origx, + int origy, + int srcx, + int srcy, + int width, + int height, + IMB_BlendMode mode, + bool accumulate); /** * @@ -228,50 +272,54 @@ void IMB_rectblend_threaded(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf */ typedef enum IMB_Timecode_Type { - IMB_TC_NONE = 0, /* don't use timecode files at all */ - - IMB_TC_RECORD_RUN = 1, /* use images in the order as they are recorded - * (currently, this is the only one implemented - * and is a sane default) */ - - IMB_TC_FREE_RUN = 2, /* use global timestamp written by recording - * device (prosumer camcorders e.g. can do that) */ - IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN = 4, /* interpolate a global timestamp using the - * record date and time written by recording - * device (*every* consumer camcorder can do - * that :) )*/ - IMB_TC_RECORD_RUN_NO_GAPS = 8, - IMB_TC_MAX_SLOT = 4, + IMB_TC_NONE = 0, /* don't use timecode files at all */ + + IMB_TC_RECORD_RUN = 1, /* use images in the order as they are recorded + * (currently, this is the only one implemented + * and is a sane default) */ + + IMB_TC_FREE_RUN = 2, /* use global timestamp written by recording + * device (prosumer camcorders e.g. can do that) */ + IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN = 4, /* interpolate a global timestamp using the + * record date and time written by recording + * device (*every* consumer camcorder can do + * that :) )*/ + IMB_TC_RECORD_RUN_NO_GAPS = 8, + IMB_TC_MAX_SLOT = 4, } IMB_Timecode_Type; typedef enum IMB_Proxy_Size { - IMB_PROXY_NONE = 0, - IMB_PROXY_25 = 1, - IMB_PROXY_50 = 2, - IMB_PROXY_75 = 4, - IMB_PROXY_100 = 8, - IMB_PROXY_MAX_SLOT = 4, + IMB_PROXY_NONE = 0, + IMB_PROXY_25 = 1, + IMB_PROXY_50 = 2, + IMB_PROXY_75 = 4, + IMB_PROXY_100 = 8, + IMB_PROXY_MAX_SLOT = 4, } IMB_Proxy_Size; /* defaults to BL_proxy within the directory of the animation */ void IMB_anim_set_index_dir(struct anim *anim, const char *dir); void IMB_anim_get_fname(struct anim *anim, char *file, int size); -int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, - int position); +int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position); IMB_Proxy_Size IMB_anim_proxy_get_existing(struct anim *anim); struct IndexBuildContext; /* prepare context for proxies/imecodes builder */ -struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use, - IMB_Proxy_Size proxy_sizes_in_use, int quality, - const bool overwite, struct GSet *file_list); +struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, + IMB_Timecode_Type tcs_in_use, + IMB_Proxy_Size proxy_sizes_in_use, + int quality, + const bool overwite, + struct GSet *file_list); /* will rebuild all used indices and proxies at once */ void IMB_anim_index_rebuild(struct IndexBuildContext *context, - short *stop, short *do_update, float *progress); + short *stop, + short *do_update, + float *progress); /* finish rebuilding proxises/timecodes and free temporary contexts used */ void IMB_anim_index_rebuild_finish(struct IndexBuildContext *context, short stop); @@ -281,19 +329,20 @@ void IMB_anim_index_rebuild_finish(struct IndexBuildContext *context, short stop */ int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc); - /** * Return the fps contained in movie files (function rval is false, * and frs_sec and frs_sec_base untouched if none available!) */ -bool IMB_anim_get_fps(struct anim *anim, - short *frs_sec, float *frs_sec_base, bool no_av_base); +bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base); /** * * \attention Defined in anim_movie.c */ -struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]); +struct anim *IMB_open_anim(const char *name, + int ib_flags, + int streamindex, + char colorspace[IM_MAX_SPACE]); void IMB_suffix_anim(struct anim *anim, const char *suffix); void IMB_close_anim(struct anim *anim); void IMB_close_anim_proxies(struct anim *anim); @@ -312,10 +361,10 @@ int IMB_anim_get_preseek(struct anim *anim); * \attention Defined in anim_movie.c */ -struct ImBuf *IMB_anim_absolute( - struct anim *anim, int position, - IMB_Timecode_Type tc /* = 1 = IMB_TC_RECORD_RUN */, - IMB_Proxy_Size preview_size /* = 0 = IMB_PROXY_NONE */); +struct ImBuf *IMB_anim_absolute(struct anim *anim, + int position, + IMB_Timecode_Type tc /* = 1 = IMB_TC_RECORD_RUN */, + IMB_Proxy_Size preview_size /* = 0 = IMB_PROXY_NONE */); /** * @@ -335,9 +384,9 @@ void IMB_free_anim(struct anim *anim); * \attention Defined in filter.c */ -#define FILTER_MASK_NULL 0 -#define FILTER_MASK_MARGIN 1 -#define FILTER_MASK_USED 2 +#define FILTER_MASK_NULL 0 +#define FILTER_MASK_MARGIN 1 +#define FILTER_MASK_USED 2 void IMB_filter(struct ImBuf *ibuf); void IMB_mask_filter_extend(char *mask, int width, int height); @@ -398,7 +447,7 @@ bool IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf); * \attention Defined in util.c */ bool IMB_ispic(const char *name); -int IMB_ispic_type(const char *name); +int IMB_ispic_type(const char *name); /** * @@ -422,32 +471,80 @@ bool IMB_isfloat(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, bool is_data); +void IMB_partial_rect_from_float( + struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data); void IMB_float_from_rect(struct ImBuf *ibuf); void IMB_color_to_bw(struct ImBuf *ibuf); void IMB_saturation(struct ImBuf *ibuf, float sat); /* converting pixel buffers */ -void IMB_buffer_byte_from_float(unsigned char *rect_to, const float *rect_from, - int channels_from, float dither, int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from); -void IMB_buffer_byte_from_float_mask(unsigned char *rect_to, const float *rect_from, - int channels_from, float dither, bool predivide, - int width, int height, int stride_to, int stride_from, char *mask); -void IMB_buffer_float_from_byte(float *rect_to, const unsigned char *rect_from, - int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from); -void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, - int channels_from, int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from); -void IMB_buffer_float_from_float_threaded(float *rect_to, const float *rect_from, - int channels_from, int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from); -void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, - int channels_from, int width, int height, int stride_to, int stride_from, char *mask); -void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect_from, - int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from); +void IMB_buffer_byte_from_float(unsigned char *rect_to, + const float *rect_from, + int channels_from, + float dither, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from); +void IMB_buffer_byte_from_float_mask(unsigned char *rect_to, + const float *rect_from, + int channels_from, + float dither, + bool predivide, + int width, + int height, + int stride_to, + int stride_from, + char *mask); +void IMB_buffer_float_from_byte(float *rect_to, + const unsigned char *rect_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from); +void IMB_buffer_float_from_float(float *rect_to, + const float *rect_from, + int channels_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from); +void IMB_buffer_float_from_float_threaded(float *rect_to, + const float *rect_from, + int channels_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from); +void IMB_buffer_float_from_float_mask(float *rect_to, + const float *rect_from, + int channels_from, + int width, + int height, + int stride_to, + int stride_from, + char *mask); +void IMB_buffer_byte_from_byte(unsigned char *rect_to, + const unsigned char *rect_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from); void IMB_buffer_float_clamp(float *buf, int width, int height); void IMB_buffer_float_unpremultiply(float *buf, int width, int height); void IMB_buffer_float_premultiply(float *buf, int width, int height); @@ -464,15 +561,23 @@ void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf); * * \attention defined in imageprocess.c */ -void bicubic_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); -void nearest_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); -void bilinear_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); - -void bicubic_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); -void nearest_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); -void nearest_interpolation_color_wrap(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); -void bilinear_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); -void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void bicubic_interpolation( + struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); +void nearest_interpolation( + struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); +void bilinear_interpolation( + struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); + +void bicubic_interpolation_color( + struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void nearest_interpolation_color( + struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void nearest_interpolation_color_wrap( + struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void bilinear_interpolation_color( + struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void bilinear_interpolation_color_wrap( + struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]); void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]); @@ -481,7 +586,8 @@ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol * * \attention defined in readimage.c */ -struct ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr); +struct ImBuf *IMB_loadifffile( + int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr); /** * @@ -543,20 +649,30 @@ void IMB_freezbuffloatImBuf(struct ImBuf *ibuf); * \attention Defined in rectop.c */ void IMB_rectfill(struct ImBuf *drect, const float col[4]); -void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display); +void IMB_rectfill_area(struct ImBuf *ibuf, + const float col[4], + int x1, + int y1, + int x2, + int y2, + struct ColorManagedDisplay *display); void IMB_rectfill_alpha(struct ImBuf *ibuf, const float value); /* this should not be here, really, we needed it for operating on render data, IMB_rectfill_area calls it */ -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); +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); /* exported for image tools in blender, to quickly allocate 32 bits rect */ -void *imb_alloc_pixels(unsigned int x, - unsigned int y, - unsigned int channels, - size_t typesize, - const char *name); +void *imb_alloc_pixels( + unsigned int x, unsigned int y, unsigned int channels, size_t typesize, const char *name); bool imb_addrectImBuf(struct ImBuf *ibuf); void imb_freerectImBuf(struct ImBuf *ibuf); @@ -569,19 +685,18 @@ bool imb_addtilesImBuf(struct ImBuf *ibuf); void imb_freetilesImBuf(struct ImBuf *ibuf); /* threaded processors */ -void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_customdata, - void (init_handle) (void *handle, int start_line, int tot_line, - void *customdata), - void *(do_thread) (void *)); - -typedef void (*ScanlineThreadFunc) (void *custom_data, - int start_scanline, - int num_scanlines); +void IMB_processor_apply_threaded( + int buffer_lines, + int handle_size, + void *init_customdata, + void(init_handle)(void *handle, int start_line, int tot_line, void *customdata), + void *(do_thread)(void *)); + +typedef void (*ScanlineThreadFunc)(void *custom_data, int start_scanline, int num_scanlines); void IMB_processor_apply_threaded_scanlines(int total_scanlines, ScanlineThreadFunc do_thread, void *custom_data); - /* ffmpeg */ void IMB_ffmpeg_init(void); const char *IMB_ffmpeg_last_error(void); @@ -590,23 +705,36 @@ const char *IMB_ffmpeg_last_error(void); * * \attention defined in stereoimbuf.c */ -void IMB_stereo3d_write_dimensions( - const char mode, const bool is_squeezed, const size_t width, const size_t height, - size_t *r_width, size_t *r_height); -void IMB_stereo3d_read_dimensions( - const char mode, const bool is_squeezed, const size_t width, const size_t height, - size_t *r_width, size_t *r_height); -int *IMB_stereo3d_from_rect( - struct ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, - int *rect_left, int *rect_right); -float *IMB_stereo3d_from_rectf( - struct ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, - float *rectf_left, float *rectf_right); -struct ImBuf *IMB_stereo3d_ImBuf( - struct ImageFormatData *im_format, - struct ImBuf *ibuf_left, struct ImBuf *ibuf_right); -void IMB_ImBufFromStereo3d( - struct Stereo3dFormat *s3d, struct ImBuf *ibuf_stereo, - struct ImBuf **r_ibuf_left, struct ImBuf **r_ibuf_right); +void IMB_stereo3d_write_dimensions(const char mode, + const bool is_squeezed, + const size_t width, + const size_t height, + size_t *r_width, + size_t *r_height); +void IMB_stereo3d_read_dimensions(const char mode, + const bool is_squeezed, + const size_t width, + const size_t height, + size_t *r_width, + size_t *r_height); +int *IMB_stereo3d_from_rect(struct ImageFormatData *im_format, + const size_t x, + const size_t y, + const size_t channels, + int *rect_left, + int *rect_right); +float *IMB_stereo3d_from_rectf(struct ImageFormatData *im_format, + const size_t x, + const size_t y, + const size_t channels, + float *rectf_left, + float *rectf_right); +struct ImBuf *IMB_stereo3d_ImBuf(struct ImageFormatData *im_format, + struct ImBuf *ibuf_left, + struct ImBuf *ibuf_right); +void IMB_ImBufFromStereo3d(struct Stereo3dFormat *s3d, + struct ImBuf *ibuf_stereo, + struct ImBuf **r_ibuf_left, + struct ImBuf **r_ibuf_right); #endif diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index d6e33d0d186..d6bebe197c4 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -20,7 +20,7 @@ #ifndef __IMB_IMBUF_TYPES_H__ #define __IMB_IMBUF_TYPES_H__ -#include "DNA_vec_types.h" /* for rcti */ +#include "DNA_vec_types.h" /* for rcti */ /** \file * \ingroup imbuf @@ -38,18 +38,18 @@ * contains an Amiga-format file). */ -#define IMB_MIPMAP_LEVELS 20 -#define IMB_FILENAME_SIZE 1024 +#define IMB_MIPMAP_LEVELS 20 +#define IMB_FILENAME_SIZE 1024 typedef struct DDSData { - /** DDS fourcc info */ - unsigned int fourcc; - /** The number of mipmaps in the dds file */ - unsigned int nummipmaps; - /** The compressed image data */ - unsigned char *data; - /** The size of the compressed data */ - unsigned int size; + /** DDS fourcc info */ + unsigned int fourcc; + /** The number of mipmaps in the dds file */ + unsigned int nummipmaps; + /** The compressed image data */ + unsigned char *data; + /** The size of the compressed data */ + unsigned int size; } DDSData; /** @@ -60,7 +60,6 @@ typedef struct DDSData { * Also; add new variables to the end to save pain! */ - /* Warning: Keep explicit value assignments here, * this file is included in areas where not all format defines are set * (e.g. intern/dds only get WITH_DDS, even if TIFF, HDR etc are also defined). @@ -68,183 +67,183 @@ typedef struct DDSData { /** #ImBuf.ftype flag, main image types. */ enum eImbTypes { - IMB_FTYPE_PNG = 1, - IMB_FTYPE_TGA = 2, - IMB_FTYPE_JPG = 3, - IMB_FTYPE_BMP = 4, - IMB_FTYPE_OPENEXR = 5, - IMB_FTYPE_IMAGIC = 6, + IMB_FTYPE_PNG = 1, + IMB_FTYPE_TGA = 2, + IMB_FTYPE_JPG = 3, + IMB_FTYPE_BMP = 4, + IMB_FTYPE_OPENEXR = 5, + IMB_FTYPE_IMAGIC = 6, #ifdef WITH_OPENIMAGEIO - IMB_FTYPE_PSD = 7, + IMB_FTYPE_PSD = 7, #endif #ifdef WITH_OPENJPEG - IMB_FTYPE_JP2 = 8, + IMB_FTYPE_JP2 = 8, #endif #ifdef WITH_HDR - IMB_FTYPE_RADHDR = 9, + IMB_FTYPE_RADHDR = 9, #endif #ifdef WITH_TIFF - IMB_FTYPE_TIF = 10, + IMB_FTYPE_TIF = 10, #endif #ifdef WITH_CINEON - IMB_FTYPE_CINEON = 11, - IMB_FTYPE_DPX = 12, + IMB_FTYPE_CINEON = 11, + IMB_FTYPE_DPX = 12, #endif #ifdef WITH_DDS - IMB_FTYPE_DDS = 13, + IMB_FTYPE_DDS = 13, #endif }; /* ibuf->foptions flag, type specific options. * Some formats include compression rations on some bits */ -#define OPENEXR_HALF (1 << 8 ) +#define OPENEXR_HALF (1 << 8) /* careful changing this, it's used in DNA as well */ #define OPENEXR_COMPRESS (15) #ifdef WITH_CINEON -#define CINEON_LOG (1 << 8) -#define CINEON_16BIT (1 << 7) -#define CINEON_12BIT (1 << 6) -#define CINEON_10BIT (1 << 5) +# define CINEON_LOG (1 << 8) +# define CINEON_16BIT (1 << 7) +# define CINEON_12BIT (1 << 6) +# define CINEON_10BIT (1 << 5) #endif #ifdef WITH_OPENJPEG -#define JP2_12BIT (1 << 9) -#define JP2_16BIT (1 << 8) -#define JP2_YCC (1 << 7) -#define JP2_CINE (1 << 6) -#define JP2_CINE_48FPS (1 << 5) -#define JP2_JP2 (1 << 4) -#define JP2_J2K (1 << 3) +# define JP2_12BIT (1 << 9) +# define JP2_16BIT (1 << 8) +# define JP2_YCC (1 << 7) +# define JP2_CINE (1 << 6) +# define JP2_CINE_48FPS (1 << 5) +# define JP2_JP2 (1 << 4) +# define JP2_J2K (1 << 3) #endif -#define PNG_16BIT (1 << 10) +#define PNG_16BIT (1 << 10) -#define RAWTGA 1 +#define RAWTGA 1 #ifdef WITH_TIFF -#define TIF_16BIT (1 << 8) -#define TIF_COMPRESS_NONE (1 << 7) -#define TIF_COMPRESS_DEFLATE (1 << 6) -#define TIF_COMPRESS_LZW (1 << 5) -#define TIF_COMPRESS_PACKBITS (1 << 4) +# define TIF_16BIT (1 << 8) +# define TIF_COMPRESS_NONE (1 << 7) +# define TIF_COMPRESS_DEFLATE (1 << 6) +# define TIF_COMPRESS_LZW (1 << 5) +# define TIF_COMPRESS_PACKBITS (1 << 4) #endif typedef struct ImbFormatOptions { - short flag; - /** quality serves dual purpose as quality number for jpeg or compression amount for png */ - char quality; + short flag; + /** quality serves dual purpose as quality number for jpeg or compression amount for png */ + char quality; } ImbFormatOptions; typedef struct ImBuf { - struct ImBuf *next, *prev; /**< allow lists of ImBufs, for caches or flipbooks */ - - /* dimensions */ - /** Width and Height of our image buffer. - * Should be 'unsigned int' since most formats use this. - * but this is problematic with texture math in imagetexture.c - * avoid problems and use int. - campbell */ - int x, y; - - /** Active amount of bits/bitplanes */ - unsigned char planes; - /** Number of channels in `rect_float` (0 = 4 channel default) */ - int channels; - - /* flags */ - /** Controls which components should exist. */ - int flags; - /** what is malloced internal, and can be freed */ - int mall; - - /* pixels */ - - /** Image pixel buffer (8bit representation): - * - color space defaults to `sRGB`. - * - alpha defaults to 'straight'. - */ - unsigned int *rect; - /** Image pixel buffer (float representation): - * - color space defaults to 'linear' (`rec709`). - * - alpha defaults to 'premul'. - * \note May need gamma correction to `sRGB` when generating 8bit representations. - * \note Formats that support higher more than 8 but channels load as floats. - */ - float *rect_float; - - /* resolution - pixels per meter */ - double ppm[2]; - - /* tiled pixel storage */ - int tilex, tiley; - int xtiles, ytiles; - unsigned int **tiles; - - /* zbuffer */ - /** z buffer data, original zbuffer */ - int *zbuf; - /** z buffer data, camera coordinates */ - float *zbuf_float; - - /* parameters used by conversion between byte and float */ - /** random dither value, for conversion from float -> byte rect */ - float dither; - - /* mipmapping */ - /** MipMap levels, a series of halved images */ - struct ImBuf *mipmap[IMB_MIPMAP_LEVELS]; - int miptot, miplevel; - - /* externally used data */ - /** reference index for ImBuf lists */ - int index; - /** used to set imbuf to dirty and other stuff */ - int userflags; - /** image metadata */ - struct IDProperty *metadata; - /** temporary storage */ - void *userdata; - - /* file information */ - /** file type we are going to save as */ - enum eImbTypes ftype; - /** file format specific flags */ - ImbFormatOptions foptions; - /** filename associated with this image */ - char name[IMB_FILENAME_SIZE]; - /** full filename used for reading from cache */ - char cachename[IMB_FILENAME_SIZE]; - - /* memory cache limiter */ - /** handle for cache limiter */ - struct MEM_CacheLimiterHandle_s *c_handle; - /** reference counter for multiple users */ - int refcounter; - - /* some parameters to pass along for packing images */ - /** Compressed image only used with png currently */ - unsigned char *encodedbuffer; - /** Size of data written to encodedbuffer */ - unsigned int encodedsize; - /** Size of encodedbuffer */ - unsigned int encodedbuffersize; - - /* color management */ - /** color space of byte buffer */ - struct ColorSpace *rect_colorspace; - /** color space of float buffer, used by sequencer only */ - struct ColorSpace *float_colorspace; - /** array of per-display display buffers dirty flags */ - unsigned int *display_buffer_flags; - /** cache used by color management */ - struct ColormanageCache *colormanage_cache; - int colormanage_flag; - rcti invalid_rect; - - /* information for compressed textures */ - struct DDSData dds_data; + struct ImBuf *next, *prev; /**< allow lists of ImBufs, for caches or flipbooks */ + + /* dimensions */ + /** Width and Height of our image buffer. + * Should be 'unsigned int' since most formats use this. + * but this is problematic with texture math in imagetexture.c + * avoid problems and use int. - campbell */ + int x, y; + + /** Active amount of bits/bitplanes */ + unsigned char planes; + /** Number of channels in `rect_float` (0 = 4 channel default) */ + int channels; + + /* flags */ + /** Controls which components should exist. */ + int flags; + /** what is malloced internal, and can be freed */ + int mall; + + /* pixels */ + + /** Image pixel buffer (8bit representation): + * - color space defaults to `sRGB`. + * - alpha defaults to 'straight'. + */ + unsigned int *rect; + /** Image pixel buffer (float representation): + * - color space defaults to 'linear' (`rec709`). + * - alpha defaults to 'premul'. + * \note May need gamma correction to `sRGB` when generating 8bit representations. + * \note Formats that support higher more than 8 but channels load as floats. + */ + float *rect_float; + + /* resolution - pixels per meter */ + double ppm[2]; + + /* tiled pixel storage */ + int tilex, tiley; + int xtiles, ytiles; + unsigned int **tiles; + + /* zbuffer */ + /** z buffer data, original zbuffer */ + int *zbuf; + /** z buffer data, camera coordinates */ + float *zbuf_float; + + /* parameters used by conversion between byte and float */ + /** random dither value, for conversion from float -> byte rect */ + float dither; + + /* mipmapping */ + /** MipMap levels, a series of halved images */ + struct ImBuf *mipmap[IMB_MIPMAP_LEVELS]; + int miptot, miplevel; + + /* externally used data */ + /** reference index for ImBuf lists */ + int index; + /** used to set imbuf to dirty and other stuff */ + int userflags; + /** image metadata */ + struct IDProperty *metadata; + /** temporary storage */ + void *userdata; + + /* file information */ + /** file type we are going to save as */ + enum eImbTypes ftype; + /** file format specific flags */ + ImbFormatOptions foptions; + /** filename associated with this image */ + char name[IMB_FILENAME_SIZE]; + /** full filename used for reading from cache */ + char cachename[IMB_FILENAME_SIZE]; + + /* memory cache limiter */ + /** handle for cache limiter */ + struct MEM_CacheLimiterHandle_s *c_handle; + /** reference counter for multiple users */ + int refcounter; + + /* some parameters to pass along for packing images */ + /** Compressed image only used with png currently */ + unsigned char *encodedbuffer; + /** Size of data written to encodedbuffer */ + unsigned int encodedsize; + /** Size of encodedbuffer */ + unsigned int encodedbuffersize; + + /* color management */ + /** color space of byte buffer */ + struct ColorSpace *rect_colorspace; + /** color space of float buffer, used by sequencer only */ + struct ColorSpace *float_colorspace; + /** array of per-display display buffers dirty flags */ + unsigned int *display_buffer_flags; + /** cache used by color management */ + struct ColormanageCache *colormanage_cache; + int colormanage_flag; + rcti invalid_rect; + + /* information for compressed textures */ + struct DDSData dds_data; } ImBuf; /** @@ -252,16 +251,16 @@ typedef struct ImBuf { */ enum { - /** image needs to be saved is not the same as filename */ - IB_BITMAPDIRTY = (1 << 1), - /** image mipmaps are invalid, need recreate */ - IB_MIPMAP_INVALID = (1 << 2), - /** float buffer changed, needs recreation of byte rect */ - IB_RECT_INVALID = (1 << 3), - /** either float or byte buffer changed, need to re-calculate display buffers */ - IB_DISPLAY_BUFFER_INVALID = (1 << 4), - /** image buffer is persistent in the memory and should never be removed from the cache */ - IB_PERSISTENT = (1 << 5), + /** image needs to be saved is not the same as filename */ + IB_BITMAPDIRTY = (1 << 1), + /** image mipmaps are invalid, need recreate */ + IB_MIPMAP_INVALID = (1 << 2), + /** float buffer changed, needs recreation of byte rect */ + IB_RECT_INVALID = (1 << 3), + /** either float or byte buffer changed, need to re-calculate display buffers */ + IB_DISPLAY_BUFFER_INVALID = (1 << 4), + /** image buffer is persistent in the memory and should never be removed from the cache */ + IB_PERSISTENT = (1 << 5), }; /** @@ -271,25 +270,25 @@ enum { * \{ */ enum { - IB_rect = 1 << 0, - IB_test = 1 << 1, - IB_zbuf = 1 << 3, - IB_mem = 1 << 4, - IB_rectfloat = 1 << 5, - IB_zbuffloat = 1 << 6, - IB_multilayer = 1 << 7, - IB_metadata = 1 << 8, - IB_animdeinterlace = 1 << 9, - IB_tiles = 1 << 10, - IB_tilecache = 1 << 11, - /** indicates whether image on disk have premul alpha */ - IB_alphamode_premul = 1 << 12, - /** if this flag is set, alpha mode would be guessed from file */ - IB_alphamode_detect = 1 << 13, - /** ignore alpha on load and substitute it with 1.0f */ - IB_ignore_alpha = 1 << 14, - IB_thumbnail = 1 << 15, - IB_multiview = 1 << 16, + IB_rect = 1 << 0, + IB_test = 1 << 1, + IB_zbuf = 1 << 3, + IB_mem = 1 << 4, + IB_rectfloat = 1 << 5, + IB_zbuffloat = 1 << 6, + IB_multilayer = 1 << 7, + IB_metadata = 1 << 8, + IB_animdeinterlace = 1 << 9, + IB_tiles = 1 << 10, + IB_tilecache = 1 << 11, + /** indicates whether image on disk have premul alpha */ + IB_alphamode_premul = 1 << 12, + /** if this flag is set, alpha mode would be guessed from file */ + IB_alphamode_detect = 1 << 13, + /** ignore alpha on load and substitute it with 1.0f */ + IB_ignore_alpha = 1 << 14, + IB_thumbnail = 1 << 15, + IB_multiview = 1 << 16, }; /** \} */ @@ -299,35 +298,33 @@ enum { * \brief Some predefined color space profiles that 8 bit imbufs can represent * * \{ */ -#define IB_PROFILE_NONE 0 -#define IB_PROFILE_LINEAR_RGB 1 -#define IB_PROFILE_SRGB 2 -#define IB_PROFILE_CUSTOM 3 +#define IB_PROFILE_NONE 0 +#define IB_PROFILE_LINEAR_RGB 1 +#define IB_PROFILE_SRGB 2 +#define IB_PROFILE_CUSTOM 3 /** \} */ /* dds */ #ifdef WITH_DDS -#ifndef DDS_MAKEFOURCC -#define DDS_MAKEFOURCC(ch0, ch1, ch2, ch3)\ - ((unsigned long)(unsigned char)(ch0) | \ - ((unsigned long)(unsigned char)(ch1) << 8) | \ - ((unsigned long)(unsigned char)(ch2) << 16) | \ - ((unsigned long)(unsigned char)(ch3) << 24)) -#endif /* DDS_MAKEFOURCC */ +# ifndef DDS_MAKEFOURCC +# define DDS_MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((unsigned long)(unsigned char)(ch0) | ((unsigned long)(unsigned char)(ch1) << 8) | \ + ((unsigned long)(unsigned char)(ch2) << 16) | ((unsigned long)(unsigned char)(ch3) << 24)) +# endif /* DDS_MAKEFOURCC */ /* * FOURCC codes for DX compressed-texture pixel formats */ -#define FOURCC_DDS (DDS_MAKEFOURCC('D','D','S',' ')) -#define FOURCC_DXT1 (DDS_MAKEFOURCC('D','X','T','1')) -#define FOURCC_DXT2 (DDS_MAKEFOURCC('D','X','T','2')) -#define FOURCC_DXT3 (DDS_MAKEFOURCC('D','X','T','3')) -#define FOURCC_DXT4 (DDS_MAKEFOURCC('D','X','T','4')) -#define FOURCC_DXT5 (DDS_MAKEFOURCC('D','X','T','5')) +# define FOURCC_DDS (DDS_MAKEFOURCC('D', 'D', 'S', ' ')) +# define FOURCC_DXT1 (DDS_MAKEFOURCC('D', 'X', 'T', '1')) +# define FOURCC_DXT2 (DDS_MAKEFOURCC('D', 'X', 'T', '2')) +# define FOURCC_DXT3 (DDS_MAKEFOURCC('D', 'X', 'T', '3')) +# define FOURCC_DXT4 (DDS_MAKEFOURCC('D', 'X', 'T', '4')) +# define FOURCC_DXT5 (DDS_MAKEFOURCC('D', 'X', 'T', '5')) -#endif /* DDS */ +#endif /* DDS */ extern const char *imb_ext_image[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; @@ -342,9 +339,9 @@ extern const char *imb_ext_image_filepath_only[]; * \{ */ enum { - IMB_COLORMANAGE_IS_DATA = (1 << 0), + IMB_COLORMANAGE_IS_DATA = (1 << 0), }; /** \} */ -#endif /* __IMB_IMBUF_TYPES_H__ */ +#endif /* __IMB_IMBUF_TYPES_H__ */ diff --git a/source/blender/imbuf/IMB_metadata.h b/source/blender/imbuf/IMB_metadata.h index d4e8dc1a3b6..64a8db6c526 100644 --- a/source/blender/imbuf/IMB_metadata.h +++ b/source/blender/imbuf/IMB_metadata.h @@ -21,7 +21,6 @@ * \ingroup imbuf */ - #ifndef __IMB_METADATA_H__ #define __IMB_METADATA_H__ @@ -53,7 +52,10 @@ void IMB_metadata_free(struct IDProperty *metadata); * \param len: length of value buffer allocated by user. * \return - 1 (true) if metadata is present and value for the key found, 0 (false) otherwise */ -bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *value, const size_t len); +bool IMB_metadata_get_field(struct IDProperty *metadata, + const char *key, + char *value, + const size_t len); /** Set user data in the metadata. * If the field already exists its value is overwritten, otherwise the field diff --git a/source/blender/imbuf/IMB_moviecache.h b/source/blender/imbuf/IMB_moviecache.h index 706c7b1a7db..25494df9c00 100644 --- a/source/blender/imbuf/IMB_moviecache.h +++ b/source/blender/imbuf/IMB_moviecache.h @@ -34,18 +34,23 @@ struct ImBuf; struct MovieCache; -typedef void (*MovieCacheGetKeyDataFP) (void *userkey, int *framenr, int *proxy, int *render_flags); +typedef void (*MovieCacheGetKeyDataFP)(void *userkey, int *framenr, int *proxy, int *render_flags); -typedef void *(*MovieCacheGetPriorityDataFP) (void *userkey); -typedef int (*MovieCacheGetItemPriorityFP) (void *last_userkey, void *priority_data); -typedef void (*MovieCachePriorityDeleterFP) (void *priority_data); +typedef void *(*MovieCacheGetPriorityDataFP)(void *userkey); +typedef int (*MovieCacheGetItemPriorityFP)(void *last_userkey, void *priority_data); +typedef void (*MovieCachePriorityDeleterFP)(void *priority_data); void IMB_moviecache_init(void); void IMB_moviecache_destruct(void); -struct MovieCache *IMB_moviecache_create(const char *name, int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp); -void IMB_moviecache_set_getdata_callback(struct MovieCache *cache, MovieCacheGetKeyDataFP getdatafp); -void IMB_moviecache_set_priority_callback(struct MovieCache *cache, MovieCacheGetPriorityDataFP getprioritydatafp, +struct MovieCache *IMB_moviecache_create(const char *name, + int keysize, + GHashHashFP hashfp, + GHashCmpFP cmpfp); +void IMB_moviecache_set_getdata_callback(struct MovieCache *cache, + MovieCacheGetKeyDataFP getdatafp); +void IMB_moviecache_set_priority_callback(struct MovieCache *cache, + MovieCacheGetPriorityDataFP getprioritydatafp, MovieCacheGetItemPriorityFP getitempriorityfp, MovieCachePriorityDeleterFP prioritydeleterfp); @@ -56,10 +61,13 @@ bool IMB_moviecache_has_frame(struct MovieCache *cache, void *userkey); void IMB_moviecache_free(struct MovieCache *cache); void IMB_moviecache_cleanup(struct MovieCache *cache, - bool (cleanup_check_cb) (struct ImBuf *ibuf, void *userkey, void *userdata), + bool(cleanup_check_cb)(struct ImBuf *ibuf, + void *userkey, + void *userdata), void *userdata); -void IMB_moviecache_get_cache_segments(struct MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r); +void IMB_moviecache_get_cache_segments( + struct MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r); struct MovieCacheIter; struct MovieCacheIter *IMB_moviecacheIter_new(struct MovieCache *cache); diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index 1c64edb21da..bac408e869b 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -21,7 +21,6 @@ * \ingroup imbuf */ - #ifndef __IMB_THUMBS_H__ #define __IMB_THUMBS_H__ @@ -36,18 +35,17 @@ struct ImBuf; * Reference: http://jens.triq.net/thumbnail-spec/index.html */ - typedef enum ThumbSize { - THB_NORMAL, - THB_LARGE, - THB_FAIL, + THB_NORMAL, + THB_LARGE, + THB_FAIL, } ThumbSize; typedef enum ThumbSource { - THB_SOURCE_IMAGE, - THB_SOURCE_MOVIE, - THB_SOURCE_BLEND, - THB_SOURCE_FONT, + THB_SOURCE_IMAGE, + THB_SOURCE_MOVIE, + THB_SOURCE_BLEND, + THB_SOURCE_FONT, } ThumbSource; /* don't generate thumbs for images bigger then this (100mb) */ @@ -58,7 +56,7 @@ typedef enum ThumbSource { /* Note this can also be used as versioning system, * to force refreshing all thumbnails if e.g. we change some thumb generating code or so. * Only used by fonts so far. */ -#define THUMB_DEFAULT_HASH "00000000000000000000000000000000" +#define THUMB_DEFAULT_HASH "00000000000000000000000000000000" /* create thumbnail for file and returns new imbuf for thumbnail */ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *ibuf); @@ -77,7 +75,7 @@ void IMB_thumb_makedirs(void); /* special function for loading a thumbnail embedded into a blend file */ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id); -void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect); +void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect); /* special function for previewing fonts */ ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y); diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index a0a8a938870..065c7e64d07 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -21,7 +21,6 @@ * \ingroup imbuf */ - #ifndef __IMB_ANIM_H__ #define __IMB_ANIM_H__ @@ -34,9 +33,9 @@ # include # include -# undef AVIIF_KEYFRAME // redefined in AVI_avi.h -# undef AVIIF_LIST // redefined in AVI_avi.h -#endif /* _WIN32 */ +# undef AVIIF_KEYFRAME // redefined in AVI_avi.h +# undef AVIIF_LIST // redefined in AVI_avi.h +#endif /* _WIN32 */ #include #include @@ -74,84 +73,84 @@ #endif /* anim.curtype, runtime only */ -#define ANIM_NONE 0 -#define ANIM_SEQUENCE (1 << 0) -#define ANIM_MOVIE (1 << 4) -#define ANIM_AVI (1 << 6) -#define ANIM_FFMPEG (1 << 8) +#define ANIM_NONE 0 +#define ANIM_SEQUENCE (1 << 0) +#define ANIM_MOVIE (1 << 4) +#define ANIM_AVI (1 << 6) +#define ANIM_FFMPEG (1 << 8) -#define MAXNUMSTREAMS 50 +#define MAXNUMSTREAMS 50 struct IDProperty; struct _AviMovie; struct anim_index; struct anim { - int ib_flags; - int curtype; - int curposition; /* index 0 = 1e, 1 = 2e, enz. */ - int duration; - int frs_sec; - double frs_sec_base; - int x, y; - - /* for number */ - char name[1024]; - /* for sequence */ - char first[1024]; - - /* movie */ - void *movie; - void *track; - void *params; - int orientation; - size_t framesize; - int interlacing; - int preseek; - int streamindex; - - /* avi */ - struct _AviMovie *avi; + int ib_flags; + int curtype; + int curposition; /* index 0 = 1e, 1 = 2e, enz. */ + int duration; + int frs_sec; + double frs_sec_base; + int x, y; + + /* for number */ + char name[1024]; + /* for sequence */ + char first[1024]; + + /* movie */ + void *movie; + void *track; + void *params; + int orientation; + size_t framesize; + int interlacing; + int preseek; + int streamindex; + + /* avi */ + struct _AviMovie *avi; #if defined(_WIN32) - /* windows avi */ - int avistreams; - int firstvideo; - int pfileopen; - PAVIFILE pfile; - PAVISTREAM pavi[MAXNUMSTREAMS]; // the current streams - PGETFRAME pgf; + /* windows avi */ + int avistreams; + int firstvideo; + int pfileopen; + PAVIFILE pfile; + PAVISTREAM pavi[MAXNUMSTREAMS]; // the current streams + PGETFRAME pgf; #endif #ifdef WITH_FFMPEG - AVFormatContext *pFormatCtx; - AVCodecContext *pCodecCtx; - AVCodec *pCodec; - AVFrame *pFrame; - int pFrameComplete; - AVFrame *pFrameRGB; - AVFrame *pFrameDeinterlaced; - struct SwsContext *img_convert_ctx; - int videoStream; - - struct ImBuf *last_frame; - int64_t last_pts; - int64_t next_pts; - AVPacket next_packet; + AVFormatContext *pFormatCtx; + AVCodecContext *pCodecCtx; + AVCodec *pCodec; + AVFrame *pFrame; + int pFrameComplete; + AVFrame *pFrameRGB; + AVFrame *pFrameDeinterlaced; + struct SwsContext *img_convert_ctx; + int videoStream; + + struct ImBuf *last_frame; + int64_t last_pts; + int64_t next_pts; + AVPacket next_packet; #endif - char index_dir[768]; + char index_dir[768]; - int proxies_tried; - int indices_tried; + int proxies_tried; + int indices_tried; - struct anim *proxy_anim[IMB_PROXY_MAX_SLOT]; - struct anim_index *curr_idx[IMB_TC_MAX_SLOT]; + struct anim *proxy_anim[IMB_PROXY_MAX_SLOT]; + struct anim_index *curr_idx[IMB_TC_MAX_SLOT]; - char colorspace[64]; - char suffix[64]; /* MAX_NAME - multiview */ + char colorspace[64]; + char suffix[64]; /* MAX_NAME - multiview */ - struct IDProperty *metadata; + struct IDProperty *metadata; }; #endif diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 7ab36b69704..2566016ffdd 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -34,46 +34,46 @@ extern float imbuf_luma_coefficients[3]; extern float imbuf_xyz_to_rgb[3][3]; extern float imbuf_rgb_to_xyz[3][3]; -#define MAX_COLORSPACE_NAME 64 -#define MAX_COLORSPACE_DESCRIPTION 512 +#define MAX_COLORSPACE_NAME 64 +#define MAX_COLORSPACE_DESCRIPTION 512 typedef struct ColorSpace { - struct ColorSpace *next, *prev; - int index; - char name[MAX_COLORSPACE_NAME]; - char description[MAX_COLORSPACE_DESCRIPTION]; + struct ColorSpace *next, *prev; + int index; + char name[MAX_COLORSPACE_NAME]; + char description[MAX_COLORSPACE_DESCRIPTION]; - struct OCIO_ConstProcessorRcPtr *to_scene_linear; - struct OCIO_ConstProcessorRcPtr *from_scene_linear; + struct OCIO_ConstProcessorRcPtr *to_scene_linear; + struct OCIO_ConstProcessorRcPtr *from_scene_linear; - bool is_invertible; - bool is_data; + bool is_invertible; + bool is_data; } ColorSpace; typedef struct ColorManagedDisplay { - struct ColorManagedDisplay *next, *prev; - int index; - char name[MAX_COLORSPACE_NAME]; - ListBase views; /* LinkData.data -> ColorManagedView */ + struct ColorManagedDisplay *next, *prev; + int index; + char name[MAX_COLORSPACE_NAME]; + ListBase views; /* LinkData.data -> ColorManagedView */ - struct OCIO_ConstProcessorRcPtr *to_scene_linear; - struct OCIO_ConstProcessorRcPtr *from_scene_linear; + struct OCIO_ConstProcessorRcPtr *to_scene_linear; + struct OCIO_ConstProcessorRcPtr *from_scene_linear; } ColorManagedDisplay; typedef struct ColorManagedView { - struct ColorManagedView *next, *prev; - int index; - char name[MAX_COLORSPACE_NAME]; + struct ColorManagedView *next, *prev; + int index; + char name[MAX_COLORSPACE_NAME]; } ColorManagedView; typedef struct ColorManagedLook { - struct ColorManagedLook *next, *prev; - int index; - char name[MAX_COLORSPACE_NAME]; - char ui_name[MAX_COLORSPACE_NAME]; - char view[MAX_COLORSPACE_NAME]; - char process_space[MAX_COLORSPACE_NAME]; - bool is_noop; + struct ColorManagedLook *next, *prev; + int index; + char name[MAX_COLORSPACE_NAME]; + char ui_name[MAX_COLORSPACE_NAME]; + char view[MAX_COLORSPACE_NAME]; + char process_space[MAX_COLORSPACE_NAME]; + bool is_noop; } ColorManagedLook; /* ** Initialization / De-initialization ** */ @@ -94,15 +94,20 @@ struct ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); struct ColorManagedView *colormanage_view_get_named(const char *name); -struct ColorManagedView *colormanage_view_get_named_for_display( - const char *display_name, const char *name); +struct ColorManagedView *colormanage_view_get_named_for_display(const char *display_name, + const char *name); -struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, bool is_invertible, bool is_data); +struct ColorSpace *colormanage_colorspace_add(const char *name, + const char *description, + bool is_invertible, + bool is_data); struct ColorSpace *colormanage_colorspace_get_named(const char *name); struct ColorSpace *colormanage_colorspace_get_roled(int role); struct ColorSpace *colormanage_colorspace_get_indexed(int index); -struct ColorManagedLook *colormanage_look_add(const char *name, const char *process_space, bool is_noop); +struct ColorManagedLook *colormanage_look_add(const char *name, + const char *process_space, + bool is_noop); struct ColorManagedLook *colormanage_look_get_named(const char *name); struct ColorManagedLook *colormanage_look_get_indexed(int index); @@ -111,4 +116,4 @@ void colorspace_set_default_role(char *colorspace, int size, int role); void colormanage_imbuf_set_default_spaces(struct ImBuf *ibuf); void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace); -#endif /* __IMB_COLORMANAGEMENT_INTERN_H__ */ +#endif /* __IMB_COLORMANAGEMENT_INTERN_H__ */ diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 8ce1a293d0f..5048414ac65 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -18,7 +18,6 @@ * \ingroup imbuf */ - #ifndef __IMB_FILETYPE_H__ #define __IMB_FILETYPE_H__ @@ -26,23 +25,31 @@ struct ImBuf; -#define IM_FTYPE_FLOAT 1 +#define IM_FTYPE_FLOAT 1 typedef struct ImFileType { - void (*init)(void); - void (*exit)(void); - - int (*is_a)(const unsigned char *buf); - int (*is_a_filepath)(const char *name); - int (*ftype)(const struct ImFileType *type, struct ImBuf *ibuf); - struct ImBuf *(*load)(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); - struct ImBuf *(*load_filepath)(const char *name, int flags, char colorspace[IM_MAX_SPACE]); - int (*save)(struct ImBuf *ibuf, const char *name, int flags); - void (*load_tile)(struct ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect); - - int flag; - int filetype; - int default_save_role; + void (*init)(void); + void (*exit)(void); + + int (*is_a)(const unsigned char *buf); + int (*is_a_filepath)(const char *name); + int (*ftype)(const struct ImFileType *type, struct ImBuf *ibuf); + struct ImBuf *(*load)(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); + struct ImBuf *(*load_filepath)(const char *name, int flags, char colorspace[IM_MAX_SPACE]); + int (*save)(struct ImBuf *ibuf, const char *name, int flags); + void (*load_tile)(struct ImBuf *ibuf, + const unsigned char *mem, + size_t size, + int tx, + int ty, + unsigned int *rect); + + int flag; + int filetype; + int default_save_role; } ImFileType; extern const ImFileType IMB_FILE_TYPES[]; @@ -61,56 +68,86 @@ void imb_tile_cache_tile_free(struct ImBuf *ibuf, int tx, int ty); /* png */ int imb_is_a_png(const unsigned char *buf); -struct ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_loadpng(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); int imb_savepng(struct ImBuf *ibuf, const char *name, int flags); /* targa */ int imb_is_a_targa(const unsigned char *buf); -struct ImBuf *imb_loadtarga(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_loadtarga(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags); /* iris */ int imb_is_a_iris(const unsigned char *mem); -struct ImBuf *imb_loadiris(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_loadiris(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); int imb_saveiris(struct ImBuf *ibuf, const char *name, int flags); /* jp2 */ int imb_is_a_jp2(const unsigned char *buf); -struct ImBuf *imb_load_jp2(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_jp2(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); struct ImBuf *imb_load_jp2_filepath(const char *name, int flags, char colorspace[IM_MAX_SPACE]); int imb_save_jp2(struct ImBuf *ibuf, const char *name, int flags); /* jpeg */ int imb_is_a_jpeg(const unsigned char *mem); int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_jpeg(const unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_jpeg(const unsigned char *buffer, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); /* bmp */ int imb_is_a_bmp(const unsigned char *buf); -struct ImBuf *imb_bmp_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_bmp_decode(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags); /* cineon */ int imb_is_cineon(const unsigned char *buf); int imb_save_cineon(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_load_cineon(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_cineon(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); /* dpx */ int imb_is_dpx(const unsigned char *buf); int imb_save_dpx(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_load_dpx(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_dpx(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); /* hdr */ int imb_is_a_hdr(const unsigned char *buf); -struct ImBuf *imb_loadhdr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_loadhdr(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); int imb_savehdr(struct ImBuf *ibuf, const char *name, int flags); /* tiff */ void imb_inittiff(void); int imb_is_a_tiff(const unsigned char *buf); -struct ImBuf *imb_loadtiff(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); -void imb_loadtiletiff(struct ImBuf *ibuf, const unsigned char *mem, size_t size, - int tx, int ty, unsigned int *rect); +struct ImBuf *imb_loadtiff(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); +void imb_loadtiletiff( + struct ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect); int imb_savetiff(struct ImBuf *ibuf, const char *name, int flags); -#endif /* __IMB_FILETYPE_H__ */ +#endif /* __IMB_FILETYPE_H__ */ diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h index 02ba846d148..4817518dab6 100644 --- a/source/blender/imbuf/intern/IMB_indexer.h +++ b/source/blender/imbuf/intern/IMB_indexer.h @@ -14,7 +14,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #ifndef __IMB_INDEXER_H__ #define __IMB_INDEXER_H__ @@ -49,74 +48,68 @@ */ typedef struct anim_index_entry { - int frameno; - unsigned long long seek_pos; - unsigned long long seek_pos_dts; - unsigned long long pts; + int frameno; + unsigned long long seek_pos; + unsigned long long seek_pos_dts; + unsigned long long pts; } anim_index_entry; struct anim_index { - char name[1024]; + char name[1024]; - int num_entries; - struct anim_index_entry *entries; + int num_entries; + struct anim_index_entry *entries; }; struct anim_index_builder; typedef struct anim_index_builder { - FILE *fp; - char name[FILE_MAX]; - char temp_name[FILE_MAX]; + FILE *fp; + 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, - unsigned char *buffer, - int data_size, - struct anim_index_entry *entry); + void (*delete_priv_data)(struct anim_index_builder *idx); + void (*proc_frame)(struct anim_index_builder *idx, + unsigned char *buffer, + int data_size, + struct anim_index_entry *entry); } anim_index_builder; anim_index_builder *IMB_index_builder_create(const char *name); -void IMB_index_builder_add_entry( - anim_index_builder *fp, - int frameno, unsigned long long seek_pos, - unsigned long long seek_pos_dts, - unsigned long long pts); - -void IMB_index_builder_proc_frame( - anim_index_builder *fp, - unsigned char *buffer, - int data_size, - int frameno, unsigned long long seek_pos, - unsigned long long seek_pos_dts, - unsigned long long pts); +void IMB_index_builder_add_entry(anim_index_builder *fp, + int frameno, + unsigned long long seek_pos, + unsigned long long seek_pos_dts, + unsigned long long pts); + +void IMB_index_builder_proc_frame(anim_index_builder *fp, + unsigned char *buffer, + int data_size, + int frameno, + unsigned long long seek_pos, + unsigned long long seek_pos_dts, + unsigned long long pts); void IMB_index_builder_finish(anim_index_builder *fp, int rollback); struct anim_index *IMB_indexer_open(const char *name); -unsigned long long IMB_indexer_get_seek_pos( - struct anim_index *idx, int frameno_index); -unsigned long long IMB_indexer_get_seek_pos_dts( - struct anim_index *idx, int frameno_index); +unsigned long long IMB_indexer_get_seek_pos(struct anim_index *idx, int frameno_index); +unsigned long long IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frameno_index); int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno); -unsigned long long IMB_indexer_get_pts(struct anim_index *idx, - int frame_index); +unsigned long long IMB_indexer_get_pts(struct anim_index *idx, int frame_index); int IMB_indexer_get_duration(struct anim_index *idx); -int IMB_indexer_can_scan(struct anim_index *idx, - int old_frame_index, int new_frame_index); +int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index); void IMB_indexer_close(struct anim_index *idx); void IMB_free_indices(struct anim *anim); -struct anim *IMB_anim_open_proxy( - struct anim *anim, IMB_Proxy_Size preview_size); -struct anim_index *IMB_anim_open_index( - struct anim *anim, IMB_Timecode_Type tc); +struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size); +struct anim_index *IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc); int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size); int IMB_timecode_to_array_index(IMB_Timecode_Type tc); diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index ac284657c5c..2c253f7f0e6 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -21,7 +21,6 @@ * \ingroup imbuf */ - /* It's become a bit messy... Basically, only the IMB_ prefixed files * should remain. */ @@ -46,12 +45,12 @@ static SpinLock refcounter_spin; void imb_refcounter_lock_init(void) { - BLI_spin_init(&refcounter_spin); + BLI_spin_init(&refcounter_spin); } void imb_refcounter_lock_exit(void) { - BLI_spin_end(&refcounter_spin); + BLI_spin_end(&refcounter_spin); } #ifdef WIN32 @@ -59,505 +58,528 @@ static SpinLock mmap_spin; void imb_mmap_lock_init(void) { - BLI_spin_init(&mmap_spin); + BLI_spin_init(&mmap_spin); } void imb_mmap_lock_exit(void) { - BLI_spin_end(&mmap_spin); + BLI_spin_end(&mmap_spin); } void imb_mmap_lock(void) { - BLI_spin_lock(&mmap_spin); + BLI_spin_lock(&mmap_spin); } void imb_mmap_unlock(void) { - BLI_spin_unlock(&mmap_spin); + BLI_spin_unlock(&mmap_spin); } #endif void imb_freemipmapImBuf(ImBuf *ibuf) { - int a; - - /* Do not trust ibuf->miptot, in some cases IMB_remakemipmap can leave unfreed unused levels, - * leading to memory leaks... */ - for (a = 0; a < IMB_MIPMAP_LEVELS; a++) { - if (ibuf->mipmap[a] != NULL) { - IMB_freeImBuf(ibuf->mipmap[a]); - ibuf->mipmap[a] = NULL; - } - } - - ibuf->miptot = 0; + int a; + + /* Do not trust ibuf->miptot, in some cases IMB_remakemipmap can leave unfreed unused levels, + * leading to memory leaks... */ + for (a = 0; a < IMB_MIPMAP_LEVELS; a++) { + if (ibuf->mipmap[a] != NULL) { + IMB_freeImBuf(ibuf->mipmap[a]); + ibuf->mipmap[a] = NULL; + } + } + + ibuf->miptot = 0; } /* any free rect frees mipmaps to be sure, creation is in render on first request */ void imb_freerectfloatImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return; + if (ibuf == NULL) + return; - if (ibuf->rect_float && (ibuf->mall & IB_rectfloat)) { - MEM_freeN(ibuf->rect_float); - ibuf->rect_float = NULL; - } + if (ibuf->rect_float && (ibuf->mall & IB_rectfloat)) { + MEM_freeN(ibuf->rect_float); + ibuf->rect_float = NULL; + } - imb_freemipmapImBuf(ibuf); + imb_freemipmapImBuf(ibuf); - ibuf->rect_float = NULL; - ibuf->mall &= ~IB_rectfloat; + ibuf->rect_float = NULL; + ibuf->mall &= ~IB_rectfloat; } /* any free rect frees mipmaps to be sure, creation is in render on first request */ void imb_freerectImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return; + if (ibuf == NULL) + return; - if (ibuf->rect && (ibuf->mall & IB_rect)) - MEM_freeN(ibuf->rect); - ibuf->rect = NULL; + if (ibuf->rect && (ibuf->mall & IB_rect)) + MEM_freeN(ibuf->rect); + ibuf->rect = NULL; - imb_freemipmapImBuf(ibuf); + imb_freemipmapImBuf(ibuf); - ibuf->mall &= ~IB_rect; + ibuf->mall &= ~IB_rect; } void imb_freetilesImBuf(ImBuf *ibuf) { - int tx, ty; - - if (ibuf == NULL) return; - - if (ibuf->tiles && (ibuf->mall & IB_tiles)) { - for (ty = 0; ty < ibuf->ytiles; ty++) { - for (tx = 0; tx < ibuf->xtiles; tx++) { - if (ibuf->tiles[ibuf->xtiles * ty + tx]) { - imb_tile_cache_tile_free(ibuf, tx, ty); - MEM_freeN(ibuf->tiles[ibuf->xtiles * ty + tx]); - } - } - } - - MEM_freeN(ibuf->tiles); - } - - ibuf->tiles = NULL; - ibuf->mall &= ~IB_tiles; + int tx, ty; + + if (ibuf == NULL) + return; + + if (ibuf->tiles && (ibuf->mall & IB_tiles)) { + for (ty = 0; ty < ibuf->ytiles; ty++) { + for (tx = 0; tx < ibuf->xtiles; tx++) { + if (ibuf->tiles[ibuf->xtiles * ty + tx]) { + imb_tile_cache_tile_free(ibuf, tx, ty); + MEM_freeN(ibuf->tiles[ibuf->xtiles * ty + tx]); + } + } + } + + MEM_freeN(ibuf->tiles); + } + + ibuf->tiles = NULL; + ibuf->mall &= ~IB_tiles; } static void freeencodedbufferImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return; + if (ibuf == NULL) + return; - if (ibuf->encodedbuffer && (ibuf->mall & IB_mem)) - MEM_freeN(ibuf->encodedbuffer); + if (ibuf->encodedbuffer && (ibuf->mall & IB_mem)) + MEM_freeN(ibuf->encodedbuffer); - ibuf->encodedbuffer = NULL; - ibuf->encodedbuffersize = 0; - ibuf->encodedsize = 0; - ibuf->mall &= ~IB_mem; + ibuf->encodedbuffer = NULL; + ibuf->encodedbuffersize = 0; + ibuf->encodedsize = 0; + ibuf->mall &= ~IB_mem; } void IMB_freezbufImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return; + if (ibuf == NULL) + return; - if (ibuf->zbuf && (ibuf->mall & IB_zbuf)) - MEM_freeN(ibuf->zbuf); + if (ibuf->zbuf && (ibuf->mall & IB_zbuf)) + MEM_freeN(ibuf->zbuf); - ibuf->zbuf = NULL; - ibuf->mall &= ~IB_zbuf; + ibuf->zbuf = NULL; + ibuf->mall &= ~IB_zbuf; } void IMB_freezbuffloatImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return; + if (ibuf == NULL) + return; - if (ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat)) - MEM_freeN(ibuf->zbuf_float); + if (ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat)) + MEM_freeN(ibuf->zbuf_float); - ibuf->zbuf_float = NULL; - ibuf->mall &= ~IB_zbuffloat; + ibuf->zbuf_float = NULL; + ibuf->mall &= ~IB_zbuffloat; } void IMB_freeImBuf(ImBuf *ibuf) { - if (ibuf) { - bool needs_free = false; - - BLI_spin_lock(&refcounter_spin); - if (ibuf->refcounter > 0) { - ibuf->refcounter--; - } - else { - needs_free = true; - } - BLI_spin_unlock(&refcounter_spin); - - if (needs_free) { - imb_freerectImBuf(ibuf); - imb_freerectfloatImBuf(ibuf); - imb_freetilesImBuf(ibuf); - IMB_freezbufImBuf(ibuf); - IMB_freezbuffloatImBuf(ibuf); - freeencodedbufferImBuf(ibuf); - IMB_metadata_free(ibuf->metadata); - colormanage_cache_free(ibuf); - - if (ibuf->dds_data.data != NULL) { - free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */ - } - MEM_freeN(ibuf); - } - } + if (ibuf) { + bool needs_free = false; + + BLI_spin_lock(&refcounter_spin); + if (ibuf->refcounter > 0) { + ibuf->refcounter--; + } + else { + needs_free = true; + } + BLI_spin_unlock(&refcounter_spin); + + if (needs_free) { + imb_freerectImBuf(ibuf); + imb_freerectfloatImBuf(ibuf); + imb_freetilesImBuf(ibuf); + IMB_freezbufImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); + freeencodedbufferImBuf(ibuf); + IMB_metadata_free(ibuf->metadata); + colormanage_cache_free(ibuf); + + if (ibuf->dds_data.data != NULL) { + free( + ibuf->dds_data + .data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */ + } + MEM_freeN(ibuf); + } + } } void IMB_refImBuf(ImBuf *ibuf) { - BLI_spin_lock(&refcounter_spin); - ibuf->refcounter++; - BLI_spin_unlock(&refcounter_spin); + BLI_spin_lock(&refcounter_spin); + ibuf->refcounter++; + BLI_spin_unlock(&refcounter_spin); } ImBuf *IMB_makeSingleUser(ImBuf *ibuf) { - ImBuf *rval; + ImBuf *rval; - if (ibuf) { - bool is_single; - BLI_spin_lock(&refcounter_spin); - is_single = (ibuf->refcounter == 0); - BLI_spin_unlock(&refcounter_spin); - if (is_single) { - return ibuf; - } - } - else { - return NULL; - } + if (ibuf) { + bool is_single; + BLI_spin_lock(&refcounter_spin); + is_single = (ibuf->refcounter == 0); + BLI_spin_unlock(&refcounter_spin); + if (is_single) { + return ibuf; + } + } + else { + return NULL; + } - rval = IMB_dupImBuf(ibuf); + rval = IMB_dupImBuf(ibuf); - IMB_metadata_copy(rval, ibuf); + IMB_metadata_copy(rval, ibuf); - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); - return rval; + return rval; } bool addzbufImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return false; + if (ibuf == NULL) + return false; - IMB_freezbufImBuf(ibuf); + IMB_freezbufImBuf(ibuf); - if ((ibuf->zbuf = imb_alloc_pixels(ibuf->x, ibuf->y, 1, sizeof(unsigned int), __func__))) { - ibuf->mall |= IB_zbuf; - ibuf->flags |= IB_zbuf; - return true; - } + if ((ibuf->zbuf = imb_alloc_pixels(ibuf->x, ibuf->y, 1, sizeof(unsigned int), __func__))) { + ibuf->mall |= IB_zbuf; + ibuf->flags |= IB_zbuf; + return true; + } - return false; + return false; } bool addzbuffloatImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return false; + if (ibuf == NULL) + return false; - IMB_freezbuffloatImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); - if ((ibuf->zbuf_float = imb_alloc_pixels(ibuf->x, ibuf->y, 1, sizeof(float), __func__))) { - ibuf->mall |= IB_zbuffloat; - ibuf->flags |= IB_zbuffloat; - return true; - } + if ((ibuf->zbuf_float = imb_alloc_pixels(ibuf->x, ibuf->y, 1, sizeof(float), __func__))) { + ibuf->mall |= IB_zbuffloat; + ibuf->flags |= IB_zbuffloat; + return true; + } - return false; + return false; } - bool imb_addencodedbufferImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return false; + if (ibuf == NULL) + return false; - freeencodedbufferImBuf(ibuf); + freeencodedbufferImBuf(ibuf); - if (ibuf->encodedbuffersize == 0) - ibuf->encodedbuffersize = 10000; + if (ibuf->encodedbuffersize == 0) + ibuf->encodedbuffersize = 10000; - ibuf->encodedsize = 0; + ibuf->encodedsize = 0; - if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, __func__))) { - ibuf->mall |= IB_mem; - ibuf->flags |= IB_mem; - return true; - } + if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, __func__))) { + ibuf->mall |= IB_mem; + ibuf->flags |= IB_mem; + return true; + } - return false; + return false; } - bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf) { - unsigned int newsize, encodedsize; - void *newbuffer; + unsigned int newsize, encodedsize; + void *newbuffer; - if (ibuf == NULL) return false; + if (ibuf == NULL) + return false; - if (ibuf->encodedbuffersize < ibuf->encodedsize) { - printf("%s: error in parameters\n", __func__); - return false; - } + if (ibuf->encodedbuffersize < ibuf->encodedsize) { + printf("%s: error in parameters\n", __func__); + return false; + } - newsize = 2 * ibuf->encodedbuffersize; - if (newsize < 10000) newsize = 10000; + newsize = 2 * ibuf->encodedbuffersize; + if (newsize < 10000) + newsize = 10000; - newbuffer = MEM_mallocN(newsize, __func__); - if (newbuffer == NULL) return false; + newbuffer = MEM_mallocN(newsize, __func__); + if (newbuffer == NULL) + return false; - if (ibuf->encodedbuffer) { - memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize); - } - else { - ibuf->encodedsize = 0; - } + if (ibuf->encodedbuffer) { + memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize); + } + else { + ibuf->encodedsize = 0; + } - encodedsize = ibuf->encodedsize; + encodedsize = ibuf->encodedsize; - freeencodedbufferImBuf(ibuf); + freeencodedbufferImBuf(ibuf); - ibuf->encodedbuffersize = newsize; - ibuf->encodedsize = encodedsize; - ibuf->encodedbuffer = newbuffer; - ibuf->mall |= IB_mem; - ibuf->flags |= IB_mem; + ibuf->encodedbuffersize = newsize; + ibuf->encodedsize = encodedsize; + ibuf->encodedbuffer = newbuffer; + ibuf->mall |= IB_mem; + ibuf->flags |= IB_mem; - return true; + return true; } -void *imb_alloc_pixels(unsigned int x, - unsigned int y, - unsigned int channels, - size_t typesize, - const char *name) +void *imb_alloc_pixels( + unsigned int x, unsigned int y, unsigned int channels, size_t typesize, const char *name) { - /* Protect against buffer overflow vulnerabilities from files specifying - * a width and height that overflow and alloc too little memory. */ - if (!((uint64_t)x * (uint64_t)y < (SIZE_MAX / (channels * typesize)))) { - return NULL; - } - - size_t size = (size_t)x * (size_t)y * (size_t)channels * typesize; - return MEM_mapallocN(size, name); + /* Protect against buffer overflow vulnerabilities from files specifying + * a width and height that overflow and alloc too little memory. */ + if (!((uint64_t)x * (uint64_t)y < (SIZE_MAX / (channels * typesize)))) { + return NULL; + } + + size_t size = (size_t)x * (size_t)y * (size_t)channels * typesize; + return MEM_mapallocN(size, name); } bool imb_addrectfloatImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return false; + if (ibuf == NULL) + return false; - if (ibuf->rect_float) - imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */ + if (ibuf->rect_float) + imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */ - ibuf->channels = 4; - if ((ibuf->rect_float = imb_alloc_pixels(ibuf->x, ibuf->y, 4, sizeof(float), __func__))) { - ibuf->mall |= IB_rectfloat; - ibuf->flags |= IB_rectfloat; - return true; - } + ibuf->channels = 4; + if ((ibuf->rect_float = imb_alloc_pixels(ibuf->x, ibuf->y, 4, sizeof(float), __func__))) { + ibuf->mall |= IB_rectfloat; + ibuf->flags |= IB_rectfloat; + return true; + } - return false; + return false; } /* question; why also add zbuf? */ bool imb_addrectImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return false; - - /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */ - if (ibuf->rect && (ibuf->mall & IB_rect)) - MEM_freeN(ibuf->rect); - ibuf->rect = NULL; - - if ((ibuf->rect = imb_alloc_pixels(ibuf->x, ibuf->y, 4, sizeof(unsigned char), __func__))) { - ibuf->mall |= IB_rect; - ibuf->flags |= IB_rect; - if (ibuf->planes > 32) { - return (addzbufImBuf(ibuf)); - } - else { - return true; - } - } - - return false; + if (ibuf == NULL) + return false; + + /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */ + if (ibuf->rect && (ibuf->mall & IB_rect)) + MEM_freeN(ibuf->rect); + ibuf->rect = NULL; + + if ((ibuf->rect = imb_alloc_pixels(ibuf->x, ibuf->y, 4, sizeof(unsigned char), __func__))) { + ibuf->mall |= IB_rect; + ibuf->flags |= IB_rect; + if (ibuf->planes > 32) { + return (addzbufImBuf(ibuf)); + } + else { + return true; + } + } + + return false; } -struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, - unsigned int w, unsigned int h) +struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, + const float *rectf, + unsigned int w, + unsigned int h) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = NULL; - if (!(rect || rectf)) - return NULL; + if (!(rect || rectf)) + return NULL; - ibuf = IMB_allocImBuf(w, h, 32, 0); + ibuf = IMB_allocImBuf(w, h, 32, 0); - if (rectf) { - ibuf->rect_float = MEM_dupallocN(rectf); - ibuf->flags |= IB_rectfloat; - ibuf->mall |= IB_rectfloat; - } - if (rect) { - ibuf->rect = MEM_dupallocN(rect); - ibuf->flags |= IB_rect; - ibuf->mall |= IB_rect; - } + if (rectf) { + ibuf->rect_float = MEM_dupallocN(rectf); + ibuf->flags |= IB_rectfloat; + ibuf->mall |= IB_rectfloat; + } + if (rect) { + ibuf->rect = MEM_dupallocN(rect); + ibuf->flags |= IB_rect; + ibuf->mall |= IB_rect; + } - return ibuf; + return ibuf; } bool imb_addtilesImBuf(ImBuf *ibuf) { - if (ibuf == NULL) return false; + if (ibuf == NULL) + return false; - if (!ibuf->tiles) - if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles, "imb_tiles"))) - ibuf->mall |= IB_tiles; + if (!ibuf->tiles) + if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles, + "imb_tiles"))) + ibuf->mall |= IB_tiles; - return (ibuf->tiles != NULL); + return (ibuf->tiles != NULL); } ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int flags) { - ImBuf *ibuf; + ImBuf *ibuf; - ibuf = MEM_mallocN(sizeof(ImBuf), "ImBuf_struct"); + ibuf = MEM_mallocN(sizeof(ImBuf), "ImBuf_struct"); - if (ibuf) { - if (!IMB_initImBuf(ibuf, x, y, planes, flags)) { - IMB_freeImBuf(ibuf); - return NULL; - } - } + if (ibuf) { + if (!IMB_initImBuf(ibuf, x, y, planes, flags)) { + IMB_freeImBuf(ibuf); + return NULL; + } + } - return (ibuf); + return (ibuf); } -bool IMB_initImBuf(struct ImBuf *ibuf, - unsigned int x, unsigned int y, - unsigned char planes, unsigned int flags) +bool IMB_initImBuf( + struct ImBuf *ibuf, unsigned int x, unsigned int y, unsigned char planes, unsigned int flags) { - memset(ibuf, 0, sizeof(ImBuf)); - - ibuf->x = x; - ibuf->y = y; - ibuf->planes = planes; - ibuf->ftype = IMB_FTYPE_PNG; - ibuf->foptions.quality = 15; /* the 15 means, set compression to low ratio but not time consuming */ - ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ - 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) { - return false; - } - } - - if (flags & IB_rectfloat) { - if (imb_addrectfloatImBuf(ibuf) == false) { - return false; - } - } - - if (flags & IB_zbuf) { - if (addzbufImBuf(ibuf) == false) { - return false; - } - } - - if (flags & IB_zbuffloat) { - if (addzbuffloatImBuf(ibuf) == false) { - return false; - } - } - - /* assign default spaces */ - colormanage_imbuf_set_default_spaces(ibuf); - - return true; + memset(ibuf, 0, sizeof(ImBuf)); + + ibuf->x = x; + ibuf->y = y; + ibuf->planes = planes; + ibuf->ftype = IMB_FTYPE_PNG; + ibuf->foptions.quality = + 15; /* the 15 means, set compression to low ratio but not time consuming */ + ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ + 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) { + return false; + } + } + + if (flags & IB_rectfloat) { + if (imb_addrectfloatImBuf(ibuf) == false) { + return false; + } + } + + if (flags & IB_zbuf) { + if (addzbufImBuf(ibuf) == false) { + return false; + } + } + + if (flags & IB_zbuffloat) { + if (addzbuffloatImBuf(ibuf) == false) { + return false; + } + } + + /* assign default spaces */ + colormanage_imbuf_set_default_spaces(ibuf); + + return true; } /* does no zbuffers? */ ImBuf *IMB_dupImBuf(const ImBuf *ibuf1) { - ImBuf *ibuf2, tbuf; - int flags = 0; - int a, x, y; - - if (ibuf1 == NULL) return NULL; - - if (ibuf1->rect) flags |= IB_rect; - if (ibuf1->rect_float) flags |= IB_rectfloat; - if (ibuf1->zbuf) flags |= IB_zbuf; - if (ibuf1->zbuf_float) flags |= IB_zbuffloat; - - x = ibuf1->x; - y = ibuf1->y; - - ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags); - if (ibuf2 == NULL) return NULL; - - if (flags & IB_rect) - memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int)); - - if (flags & IB_rectfloat) - memcpy(ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float)); - - if (flags & IB_zbuf) - memcpy(ibuf2->zbuf, ibuf1->zbuf, ((size_t)x) * y * sizeof(int)); - - if (flags & IB_zbuffloat) - memcpy(ibuf2->zbuf_float, ibuf1->zbuf_float, ((size_t)x) * y * sizeof(float)); - - if (ibuf1->encodedbuffer) { - ibuf2->encodedbuffersize = ibuf1->encodedbuffersize; - if (imb_addencodedbufferImBuf(ibuf2) == false) { - IMB_freeImBuf(ibuf2); - return NULL; - } - - memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize); - } - - /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */ - tbuf = *ibuf1; - - /* fix pointers */ - tbuf.rect = ibuf2->rect; - tbuf.rect_float = ibuf2->rect_float; - tbuf.encodedbuffer = ibuf2->encodedbuffer; - tbuf.zbuf = ibuf2->zbuf; - tbuf.zbuf_float = ibuf2->zbuf_float; - for (a = 0; a < IMB_MIPMAP_LEVELS; a++) - tbuf.mipmap[a] = NULL; - tbuf.dds_data.data = NULL; - - /* set malloc flag */ - tbuf.mall = ibuf2->mall; - tbuf.c_handle = NULL; - tbuf.refcounter = 0; - - /* for now don't duplicate metadata */ - tbuf.metadata = NULL; - - tbuf.display_buffer_flags = NULL; - tbuf.colormanage_cache = NULL; - - *ibuf2 = tbuf; - - return(ibuf2); + ImBuf *ibuf2, tbuf; + int flags = 0; + int a, x, y; + + if (ibuf1 == NULL) + return NULL; + + if (ibuf1->rect) + flags |= IB_rect; + if (ibuf1->rect_float) + flags |= IB_rectfloat; + if (ibuf1->zbuf) + flags |= IB_zbuf; + if (ibuf1->zbuf_float) + flags |= IB_zbuffloat; + + x = ibuf1->x; + y = ibuf1->y; + + ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags); + if (ibuf2 == NULL) + return NULL; + + if (flags & IB_rect) + memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int)); + + if (flags & IB_rectfloat) + memcpy( + ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float)); + + if (flags & IB_zbuf) + memcpy(ibuf2->zbuf, ibuf1->zbuf, ((size_t)x) * y * sizeof(int)); + + if (flags & IB_zbuffloat) + memcpy(ibuf2->zbuf_float, ibuf1->zbuf_float, ((size_t)x) * y * sizeof(float)); + + if (ibuf1->encodedbuffer) { + ibuf2->encodedbuffersize = ibuf1->encodedbuffersize; + if (imb_addencodedbufferImBuf(ibuf2) == false) { + IMB_freeImBuf(ibuf2); + return NULL; + } + + memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize); + } + + /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */ + tbuf = *ibuf1; + + /* fix pointers */ + tbuf.rect = ibuf2->rect; + tbuf.rect_float = ibuf2->rect_float; + tbuf.encodedbuffer = ibuf2->encodedbuffer; + tbuf.zbuf = ibuf2->zbuf; + tbuf.zbuf_float = ibuf2->zbuf_float; + for (a = 0; a < IMB_MIPMAP_LEVELS; a++) + tbuf.mipmap[a] = NULL; + tbuf.dds_data.data = NULL; + + /* set malloc flag */ + tbuf.mall = ibuf2->mall; + tbuf.c_handle = NULL; + tbuf.refcounter = 0; + + /* for now don't duplicate metadata */ + tbuf.metadata = NULL; + + tbuf.display_buffer_flags = NULL; + tbuf.colormanage_cache = NULL; + + *ibuf2 = tbuf; + + return (ibuf2); } #if 0 /* remove? - campbell */ @@ -565,25 +587,25 @@ ImBuf *IMB_dupImBuf(const ImBuf *ibuf1) static void imbuf_cache_destructor(void *data) { - ImBuf *ibuf = (ImBuf *) data; + ImBuf *ibuf = (ImBuf *) data; - imb_freerectImBuf(ibuf); - imb_freerectfloatImBuf(ibuf); - IMB_freezbufImBuf(ibuf); - IMB_freezbuffloatImBuf(ibuf); - freeencodedbufferImBuf(ibuf); + imb_freerectImBuf(ibuf); + imb_freerectfloatImBuf(ibuf); + IMB_freezbufImBuf(ibuf); + IMB_freezbuffloatImBuf(ibuf); + freeencodedbufferImBuf(ibuf); - ibuf->c_handle = NULL; + ibuf->c_handle = NULL; } static MEM_CacheLimiterC **get_imbuf_cache_limiter(void) { - static MEM_CacheLimiterC *c = NULL; + static MEM_CacheLimiterC *c = NULL; - if (!c) - c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL); + if (!c) + c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL); - return &c; + return &c; } #endif diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 43d91dc0d8e..13813fb23b3 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -21,24 +21,28 @@ * \ingroup imbuf */ - #ifdef _WIN32 -#define INC_OLE2 -#include -#include -#include -#include -#include -#include - -#undef AVIIF_KEYFRAME /* redefined in AVI_avi.h */ -#undef AVIIF_LIST /* redefined in AVI_avi.h */ - -#define FIXCC(fcc) \ - { \ - if (fcc == 0) { fcc = mmioFOURCC('N', 'o', 'n', 'e'); } \ - if (fcc == BI_RLE8) { fcc = mmioFOURCC('R', 'l', 'e', '8'); } \ - } (void)0 +# define INC_OLE2 +# include +# include +# include +# include +# include +# include + +# undef AVIIF_KEYFRAME /* redefined in AVI_avi.h */ +# undef AVIIF_LIST /* redefined in AVI_avi.h */ + +# define FIXCC(fcc) \ + { \ + if (fcc == 0) { \ + fcc = mmioFOURCC('N', 'o', 'n', 'e'); \ + } \ + if (fcc == BI_RLE8) { \ + fcc = mmioFOURCC('R', 'l', 'e', '8'); \ + } \ + } \ + (void)0 #endif @@ -49,9 +53,9 @@ #include #include #ifndef _WIN32 -#include +# include #else -#include +# include #endif #include "BLI_utildefines.h" @@ -75,7 +79,7 @@ #include "IMB_metadata.h" #ifdef WITH_FFMPEG -# include "BKE_global.h" /* ENDIAN_ORDER */ +# include "BKE_global.h" /* ENDIAN_ORDER */ # include # include @@ -83,28 +87,27 @@ # include # include "ffmpeg_compat.h" -#endif //WITH_FFMPEG +#endif //WITH_FFMPEG int ismovie(const char *UNUSED(filepath)) { - return 0; + return 0; } /* never called, just keep the linker happy */ static int startmovie(struct anim *UNUSED(anim)) { - return 1; + return 1; } static ImBuf *movie_fetchibuf(struct anim *UNUSED(anim), int UNUSED(position)) { - return NULL; + return NULL; } static void free_anim_movie(struct anim *UNUSED(anim)) { - /* pass */ + /* pass */ } - #if defined(_WIN32) # define PATHSEPARATOR '\\' #else @@ -113,84 +116,88 @@ static void free_anim_movie(struct anim *UNUSED(anim)) static int an_stringdec(const char *string, char *head, char *tail, unsigned short *numlen) { - unsigned short len, nume, nums = 0; - short i; - bool found = false; - - len = strlen(string); - nume = len; - - for (i = len - 1; i >= 0; i--) { - if (string[i] == PATHSEPARATOR) break; - if (isdigit(string[i])) { - if (found) { - nums = i; - } - else { - nume = i; - nums = i; - found = true; - } - } - else { - if (found) break; - } - } - if (found) { - strcpy(tail, &string[nume + 1]); - strcpy(head, string); - head[nums] = '\0'; - *numlen = nume - nums + 1; - return ((int)atoi(&(string[nums]))); - } - tail[0] = '\0'; - strcpy(head, string); - *numlen = 0; - return true; + unsigned short len, nume, nums = 0; + short i; + bool found = false; + + len = strlen(string); + nume = len; + + for (i = len - 1; i >= 0; i--) { + if (string[i] == PATHSEPARATOR) + break; + if (isdigit(string[i])) { + if (found) { + nums = i; + } + else { + nume = i; + nums = i; + found = true; + } + } + else { + if (found) + break; + } + } + if (found) { + strcpy(tail, &string[nume + 1]); + strcpy(head, string); + head[nums] = '\0'; + *numlen = nume - nums + 1; + return ((int)atoi(&(string[nums]))); + } + tail[0] = '\0'; + strcpy(head, string); + *numlen = 0; + return true; } - -static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) +static void an_stringenc( + char *string, const char *head, const char *tail, unsigned short numlen, int pic) { - BLI_stringenc(string, head, tail, numlen, pic); + BLI_stringenc(string, head, tail, numlen, pic); } #ifdef WITH_AVI static void free_anim_avi(struct anim *anim) { -#if defined(_WIN32) - int i; -#endif - - if (anim == NULL) return; - if (anim->avi == NULL) return; - - AVI_close(anim->avi); - MEM_freeN(anim->avi); - anim->avi = NULL; - -#if defined(_WIN32) - - if (anim->pgf) { - AVIStreamGetFrameClose(anim->pgf); - anim->pgf = NULL; - } - - for (i = 0; i < anim->avistreams; i++) { - AVIStreamRelease(anim->pavi[i]); - } - anim->avistreams = 0; - - if (anim->pfileopen) { - AVIFileRelease(anim->pfile); - anim->pfileopen = 0; - AVIFileExit(); - } -#endif - - anim->duration = 0; +# if defined(_WIN32) + int i; +# endif + + if (anim == NULL) + return; + if (anim->avi == NULL) + return; + + AVI_close(anim->avi); + MEM_freeN(anim->avi); + anim->avi = NULL; + +# if defined(_WIN32) + + if (anim->pgf) { + AVIStreamGetFrameClose(anim->pgf); + anim->pgf = NULL; + } + + for (i = 0; i < anim->avistreams; i++) { + AVIStreamRelease(anim->pavi[i]); + } + anim->avistreams = 0; + + if (anim->pfileopen) { + AVIFileRelease(anim->pfile); + anim->pfileopen = 0; + AVIFileExit(); + } +# endif + + anim->duration = 0; } -#endif /* WITH_AVI */ +#endif /* WITH_AVI */ #ifdef WITH_FFMPEG static void free_anim_ffmpeg(struct anim *anim); @@ -198,487 +205,496 @@ static void free_anim_ffmpeg(struct anim *anim); void IMB_free_anim(struct anim *anim) { - if (anim == NULL) { - printf("free anim, anim == NULL\n"); - return; - } + if (anim == NULL) { + printf("free anim, anim == NULL\n"); + return; + } - free_anim_movie(anim); + free_anim_movie(anim); #ifdef WITH_AVI - free_anim_avi(anim); + free_anim_avi(anim); #endif #ifdef WITH_FFMPEG - free_anim_ffmpeg(anim); + free_anim_ffmpeg(anim); #endif - IMB_free_indices(anim); - IMB_metadata_free(anim->metadata); + IMB_free_indices(anim); + IMB_metadata_free(anim->metadata); - MEM_freeN(anim); + MEM_freeN(anim); } void IMB_close_anim(struct anim *anim) { - if (anim == NULL) return; + if (anim == NULL) + return; - IMB_free_anim(anim); + IMB_free_anim(anim); } void IMB_close_anim_proxies(struct anim *anim) { - if (anim == NULL) - return; + if (anim == NULL) + return; - IMB_free_indices(anim); + IMB_free_indices(anim); } struct IDProperty *IMB_anim_load_metadata(struct anim *anim) { - switch (anim->curtype) { - case ANIM_FFMPEG: - { + switch (anim->curtype) { + case ANIM_FFMPEG: { #ifdef WITH_FFMPEG - AVDictionaryEntry *entry = NULL; + AVDictionaryEntry *entry = NULL; - BLI_assert(anim->pFormatCtx != NULL); - av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n"); + BLI_assert(anim->pFormatCtx != NULL); + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "METADATA FETCH\n"); - while (true) { - entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX); - if (entry == NULL) break; + while (true) { + entry = av_dict_get(anim->pFormatCtx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX); + if (entry == NULL) + break; - /* Delay creation of the property group until there is actual metadata to put in there. */ - IMB_metadata_ensure(&anim->metadata); - IMB_metadata_set_field(anim->metadata, entry->key, entry->value); - } + /* Delay creation of the property group until there is actual metadata to put in there. */ + IMB_metadata_ensure(&anim->metadata); + IMB_metadata_set_field(anim->metadata, entry->key, entry->value); + } #endif - break; - } - case ANIM_SEQUENCE: - case ANIM_AVI: - case ANIM_MOVIE: - /* TODO */ - break; - case ANIM_NONE: - default: - break; - } - return anim->metadata; + break; + } + case ANIM_SEQUENCE: + case ANIM_AVI: + case ANIM_MOVIE: + /* TODO */ + break; + case ANIM_NONE: + default: + break; + } + return anim->metadata; } -struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]) +struct anim *IMB_open_anim(const char *name, + int ib_flags, + int streamindex, + char colorspace[IM_MAX_SPACE]) { - struct anim *anim; - - BLI_assert(!BLI_path_is_rel(name)); - - anim = (struct anim *)MEM_callocN(sizeof(struct anim), "anim struct"); - if (anim != NULL) { - if (colorspace) { - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - BLI_strncpy(anim->colorspace, colorspace, sizeof(anim->colorspace)); - } - else { - colorspace_set_default_role(anim->colorspace, sizeof(anim->colorspace), COLOR_ROLE_DEFAULT_BYTE); - } - - BLI_strncpy(anim->name, name, sizeof(anim->name)); - anim->ib_flags = ib_flags; - anim->streamindex = streamindex; - } - return(anim); + struct anim *anim; + + BLI_assert(!BLI_path_is_rel(name)); + + anim = (struct anim *)MEM_callocN(sizeof(struct anim), "anim struct"); + if (anim != NULL) { + if (colorspace) { + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + BLI_strncpy(anim->colorspace, colorspace, sizeof(anim->colorspace)); + } + else { + colorspace_set_default_role( + anim->colorspace, sizeof(anim->colorspace), COLOR_ROLE_DEFAULT_BYTE); + } + + BLI_strncpy(anim->name, name, sizeof(anim->name)); + anim->ib_flags = ib_flags; + anim->streamindex = streamindex; + } + return (anim); } void IMB_suffix_anim(struct anim *anim, const char *suffix) { - BLI_strncpy(anim->suffix, suffix, sizeof(anim->suffix)); + BLI_strncpy(anim->suffix, suffix, sizeof(anim->suffix)); } #ifdef WITH_AVI static int startavi(struct anim *anim) { - AviError avierror; -#if defined(_WIN32) - HRESULT hr; - int i, firstvideo = -1; - int streamcount; - BYTE abFormat[1024]; - LONG l; - LPBITMAPINFOHEADER lpbi; - AVISTREAMINFO avis; - - streamcount = anim->streamindex; -#endif - - anim->avi = MEM_callocN(sizeof(AviMovie), "animavi"); - - if (anim->avi == NULL) { - printf("Can't open avi: %s\n", anim->name); - return -1; - } - - avierror = AVI_open_movie(anim->name, anim->avi); - -#if defined(_WIN32) - if (avierror == AVI_ERROR_COMPRESSION) { - AVIFileInit(); - hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L); - if (hr == 0) { - anim->pfileopen = 1; - for (i = 0; i < MAXNUMSTREAMS; i++) { - if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) { - break; - } - - AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis)); - if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) { - if (streamcount > 0) { - streamcount--; - continue; - } - anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL); - if (anim->pgf) { - firstvideo = i; - - /* get stream length */ - anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]); - - /* get information about images inside the stream */ - l = sizeof(abFormat); - AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l); - lpbi = (LPBITMAPINFOHEADER)abFormat; - anim->avi->header->Height = lpbi->biHeight; - anim->avi->header->Width = lpbi->biWidth; - } - else { - FIXCC(avis.fccHandler); - FIXCC(avis.fccType); - printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n", - (LPSTR)&avis.fccType, - (LPSTR)&avis.fccHandler); - } - } - } - - /* register number of opened avistreams */ - anim->avistreams = i; - - /* - * Couldn't get any video streams out of this file - */ - if ((anim->avistreams == 0) || (firstvideo == -1)) { - avierror = AVI_ERROR_FORMAT; - } - else { - avierror = AVI_ERROR_NONE; - anim->firstvideo = firstvideo; - } - } - else { - AVIFileExit(); - } - } -#endif - - if (avierror != AVI_ERROR_NONE) { - AVI_print_error(avierror); - printf("Error loading avi: %s\n", anim->name); - free_anim_avi(anim); - return -1; - } - - anim->duration = anim->avi->header->TotalFrames; - anim->params = NULL; - - anim->x = anim->avi->header->Width; - anim->y = anim->avi->header->Height; - anim->interlacing = 0; - anim->orientation = 0; - anim->framesize = anim->x * anim->y * 4; - - anim->curposition = 0; - anim->preseek = 0; - - /* printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ - - return 0; + AviError avierror; +# if defined(_WIN32) + HRESULT hr; + int i, firstvideo = -1; + int streamcount; + BYTE abFormat[1024]; + LONG l; + LPBITMAPINFOHEADER lpbi; + AVISTREAMINFO avis; + + streamcount = anim->streamindex; +# endif + + anim->avi = MEM_callocN(sizeof(AviMovie), "animavi"); + + if (anim->avi == NULL) { + printf("Can't open avi: %s\n", anim->name); + return -1; + } + + avierror = AVI_open_movie(anim->name, anim->avi); + +# if defined(_WIN32) + if (avierror == AVI_ERROR_COMPRESSION) { + AVIFileInit(); + hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L); + if (hr == 0) { + anim->pfileopen = 1; + for (i = 0; i < MAXNUMSTREAMS; i++) { + if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) { + break; + } + + AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis)); + if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) { + if (streamcount > 0) { + streamcount--; + continue; + } + anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL); + if (anim->pgf) { + firstvideo = i; + + /* get stream length */ + anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]); + + /* get information about images inside the stream */ + l = sizeof(abFormat); + AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l); + lpbi = (LPBITMAPINFOHEADER)abFormat; + anim->avi->header->Height = lpbi->biHeight; + anim->avi->header->Width = lpbi->biWidth; + } + else { + FIXCC(avis.fccHandler); + FIXCC(avis.fccType); + printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n", + (LPSTR)&avis.fccType, + (LPSTR)&avis.fccHandler); + } + } + } + + /* register number of opened avistreams */ + anim->avistreams = i; + + /* + * Couldn't get any video streams out of this file + */ + if ((anim->avistreams == 0) || (firstvideo == -1)) { + avierror = AVI_ERROR_FORMAT; + } + else { + avierror = AVI_ERROR_NONE; + anim->firstvideo = firstvideo; + } + } + else { + AVIFileExit(); + } + } +# endif + + if (avierror != AVI_ERROR_NONE) { + AVI_print_error(avierror); + printf("Error loading avi: %s\n", anim->name); + free_anim_avi(anim); + return -1; + } + + anim->duration = anim->avi->header->TotalFrames; + anim->params = NULL; + + anim->x = anim->avi->header->Width; + anim->y = anim->avi->header->Height; + anim->interlacing = 0; + anim->orientation = 0; + anim->framesize = anim->x * anim->y * 4; + + anim->curposition = 0; + anim->preseek = 0; + + /* printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ + + return 0; } -#endif /* WITH_AVI */ +#endif /* WITH_AVI */ #ifdef WITH_AVI static ImBuf *avi_fetchibuf(struct anim *anim, int position) { - ImBuf *ibuf = NULL; - int *tmp; - int y; - - if (anim == NULL) { - return NULL; - } - -#if defined(_WIN32) - if (anim->avistreams) { - LPBITMAPINFOHEADER lpbi; - - if (anim->pgf) { - lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo])); - if (lpbi) { - ibuf = IMB_ibImageFromMemory((const unsigned char *) lpbi, 100, IB_rect, anim->colorspace, ""); -//Oh brother... - } - } - } - else -#endif - { - ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect); - - tmp = AVI_read_frame(anim->avi, AVI_FORMAT_RGB32, position, - AVI_get_stream(anim->avi, AVIST_VIDEO, 0)); - - if (tmp == NULL) { - printf("Error reading frame from AVI: '%s'\n", anim->name); - IMB_freeImBuf(ibuf); - return NULL; - } - - for (y = 0; y < anim->y; y++) { - memcpy(&(ibuf->rect)[((anim->y - y) - 1) * anim->x], &tmp[y * anim->x], - anim->x * 4); - } - - MEM_freeN(tmp); - } - - ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); - - return ibuf; + ImBuf *ibuf = NULL; + int *tmp; + int y; + + if (anim == NULL) { + return NULL; + } + +# if defined(_WIN32) + if (anim->avistreams) { + LPBITMAPINFOHEADER lpbi; + + if (anim->pgf) { + lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo])); + if (lpbi) { + ibuf = IMB_ibImageFromMemory( + (const unsigned char *)lpbi, 100, IB_rect, anim->colorspace, ""); + //Oh brother... + } + } + } + else +# endif + { + ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect); + + tmp = AVI_read_frame( + anim->avi, AVI_FORMAT_RGB32, position, AVI_get_stream(anim->avi, AVIST_VIDEO, 0)); + + if (tmp == NULL) { + printf("Error reading frame from AVI: '%s'\n", anim->name); + IMB_freeImBuf(ibuf); + return NULL; + } + + for (y = 0; y < anim->y; y++) { + memcpy(&(ibuf->rect)[((anim->y - y) - 1) * anim->x], &tmp[y * anim->x], anim->x * 4); + } + + MEM_freeN(tmp); + } + + ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); + + return ibuf; } -#endif /* WITH_AVI */ +#endif /* WITH_AVI */ #ifdef WITH_FFMPEG BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim) { - return (anim->x & 31) != 0; + return (anim->x & 31) != 0; } static int startffmpeg(struct anim *anim) { - int i, videoStream; - - AVCodec *pCodec; - AVFormatContext *pFormatCtx = NULL; - AVCodecContext *pCodecCtx; - AVRational frame_rate; - int frs_num; - double frs_den; - int streamcount; - -#ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT - /* The following for color space determination */ - int srcRange, dstRange, brightness, contrast, saturation; - int *table; - const int *inv_table; -#endif - - if (anim == NULL) return(-1); - - streamcount = anim->streamindex; - - if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) { - return -1; - } - - if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { - avformat_close_input(&pFormatCtx); - return -1; - } - - av_dump_format(pFormatCtx, 0, anim->name, 0); - - - /* Find the video stream */ - videoStream = -1; - - for (i = 0; i < pFormatCtx->nb_streams; i++) - if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if (streamcount > 0) { - streamcount--; - continue; - } - videoStream = i; - break; - } - - if (videoStream == -1) { - avformat_close_input(&pFormatCtx); - return -1; - } - - pCodecCtx = pFormatCtx->streams[videoStream]->codec; - - /* Find the decoder for the video stream */ - pCodec = avcodec_find_decoder(pCodecCtx->codec_id); - if (pCodec == NULL) { - avformat_close_input(&pFormatCtx); - return -1; - } - - pCodecCtx->workaround_bugs = 1; - - if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { - avformat_close_input(&pFormatCtx); - return -1; - } - if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) { - avcodec_close(anim->pCodecCtx); - avformat_close_input(&pFormatCtx); - return -1; - } - - frame_rate = av_get_r_frame_rate_compat(pFormatCtx, pFormatCtx->streams[videoStream]); - if (pFormatCtx->streams[videoStream]->nb_frames != 0) { - anim->duration = pFormatCtx->streams[videoStream]->nb_frames; - } - else { - anim->duration = (int)(pFormatCtx->duration * - av_q2d(frame_rate) / - AV_TIME_BASE + 0.5f); - } - - frs_num = frame_rate.num; - frs_den = frame_rate.den; - - frs_den *= AV_TIME_BASE; - - while (frs_num % 10 == 0 && frs_den >= 2.0 && frs_num > 10) { - frs_num /= 10; - frs_den /= 10; - } - - anim->frs_sec = frs_num; - anim->frs_sec_base = frs_den; - - anim->params = 0; - - anim->x = pCodecCtx->width; - anim->y = av_get_cropped_height_from_codec(pCodecCtx); - - anim->pFormatCtx = pFormatCtx; - anim->pCodecCtx = pCodecCtx; - anim->pCodec = pCodec; - anim->videoStream = videoStream; - - anim->interlacing = 0; - anim->orientation = 0; - anim->framesize = anim->x * anim->y * 4; - - anim->curposition = -1; - anim->last_frame = 0; - anim->last_pts = -1; - anim->next_pts = -1; - anim->next_packet.stream_index = -1; - - anim->pFrame = av_frame_alloc(); - anim->pFrameComplete = false; - anim->pFrameDeinterlaced = av_frame_alloc(); - anim->pFrameRGB = av_frame_alloc(); - - if (need_aligned_ffmpeg_buffer(anim)) { - anim->pFrameRGB->format = AV_PIX_FMT_RGBA; - anim->pFrameRGB->width = anim->x; - anim->pFrameRGB->height = anim->y; - - if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) { - fprintf(stderr, "Could not allocate frame data.\n"); - avcodec_close(anim->pCodecCtx); - avformat_close_input(&anim->pFormatCtx); - av_frame_free(&anim->pFrameRGB); - av_frame_free(&anim->pFrameDeinterlaced); - av_frame_free(&anim->pFrame); - anim->pCodecCtx = NULL; - return -1; - } - } - - if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) != - anim->x * anim->y * 4) - { - fprintf(stderr, - "ffmpeg has changed alloc scheme ... ARGHHH!\n"); - avcodec_close(anim->pCodecCtx); - avformat_close_input(&anim->pFormatCtx); - av_frame_free(&anim->pFrameRGB); - av_frame_free(&anim->pFrameDeinterlaced); - av_frame_free(&anim->pFrame); - anim->pCodecCtx = NULL; - return -1; - } - - if (anim->ib_flags & IB_animdeinterlace) { - avpicture_fill((AVPicture *) anim->pFrameDeinterlaced, - MEM_callocN(avpicture_get_size( - anim->pCodecCtx->pix_fmt, - anim->pCodecCtx->width, - anim->pCodecCtx->height), - "ffmpeg deinterlace"), - anim->pCodecCtx->pix_fmt, - anim->pCodecCtx->width, - anim->pCodecCtx->height); - } - - if (pCodecCtx->has_b_frames) { - anim->preseek = 25; /* FIXME: detect gopsize ... */ - } - else { - anim->preseek = 0; - } - - anim->img_convert_ctx = sws_getContext( - anim->x, - anim->y, - anim->pCodecCtx->pix_fmt, - anim->x, - anim->y, - AV_PIX_FMT_RGBA, - SWS_FAST_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT, - NULL, NULL, NULL); - - if (!anim->img_convert_ctx) { - fprintf(stderr, - "Can't transform color space??? Bailing out...\n"); - avcodec_close(anim->pCodecCtx); - avformat_close_input(&anim->pFormatCtx); - av_frame_free(&anim->pFrameRGB); - av_frame_free(&anim->pFrameDeinterlaced); - av_frame_free(&anim->pFrame); - anim->pCodecCtx = NULL; - return -1; - } - -#ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT - /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */ - if (!sws_getColorspaceDetails(anim->img_convert_ctx, (int **)&inv_table, &srcRange, - &table, &dstRange, &brightness, &contrast, &saturation)) - { - srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG; - inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace); - - if (sws_setColorspaceDetails(anim->img_convert_ctx, (int *)inv_table, srcRange, - table, dstRange, brightness, contrast, saturation)) - { - fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); - } - } - else { - fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); - } -#endif - - return (0); + int i, videoStream; + + AVCodec *pCodec; + AVFormatContext *pFormatCtx = NULL; + AVCodecContext *pCodecCtx; + AVRational frame_rate; + int frs_num; + double frs_den; + int streamcount; + +# ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT + /* The following for color space determination */ + int srcRange, dstRange, brightness, contrast, saturation; + int *table; + const int *inv_table; +# endif + + if (anim == NULL) + return (-1); + + streamcount = anim->streamindex; + + if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) { + return -1; + } + + if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { + avformat_close_input(&pFormatCtx); + return -1; + } + + av_dump_format(pFormatCtx, 0, anim->name, 0); + + /* Find the video stream */ + videoStream = -1; + + for (i = 0; i < pFormatCtx->nb_streams; i++) + if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (streamcount > 0) { + streamcount--; + continue; + } + videoStream = i; + break; + } + + if (videoStream == -1) { + avformat_close_input(&pFormatCtx); + return -1; + } + + pCodecCtx = pFormatCtx->streams[videoStream]->codec; + + /* Find the decoder for the video stream */ + pCodec = avcodec_find_decoder(pCodecCtx->codec_id); + if (pCodec == NULL) { + avformat_close_input(&pFormatCtx); + return -1; + } + + pCodecCtx->workaround_bugs = 1; + + if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { + avformat_close_input(&pFormatCtx); + return -1; + } + if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) { + avcodec_close(anim->pCodecCtx); + avformat_close_input(&pFormatCtx); + return -1; + } + + frame_rate = av_get_r_frame_rate_compat(pFormatCtx, pFormatCtx->streams[videoStream]); + if (pFormatCtx->streams[videoStream]->nb_frames != 0) { + anim->duration = pFormatCtx->streams[videoStream]->nb_frames; + } + else { + anim->duration = (int)(pFormatCtx->duration * av_q2d(frame_rate) / AV_TIME_BASE + 0.5f); + } + + frs_num = frame_rate.num; + frs_den = frame_rate.den; + + frs_den *= AV_TIME_BASE; + + while (frs_num % 10 == 0 && frs_den >= 2.0 && frs_num > 10) { + frs_num /= 10; + frs_den /= 10; + } + + anim->frs_sec = frs_num; + anim->frs_sec_base = frs_den; + + anim->params = 0; + + anim->x = pCodecCtx->width; + anim->y = av_get_cropped_height_from_codec(pCodecCtx); + + anim->pFormatCtx = pFormatCtx; + anim->pCodecCtx = pCodecCtx; + anim->pCodec = pCodec; + anim->videoStream = videoStream; + + anim->interlacing = 0; + anim->orientation = 0; + anim->framesize = anim->x * anim->y * 4; + + anim->curposition = -1; + anim->last_frame = 0; + anim->last_pts = -1; + anim->next_pts = -1; + anim->next_packet.stream_index = -1; + + anim->pFrame = av_frame_alloc(); + anim->pFrameComplete = false; + anim->pFrameDeinterlaced = av_frame_alloc(); + anim->pFrameRGB = av_frame_alloc(); + + if (need_aligned_ffmpeg_buffer(anim)) { + anim->pFrameRGB->format = AV_PIX_FMT_RGBA; + anim->pFrameRGB->width = anim->x; + anim->pFrameRGB->height = anim->y; + + if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) { + fprintf(stderr, "Could not allocate frame data.\n"); + avcodec_close(anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + av_frame_free(&anim->pFrame); + anim->pCodecCtx = NULL; + return -1; + } + } + + if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) != anim->x * anim->y * 4) { + fprintf(stderr, "ffmpeg has changed alloc scheme ... ARGHHH!\n"); + avcodec_close(anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + av_frame_free(&anim->pFrame); + anim->pCodecCtx = NULL; + return -1; + } + + if (anim->ib_flags & IB_animdeinterlace) { + avpicture_fill((AVPicture *)anim->pFrameDeinterlaced, + MEM_callocN(avpicture_get_size(anim->pCodecCtx->pix_fmt, + anim->pCodecCtx->width, + anim->pCodecCtx->height), + "ffmpeg deinterlace"), + anim->pCodecCtx->pix_fmt, + anim->pCodecCtx->width, + anim->pCodecCtx->height); + } + + if (pCodecCtx->has_b_frames) { + anim->preseek = 25; /* FIXME: detect gopsize ... */ + } + else { + anim->preseek = 0; + } + + anim->img_convert_ctx = sws_getContext(anim->x, + anim->y, + anim->pCodecCtx->pix_fmt, + anim->x, + anim->y, + AV_PIX_FMT_RGBA, + SWS_FAST_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT, + NULL, + NULL, + NULL); + + if (!anim->img_convert_ctx) { + fprintf(stderr, "Can't transform color space??? Bailing out...\n"); + avcodec_close(anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + av_frame_free(&anim->pFrame); + anim->pCodecCtx = NULL; + return -1; + } + +# ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT + /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */ + if (!sws_getColorspaceDetails(anim->img_convert_ctx, + (int **)&inv_table, + &srcRange, + &table, + &dstRange, + &brightness, + &contrast, + &saturation)) { + srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG; + inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace); + + if (sws_setColorspaceDetails(anim->img_convert_ctx, + (int *)inv_table, + srcRange, + table, + dstRange, + brightness, + contrast, + saturation)) { + fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); + } + } + else { + fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); + } +# endif + + return (0); } /* postprocess the image in anim->pFrame and do color conversion @@ -689,535 +705,504 @@ static int startffmpeg(struct anim *anim) static void ffmpeg_postprocess(struct anim *anim) { - AVFrame *input = anim->pFrame; - ImBuf *ibuf = anim->last_frame; - int filter_y = 0; - - if (!anim->pFrameComplete) { - return; - } - - /* This means the data wasnt read properly, - * this check stops crashing */ - if (input->data[0] == 0 && input->data[1] == 0 && - input->data[2] == 0 && input->data[3] == 0) - { - fprintf(stderr, "ffmpeg_fetchibuf: " - "data not read properly...\n"); - return; - } - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - " POSTPROC: anim->pFrame planes: %p %p %p %p\n", - input->data[0], input->data[1], input->data[2], - input->data[3]); - - - if (anim->ib_flags & IB_animdeinterlace) { - if (avpicture_deinterlace( - (AVPicture *) - anim->pFrameDeinterlaced, - (const AVPicture *) - anim->pFrame, - anim->pCodecCtx->pix_fmt, - anim->pCodecCtx->width, - anim->pCodecCtx->height) < 0) - { - filter_y = true; - } - else { - input = anim->pFrameDeinterlaced; - } - } - - if (!need_aligned_ffmpeg_buffer(anim)) { - avpicture_fill((AVPicture *) anim->pFrameRGB, - (unsigned char *) ibuf->rect, - AV_PIX_FMT_RGBA, anim->x, anim->y); - } - - if (ENDIAN_ORDER == B_ENDIAN) { - int *dstStride = anim->pFrameRGB->linesize; - uint8_t **dst = anim->pFrameRGB->data; - int dstStride2[4] = { dstStride[0], 0, 0, 0 }; - uint8_t *dst2[4] = { dst[0], 0, 0, 0 }; - int x, y, h, w; - unsigned char *bottom; - unsigned char *top; - - sws_scale(anim->img_convert_ctx, - (const uint8_t *const *)input->data, - input->linesize, - 0, - anim->y, - dst2, - dstStride2); - - bottom = (unsigned char *) ibuf->rect; - top = bottom + ibuf->x * (ibuf->y - 1) * 4; - - h = (ibuf->y + 1) / 2; - w = ibuf->x; - - for (y = 0; y < h; y++) { - unsigned char tmp[4]; - unsigned int *tmp_l = - (unsigned int *) tmp; - - for (x = 0; x < w; x++) { - tmp[0] = bottom[0]; - tmp[1] = bottom[1]; - tmp[2] = bottom[2]; - tmp[3] = bottom[3]; - - bottom[0] = top[0]; - bottom[1] = top[1]; - bottom[2] = top[2]; - bottom[3] = top[3]; - - *(unsigned int *) top = *tmp_l; - - bottom += 4; - top += 4; - } - top -= 8 * w; - } - } - else { - int *dstStride = anim->pFrameRGB->linesize; - uint8_t **dst = anim->pFrameRGB->data; - int dstStride2[4] = { -dstStride[0], 0, 0, 0 }; - uint8_t *dst2[4] = { dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0 }; - - sws_scale(anim->img_convert_ctx, - (const uint8_t *const *)input->data, - input->linesize, - 0, - anim->y, - dst2, - dstStride2); - } - - if (need_aligned_ffmpeg_buffer(anim)) { - uint8_t *src = anim->pFrameRGB->data[0]; - uint8_t *dst = (uint8_t *) ibuf->rect; - for (int y = 0; y < anim->y; y++) { - memcpy(dst, src, anim->x * 4); - dst += anim->x * 4; - src += anim->pFrameRGB->linesize[0]; - } - } - - if (filter_y) { - IMB_filtery(ibuf); - } + AVFrame *input = anim->pFrame; + ImBuf *ibuf = anim->last_frame; + int filter_y = 0; + + if (!anim->pFrameComplete) { + return; + } + + /* This means the data wasnt read properly, + * this check stops crashing */ + if (input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) { + fprintf(stderr, + "ffmpeg_fetchibuf: " + "data not read properly...\n"); + return; + } + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + " POSTPROC: anim->pFrame planes: %p %p %p %p\n", + input->data[0], + input->data[1], + input->data[2], + input->data[3]); + + if (anim->ib_flags & IB_animdeinterlace) { + if (avpicture_deinterlace((AVPicture *)anim->pFrameDeinterlaced, + (const AVPicture *)anim->pFrame, + anim->pCodecCtx->pix_fmt, + anim->pCodecCtx->width, + anim->pCodecCtx->height) < 0) { + filter_y = true; + } + else { + input = anim->pFrameDeinterlaced; + } + } + + if (!need_aligned_ffmpeg_buffer(anim)) { + avpicture_fill((AVPicture *)anim->pFrameRGB, + (unsigned char *)ibuf->rect, + AV_PIX_FMT_RGBA, + anim->x, + anim->y); + } + + if (ENDIAN_ORDER == B_ENDIAN) { + int *dstStride = anim->pFrameRGB->linesize; + uint8_t **dst = anim->pFrameRGB->data; + int dstStride2[4] = {dstStride[0], 0, 0, 0}; + uint8_t *dst2[4] = {dst[0], 0, 0, 0}; + int x, y, h, w; + unsigned char *bottom; + unsigned char *top; + + sws_scale(anim->img_convert_ctx, + (const uint8_t *const *)input->data, + input->linesize, + 0, + anim->y, + dst2, + dstStride2); + + bottom = (unsigned char *)ibuf->rect; + top = bottom + ibuf->x * (ibuf->y - 1) * 4; + + h = (ibuf->y + 1) / 2; + w = ibuf->x; + + for (y = 0; y < h; y++) { + unsigned char tmp[4]; + unsigned int *tmp_l = (unsigned int *)tmp; + + for (x = 0; x < w; x++) { + tmp[0] = bottom[0]; + tmp[1] = bottom[1]; + tmp[2] = bottom[2]; + tmp[3] = bottom[3]; + + bottom[0] = top[0]; + bottom[1] = top[1]; + bottom[2] = top[2]; + bottom[3] = top[3]; + + *(unsigned int *)top = *tmp_l; + + bottom += 4; + top += 4; + } + top -= 8 * w; + } + } + else { + int *dstStride = anim->pFrameRGB->linesize; + uint8_t **dst = anim->pFrameRGB->data; + int dstStride2[4] = {-dstStride[0], 0, 0, 0}; + uint8_t *dst2[4] = {dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0}; + + sws_scale(anim->img_convert_ctx, + (const uint8_t *const *)input->data, + input->linesize, + 0, + anim->y, + dst2, + dstStride2); + } + + if (need_aligned_ffmpeg_buffer(anim)) { + uint8_t *src = anim->pFrameRGB->data[0]; + uint8_t *dst = (uint8_t *)ibuf->rect; + for (int y = 0; y < anim->y; y++) { + memcpy(dst, src, anim->x * 4); + dst += anim->x * 4; + src += anim->pFrameRGB->linesize[0]; + } + } + + if (filter_y) { + IMB_filtery(ibuf); + } } /* decode one video frame also considering the packet read into next_packet */ static int ffmpeg_decode_video_frame(struct anim *anim) { - int rval = 0; - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n"); - - if (anim->next_packet.stream_index == anim->videoStream) { - av_free_packet(&anim->next_packet); - anim->next_packet.stream_index = -1; - } - - while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) { - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - "%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld " - "%s\n", - (anim->next_packet.stream_index == anim->videoStream) - ? "->" : " ", - anim->next_packet.stream_index, - anim->videoStream, - (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 : - (long long int)anim->next_packet.dts, - (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 : - (long long int)anim->next_packet.pts, - (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? - " KEY" : ""); - if (anim->next_packet.stream_index == anim->videoStream) { - anim->pFrameComplete = 0; - - avcodec_decode_video2( - anim->pCodecCtx, - anim->pFrame, &anim->pFrameComplete, - &anim->next_packet); - - if (anim->pFrameComplete) { - anim->next_pts = av_get_pts_from_frame( - anim->pFormatCtx, anim->pFrame); - - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - " FRAME DONE: next_pts=%lld " - "pkt_pts=%lld, guessed_pts=%lld\n", - (anim->pFrame->pts == AV_NOPTS_VALUE) ? - -1 : (long long int)anim->pFrame->pts, - (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? - -1 : (long long int)anim->pFrame->pkt_pts, - (long long int)anim->next_pts); - break; - } - } - av_free_packet(&anim->next_packet); - anim->next_packet.stream_index = -1; - } - - if (rval == AVERROR_EOF) { - /* this sets size and data fields to zero, - * which is necessary to decode the remaining data - * in the decoder engine after EOF. It also prevents a memory - * leak, since av_read_frame spills out a full size packet even - * on EOF... (and: it's safe to call on NULL packets) */ - - av_free_packet(&anim->next_packet); - - anim->next_packet.size = 0; - anim->next_packet.data = 0; - - anim->pFrameComplete = 0; - - avcodec_decode_video2( - anim->pCodecCtx, - anim->pFrame, &anim->pFrameComplete, - &anim->next_packet); - - if (anim->pFrameComplete) { - anim->next_pts = av_get_pts_from_frame( - anim->pFormatCtx, anim->pFrame); - - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - " FRAME DONE (after EOF): next_pts=%lld " - "pkt_pts=%lld, guessed_pts=%lld\n", - (anim->pFrame->pts == AV_NOPTS_VALUE) ? - -1 : (long long int)anim->pFrame->pts, - (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? - -1 : (long long int)anim->pFrame->pkt_pts, - (long long int)anim->next_pts); - rval = 0; - } - } - - if (rval < 0) { - anim->next_packet.stream_index = -1; - - av_log(anim->pFormatCtx, - AV_LOG_ERROR, " DECODE READ FAILED: av_read_frame() " - "returned error: %d\n", rval); - } - - return (rval >= 0); + int rval = 0; + + av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n"); + + if (anim->next_packet.stream_index == anim->videoStream) { + av_free_packet(&anim->next_packet); + anim->next_packet.stream_index = -1; + } + + while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) { + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld " + "%s\n", + (anim->next_packet.stream_index == anim->videoStream) ? "->" : " ", + anim->next_packet.stream_index, + anim->videoStream, + (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->next_packet.dts, + (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->next_packet.pts, + (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? " KEY" : ""); + if (anim->next_packet.stream_index == anim->videoStream) { + anim->pFrameComplete = 0; + + avcodec_decode_video2( + anim->pCodecCtx, anim->pFrame, &anim->pFrameComplete, &anim->next_packet); + + if (anim->pFrameComplete) { + anim->next_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame); + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + " FRAME DONE: next_pts=%lld " + "pkt_pts=%lld, guessed_pts=%lld\n", + (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pts, + (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : + (long long int)anim->pFrame->pkt_pts, + (long long int)anim->next_pts); + break; + } + } + av_free_packet(&anim->next_packet); + anim->next_packet.stream_index = -1; + } + + if (rval == AVERROR_EOF) { + /* this sets size and data fields to zero, + * which is necessary to decode the remaining data + * in the decoder engine after EOF. It also prevents a memory + * leak, since av_read_frame spills out a full size packet even + * on EOF... (and: it's safe to call on NULL packets) */ + + av_free_packet(&anim->next_packet); + + anim->next_packet.size = 0; + anim->next_packet.data = 0; + + anim->pFrameComplete = 0; + + avcodec_decode_video2( + anim->pCodecCtx, anim->pFrame, &anim->pFrameComplete, &anim->next_packet); + + if (anim->pFrameComplete) { + anim->next_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame); + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + " FRAME DONE (after EOF): next_pts=%lld " + "pkt_pts=%lld, guessed_pts=%lld\n", + (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pts, + (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pkt_pts, + (long long int)anim->next_pts); + rval = 0; + } + } + + if (rval < 0) { + anim->next_packet.stream_index = -1; + + av_log(anim->pFormatCtx, + AV_LOG_ERROR, + " DECODE READ FAILED: av_read_frame() " + "returned error: %d\n", + rval); + } + + return (rval >= 0); } -static void ffmpeg_decode_video_frame_scan( - struct anim *anim, int64_t pts_to_search) +static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_search) { - /* there seem to exist *very* silly GOP lengths out in the wild... */ - int count = 1000; - - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - "SCAN start: considering pts=%lld in search of %lld\n", - (long long int)anim->next_pts, (long long int)pts_to_search); - - while (count > 0 && anim->next_pts < pts_to_search) { - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, - " WHILE: pts=%lld in search of %lld\n", - (long long int)anim->next_pts, (long long int)pts_to_search); - if (!ffmpeg_decode_video_frame(anim)) { - break; - } - count--; - } - if (count == 0) { - av_log(anim->pFormatCtx, - AV_LOG_ERROR, - "SCAN failed: completely lost in stream, " - "bailing out at PTS=%lld, searching for PTS=%lld\n", - (long long int)anim->next_pts, (long long int)pts_to_search); - } - if (anim->next_pts == pts_to_search) { - av_log(anim->pFormatCtx, - AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n"); - } - else { - av_log(anim->pFormatCtx, - AV_LOG_ERROR, "SCAN UNHAPPY: PTS not matched!\n"); - } + /* there seem to exist *very* silly GOP lengths out in the wild... */ + int count = 1000; + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "SCAN start: considering pts=%lld in search of %lld\n", + (long long int)anim->next_pts, + (long long int)pts_to_search); + + while (count > 0 && anim->next_pts < pts_to_search) { + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + " WHILE: pts=%lld in search of %lld\n", + (long long int)anim->next_pts, + (long long int)pts_to_search); + if (!ffmpeg_decode_video_frame(anim)) { + break; + } + count--; + } + if (count == 0) { + av_log(anim->pFormatCtx, + AV_LOG_ERROR, + "SCAN failed: completely lost in stream, " + "bailing out at PTS=%lld, searching for PTS=%lld\n", + (long long int)anim->next_pts, + (long long int)pts_to_search); + } + if (anim->next_pts == pts_to_search) { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n"); + } + else { + av_log(anim->pFormatCtx, AV_LOG_ERROR, "SCAN UNHAPPY: PTS not matched!\n"); + } } static int match_format(const char *name, AVFormatContext *pFormatCtx) { - const char *p; - int len, namelen; - - const char *names = pFormatCtx->iformat->name; - - if (!name || !names) - return 0; - - namelen = strlen(name); - while ((p = strchr(names, ','))) { - len = MAX2(p - names, namelen); - if (!BLI_strncasecmp(name, names, len)) - return 1; - names = p + 1; - } - return !BLI_strcasecmp(name, names); + const char *p; + int len, namelen; + + const char *names = pFormatCtx->iformat->name; + + if (!name || !names) + return 0; + + namelen = strlen(name); + while ((p = strchr(names, ','))) { + len = MAX2(p - names, namelen); + if (!BLI_strncasecmp(name, names, len)) + return 1; + names = p + 1; + } + return !BLI_strcasecmp(name, names); } static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx) { - static const char *byte_seek_list[] = { "mpegts", 0 }; - const char **p; + static const char *byte_seek_list[] = {"mpegts", 0}; + const char **p; - if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) { - return true; - } + if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) { + return true; + } - p = byte_seek_list; + p = byte_seek_list; - while (*p) { - if (match_format(*p++, pFormatCtx)) { - return true; - } - } + while (*p) { + if (match_format(*p++, pFormatCtx)) { + return true; + } + } - return false; + return false; } -static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, - IMB_Timecode_Type tc) +static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc) { - int64_t pts_to_search = 0; - double frame_rate; - double pts_time_base; - long long st_time; - struct anim_index *tc_index = 0; - AVStream *v_st; - int new_frame_index = 0; /* To quiet gcc barking... */ - int old_frame_index = 0; /* To quiet gcc barking... */ - - if (anim == NULL) return (0); - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position); - - if (tc != IMB_TC_NONE) { - tc_index = IMB_anim_open_index(anim, tc); - } - - v_st = anim->pFormatCtx->streams[anim->videoStream]; - - frame_rate = av_q2d(av_get_r_frame_rate_compat(anim->pFormatCtx, v_st)); - - st_time = anim->pFormatCtx->start_time; - pts_time_base = av_q2d(v_st->time_base); - - if (tc_index) { - new_frame_index = IMB_indexer_get_frame_index( - tc_index, position); - old_frame_index = IMB_indexer_get_frame_index( - tc_index, anim->curposition); - pts_to_search = IMB_indexer_get_pts( - tc_index, new_frame_index); - } - else { - pts_to_search = (long long) - floor(((double) position) / - pts_time_base / frame_rate + 0.5); - - if (st_time != AV_NOPTS_VALUE) { - pts_to_search += st_time / pts_time_base / AV_TIME_BASE; - } - } - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "FETCH: looking for PTS=%lld " - "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", - (long long int)pts_to_search, pts_time_base, frame_rate, st_time); - - if (anim->last_frame && - anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search) - { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "FETCH: frame repeat: last: %lld next: %lld\n", - (long long int)anim->last_pts, - (long long int)anim->next_pts); - IMB_refImBuf(anim->last_frame); - anim->curposition = position; - return anim->last_frame; - } - - if (position > anim->curposition + 1 && - anim->preseek && - !tc_index && - position - (anim->curposition + 1) < anim->preseek) - { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "FETCH: within preseek interval (no index)\n"); - - ffmpeg_decode_video_frame_scan(anim, pts_to_search); - } - else if (tc_index && - IMB_indexer_can_scan(tc_index, old_frame_index, - new_frame_index)) - { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "FETCH: within preseek interval " - "(index tells us)\n"); - - ffmpeg_decode_video_frame_scan(anim, pts_to_search); - } - else if (position != anim->curposition + 1) { - long long pos; - int ret; - - if (tc_index) { - unsigned long long dts; - - pos = IMB_indexer_get_seek_pos( - tc_index, new_frame_index); - dts = IMB_indexer_get_seek_pos_dts( - tc_index, new_frame_index); - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "TC INDEX seek pos = %lld\n", pos); - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "TC INDEX seek dts = %llu\n", dts); - - if (ffmpeg_seek_by_byte(anim->pFormatCtx)) { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "... using BYTE pos\n"); - - ret = av_seek_frame(anim->pFormatCtx, - -1, - pos, AVSEEK_FLAG_BYTE); - av_update_cur_dts(anim->pFormatCtx, v_st, dts); - } - else { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "... using DTS pos\n"); - ret = av_seek_frame(anim->pFormatCtx, - anim->videoStream, - dts, AVSEEK_FLAG_BACKWARD); - } - } - else { - pos = (long long) (position - anim->preseek) * - AV_TIME_BASE / frame_rate; - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "NO INDEX seek pos = %lld, st_time = %lld\n", - pos, (st_time != AV_NOPTS_VALUE) ? st_time : 0); - - if (pos < 0) { - pos = 0; - } - - if (st_time != AV_NOPTS_VALUE) { - pos += st_time; - } - - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "NO INDEX final seek pos = %lld\n", pos); - - ret = av_seek_frame(anim->pFormatCtx, -1, - pos, AVSEEK_FLAG_BACKWARD); - } - - if (ret < 0) { - av_log(anim->pFormatCtx, AV_LOG_ERROR, - "FETCH: " - "error while seeking to DTS = %lld " - "(frameno = %d, PTS = %lld): errcode = %d\n", - pos, position, (long long int)pts_to_search, ret); - } - - avcodec_flush_buffers(anim->pCodecCtx); - - anim->next_pts = -1; - - if (anim->next_packet.stream_index == anim->videoStream) { - av_free_packet(&anim->next_packet); - anim->next_packet.stream_index = -1; - } - - /* memset(anim->pFrame, ...) ?? */ - - if (ret >= 0) { - ffmpeg_decode_video_frame_scan(anim, pts_to_search); - } - } - else if (position == 0 && anim->curposition == -1) { - /* first frame without seeking special case... */ - ffmpeg_decode_video_frame(anim); - } - else { - av_log(anim->pFormatCtx, AV_LOG_DEBUG, - "FETCH: no seek necessary, just continue...\n"); - } - - IMB_freeImBuf(anim->last_frame); - anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect); - anim->last_frame->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); - - ffmpeg_postprocess(anim); - - anim->last_pts = anim->next_pts; - - ffmpeg_decode_video_frame(anim); - - anim->curposition = position; - - IMB_refImBuf(anim->last_frame); - - return anim->last_frame; + int64_t pts_to_search = 0; + double frame_rate; + double pts_time_base; + long long st_time; + struct anim_index *tc_index = 0; + AVStream *v_st; + int new_frame_index = 0; /* To quiet gcc barking... */ + int old_frame_index = 0; /* To quiet gcc barking... */ + + if (anim == NULL) + return (0); + + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position); + + if (tc != IMB_TC_NONE) { + tc_index = IMB_anim_open_index(anim, tc); + } + + v_st = anim->pFormatCtx->streams[anim->videoStream]; + + frame_rate = av_q2d(av_get_r_frame_rate_compat(anim->pFormatCtx, v_st)); + + st_time = anim->pFormatCtx->start_time; + pts_time_base = av_q2d(v_st->time_base); + + if (tc_index) { + new_frame_index = IMB_indexer_get_frame_index(tc_index, position); + old_frame_index = IMB_indexer_get_frame_index(tc_index, anim->curposition); + pts_to_search = IMB_indexer_get_pts(tc_index, new_frame_index); + } + else { + pts_to_search = (long long)floor(((double)position) / pts_time_base / frame_rate + 0.5); + + if (st_time != AV_NOPTS_VALUE) { + pts_to_search += st_time / pts_time_base / AV_TIME_BASE; + } + } + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "FETCH: looking for PTS=%lld " + "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", + (long long int)pts_to_search, + pts_time_base, + frame_rate, + st_time); + + if (anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search) { + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "FETCH: frame repeat: last: %lld next: %lld\n", + (long long int)anim->last_pts, + (long long int)anim->next_pts); + IMB_refImBuf(anim->last_frame); + anim->curposition = position; + return anim->last_frame; + } + + if (position > anim->curposition + 1 && anim->preseek && !tc_index && + position - (anim->curposition + 1) < anim->preseek) { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: within preseek interval (no index)\n"); + + ffmpeg_decode_video_frame_scan(anim, pts_to_search); + } + else if (tc_index && IMB_indexer_can_scan(tc_index, old_frame_index, new_frame_index)) { + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "FETCH: within preseek interval " + "(index tells us)\n"); + + ffmpeg_decode_video_frame_scan(anim, pts_to_search); + } + else if (position != anim->curposition + 1) { + long long pos; + int ret; + + if (tc_index) { + unsigned long long dts; + + pos = IMB_indexer_get_seek_pos(tc_index, new_frame_index); + dts = IMB_indexer_get_seek_pos_dts(tc_index, new_frame_index); + + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pos = %lld\n", pos); + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %llu\n", dts); + + if (ffmpeg_seek_by_byte(anim->pFormatCtx)) { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using BYTE pos\n"); + + ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BYTE); + av_update_cur_dts(anim->pFormatCtx, v_st, dts); + } + else { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using DTS pos\n"); + ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, dts, AVSEEK_FLAG_BACKWARD); + } + } + else { + pos = (long long)(position - anim->preseek) * AV_TIME_BASE / frame_rate; + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "NO INDEX seek pos = %lld, st_time = %lld\n", + pos, + (st_time != AV_NOPTS_VALUE) ? st_time : 0); + + if (pos < 0) { + pos = 0; + } + + if (st_time != AV_NOPTS_VALUE) { + pos += st_time; + } + + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek pos = %lld\n", pos); + + ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD); + } + + if (ret < 0) { + av_log(anim->pFormatCtx, + AV_LOG_ERROR, + "FETCH: " + "error while seeking to DTS = %lld " + "(frameno = %d, PTS = %lld): errcode = %d\n", + pos, + position, + (long long int)pts_to_search, + ret); + } + + avcodec_flush_buffers(anim->pCodecCtx); + + anim->next_pts = -1; + + if (anim->next_packet.stream_index == anim->videoStream) { + av_free_packet(&anim->next_packet); + anim->next_packet.stream_index = -1; + } + + /* memset(anim->pFrame, ...) ?? */ + + if (ret >= 0) { + ffmpeg_decode_video_frame_scan(anim, pts_to_search); + } + } + else if (position == 0 && anim->curposition == -1) { + /* first frame without seeking special case... */ + ffmpeg_decode_video_frame(anim); + } + else { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n"); + } + + IMB_freeImBuf(anim->last_frame); + anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect); + anim->last_frame->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); + + ffmpeg_postprocess(anim); + + anim->last_pts = anim->next_pts; + + ffmpeg_decode_video_frame(anim); + + anim->curposition = position; + + IMB_refImBuf(anim->last_frame); + + return anim->last_frame; } static void free_anim_ffmpeg(struct anim *anim) { - if (anim == NULL) return; - - if (anim->pCodecCtx) { - avcodec_close(anim->pCodecCtx); - avformat_close_input(&anim->pFormatCtx); - - /* Special case here: pFrame could share pointers with codec, - * so in order to avoid double-free we don't use av_frame_free() - * to free the frame. - * - * Could it be a bug in FFmpeg? - */ - av_free(anim->pFrame); - - if (!need_aligned_ffmpeg_buffer(anim)) { - /* If there's no need for own aligned buffer it means that FFmpeg's - * frame shares the same buffer as temporary ImBuf. In this case we - * should not free the buffer when freeing the FFmpeg buffer. - */ - avpicture_fill((AVPicture *)anim->pFrameRGB, - NULL, - AV_PIX_FMT_RGBA, - anim->x, anim->y); - } - av_frame_free(&anim->pFrameRGB); - av_frame_free(&anim->pFrameDeinterlaced); - - sws_freeContext(anim->img_convert_ctx); - IMB_freeImBuf(anim->last_frame); - if (anim->next_packet.stream_index != -1) { - av_free_packet(&anim->next_packet); - } - } - anim->duration = 0; + if (anim == NULL) + return; + + if (anim->pCodecCtx) { + avcodec_close(anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); + + /* Special case here: pFrame could share pointers with codec, + * so in order to avoid double-free we don't use av_frame_free() + * to free the frame. + * + * Could it be a bug in FFmpeg? + */ + av_free(anim->pFrame); + + if (!need_aligned_ffmpeg_buffer(anim)) { + /* If there's no need for own aligned buffer it means that FFmpeg's + * frame shares the same buffer as temporary ImBuf. In this case we + * should not free the buffer when freeing the FFmpeg buffer. + */ + avpicture_fill((AVPicture *)anim->pFrameRGB, NULL, AV_PIX_FMT_RGBA, anim->x, anim->y); + } + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + + sws_freeContext(anim->img_convert_ctx); + IMB_freeImBuf(anim->last_frame); + if (anim->next_packet.stream_index != -1) { + av_free_packet(&anim->next_packet); + } + } + anim->duration = 0; } #endif @@ -1228,208 +1213,211 @@ static void free_anim_ffmpeg(struct anim *anim) static ImBuf *anim_getnew(struct anim *anim) { - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = NULL; - if (anim == NULL) return(NULL); + if (anim == NULL) + return (NULL); - free_anim_movie(anim); + free_anim_movie(anim); #ifdef WITH_AVI - free_anim_avi(anim); + free_anim_avi(anim); #endif #ifdef WITH_FFMPEG - free_anim_ffmpeg(anim); + free_anim_ffmpeg(anim); #endif - if (anim->curtype != 0) return (NULL); - anim->curtype = imb_get_anim_type(anim->name); - - switch (anim->curtype) { - case ANIM_SEQUENCE: - ibuf = IMB_loadiffname(anim->name, anim->ib_flags, anim->colorspace); - if (ibuf) { - BLI_strncpy(anim->first, anim->name, sizeof(anim->first)); - anim->duration = 1; - } - break; - case ANIM_MOVIE: - if (startmovie(anim)) return (NULL); - ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); /* fake */ - break; + if (anim->curtype != 0) + return (NULL); + anim->curtype = imb_get_anim_type(anim->name); + + switch (anim->curtype) { + case ANIM_SEQUENCE: + ibuf = IMB_loadiffname(anim->name, anim->ib_flags, anim->colorspace); + if (ibuf) { + BLI_strncpy(anim->first, anim->name, sizeof(anim->first)); + anim->duration = 1; + } + break; + case ANIM_MOVIE: + 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("couldn't start avi\n"); - return (NULL); - } - ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); - break; + case ANIM_AVI: + if (startavi(anim)) { + printf("couldn't start avi\n"); + return (NULL); + } + ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); + break; #endif #ifdef WITH_FFMPEG - case ANIM_FFMPEG: - if (startffmpeg(anim)) return (0); - ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); - break; + case ANIM_FFMPEG: + if (startffmpeg(anim)) + return (0); + ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); + break; #endif - } - return(ibuf); + } + return (ibuf); } struct ImBuf *IMB_anim_previewframe(struct anim *anim) { - struct ImBuf *ibuf = NULL; - int position = 0; - - ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); - if (ibuf) { - IMB_freeImBuf(ibuf); - position = anim->duration / 2; - ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE, - IMB_PROXY_NONE); - } - return ibuf; + struct ImBuf *ibuf = NULL; + int position = 0; + + ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); + if (ibuf) { + IMB_freeImBuf(ibuf); + position = anim->duration / 2; + ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE, IMB_PROXY_NONE); + } + return ibuf; } -struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, +struct ImBuf *IMB_anim_absolute(struct anim *anim, + int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size) { - struct ImBuf *ibuf = NULL; - char head[256], tail[256]; - unsigned short digits; - int pic; - int filter_y; - if (anim == NULL) return(NULL); - - filter_y = (anim->ib_flags & IB_animdeinterlace); - - if (preview_size == IMB_PROXY_NONE) { - if (anim->curtype == 0) { - ibuf = anim_getnew(anim); - if (ibuf == NULL) { - return(NULL); - } - - IMB_freeImBuf(ibuf); /* ???? */ - ibuf = NULL; - } - - if (position < 0) return(NULL); - if (position >= anim->duration) return(NULL); - } - else { - struct anim *proxy = IMB_anim_open_proxy(anim, preview_size); - - if (proxy) { - position = IMB_anim_index_get_frame_index( - anim, tc, position); - - return IMB_anim_absolute( - proxy, position, - IMB_TC_NONE, IMB_PROXY_NONE); - } - } - - switch (anim->curtype) { - case ANIM_SEQUENCE: - pic = an_stringdec(anim->first, head, tail, &digits); - pic += position; - an_stringenc(anim->name, head, tail, digits, pic); - ibuf = IMB_loadiffname(anim->name, IB_rect, anim->colorspace); - if (ibuf) { - anim->curposition = position; - } - break; - case ANIM_MOVIE: - ibuf = movie_fetchibuf(anim, position); - if (ibuf) { - anim->curposition = position; - IMB_convert_rgba_to_abgr(ibuf); - } - break; + struct ImBuf *ibuf = NULL; + char head[256], tail[256]; + unsigned short digits; + int pic; + int filter_y; + if (anim == NULL) + return (NULL); + + filter_y = (anim->ib_flags & IB_animdeinterlace); + + if (preview_size == IMB_PROXY_NONE) { + if (anim->curtype == 0) { + ibuf = anim_getnew(anim); + if (ibuf == NULL) { + return (NULL); + } + + IMB_freeImBuf(ibuf); /* ???? */ + ibuf = NULL; + } + + if (position < 0) + return (NULL); + if (position >= anim->duration) + return (NULL); + } + else { + struct anim *proxy = IMB_anim_open_proxy(anim, preview_size); + + if (proxy) { + position = IMB_anim_index_get_frame_index(anim, tc, position); + + return IMB_anim_absolute(proxy, position, IMB_TC_NONE, IMB_PROXY_NONE); + } + } + + switch (anim->curtype) { + case ANIM_SEQUENCE: + pic = an_stringdec(anim->first, head, tail, &digits); + pic += position; + an_stringenc(anim->name, head, tail, digits, pic); + ibuf = IMB_loadiffname(anim->name, IB_rect, anim->colorspace); + if (ibuf) { + anim->curposition = position; + } + break; + case ANIM_MOVIE: + ibuf = movie_fetchibuf(anim, position); + if (ibuf) { + anim->curposition = 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; + case ANIM_AVI: + ibuf = avi_fetchibuf(anim, position); + if (ibuf) + anim->curposition = position; + break; #endif #ifdef WITH_FFMPEG - case ANIM_FFMPEG: - ibuf = ffmpeg_fetchibuf(anim, position, tc); - if (ibuf) - anim->curposition = position; - filter_y = 0; /* done internally */ - break; + case ANIM_FFMPEG: + ibuf = ffmpeg_fetchibuf(anim, position, tc); + if (ibuf) + anim->curposition = position; + filter_y = 0; /* done internally */ + break; #endif - } - - if (ibuf) { - if (filter_y) IMB_filtery(ibuf); - BLI_snprintf(ibuf->name, sizeof(ibuf->name), "%s.%04d", anim->name, anim->curposition + 1); - - } - return(ibuf); + } + + if (ibuf) { + if (filter_y) + IMB_filtery(ibuf); + BLI_snprintf(ibuf->name, sizeof(ibuf->name), "%s.%04d", anim->name, anim->curposition + 1); + } + return (ibuf); } /***/ int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc) { - struct anim_index *idx; - if (tc == IMB_TC_NONE) { - return anim->duration; - } + struct anim_index *idx; + if (tc == IMB_TC_NONE) { + return anim->duration; + } - idx = IMB_anim_open_index(anim, tc); - if (!idx) { - return anim->duration; - } + idx = IMB_anim_open_index(anim, tc); + if (!idx) { + return anim->duration; + } - return IMB_indexer_get_duration(idx); + return IMB_indexer_get_duration(idx); } -bool IMB_anim_get_fps(struct anim *anim, - short *frs_sec, float *frs_sec_base, bool no_av_base) +bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base) { - double frs_sec_base_double; - if (anim->frs_sec) { - if (anim->frs_sec > SHRT_MAX) { - /* We cannot store original rational in our short/float format, - * we need to approximate it as best as we can... */ - *frs_sec = SHRT_MAX; - frs_sec_base_double = anim->frs_sec_base * (double)SHRT_MAX / (double)anim->frs_sec; - } - else { - *frs_sec = anim->frs_sec; - frs_sec_base_double = anim->frs_sec_base; - } + double frs_sec_base_double; + if (anim->frs_sec) { + if (anim->frs_sec > SHRT_MAX) { + /* We cannot store original rational in our short/float format, + * we need to approximate it as best as we can... */ + *frs_sec = SHRT_MAX; + frs_sec_base_double = anim->frs_sec_base * (double)SHRT_MAX / (double)anim->frs_sec; + } + else { + *frs_sec = anim->frs_sec; + frs_sec_base_double = anim->frs_sec_base; + } #ifdef WITH_FFMPEG - if (no_av_base) { - *frs_sec_base = (float)(frs_sec_base_double / AV_TIME_BASE); - } - else { - *frs_sec_base = (float)frs_sec_base_double; - } + if (no_av_base) { + *frs_sec_base = (float)(frs_sec_base_double / AV_TIME_BASE); + } + else { + *frs_sec_base = (float)frs_sec_base_double; + } #else - UNUSED_VARS(no_av_base); - *frs_sec_base = (float)frs_sec_base_double; + UNUSED_VARS(no_av_base); + *frs_sec_base = (float)frs_sec_base_double; #endif - BLI_assert(*frs_sec > 0); - BLI_assert(*frs_sec_base > 0.0f); + BLI_assert(*frs_sec > 0); + BLI_assert(*frs_sec_base > 0.0f); - return true; - } - return false; + return true; + } + return false; } void IMB_anim_set_preseek(struct anim *anim, int preseek) { - anim->preseek = preseek; + anim->preseek = preseek; } int IMB_anim_get_preseek(struct anim *anim) { - return anim->preseek; + return anim->preseek; } diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index d92e6f4ffcb..f5c12c916f0 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -39,238 +39,242 @@ */ typedef struct BMPINFOHEADER { - unsigned int biSize; - unsigned int biWidth; - unsigned int biHeight; - unsigned short biPlanes; - unsigned short biBitCount; - unsigned int biCompression; - unsigned int biSizeImage; - unsigned int biXPelsPerMeter; - unsigned int biYPelsPerMeter; - unsigned int biClrUsed; - unsigned int biClrImportant; + unsigned int biSize; + unsigned int biWidth; + unsigned int biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + unsigned int biCompression; + unsigned int biSizeImage; + unsigned int biXPelsPerMeter; + unsigned int biYPelsPerMeter; + unsigned int biClrUsed; + unsigned int biClrImportant; } BMPINFOHEADER; #if 0 typedef struct BMPHEADER { - unsigned short biType; - unsigned int biSize; - unsigned short biRes1; - unsigned short biRes2; - unsigned int biOffBits; + unsigned short biType; + unsigned int biSize; + unsigned short biRes1; + unsigned short biRes2; + unsigned int biOffBits; } BMPHEADER; #endif #define BMP_FILEHEADER_SIZE 14 #define CHECK_HEADER_FIELD(_mem, _field) ((_mem[0] == _field[0]) && (_mem[1] == _field[1])) -#define CHECK_HEADER_FIELD_BMP(_mem) \ - (CHECK_HEADER_FIELD(_mem, "BM") || \ - CHECK_HEADER_FIELD(_mem, "BA") || \ - CHECK_HEADER_FIELD(_mem, "CI") || \ - CHECK_HEADER_FIELD(_mem, "CP") || \ - CHECK_HEADER_FIELD(_mem, "IC") || \ - CHECK_HEADER_FIELD(_mem, "PT")) +#define CHECK_HEADER_FIELD_BMP(_mem) \ + (CHECK_HEADER_FIELD(_mem, "BM") || CHECK_HEADER_FIELD(_mem, "BA") || \ + CHECK_HEADER_FIELD(_mem, "CI") || CHECK_HEADER_FIELD(_mem, "CP") || \ + CHECK_HEADER_FIELD(_mem, "IC") || CHECK_HEADER_FIELD(_mem, "PT")) static int checkbmp(const unsigned char *mem) { - int ret_val = 0; - BMPINFOHEADER bmi; - unsigned int u; - - if (mem) { - if (CHECK_HEADER_FIELD_BMP(mem)) { - /* skip fileheader */ - mem += BMP_FILEHEADER_SIZE; - } - else { - return 0; - } - - /* for systems where an int needs to be 4 bytes aligned */ - memcpy(&bmi, mem, sizeof(bmi)); - - u = LITTLE_LONG(bmi.biSize); - /* we only support uncompressed images for now. */ - if (u >= sizeof(BMPINFOHEADER)) { - if (bmi.biCompression == 0) { - u = LITTLE_SHORT(bmi.biBitCount); - if (u > 0 && u <= 32) { - ret_val = 1; - } - } - } - } - - return(ret_val); + int ret_val = 0; + BMPINFOHEADER bmi; + unsigned int u; + + if (mem) { + if (CHECK_HEADER_FIELD_BMP(mem)) { + /* skip fileheader */ + mem += BMP_FILEHEADER_SIZE; + } + else { + return 0; + } + + /* for systems where an int needs to be 4 bytes aligned */ + memcpy(&bmi, mem, sizeof(bmi)); + + u = LITTLE_LONG(bmi.biSize); + /* we only support uncompressed images for now. */ + if (u >= sizeof(BMPINFOHEADER)) { + if (bmi.biCompression == 0) { + u = LITTLE_SHORT(bmi.biBitCount); + if (u > 0 && u <= 32) { + ret_val = 1; + } + } + } + } + + return (ret_val); } int imb_is_a_bmp(const unsigned char *buf) { - return checkbmp(buf); + return checkbmp(buf); } -struct ImBuf *imb_bmp_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +struct ImBuf *imb_bmp_decode(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - struct ImBuf *ibuf = NULL; - BMPINFOHEADER bmi; - int x, y, depth, ibuf_depth, skip; - const unsigned char *bmp; - unsigned char *rect; - unsigned short col; - double xppm, yppm; - bool top_to_bottom = false; - - (void)size; /* unused */ - - if (checkbmp(mem) == 0) return(NULL); - - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - bmp = mem + LITTLE_LONG(*(int *)(mem + 10)); - - if (CHECK_HEADER_FIELD_BMP(mem)) { - /* skip fileheader */ - mem += BMP_FILEHEADER_SIZE; - } - else { - return NULL; - } - - /* for systems where an int needs to be 4 bytes aligned */ - memcpy(&bmi, mem, sizeof(bmi)); - - skip = LITTLE_LONG(bmi.biSize); - x = LITTLE_LONG(bmi.biWidth); - y = LITTLE_LONG(bmi.biHeight); - depth = LITTLE_SHORT(bmi.biBitCount); - xppm = LITTLE_LONG(bmi.biXPelsPerMeter); - yppm = LITTLE_LONG(bmi.biYPelsPerMeter); - - if (depth <= 8) { - ibuf_depth = 24; - } - else { - ibuf_depth = depth; - } - - if (y < 0) { - /* Negative height means bitmap is stored top-to-bottom... */ - y = -y; - top_to_bottom = true; - } + struct ImBuf *ibuf = NULL; + BMPINFOHEADER bmi; + int x, y, depth, ibuf_depth, skip; + const unsigned char *bmp; + unsigned char *rect; + unsigned short col; + double xppm, yppm; + bool top_to_bottom = false; + + (void)size; /* unused */ + + if (checkbmp(mem) == 0) + return (NULL); + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + bmp = mem + LITTLE_LONG(*(int *)(mem + 10)); + + if (CHECK_HEADER_FIELD_BMP(mem)) { + /* skip fileheader */ + mem += BMP_FILEHEADER_SIZE; + } + else { + return NULL; + } + + /* for systems where an int needs to be 4 bytes aligned */ + memcpy(&bmi, mem, sizeof(bmi)); + + skip = LITTLE_LONG(bmi.biSize); + x = LITTLE_LONG(bmi.biWidth); + y = LITTLE_LONG(bmi.biHeight); + depth = LITTLE_SHORT(bmi.biBitCount); + xppm = LITTLE_LONG(bmi.biXPelsPerMeter); + yppm = LITTLE_LONG(bmi.biYPelsPerMeter); + + if (depth <= 8) { + ibuf_depth = 24; + } + else { + ibuf_depth = depth; + } + + if (y < 0) { + /* Negative height means bitmap is stored top-to-bottom... */ + y = -y; + top_to_bottom = true; + } #if 0 - printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, depth, bmi.biBitCount); + printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, depth, bmi.biBitCount); #endif - if (flags & IB_test) { - ibuf = IMB_allocImBuf(x, y, ibuf_depth, 0); - } - else { - ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect); - if (!ibuf) { - return NULL; - } - - rect = (unsigned char *) ibuf->rect; - - if (depth <= 8) { - const int rowsize = (depth * x + 31) / 32 * 4; - const char (*palette)[4] = (void *)(mem + skip); - const int startmask = ((1 << depth) - 1) << 8; - for (size_t i = y; i > 0; i--) { - int index; - int bitoffs = 8; - int bitmask = startmask; - int nbytes = 0; - const char *pcol; - if (top_to_bottom) { - rect = (unsigned char *) &ibuf->rect[(i - 1) * x]; - } - for (size_t j = x; j > 0; j--) { - bitoffs -= depth; - bitmask >>= depth; - index = (bmp[0] & bitmask) >> bitoffs; - pcol = palette[index]; - /* intentionally BGR -> RGB */ - rect[0] = pcol[2]; - rect[1] = pcol[1]; - rect[2] = pcol[0]; - - rect[3] = 255; - rect += 4; - if (bitoffs == 0) { - /* Advance to the next byte */ - bitoffs = 8; - bitmask = startmask; - nbytes += 1; - bmp += 1; - } - } - /* Advance to the next row */ - bmp += (rowsize - nbytes); - } - } - else if (depth == 16) { - for (size_t i = y; i > 0; i--) { - if (top_to_bottom) { - rect = (unsigned char *) &ibuf->rect[(i - 1) * x]; - } - for (size_t j = x; j > 0; j--) { - col = bmp[0] + (bmp[1] << 8); - rect[0] = ((col >> 10) & 0x1f) << 3; - rect[1] = ((col >> 5) & 0x1f) << 3; - rect[2] = ((col >> 0) & 0x1f) << 3; - - rect[3] = 255; - rect += 4; bmp += 2; - } - } - } - else if (depth == 24) { - const int x_pad = x % 4; - for (size_t i = y; i > 0; i--) { - if (top_to_bottom) { - rect = (unsigned char *) &ibuf->rect[(i - 1) * x]; - } - for (size_t j = x; j > 0; j--) { - rect[0] = bmp[2]; - rect[1] = bmp[1]; - rect[2] = bmp[0]; - - rect[3] = 255; - rect += 4; bmp += 3; - } - /* for 24-bit images, rows are padded to multiples of 4 */ - bmp += x_pad; - } - } - else if (depth == 32) { - for (size_t i = y; i > 0; i--) { - if (top_to_bottom) { - rect = (unsigned char *) &ibuf->rect[(i - 1) * x]; - } - for (size_t j = x; j > 0; j--) { - rect[0] = bmp[2]; - rect[1] = bmp[1]; - rect[2] = bmp[0]; - rect[3] = bmp[3]; - rect += 4; bmp += 4; - } - } - } - } - - if (ibuf) { - ibuf->ppm[0] = xppm; - ibuf->ppm[1] = yppm; - ibuf->ftype = IMB_FTYPE_BMP; - } - - return(ibuf); + if (flags & IB_test) { + ibuf = IMB_allocImBuf(x, y, ibuf_depth, 0); + } + else { + ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect); + if (!ibuf) { + return NULL; + } + + rect = (unsigned char *)ibuf->rect; + + if (depth <= 8) { + const int rowsize = (depth * x + 31) / 32 * 4; + const char(*palette)[4] = (void *)(mem + skip); + const int startmask = ((1 << depth) - 1) << 8; + for (size_t i = y; i > 0; i--) { + int index; + int bitoffs = 8; + int bitmask = startmask; + int nbytes = 0; + const char *pcol; + if (top_to_bottom) { + rect = (unsigned char *)&ibuf->rect[(i - 1) * x]; + } + for (size_t j = x; j > 0; j--) { + bitoffs -= depth; + bitmask >>= depth; + index = (bmp[0] & bitmask) >> bitoffs; + pcol = palette[index]; + /* intentionally BGR -> RGB */ + rect[0] = pcol[2]; + rect[1] = pcol[1]; + rect[2] = pcol[0]; + + rect[3] = 255; + rect += 4; + if (bitoffs == 0) { + /* Advance to the next byte */ + bitoffs = 8; + bitmask = startmask; + nbytes += 1; + bmp += 1; + } + } + /* Advance to the next row */ + bmp += (rowsize - nbytes); + } + } + else if (depth == 16) { + for (size_t i = y; i > 0; i--) { + if (top_to_bottom) { + rect = (unsigned char *)&ibuf->rect[(i - 1) * x]; + } + for (size_t j = x; j > 0; j--) { + col = bmp[0] + (bmp[1] << 8); + rect[0] = ((col >> 10) & 0x1f) << 3; + rect[1] = ((col >> 5) & 0x1f) << 3; + rect[2] = ((col >> 0) & 0x1f) << 3; + + rect[3] = 255; + rect += 4; + bmp += 2; + } + } + } + else if (depth == 24) { + const int x_pad = x % 4; + for (size_t i = y; i > 0; i--) { + if (top_to_bottom) { + rect = (unsigned char *)&ibuf->rect[(i - 1) * x]; + } + for (size_t j = x; j > 0; j--) { + rect[0] = bmp[2]; + rect[1] = bmp[1]; + rect[2] = bmp[0]; + + rect[3] = 255; + rect += 4; + bmp += 3; + } + /* for 24-bit images, rows are padded to multiples of 4 */ + bmp += x_pad; + } + } + else if (depth == 32) { + for (size_t i = y; i > 0; i--) { + if (top_to_bottom) { + rect = (unsigned char *)&ibuf->rect[(i - 1) * x]; + } + for (size_t j = x; j > 0; j--) { + rect[0] = bmp[2]; + rect[1] = bmp[1]; + rect[2] = bmp[0]; + rect[3] = bmp[3]; + rect += 4; + bmp += 4; + } + } + } + } + + if (ibuf) { + ibuf->ppm[0] = xppm; + ibuf->ppm[1] = yppm; + ibuf->ftype = IMB_FTYPE_BMP; + } + + return (ibuf); } #undef CHECK_HEADER_FIELD_BMP @@ -279,69 +283,74 @@ struct ImBuf *imb_bmp_decode(const unsigned char *mem, size_t size, int flags, c /* Couple of helper functions for writing our data */ static int putIntLSB(unsigned int ui, FILE *ofile) { - putc((ui >> 0) & 0xFF, ofile); - putc((ui >> 8) & 0xFF, ofile); - putc((ui >> 16) & 0xFF, ofile); - return putc((ui >> 24) & 0xFF, ofile); + putc((ui >> 0) & 0xFF, ofile); + putc((ui >> 8) & 0xFF, ofile); + putc((ui >> 16) & 0xFF, ofile); + return putc((ui >> 24) & 0xFF, ofile); } static int putShortLSB(unsigned short us, FILE *ofile) { - putc((us >> 0) & 0xFF, ofile); - return putc((us >> 8) & 0xFF, ofile); + putc((us >> 0) & 0xFF, ofile); + return putc((us >> 8) & 0xFF, ofile); } /* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) { - BMPINFOHEADER infoheader; - size_t bytesize, extrabytes, ptr; - uchar *data; - FILE *ofile; - - (void)flags; /* unused */ - - extrabytes = (4 - ibuf->x * 3 % 4) % 4; - bytesize = (ibuf->x * 3 + extrabytes) * ibuf->y; - - data = (uchar *) ibuf->rect; - ofile = BLI_fopen(name, "wb"); - if (!ofile) return 0; - - putShortLSB(19778, ofile); /* "BM" */ - putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); /* Total file size */ - putShortLSB(0, ofile); /* Res1 */ - putShortLSB(0, ofile); /* Res2 */ - putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); - - putIntLSB(sizeof(infoheader), ofile); - putIntLSB(ibuf->x, ofile); - putIntLSB(ibuf->y, ofile); - putShortLSB(1, ofile); - putShortLSB(24, ofile); - putIntLSB(0, ofile); - putIntLSB(bytesize, ofile); - putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile); - putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile); - putIntLSB(0, ofile); - putIntLSB(0, ofile); - - /* Need to write out padded image data in bgr format */ - for (size_t y = 0; y < ibuf->y; y++) { - for (size_t x = 0; x < ibuf->x; x++) { - ptr = (x + y * ibuf->x) * 4; - if (putc(data[ptr + 2], ofile) == EOF) return 0; - if (putc(data[ptr + 1], ofile) == EOF) return 0; - if (putc(data[ptr], ofile) == EOF) return 0; - } - /* add padding here */ - for (size_t t = 0; t < extrabytes; t++) { - if (putc(0, ofile) == EOF) return 0; - } - } - if (ofile) { - fflush(ofile); - fclose(ofile); - } - return 1; + BMPINFOHEADER infoheader; + size_t bytesize, extrabytes, ptr; + uchar *data; + FILE *ofile; + + (void)flags; /* unused */ + + extrabytes = (4 - ibuf->x * 3 % 4) % 4; + bytesize = (ibuf->x * 3 + extrabytes) * ibuf->y; + + data = (uchar *)ibuf->rect; + ofile = BLI_fopen(name, "wb"); + if (!ofile) + return 0; + + putShortLSB(19778, ofile); /* "BM" */ + putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); /* Total file size */ + putShortLSB(0, ofile); /* Res1 */ + putShortLSB(0, ofile); /* Res2 */ + putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); + + putIntLSB(sizeof(infoheader), ofile); + putIntLSB(ibuf->x, ofile); + putIntLSB(ibuf->y, ofile); + putShortLSB(1, ofile); + putShortLSB(24, ofile); + putIntLSB(0, ofile); + putIntLSB(bytesize, ofile); + putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile); + putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile); + putIntLSB(0, ofile); + putIntLSB(0, ofile); + + /* Need to write out padded image data in bgr format */ + for (size_t y = 0; y < ibuf->y; y++) { + for (size_t x = 0; x < ibuf->x; x++) { + ptr = (x + y * ibuf->x) * 4; + if (putc(data[ptr + 2], ofile) == EOF) + return 0; + if (putc(data[ptr + 1], ofile) == EOF) + return 0; + if (putc(data[ptr], ofile) == EOF) + return 0; + } + /* add padding here */ + for (size_t t = 0; t < extrabytes; t++) { + if (putc(0, ofile) == EOF) + return 0; + } + } + if (ofile) { + fflush(ofile); + fclose(ofile); + } + return 1; } diff --git a/source/blender/imbuf/intern/cache.c b/source/blender/imbuf/intern/cache.c index 92e9d21bb65..e6244364ba8 100644 --- a/source/blender/imbuf/intern/cache.c +++ b/source/blender/imbuf/intern/cache.c @@ -41,46 +41,46 @@ * back to the global cache every pixel, but not to big to keep too many tiles * locked and using memory. */ -#define IB_THREAD_CACHE_SIZE 100 +#define IB_THREAD_CACHE_SIZE 100 typedef struct ImGlobalTile { - struct ImGlobalTile *next, *prev; + struct ImGlobalTile *next, *prev; - ImBuf *ibuf; - int tx, ty; - int refcount; - volatile int loading; + ImBuf *ibuf; + int tx, ty; + int refcount; + volatile int loading; } ImGlobalTile; typedef struct ImThreadTile { - struct ImThreadTile *next, *prev; + struct ImThreadTile *next, *prev; - ImBuf *ibuf; - int tx, ty; + ImBuf *ibuf; + int tx, ty; - ImGlobalTile *global; + ImGlobalTile *global; } ImThreadTile; typedef struct ImThreadTileCache { - ListBase tiles; - ListBase unused; - GHash *tilehash; + ListBase tiles; + ListBase unused; + GHash *tilehash; } ImThreadTileCache; typedef struct ImGlobalTileCache { - ListBase tiles; - ListBase unused; - GHash *tilehash; + ListBase tiles; + ListBase unused; + GHash *tilehash; - MemArena *memarena; - uintptr_t totmem, maxmem; + MemArena *memarena; + uintptr_t totmem, maxmem; - ImThreadTileCache thread_cache[BLENDER_MAX_THREADS + 1]; - int totthread; + ImThreadTileCache thread_cache[BLENDER_MAX_THREADS + 1]; + int totthread; - ThreadMutex mutex; + ThreadMutex mutex; - int initialized; + int initialized; } ImGlobalTileCache; static ImGlobalTileCache GLOBAL_CACHE; @@ -89,360 +89,365 @@ static ImGlobalTileCache GLOBAL_CACHE; static unsigned int imb_global_tile_hash(const void *gtile_p) { - const ImGlobalTile *gtile = gtile_p; + const ImGlobalTile *gtile = gtile_p; - return ((unsigned int)(intptr_t)gtile->ibuf) * 769 + gtile->tx * 53 + gtile->ty * 97; + return ((unsigned int)(intptr_t)gtile->ibuf) * 769 + gtile->tx * 53 + gtile->ty * 97; } static bool imb_global_tile_cmp(const void *a_p, const void *b_p) { - const ImGlobalTile *a = a_p; - const ImGlobalTile *b = b_p; + const ImGlobalTile *a = a_p; + const ImGlobalTile *b = b_p; - return ((a->ibuf != b->ibuf) || - (a->tx != b->tx) || - (a->ty != b->ty)); + return ((a->ibuf != b->ibuf) || (a->tx != b->tx) || (a->ty != b->ty)); } static unsigned int imb_thread_tile_hash(const void *ttile_p) { - const ImThreadTile *ttile = ttile_p; + const ImThreadTile *ttile = ttile_p; - return ((unsigned int)(intptr_t)ttile->ibuf) * 769 + ttile->tx * 53 + ttile->ty * 97; + return ((unsigned int)(intptr_t)ttile->ibuf) * 769 + ttile->tx * 53 + ttile->ty * 97; } static bool imb_thread_tile_cmp(const void *a_p, const void *b_p) { - const ImThreadTile *a = a_p; - const ImThreadTile *b = b_p; + const ImThreadTile *a = a_p; + const ImThreadTile *b = b_p; - return ((a->ibuf != b->ibuf) || - (a->tx != b->tx) || - (a->ty != b->ty)); + return ((a->ibuf != b->ibuf) || (a->tx != b->tx) || (a->ty != b->ty)); } /******************************** Load/Unload ********************************/ static void imb_global_cache_tile_load(ImGlobalTile *gtile) { - ImBuf *ibuf = gtile->ibuf; - int toffs = ibuf->xtiles * gtile->ty + gtile->tx; - unsigned int *rect; + ImBuf *ibuf = gtile->ibuf; + int toffs = ibuf->xtiles * gtile->ty + gtile->tx; + unsigned int *rect; - rect = MEM_callocN(sizeof(unsigned int) * ibuf->tilex * ibuf->tiley, "imb_tile"); - imb_loadtile(ibuf, gtile->tx, gtile->ty, rect); - ibuf->tiles[toffs] = rect; + rect = MEM_callocN(sizeof(unsigned int) * ibuf->tilex * ibuf->tiley, "imb_tile"); + imb_loadtile(ibuf, gtile->tx, gtile->ty, rect); + ibuf->tiles[toffs] = rect; } static void imb_global_cache_tile_unload(ImGlobalTile *gtile) { - ImBuf *ibuf = gtile->ibuf; - int toffs = ibuf->xtiles * gtile->ty + gtile->tx; + ImBuf *ibuf = gtile->ibuf; + int toffs = ibuf->xtiles * gtile->ty + gtile->tx; - MEM_freeN(ibuf->tiles[toffs]); - ibuf->tiles[toffs] = NULL; + MEM_freeN(ibuf->tiles[toffs]); + ibuf->tiles[toffs] = NULL; - GLOBAL_CACHE.totmem -= sizeof(unsigned int) * ibuf->tilex * ibuf->tiley; + GLOBAL_CACHE.totmem -= sizeof(unsigned int) * ibuf->tilex * ibuf->tiley; } /* external free */ void imb_tile_cache_tile_free(ImBuf *ibuf, int tx, int ty) { - ImGlobalTile *gtile, lookuptile; + ImGlobalTile *gtile, lookuptile; - BLI_mutex_lock(&GLOBAL_CACHE.mutex); + BLI_mutex_lock(&GLOBAL_CACHE.mutex); - lookuptile.ibuf = ibuf; - lookuptile.tx = tx; - lookuptile.ty = ty; - gtile = BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile); + lookuptile.ibuf = ibuf; + lookuptile.tx = tx; + lookuptile.ty = ty; + gtile = BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile); - if (gtile) { - /* in case another thread is loading this */ - while (gtile->loading) - ; + if (gtile) { + /* in case another thread is loading this */ + while (gtile->loading) + ; - BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL); - BLI_remlink(&GLOBAL_CACHE.tiles, gtile); - BLI_addtail(&GLOBAL_CACHE.unused, gtile); - } + BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL); + BLI_remlink(&GLOBAL_CACHE.tiles, gtile); + BLI_addtail(&GLOBAL_CACHE.unused, gtile); + } - BLI_mutex_unlock(&GLOBAL_CACHE.mutex); + BLI_mutex_unlock(&GLOBAL_CACHE.mutex); } /******************************* Init/Exit ***********************************/ static void imb_thread_cache_init(ImThreadTileCache *cache) { - ImThreadTile *ttile; - int a; + ImThreadTile *ttile; + int a; - memset(cache, 0, sizeof(ImThreadTileCache)); + memset(cache, 0, sizeof(ImThreadTileCache)); - cache->tilehash = BLI_ghash_new(imb_thread_tile_hash, imb_thread_tile_cmp, "imb_thread_cache_init gh"); + cache->tilehash = BLI_ghash_new( + imb_thread_tile_hash, imb_thread_tile_cmp, "imb_thread_cache_init gh"); - /* pre-allocate all thread local tiles in unused list */ - for (a = 0; a < IB_THREAD_CACHE_SIZE; a++) { - ttile = BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImThreadTile)); - BLI_addtail(&cache->unused, ttile); - } + /* pre-allocate all thread local tiles in unused list */ + for (a = 0; a < IB_THREAD_CACHE_SIZE; a++) { + ttile = BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImThreadTile)); + BLI_addtail(&cache->unused, ttile); + } } static void imb_thread_cache_exit(ImThreadTileCache *cache) { - BLI_ghash_free(cache->tilehash, NULL, NULL); + BLI_ghash_free(cache->tilehash, NULL, NULL); } void imb_tile_cache_init(void) { - memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); + memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); - BLI_mutex_init(&GLOBAL_CACHE.mutex); + BLI_mutex_init(&GLOBAL_CACHE.mutex); - /* initialize for one thread, for places that access textures - * outside of rendering (displace modifier, painting, ..) */ - IMB_tile_cache_params(0, 0); + /* initialize for one thread, for places that access textures + * outside of rendering (displace modifier, painting, ..) */ + IMB_tile_cache_params(0, 0); - GLOBAL_CACHE.initialized = 1; + GLOBAL_CACHE.initialized = 1; } void imb_tile_cache_exit(void) { - ImGlobalTile *gtile; - int a; + ImGlobalTile *gtile; + int a; - if (GLOBAL_CACHE.initialized) { - for (gtile = GLOBAL_CACHE.tiles.first; gtile; gtile = gtile->next) - imb_global_cache_tile_unload(gtile); + if (GLOBAL_CACHE.initialized) { + for (gtile = GLOBAL_CACHE.tiles.first; gtile; gtile = gtile->next) + imb_global_cache_tile_unload(gtile); - for (a = 0; a < GLOBAL_CACHE.totthread; a++) - imb_thread_cache_exit(&GLOBAL_CACHE.thread_cache[a]); + for (a = 0; a < GLOBAL_CACHE.totthread; a++) + imb_thread_cache_exit(&GLOBAL_CACHE.thread_cache[a]); - if (GLOBAL_CACHE.memarena) - BLI_memarena_free(GLOBAL_CACHE.memarena); + if (GLOBAL_CACHE.memarena) + BLI_memarena_free(GLOBAL_CACHE.memarena); - if (GLOBAL_CACHE.tilehash) - BLI_ghash_free(GLOBAL_CACHE.tilehash, NULL, NULL); + if (GLOBAL_CACHE.tilehash) + BLI_ghash_free(GLOBAL_CACHE.tilehash, NULL, NULL); - BLI_mutex_end(&GLOBAL_CACHE.mutex); + BLI_mutex_end(&GLOBAL_CACHE.mutex); - memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); - } + memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); + } } /* presumed to be called when no threads are running */ void IMB_tile_cache_params(int totthread, int maxmem) { - int a; + int a; - /* always one cache for non-threaded access */ - totthread++; + /* always one cache for non-threaded access */ + totthread++; - /* lazy initialize cache */ - if (GLOBAL_CACHE.totthread == totthread && GLOBAL_CACHE.maxmem == maxmem) - return; + /* lazy initialize cache */ + if (GLOBAL_CACHE.totthread == totthread && GLOBAL_CACHE.maxmem == maxmem) + return; - imb_tile_cache_exit(); + imb_tile_cache_exit(); - memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); + memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache)); - GLOBAL_CACHE.tilehash = BLI_ghash_new(imb_global_tile_hash, imb_global_tile_cmp, "tile_cache_params gh"); + GLOBAL_CACHE.tilehash = BLI_ghash_new( + imb_global_tile_hash, imb_global_tile_cmp, "tile_cache_params gh"); - GLOBAL_CACHE.memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "ImTileCache arena"); - BLI_memarena_use_calloc(GLOBAL_CACHE.memarena); + GLOBAL_CACHE.memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "ImTileCache arena"); + BLI_memarena_use_calloc(GLOBAL_CACHE.memarena); - GLOBAL_CACHE.maxmem = maxmem * 1024 * 1024; + GLOBAL_CACHE.maxmem = maxmem * 1024 * 1024; - GLOBAL_CACHE.totthread = totthread; - for (a = 0; a < totthread; a++) - imb_thread_cache_init(&GLOBAL_CACHE.thread_cache[a]); + GLOBAL_CACHE.totthread = totthread; + for (a = 0; a < totthread; a++) + imb_thread_cache_init(&GLOBAL_CACHE.thread_cache[a]); - BLI_mutex_init(&GLOBAL_CACHE.mutex); + BLI_mutex_init(&GLOBAL_CACHE.mutex); } /***************************** Global Cache **********************************/ -static ImGlobalTile *imb_global_cache_get_tile(ImBuf *ibuf, int tx, int ty, ImGlobalTile *replacetile) +static ImGlobalTile *imb_global_cache_get_tile(ImBuf *ibuf, + int tx, + int ty, + ImGlobalTile *replacetile) { - ImGlobalTile *gtile, lookuptile; - - BLI_mutex_lock(&GLOBAL_CACHE.mutex); - - if (replacetile) - replacetile->refcount--; - - /* find tile in global cache */ - lookuptile.ibuf = ibuf; - lookuptile.tx = tx; - lookuptile.ty = ty; - gtile = BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile); - - if (gtile) { - /* found tile. however it may be in the process of being loaded - * by another thread, in that case we do stupid busy loop waiting - * for the other thread to load the tile */ - gtile->refcount++; - - BLI_mutex_unlock(&GLOBAL_CACHE.mutex); - - while (gtile->loading) - ; - } - else { - /* not found, let's load it from disk */ - - /* first check if we hit the memory limit */ - if (GLOBAL_CACHE.maxmem && GLOBAL_CACHE.totmem > GLOBAL_CACHE.maxmem) { - /* find an existing tile to unload */ - for (gtile = GLOBAL_CACHE.tiles.last; gtile; gtile = gtile->prev) - if (gtile->refcount == 0 && gtile->loading == 0) - break; - } - - if (gtile) { - /* found a tile to unload */ - imb_global_cache_tile_unload(gtile); - BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL); - BLI_remlink(&GLOBAL_CACHE.tiles, gtile); - } - else { - /* allocate a new tile or reuse unused */ - if (GLOBAL_CACHE.unused.first) { - gtile = GLOBAL_CACHE.unused.first; - BLI_remlink(&GLOBAL_CACHE.unused, gtile); - } - else - gtile = BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImGlobalTile)); - } - - /* setup new tile */ - gtile->ibuf = ibuf; - gtile->tx = tx; - gtile->ty = ty; - gtile->refcount = 1; - gtile->loading = 1; - - BLI_ghash_insert(GLOBAL_CACHE.tilehash, gtile, gtile); - BLI_addhead(&GLOBAL_CACHE.tiles, gtile); - - /* mark as being loaded and unlock to allow other threads to load too */ - GLOBAL_CACHE.totmem += sizeof(unsigned int) * ibuf->tilex * ibuf->tiley; - - BLI_mutex_unlock(&GLOBAL_CACHE.mutex); - - /* load from disk */ - imb_global_cache_tile_load(gtile); - - /* mark as done loading */ - gtile->loading = 0; - } - - return gtile; + ImGlobalTile *gtile, lookuptile; + + BLI_mutex_lock(&GLOBAL_CACHE.mutex); + + if (replacetile) + replacetile->refcount--; + + /* find tile in global cache */ + lookuptile.ibuf = ibuf; + lookuptile.tx = tx; + lookuptile.ty = ty; + gtile = BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile); + + if (gtile) { + /* found tile. however it may be in the process of being loaded + * by another thread, in that case we do stupid busy loop waiting + * for the other thread to load the tile */ + gtile->refcount++; + + BLI_mutex_unlock(&GLOBAL_CACHE.mutex); + + while (gtile->loading) + ; + } + else { + /* not found, let's load it from disk */ + + /* first check if we hit the memory limit */ + if (GLOBAL_CACHE.maxmem && GLOBAL_CACHE.totmem > GLOBAL_CACHE.maxmem) { + /* find an existing tile to unload */ + for (gtile = GLOBAL_CACHE.tiles.last; gtile; gtile = gtile->prev) + if (gtile->refcount == 0 && gtile->loading == 0) + break; + } + + if (gtile) { + /* found a tile to unload */ + imb_global_cache_tile_unload(gtile); + BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL); + BLI_remlink(&GLOBAL_CACHE.tiles, gtile); + } + else { + /* allocate a new tile or reuse unused */ + if (GLOBAL_CACHE.unused.first) { + gtile = GLOBAL_CACHE.unused.first; + BLI_remlink(&GLOBAL_CACHE.unused, gtile); + } + else + gtile = BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImGlobalTile)); + } + + /* setup new tile */ + gtile->ibuf = ibuf; + gtile->tx = tx; + gtile->ty = ty; + gtile->refcount = 1; + gtile->loading = 1; + + BLI_ghash_insert(GLOBAL_CACHE.tilehash, gtile, gtile); + BLI_addhead(&GLOBAL_CACHE.tiles, gtile); + + /* mark as being loaded and unlock to allow other threads to load too */ + GLOBAL_CACHE.totmem += sizeof(unsigned int) * ibuf->tilex * ibuf->tiley; + + BLI_mutex_unlock(&GLOBAL_CACHE.mutex); + + /* load from disk */ + imb_global_cache_tile_load(gtile); + + /* mark as done loading */ + gtile->loading = 0; + } + + return gtile; } /***************************** Per-Thread Cache ******************************/ -static unsigned int *imb_thread_cache_get_tile(ImThreadTileCache *cache, ImBuf *ibuf, int tx, int ty) +static unsigned int *imb_thread_cache_get_tile(ImThreadTileCache *cache, + ImBuf *ibuf, + int tx, + int ty) { - ImThreadTile *ttile, lookuptile; - ImGlobalTile *gtile, *replacetile; - int toffs = ibuf->xtiles * ty + tx; - - /* test if it is already in our thread local cache */ - if ((ttile = cache->tiles.first)) { - /* check last used tile before going to hash */ - if (ttile->ibuf == ibuf && ttile->tx == tx && ttile->ty == ty) - return ibuf->tiles[toffs]; - - /* find tile in hash */ - lookuptile.ibuf = ibuf; - lookuptile.tx = tx; - lookuptile.ty = ty; - - if ((ttile = BLI_ghash_lookup(cache->tilehash, &lookuptile))) { - BLI_remlink(&cache->tiles, ttile); - BLI_addhead(&cache->tiles, ttile); - - return ibuf->tiles[toffs]; - } - } - - /* not found, have to do slow lookup in global cache */ - if (BLI_listbase_is_empty(&cache->unused)) { - ttile = cache->tiles.last; - replacetile = ttile->global; - BLI_remlink(&cache->tiles, ttile); - BLI_ghash_remove(cache->tilehash, ttile, NULL, NULL); - } - else { - ttile = cache->unused.first; - replacetile = NULL; - BLI_remlink(&cache->unused, ttile); - } - - BLI_addhead(&cache->tiles, ttile); - BLI_ghash_insert(cache->tilehash, ttile, ttile); - - gtile = imb_global_cache_get_tile(ibuf, tx, ty, replacetile); - - ttile->ibuf = gtile->ibuf; - ttile->tx = gtile->tx; - ttile->ty = gtile->ty; - ttile->global = gtile; - - return ibuf->tiles[toffs]; + ImThreadTile *ttile, lookuptile; + ImGlobalTile *gtile, *replacetile; + int toffs = ibuf->xtiles * ty + tx; + + /* test if it is already in our thread local cache */ + if ((ttile = cache->tiles.first)) { + /* check last used tile before going to hash */ + if (ttile->ibuf == ibuf && ttile->tx == tx && ttile->ty == ty) + return ibuf->tiles[toffs]; + + /* find tile in hash */ + lookuptile.ibuf = ibuf; + lookuptile.tx = tx; + lookuptile.ty = ty; + + if ((ttile = BLI_ghash_lookup(cache->tilehash, &lookuptile))) { + BLI_remlink(&cache->tiles, ttile); + BLI_addhead(&cache->tiles, ttile); + + return ibuf->tiles[toffs]; + } + } + + /* not found, have to do slow lookup in global cache */ + if (BLI_listbase_is_empty(&cache->unused)) { + ttile = cache->tiles.last; + replacetile = ttile->global; + BLI_remlink(&cache->tiles, ttile); + BLI_ghash_remove(cache->tilehash, ttile, NULL, NULL); + } + else { + ttile = cache->unused.first; + replacetile = NULL; + BLI_remlink(&cache->unused, ttile); + } + + BLI_addhead(&cache->tiles, ttile); + BLI_ghash_insert(cache->tilehash, ttile, ttile); + + gtile = imb_global_cache_get_tile(ibuf, tx, ty, replacetile); + + ttile->ibuf = gtile->ibuf; + ttile->tx = gtile->tx; + ttile->ty = gtile->ty; + ttile->global = gtile; + + return ibuf->tiles[toffs]; } unsigned int *IMB_gettile(ImBuf *ibuf, int tx, int ty, int thread) { - return imb_thread_cache_get_tile(&GLOBAL_CACHE.thread_cache[thread + 1], ibuf, tx, ty); + return imb_thread_cache_get_tile(&GLOBAL_CACHE.thread_cache[thread + 1], ibuf, tx, ty); } void IMB_tiles_to_rect(ImBuf *ibuf) { - ImBuf *mipbuf; - ImGlobalTile *gtile; - unsigned int *to, *from; - int a, tx, ty, y, w, h; - - for (a = 0; a < ibuf->miptot; a++) { - mipbuf = IMB_getmipmap(ibuf, a); - - /* don't call imb_addrectImBuf, it frees all mipmaps */ - if (!mipbuf->rect) { - if ((mipbuf->rect = MEM_mapallocN(ibuf->x * ibuf->y * sizeof(unsigned int), "imb_addrectImBuf"))) { - mipbuf->mall |= IB_rect; - mipbuf->flags |= IB_rect; - } - else - break; - } - - for (ty = 0; ty < mipbuf->ytiles; ty++) { - for (tx = 0; tx < mipbuf->xtiles; tx++) { - /* acquire tile through cache, this assumes cache is initialized, - * which it is always now but it's a weak assumption ... */ - gtile = imb_global_cache_get_tile(mipbuf, tx, ty, NULL); - - /* setup pointers */ - from = mipbuf->tiles[mipbuf->xtiles * ty + tx]; - to = mipbuf->rect + mipbuf->x * ty * mipbuf->tiley + tx * mipbuf->tilex; - - /* exception in tile width/height for tiles at end of image */ - w = (tx == mipbuf->xtiles - 1) ? mipbuf->x - tx * mipbuf->tilex : mipbuf->tilex; - h = (ty == mipbuf->ytiles - 1) ? mipbuf->y - ty * mipbuf->tiley : mipbuf->tiley; - - for (y = 0; y < h; y++) { - memcpy(to, from, sizeof(unsigned int) * w); - from += mipbuf->tilex; - to += mipbuf->x; - } - - /* decrease refcount for tile again */ - BLI_mutex_lock(&GLOBAL_CACHE.mutex); - gtile->refcount--; - BLI_mutex_unlock(&GLOBAL_CACHE.mutex); - } - } - } + ImBuf *mipbuf; + ImGlobalTile *gtile; + unsigned int *to, *from; + int a, tx, ty, y, w, h; + + for (a = 0; a < ibuf->miptot; a++) { + mipbuf = IMB_getmipmap(ibuf, a); + + /* don't call imb_addrectImBuf, it frees all mipmaps */ + if (!mipbuf->rect) { + if ((mipbuf->rect = MEM_mapallocN(ibuf->x * ibuf->y * sizeof(unsigned int), + "imb_addrectImBuf"))) { + mipbuf->mall |= IB_rect; + mipbuf->flags |= IB_rect; + } + else + break; + } + + for (ty = 0; ty < mipbuf->ytiles; ty++) { + for (tx = 0; tx < mipbuf->xtiles; tx++) { + /* acquire tile through cache, this assumes cache is initialized, + * which it is always now but it's a weak assumption ... */ + gtile = imb_global_cache_get_tile(mipbuf, tx, ty, NULL); + + /* setup pointers */ + from = mipbuf->tiles[mipbuf->xtiles * ty + tx]; + to = mipbuf->rect + mipbuf->x * ty * mipbuf->tiley + tx * mipbuf->tilex; + + /* exception in tile width/height for tiles at end of image */ + w = (tx == mipbuf->xtiles - 1) ? mipbuf->x - tx * mipbuf->tilex : mipbuf->tilex; + h = (ty == mipbuf->ytiles - 1) ? mipbuf->y - ty * mipbuf->tiley : mipbuf->tiley; + + for (y = 0; y < h; y++) { + memcpy(to, from, sizeof(unsigned int) * w); + from += mipbuf->tilex; + to += mipbuf->x; + } + + /* decrease refcount for tile again */ + BLI_mutex_lock(&GLOBAL_CACHE.mutex); + gtile->refcount--; + BLI_mutex_unlock(&GLOBAL_CACHE.mutex); + } + } + } } diff --git a/source/blender/imbuf/intern/cineon/CMakeLists.txt b/source/blender/imbuf/intern/cineon/CMakeLists.txt index 2f6ca2793e3..d740b080c35 100644 --- a/source/blender/imbuf/intern/cineon/CMakeLists.txt +++ b/source/blender/imbuf/intern/cineon/CMakeLists.txt @@ -19,13 +19,13 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - .. - ../.. - ../../../blenkernel - ../../../blenlib - ../../../makesdna - ../../../../../intern/guardedalloc + . + .. + ../.. + ../../../blenkernel + ../../../blenlib + ../../../makesdna + ../../../../../intern/guardedalloc ) set(INC_SYS @@ -33,23 +33,23 @@ set(INC_SYS ) set(SRC - cineonlib.h - dpxlib.h - logImageCore.h - logmemfile.h - - cineon_dpx.c - cineonlib.c - dpxlib.c - logImageCore.c - logmemfile.c + cineonlib.h + dpxlib.h + logImageCore.h + logmemfile.h + + cineon_dpx.c + cineonlib.c + dpxlib.c + logImageCore.c + logmemfile.c ) set(LIB ) if(WITH_IMAGE_CINEON) - add_definitions(-DWITH_CINEON) + add_definitions(-DWITH_CINEON) endif() blender_add_lib(bf_imbuf_cineon "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 2db7668c0ca..8f3829ee91e 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -20,7 +20,6 @@ * \ingroup imbcineon */ - #include #include #include @@ -37,164 +36,183 @@ #include "MEM_guardedalloc.h" -static struct ImBuf *imb_load_dpx_cineon( - const unsigned char *mem, size_t size, int use_cineon, int flags, - char colorspace[IM_MAX_SPACE]) +static struct ImBuf *imb_load_dpx_cineon(const unsigned char *mem, + size_t size, + int use_cineon, + int flags, + char colorspace[IM_MAX_SPACE]) { - ImBuf *ibuf; - LogImageFile *image; - int width, height, depth; + ImBuf *ibuf; + LogImageFile *image; + int width, height, depth; - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); - logImageSetVerbose((G.debug & G_DEBUG) ? 1 : 0); + logImageSetVerbose((G.debug & G_DEBUG) ? 1 : 0); - image = logImageOpenFromMemory(mem, size); + image = logImageOpenFromMemory(mem, size); - if (image == NULL) { - printf("DPX/Cineon: error opening image.\n"); - return NULL; - } + if (image == NULL) { + printf("DPX/Cineon: error opening image.\n"); + return NULL; + } - logImageGetSize(image, &width, &height, &depth); + logImageGetSize(image, &width, &height, &depth); - ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); - if (ibuf == NULL) { - logImageClose(image); - return NULL; - } + ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); + if (ibuf == NULL) { + logImageClose(image); + return NULL; + } - if (!(flags & IB_test)) { - if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { - logImageClose(image); - IMB_freeImBuf(ibuf); - return NULL; - } - IMB_flipy(ibuf); - } + if (!(flags & IB_test)) { + if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { + logImageClose(image); + IMB_freeImBuf(ibuf); + return NULL; + } + IMB_flipy(ibuf); + } - logImageClose(image); - ibuf->ftype = use_cineon ? IMB_FTYPE_CINEON : IMB_FTYPE_DPX; + logImageClose(image); + ibuf->ftype = use_cineon ? IMB_FTYPE_CINEON : IMB_FTYPE_DPX; - if (flags & IB_alphamode_detect) - ibuf->flags |= IB_alphamode_premul; + if (flags & IB_alphamode_detect) + ibuf->flags |= IB_alphamode_premul; - return ibuf; + return ibuf; } static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags) { - LogImageFile *logImage; - float *fbuf; - float *fbuf_ptr; - unsigned char *rect_ptr; - int x, y, depth, bitspersample, rvalue; - - if (flags & IB_mem) { - printf("DPX/Cineon: saving in memory is not supported.\n"); - return 0; - } - - logImageSetVerbose((G.debug & G_DEBUG) ? 1 : 0); - - depth = (ibuf->planes + 7) >> 3; - if (depth > 4 || depth < 3) { - printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename); - return 0; - } - - if (ibuf->foptions.flag & CINEON_10BIT) - bitspersample = 10; - else if (ibuf->foptions.flag & CINEON_12BIT) - bitspersample = 12; - else if (ibuf->foptions.flag & CINEON_16BIT) - bitspersample = 16; - else - bitspersample = 8; - - logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4), - (ibuf->foptions.flag & CINEON_LOG), -1, -1, -1, "Blender"); - - if (logImage == NULL) { - printf("DPX/Cineon: error creating file.\n"); - return 0; - } - - if (ibuf->rect_float != NULL && bitspersample != 8) { - /* don't use the float buffer to save 8 bpp picture to prevent color banding - * (there's no dithering algorithm behing the logImageSetDataRGBA function) */ - - fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); - - for (y = 0; y < ibuf->y; y++) { - float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x); - float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x); - - memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float)); - } - - rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0); - - MEM_freeN(fbuf); - } - else { - if (ibuf->rect == NULL) - IMB_rect_from_float(ibuf); - - fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); - if (fbuf == NULL) { - printf("DPX/Cineon: error allocating memory.\n"); - logImageClose(logImage); - return 0; - } - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x); - rect_ptr = (unsigned char *)ibuf->rect + 4 * (y * ibuf->x + x); - fbuf_ptr[0] = (float)rect_ptr[0] / 255.0f; - fbuf_ptr[1] = (float)rect_ptr[1] / 255.0f; - fbuf_ptr[2] = (float)rect_ptr[2] / 255.0f; - fbuf_ptr[3] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f; - } - } - rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0); - MEM_freeN(fbuf); - } - - logImageClose(logImage); - return rvalue; + LogImageFile *logImage; + float *fbuf; + float *fbuf_ptr; + unsigned char *rect_ptr; + int x, y, depth, bitspersample, rvalue; + + if (flags & IB_mem) { + printf("DPX/Cineon: saving in memory is not supported.\n"); + return 0; + } + + logImageSetVerbose((G.debug & G_DEBUG) ? 1 : 0); + + depth = (ibuf->planes + 7) >> 3; + if (depth > 4 || depth < 3) { + printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename); + return 0; + } + + if (ibuf->foptions.flag & CINEON_10BIT) + bitspersample = 10; + else if (ibuf->foptions.flag & CINEON_12BIT) + bitspersample = 12; + else if (ibuf->foptions.flag & CINEON_16BIT) + bitspersample = 16; + else + bitspersample = 8; + + logImage = logImageCreate(filename, + use_cineon, + ibuf->x, + ibuf->y, + bitspersample, + (depth == 4), + (ibuf->foptions.flag & CINEON_LOG), + -1, + -1, + -1, + "Blender"); + + if (logImage == NULL) { + printf("DPX/Cineon: error creating file.\n"); + return 0; + } + + if (ibuf->rect_float != NULL && bitspersample != 8) { + /* don't use the float buffer to save 8 bpp picture to prevent color banding + * (there's no dithering algorithm behing the logImageSetDataRGBA function) */ + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), + "fbuf in imb_save_dpx_cineon"); + + for (y = 0; y < ibuf->y; y++) { + float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x); + float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x); + + memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float)); + } + + rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0); + + MEM_freeN(fbuf); + } + else { + if (ibuf->rect == NULL) + IMB_rect_from_float(ibuf); + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), + "fbuf in imb_save_dpx_cineon"); + if (fbuf == NULL) { + printf("DPX/Cineon: error allocating memory.\n"); + logImageClose(logImage); + return 0; + } + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x); + rect_ptr = (unsigned char *)ibuf->rect + 4 * (y * ibuf->x + x); + fbuf_ptr[0] = (float)rect_ptr[0] / 255.0f; + fbuf_ptr[1] = (float)rect_ptr[1] / 255.0f; + fbuf_ptr[2] = (float)rect_ptr[2] / 255.0f; + fbuf_ptr[3] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f; + } + } + rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0); + MEM_freeN(fbuf); + } + + logImageClose(logImage); + return rvalue; } int imb_save_cineon(struct ImBuf *buf, const char *myfile, int flags) { - return imb_save_dpx_cineon(buf, myfile, 1, flags); + return imb_save_dpx_cineon(buf, myfile, 1, flags); } int imb_is_cineon(const unsigned char *buf) { - return logImageIsCineon(buf); + return logImageIsCineon(buf); } -ImBuf *imb_load_cineon(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_cineon(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - if (imb_is_cineon(mem)) - return imb_load_dpx_cineon(mem, size, 1, flags, colorspace); - return NULL; + if (imb_is_cineon(mem)) + return imb_load_dpx_cineon(mem, size, 1, flags, colorspace); + return NULL; } int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags) { - return imb_save_dpx_cineon(buf, myfile, 0, flags); + return imb_save_dpx_cineon(buf, myfile, 0, flags); } int imb_is_dpx(const unsigned char *buf) { - return logImageIsDpx(buf); + return logImageIsDpx(buf); } -ImBuf *imb_load_dpx(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_dpx(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - if (imb_is_dpx(mem)) - return imb_load_dpx_cineon(mem, size, 0, flags, colorspace); - return NULL; + if (imb_is_dpx(mem)) + return imb_load_dpx_cineon(mem, size, 0, flags, colorspace); + return NULL; } diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 14389a566fd..79f419e747c 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -22,7 +22,6 @@ * Cineon image file format library routines. */ - #include "cineonlib.h" #include "logmemfile.h" @@ -46,342 +45,373 @@ static int verbose = 0; void cineonSetVerbose(int verbosity) { - verbose = verbosity; + verbose = verbosity; } -static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, - const char *filename, const char *creator) +static void fillCineonMainHeader(LogImageFile *cineon, + CineonMainHeader *header, + const char *filename, + const char *creator) { - time_t fileClock; - struct tm *fileTime; - int i; - - 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(NULL); - 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 */ + time_t fileClock; + struct tm *fileTime; + int i; + + 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(NULL); + 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 */ } LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) { - CineonMainHeader header; - LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); - const char *filename = (const char *)byteStuff; - int i; - unsigned int dataOffset; - - if (cineon == NULL) { - if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n"); - return NULL; - } - - /* zero the header */ - memset(&header, 0, sizeof(CineonMainHeader)); - - /* for close routine */ - cineon->file = NULL; - - if (fromMemory == 0) { - /* byteStuff is then the filename */ - cineon->file = BLI_fopen(filename, "rb"); - if (cineon->file == NULL) { - if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename); - logImageClose(cineon); - return NULL; - } - /* not used in this case */ - cineon->memBuffer = NULL; - cineon->memCursor = NULL; - cineon->memBufferSize = 0; - } - else { - cineon->memBuffer = (unsigned char *)byteStuff; - cineon->memCursor = (unsigned char *)byteStuff; - cineon->memBufferSize = bufferSize; - } - - if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) { - if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff); - logImageClose(cineon); - return NULL; - } - - /* endianness determination */ - if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) { - cineon->isMSB = 1; - if (verbose) printf("Cineon: File is MSB.\n"); - } - else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) { - cineon->isMSB = 0; - if (verbose) printf("Cineon: File is LSB.\n"); - } - else { - if (verbose) { - printf("Cineon: Bad magic number %lu in \"%s\".\n", - (unsigned long)header.fileHeader.magic_num, byteStuff); - } - logImageClose(cineon); - return NULL; - } - - cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB); - cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB); - - if (cineon->width == 0 || cineon->height == 0) { - if (verbose) printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height); - logImageClose(cineon); - return NULL; - } - - cineon->depth = header.imageHeader.elements_per_image; - cineon->srcFormat = format_Cineon; - - if (header.imageHeader.interleave == 0) - cineon->numElements = 1; - else if (header.imageHeader.interleave == 2) - cineon->numElements = header.imageHeader.elements_per_image; - else { - if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave); - logImageClose(cineon); - return NULL; - } - - if (cineon->depth == 1) { - /* Grayscale image */ - cineon->element[0].descriptor = descriptor_Luminance; - cineon->element[0].transfer = transfer_Linear; - cineon->element[0].depth = 1; - } - else if (cineon->depth == 3) { - /* RGB image */ - if (cineon->numElements == 1) { - cineon->element[0].descriptor = descriptor_RGB; - cineon->element[0].transfer = transfer_PrintingDensity; - cineon->element[0].depth = 3; - } - else if (cineon->numElements == 3) { - cineon->element[0].descriptor = descriptor_Red; - cineon->element[0].transfer = transfer_PrintingDensity; - cineon->element[0].depth = 1; - cineon->element[1].descriptor = descriptor_Green; - cineon->element[1].transfer = transfer_PrintingDensity; - cineon->element[1].depth = 1; - cineon->element[2].descriptor = descriptor_Blue; - cineon->element[2].transfer = transfer_PrintingDensity; - cineon->element[2].depth = 1; - } - } - else { - if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth); - logImageClose(cineon); - return NULL; - } - - dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB); - - for (i = 0; i < cineon->numElements; i++) { - cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; - cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f; - cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, cineon->isMSB); - cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, cineon->isMSB); - cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, cineon->isMSB); - cineon->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, cineon->isMSB); - - switch (header.imageHeader.packing) { - case 0: - cineon->element[i].packing = 0; - break; - - case 5: - cineon->element[i].packing = 1; - break; - - case 6: - cineon->element[i].packing = 2; - break; - - default: - /* Not supported */ - if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing); - logImageClose(cineon); - return NULL; - } - - if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32) - cineon->element[i].refLowData = 0; - - if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32) - cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue; - - if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity)) - cineon->element[i].refLowQuantity = 0.0f; - - if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refHighQuantity)) { - if (cineon->element[i].transfer == transfer_PrintingDensity) - cineon->element[i].refHighQuantity = 2.048f; - else - cineon->element[i].refHighQuantity = cineon->element[i].maxValue; - } - - cineon->element[i].dataOffset = dataOffset; - dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]); - } - - cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue; - cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue; - cineon->gamma = 1.7f; - - if (verbose) { - printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements); - for (i = 0; i < cineon->numElements; i++) { - printf(" Element %d:\n", i); - printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample); - printf(" Depth: %d\n", cineon->element[i].depth); - printf(" Transfer characteristics: %d\n", cineon->element[i].transfer); - printf(" Packing: %d\n", cineon->element[i].packing); - printf(" Descriptor: %d\n", cineon->element[i].descriptor); - printf(" Data offset: %d\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("Orientation: %d\n", header.imageHeader.orientation); - printf("----------------------------\n"); - } - return cineon; + CineonMainHeader header; + LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + const char *filename = (const char *)byteStuff; + int i; + unsigned int dataOffset; + + if (cineon == NULL) { + if (verbose) + printf("Cineon: Failed to malloc cineon file structure.\n"); + return NULL; + } + + /* zero the header */ + memset(&header, 0, sizeof(CineonMainHeader)); + + /* for close routine */ + cineon->file = NULL; + + if (fromMemory == 0) { + /* byteStuff is then the filename */ + cineon->file = BLI_fopen(filename, "rb"); + if (cineon->file == NULL) { + if (verbose) + printf("Cineon: Failed to open file \"%s\".\n", filename); + logImageClose(cineon); + return NULL; + } + /* not used in this case */ + cineon->memBuffer = NULL; + cineon->memCursor = NULL; + cineon->memBufferSize = 0; + } + else { + cineon->memBuffer = (unsigned char *)byteStuff; + cineon->memCursor = (unsigned char *)byteStuff; + cineon->memBufferSize = bufferSize; + } + + if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) { + if (verbose) + printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff); + logImageClose(cineon); + return NULL; + } + + /* endianness determination */ + if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) { + cineon->isMSB = 1; + if (verbose) + printf("Cineon: File is MSB.\n"); + } + else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) { + cineon->isMSB = 0; + if (verbose) + printf("Cineon: File is LSB.\n"); + } + else { + if (verbose) { + printf("Cineon: Bad magic number %lu in \"%s\".\n", + (unsigned long)header.fileHeader.magic_num, + byteStuff); + } + logImageClose(cineon); + return NULL; + } + + cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB); + cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB); + + if (cineon->width == 0 || cineon->height == 0) { + if (verbose) + printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height); + logImageClose(cineon); + return NULL; + } + + cineon->depth = header.imageHeader.elements_per_image; + cineon->srcFormat = format_Cineon; + + if (header.imageHeader.interleave == 0) + cineon->numElements = 1; + else if (header.imageHeader.interleave == 2) + cineon->numElements = header.imageHeader.elements_per_image; + else { + if (verbose) + printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave); + logImageClose(cineon); + return NULL; + } + + if (cineon->depth == 1) { + /* Grayscale image */ + cineon->element[0].descriptor = descriptor_Luminance; + cineon->element[0].transfer = transfer_Linear; + cineon->element[0].depth = 1; + } + else if (cineon->depth == 3) { + /* RGB image */ + if (cineon->numElements == 1) { + cineon->element[0].descriptor = descriptor_RGB; + cineon->element[0].transfer = transfer_PrintingDensity; + cineon->element[0].depth = 3; + } + else if (cineon->numElements == 3) { + cineon->element[0].descriptor = descriptor_Red; + cineon->element[0].transfer = transfer_PrintingDensity; + cineon->element[0].depth = 1; + cineon->element[1].descriptor = descriptor_Green; + cineon->element[1].transfer = transfer_PrintingDensity; + cineon->element[1].depth = 1; + cineon->element[2].descriptor = descriptor_Blue; + cineon->element[2].transfer = transfer_PrintingDensity; + cineon->element[2].depth = 1; + } + } + else { + if (verbose) + printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth); + logImageClose(cineon); + return NULL; + } + + dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB); + + for (i = 0; i < cineon->numElements; i++) { + cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; + cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f; + cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, + cineon->isMSB); + cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, + cineon->isMSB); + cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, + cineon->isMSB); + cineon->element[i].refHighQuantity = swap_float( + header.imageHeader.element[i].ref_high_quantity, cineon->isMSB); + + switch (header.imageHeader.packing) { + case 0: + cineon->element[i].packing = 0; + break; + + case 5: + cineon->element[i].packing = 1; + break; + + case 6: + cineon->element[i].packing = 2; + break; + + default: + /* Not supported */ + if (verbose) + printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing); + logImageClose(cineon); + return NULL; + } + + if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32) + cineon->element[i].refLowData = 0; + + if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32) + cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue; + + if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || + isnan(cineon->element[i].refLowQuantity)) + cineon->element[i].refLowQuantity = 0.0f; + + if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || + isnan(cineon->element[i].refHighQuantity)) { + if (cineon->element[i].transfer == transfer_PrintingDensity) + cineon->element[i].refHighQuantity = 2.048f; + else + cineon->element[i].refHighQuantity = cineon->element[i].maxValue; + } + + cineon->element[i].dataOffset = dataOffset; + dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]); + } + + cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue; + cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue; + cineon->gamma = 1.7f; + + if (verbose) { + printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements); + for (i = 0; i < cineon->numElements; i++) { + printf(" Element %d:\n", i); + printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample); + printf(" Depth: %d\n", cineon->element[i].depth); + printf(" Transfer characteristics: %d\n", cineon->element[i].transfer); + printf(" Packing: %d\n", cineon->element[i].packing); + printf(" Descriptor: %d\n", cineon->element[i].descriptor); + printf(" Data offset: %d\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("Orientation: %d\n", header.imageHeader.orientation); + printf("----------------------------\n"); + } + return cineon; } -LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator) +LogImageFile *cineonCreate( + const char *filename, int width, int height, int bitsPerSample, const char *creator) { - CineonMainHeader header; - const char *shortFilename = NULL; - /* unsigned char pad[6044]; */ - - LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); - if (cineon == NULL) { - if (verbose) printf("cineon: Failed to malloc cineon file structure.\n"); - return NULL; - } - - /* Only 10 bits Cineon are supported */ - if (bitsPerSample != 10) { - if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n"); - logImageClose(cineon); - return NULL; - } - - cineon->width = width; - cineon->height = height; - cineon->element[0].bitsPerSample = 10; - cineon->element[0].dataOffset = sizeof(CineonMainHeader); - cineon->element[0].maxValue = 1023; - cineon->isMSB = 1; - cineon->numElements = 1; - cineon->element[0].packing = 1; - cineon->depth = 3; - cineon->element[0].depth = 3; - cineon->element[0].descriptor = descriptor_RGB; - cineon->element[0].transfer = transfer_PrintingDensity; - cineon->element[0].refHighQuantity = 2.048f; - cineon->element[0].refLowQuantity = 0; - cineon->element[0].refLowData = 0; - cineon->element[0].refHighData = cineon->element[0].maxValue; - cineon->referenceWhite = 685.0f; - cineon->referenceBlack = 95.0f; - cineon->gamma = 1.7f; - - shortFilename = strrchr(filename, '/'); - if (shortFilename == NULL) - shortFilename = filename; - else - shortFilename++; - - cineon->file = BLI_fopen(filename, "wb"); - if (cineon->file == NULL) { - if (verbose) printf("cineon: Couldn't open file %s\n", filename); - logImageClose(cineon); - return NULL; - } - - fillCineonMainHeader(cineon, &header, shortFilename, creator); - - if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) { - if (verbose) printf("cineon: Couldn't write image header\n"); - logImageClose(cineon); - return NULL; - } - - return cineon; + CineonMainHeader header; + const char *shortFilename = NULL; + /* unsigned char pad[6044]; */ + + LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + if (cineon == NULL) { + if (verbose) + printf("cineon: Failed to malloc cineon file structure.\n"); + return NULL; + } + + /* Only 10 bits Cineon are supported */ + if (bitsPerSample != 10) { + if (verbose) + printf("cineon: Only 10 bits Cineon are supported.\n"); + logImageClose(cineon); + return NULL; + } + + cineon->width = width; + cineon->height = height; + cineon->element[0].bitsPerSample = 10; + cineon->element[0].dataOffset = sizeof(CineonMainHeader); + cineon->element[0].maxValue = 1023; + cineon->isMSB = 1; + cineon->numElements = 1; + cineon->element[0].packing = 1; + cineon->depth = 3; + cineon->element[0].depth = 3; + cineon->element[0].descriptor = descriptor_RGB; + cineon->element[0].transfer = transfer_PrintingDensity; + cineon->element[0].refHighQuantity = 2.048f; + cineon->element[0].refLowQuantity = 0; + cineon->element[0].refLowData = 0; + cineon->element[0].refHighData = cineon->element[0].maxValue; + cineon->referenceWhite = 685.0f; + cineon->referenceBlack = 95.0f; + cineon->gamma = 1.7f; + + shortFilename = strrchr(filename, '/'); + if (shortFilename == NULL) + shortFilename = filename; + else + shortFilename++; + + cineon->file = BLI_fopen(filename, "wb"); + if (cineon->file == NULL) { + if (verbose) + printf("cineon: Couldn't open file %s\n", filename); + logImageClose(cineon); + return NULL; + } + + fillCineonMainHeader(cineon, &header, shortFilename, creator); + + if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) { + if (verbose) + printf("cineon: Couldn't write image header\n"); + logImageClose(cineon); + return NULL; + } + + return cineon; } diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h index fddef8e658f..461407fcf25 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.h +++ b/source/blender/imbuf/intern/cineon/cineonlib.h @@ -23,7 +23,6 @@ * Also handles DPX files (almost) */ - #ifndef __CINEONLIB_H__ #define __CINEONLIB_H__ @@ -33,107 +32,108 @@ extern "C" { #include "logImageCore.h" -#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 +#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 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]; + 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; 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; + 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; 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]; + 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; 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]; + 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; 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]; + 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; typedef struct { - CineonFileHeader fileHeader; - CineonImageHeader imageHeader; - CineonOriginationHeader originationHeader; - CineonFilmHeader filmHeader; + CineonFileHeader fileHeader; + CineonImageHeader imageHeader; + CineonOriginationHeader originationHeader; + CineonFilmHeader filmHeader; } CineonMainHeader; 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); +LogImageFile *cineonCreate( + const char *filename, int width, int height, int bitsPerSample, const char *creator); #ifdef __cplusplus } #endif -#endif /* __CINEONLIB_H__ */ +#endif /* __CINEONLIB_H__ */ diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index 7ffe259186d..8c0cd88f256 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -22,7 +22,6 @@ * Dpx image file format library routines. */ - #include "dpxlib.h" #include "logmemfile.h" @@ -46,452 +45,490 @@ static int verbose = 0; void dpxSetVerbose(int verbosity) { - verbose = verbosity; + verbose = verbosity; } - /* * Headers */ -static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const char *filename, const char *creator) +static void fillDpxMainHeader(LogImageFile *dpx, + DpxMainHeader *header, + const char *filename, + const char *creator) { - time_t fileClock; - struct tm *fileTime; - - memset(header, 0, sizeof(DpxMainHeader)); - - /* --- 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(NULL); - 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; + time_t fileClock; + struct tm *fileTime; + + memset(header, 0, sizeof(DpxMainHeader)); + + /* --- 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(NULL); + 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; } LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) { - DpxMainHeader header; - LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); - const char *filename = (const char *)byteStuff; - int i; - - if (dpx == NULL) { - if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); - return NULL; - } - - /* zero the header */ - memset(&header, 0, sizeof(DpxMainHeader)); - - /* for close routine */ - dpx->file = NULL; - - if (fromMemory == 0) { - /* byteStuff is then the filename */ - dpx->file = BLI_fopen(filename, "rb"); - if (dpx->file == NULL) { - if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename); - logImageClose(dpx); - return NULL; - } - /* not used in this case */ - dpx->memBuffer = NULL; - dpx->memCursor = NULL; - dpx->memBufferSize = 0; - } - else { - dpx->memBuffer = (unsigned char *)byteStuff; - dpx->memCursor = (unsigned char *)byteStuff; - dpx->memBufferSize = bufferSize; - } - - if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) { - if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff); - logImageClose(dpx); - return NULL; - } - - /* endianness determination */ - if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) { - dpx->isMSB = 1; - if (verbose) printf("DPX: File is MSB.\n"); - } - else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) { - dpx->isMSB = 0; - if (verbose) printf("DPX: File is LSB.\n"); - } - else { - if (verbose) { - printf("DPX: Bad magic number %u in \"%s\".\n", - header.fileHeader.magic_num, byteStuff); - } - logImageClose(dpx); - return NULL; - } - - dpx->srcFormat = format_DPX; - dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB); - size_t max_elements = sizeof(header.imageHeader.element) / sizeof(header.imageHeader.element[0]); - if (dpx->numElements == 0 || dpx->numElements >= max_elements) { - if (verbose) printf("DPX: Wrong number of elements: %d\n", dpx->numElements); - logImageClose(dpx); - return NULL; - } - - dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB); - dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB); - - if (dpx->width == 0 || dpx->height == 0) { - if (verbose) printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height); - logImageClose(dpx); - return NULL; - } - - dpx->depth = 0; - - for (i = 0; i < dpx->numElements; i++) { - dpx->element[i].descriptor = header.imageHeader.element[i].descriptor; - - switch (dpx->element[i].descriptor) { - case descriptor_Red: - case descriptor_Green: - case descriptor_Blue: - case descriptor_Alpha: - case descriptor_Luminance: - case descriptor_Chrominance: - dpx->depth++; - dpx->element[i].depth = 1; - break; - - case descriptor_CbYCrY: - dpx->depth += 2; - dpx->element[i].depth = 2; - break; - - case descriptor_RGB: - case descriptor_CbYCr: - case descriptor_CbYACrYA: - dpx->depth += 3; - dpx->element[i].depth = 3; - break; - - case descriptor_RGBA: - case descriptor_ABGR: - case descriptor_CbYCrA: - dpx->depth += 4; - dpx->element[i].depth = 4; - break; - - case descriptor_Depth: - case descriptor_Composite: - /* unsupported */ - break; - } - - if (dpx->depth == 0 || dpx->depth > 4) { - if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth); - logImageClose(dpx); - return NULL; - } - - dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; - if (dpx->element[i].bitsPerSample != 1 && dpx->element[i].bitsPerSample != 8 && - dpx->element[i].bitsPerSample != 10 && dpx->element[i].bitsPerSample != 12 && - dpx->element[i].bitsPerSample != 16) - { - if (verbose) printf("DPX: Unsupported bitsPerSample for elements %d: %d\n", i, dpx->element[i].bitsPerSample); - logImageClose(dpx); - return NULL; - } - - dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f; - - dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB); - if (dpx->element[i].packing > 2) { - if (verbose) printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing); - logImageClose(dpx); - return NULL; - } - - /* Sometimes, the offset is not set correctly in the header */ - dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB); - if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1) - dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB); - - if (dpx->element[i].dataOffset == 0) { - if (verbose) printf("DPX: Image header is corrupted.\n"); - logImageClose(dpx); - return NULL; - } - - dpx->element[i].transfer = header.imageHeader.element[i].transfer; - - /* if undefined, assign default */ - dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB); - dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, dpx->isMSB); - dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, dpx->isMSB); - dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, dpx->isMSB); - - switch (dpx->element[i].descriptor) { - case descriptor_Red: - case descriptor_Green: - case descriptor_Blue: - case descriptor_Alpha: - case descriptor_RGB: - case descriptor_RGBA: - case descriptor_ABGR: - if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) - dpx->element[i].refLowData = 0; - - if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) - dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue; - - if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity)) - dpx->element[i].refLowQuantity = 0.0f; - - if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) { - if (dpx->element[i].transfer == transfer_PrintingDensity || dpx->element[i].transfer == transfer_Logarithmic) - dpx->element[i].refHighQuantity = 2.048f; - else - dpx->element[i].refHighQuantity = dpx->element[i].maxValue; - } - - break; - - case descriptor_Luminance: - case descriptor_Chrominance: - case descriptor_CbYCrY: - case descriptor_CbYCr: - case descriptor_CbYACrYA: - case descriptor_CbYCrA: - if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) - dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue; - - if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) - dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue; - - if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity)) - dpx->element[i].refLowQuantity = 0.0f; - - if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) - dpx->element[i].refHighQuantity = 0.7f; - - break; - - default: - break; - } - } - - dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB); - dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB); - dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB); - - if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) || - (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) || - (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma))) - { - dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; - dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; - dpx->gamma = 1.7f; - } - - if (verbose) { - printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements); - for (i = 0; i < dpx->numElements; i++) { - printf(" Element %d:\n", i); - printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample); - printf(" Depth: %d\n", dpx->element[i].depth); - printf(" Transfer characteristics: %d\n", dpx->element[i].transfer); - printf(" Packing: %d\n", dpx->element[i].packing); - printf(" Descriptor: %d\n", dpx->element[i].descriptor); - printf(" Data offset: %d\n", dpx->element[i].dataOffset); - printf(" Reference low data: %u\n", dpx->element[i].refLowData); - printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity); - printf(" Reference high data: %u\n", dpx->element[i].refHighData); - printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity); - printf("\n"); - } - - printf("Gamma: %f\n", dpx->gamma); - printf("Reference black: %f\n", dpx->referenceBlack); - printf("Reference white: %f\n", dpx->referenceWhite); - printf("Orientation: %d\n", header.imageHeader.orientation); - printf("----------------------------\n"); - } - return dpx; + DpxMainHeader header; + LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + const char *filename = (const char *)byteStuff; + int i; + + if (dpx == NULL) { + if (verbose) + printf("DPX: Failed to malloc dpx file structure.\n"); + return NULL; + } + + /* zero the header */ + memset(&header, 0, sizeof(DpxMainHeader)); + + /* for close routine */ + dpx->file = NULL; + + if (fromMemory == 0) { + /* byteStuff is then the filename */ + dpx->file = BLI_fopen(filename, "rb"); + if (dpx->file == NULL) { + if (verbose) + printf("DPX: Failed to open file \"%s\".\n", filename); + logImageClose(dpx); + return NULL; + } + /* not used in this case */ + dpx->memBuffer = NULL; + dpx->memCursor = NULL; + dpx->memBufferSize = 0; + } + else { + dpx->memBuffer = (unsigned char *)byteStuff; + dpx->memCursor = (unsigned char *)byteStuff; + dpx->memBufferSize = bufferSize; + } + + if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) { + if (verbose) + printf("DPX: Not enough data for header in \"%s\".\n", byteStuff); + logImageClose(dpx); + return NULL; + } + + /* endianness determination */ + if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) { + dpx->isMSB = 1; + if (verbose) + printf("DPX: File is MSB.\n"); + } + else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) { + dpx->isMSB = 0; + if (verbose) + printf("DPX: File is LSB.\n"); + } + else { + if (verbose) { + printf("DPX: Bad magic number %u in \"%s\".\n", header.fileHeader.magic_num, byteStuff); + } + logImageClose(dpx); + return NULL; + } + + dpx->srcFormat = format_DPX; + dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB); + size_t max_elements = sizeof(header.imageHeader.element) / sizeof(header.imageHeader.element[0]); + if (dpx->numElements == 0 || dpx->numElements >= max_elements) { + if (verbose) + printf("DPX: Wrong number of elements: %d\n", dpx->numElements); + logImageClose(dpx); + return NULL; + } + + dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB); + dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB); + + if (dpx->width == 0 || dpx->height == 0) { + if (verbose) + printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height); + logImageClose(dpx); + return NULL; + } + + dpx->depth = 0; + + for (i = 0; i < dpx->numElements; i++) { + dpx->element[i].descriptor = header.imageHeader.element[i].descriptor; + + switch (dpx->element[i].descriptor) { + case descriptor_Red: + case descriptor_Green: + case descriptor_Blue: + case descriptor_Alpha: + case descriptor_Luminance: + case descriptor_Chrominance: + dpx->depth++; + dpx->element[i].depth = 1; + break; + + case descriptor_CbYCrY: + dpx->depth += 2; + dpx->element[i].depth = 2; + break; + + case descriptor_RGB: + case descriptor_CbYCr: + case descriptor_CbYACrYA: + dpx->depth += 3; + dpx->element[i].depth = 3; + break; + + case descriptor_RGBA: + case descriptor_ABGR: + case descriptor_CbYCrA: + dpx->depth += 4; + dpx->element[i].depth = 4; + break; + + case descriptor_Depth: + case descriptor_Composite: + /* unsupported */ + break; + } + + if (dpx->depth == 0 || dpx->depth > 4) { + if (verbose) + printf("DPX: Unsupported image depth: %d\n", dpx->depth); + logImageClose(dpx); + return NULL; + } + + dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; + if (dpx->element[i].bitsPerSample != 1 && dpx->element[i].bitsPerSample != 8 && + dpx->element[i].bitsPerSample != 10 && dpx->element[i].bitsPerSample != 12 && + dpx->element[i].bitsPerSample != 16) { + if (verbose) + printf("DPX: Unsupported bitsPerSample for elements %d: %d\n", + i, + dpx->element[i].bitsPerSample); + logImageClose(dpx); + return NULL; + } + + dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f; + + dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB); + if (dpx->element[i].packing > 2) { + if (verbose) + printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing); + logImageClose(dpx); + return NULL; + } + + /* Sometimes, the offset is not set correctly in the header */ + dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB); + if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1) + dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB); + + if (dpx->element[i].dataOffset == 0) { + if (verbose) + printf("DPX: Image header is corrupted.\n"); + logImageClose(dpx); + return NULL; + } + + dpx->element[i].transfer = header.imageHeader.element[i].transfer; + + /* if undefined, assign default */ + dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB); + dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, + dpx->isMSB); + dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, + dpx->isMSB); + dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, + dpx->isMSB); + + switch (dpx->element[i].descriptor) { + case descriptor_Red: + case descriptor_Green: + case descriptor_Blue: + case descriptor_Alpha: + case descriptor_RGB: + case descriptor_RGBA: + case descriptor_ABGR: + if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) + dpx->element[i].refLowData = 0; + + if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) + dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue; + + if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || + isnan(dpx->element[i].refLowQuantity)) + dpx->element[i].refLowQuantity = 0.0f; + + if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || + isnan(dpx->element[i].refHighQuantity)) { + if (dpx->element[i].transfer == transfer_PrintingDensity || + dpx->element[i].transfer == transfer_Logarithmic) + dpx->element[i].refHighQuantity = 2.048f; + else + dpx->element[i].refHighQuantity = dpx->element[i].maxValue; + } + + break; + + case descriptor_Luminance: + case descriptor_Chrominance: + case descriptor_CbYCrY: + case descriptor_CbYCr: + case descriptor_CbYACrYA: + case descriptor_CbYCrA: + if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) + dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue; + + if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) + dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue; + + if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || + isnan(dpx->element[i].refLowQuantity)) + dpx->element[i].refLowQuantity = 0.0f; + + if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || + isnan(dpx->element[i].refHighQuantity)) + dpx->element[i].refHighQuantity = 0.7f; + + break; + + default: + break; + } + } + + dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB); + dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB); + dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB); + + if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) || + (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || + isnan(dpx->referenceWhite)) || + (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma))) { + dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; + dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; + dpx->gamma = 1.7f; + } + + if (verbose) { + printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements); + for (i = 0; i < dpx->numElements; i++) { + printf(" Element %d:\n", i); + printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample); + printf(" Depth: %d\n", dpx->element[i].depth); + printf(" Transfer characteristics: %d\n", dpx->element[i].transfer); + printf(" Packing: %d\n", dpx->element[i].packing); + printf(" Descriptor: %d\n", dpx->element[i].descriptor); + printf(" Data offset: %d\n", dpx->element[i].dataOffset); + printf(" Reference low data: %u\n", dpx->element[i].refLowData); + printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity); + printf(" Reference high data: %u\n", dpx->element[i].refHighData); + printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity); + printf("\n"); + } + + printf("Gamma: %f\n", dpx->gamma); + printf("Reference black: %f\n", dpx->referenceBlack); + printf("Reference white: %f\n", dpx->referenceWhite); + printf("Orientation: %d\n", header.imageHeader.orientation); + 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, +LogImageFile *dpxCreate(const char *filename, + int width, + int height, + int bitsPerSample, + int hasAlpha, + int isLogarithmic, + int referenceWhite, + int referenceBlack, + float gamma, const char *creator) { - DpxMainHeader header; - const char *shortFilename = NULL; - unsigned char pad[6044]; - - LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); - if (dpx == NULL) { - if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); - return NULL; - } - - dpx->width = width; - dpx->height = height; - dpx->element[0].bitsPerSample = bitsPerSample; - dpx->element[0].dataOffset = 8092; - dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f; - dpx->isMSB = 1; - dpx->numElements = 1; - - switch (bitsPerSample) { - case 8: - case 16: - dpx->element[0].packing = 0; - break; - - case 10: - case 12: - /* Packed Type A padding is the most common 10/12 bits format */ - dpx->element[0].packing = 1; - break; - - default: - if (verbose) printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample); - logImageClose(dpx); - return NULL; - } - - if (hasAlpha == 0) { - dpx->depth = 3; - dpx->element[0].depth = 3; - dpx->element[0].descriptor = descriptor_RGB; - } - else { - dpx->depth = 4; - dpx->element[0].depth = 4; - dpx->element[0].descriptor = descriptor_RGBA; - } - - if (isLogarithmic == 0) { - dpx->element[0].transfer = transfer_Linear; - dpx->element[0].refHighQuantity = dpx->element[0].maxValue; - } - else { - dpx->element[0].transfer = transfer_PrintingDensity; - dpx->element[0].refHighQuantity = 2.048f; - - } - - dpx->element[0].refLowQuantity = 0; - dpx->element[0].refLowData = 0; - dpx->element[0].refHighData = dpx->element[0].maxValue; - - if (referenceWhite > 0) - dpx->referenceWhite = referenceWhite; - else - dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; - - if (referenceBlack > 0) - dpx->referenceBlack = referenceBlack; - else - dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; - - if (gamma > 0.0f) - dpx->gamma = gamma; - else - dpx->gamma = 1.7f; - - - shortFilename = strrchr(filename, '/'); - if (shortFilename == NULL) - shortFilename = filename; - else - shortFilename++; - - dpx->file = BLI_fopen(filename, "wb"); - - if (dpx->file == NULL) { - if (verbose) printf("DPX: Couldn't open file %s\n", filename); - logImageClose(dpx); - return NULL; - } - - fillDpxMainHeader(dpx, &header, shortFilename, creator); - - if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { - if (verbose) printf("DPX: Couldn't write image header\n"); - logImageClose(dpx); - return NULL; - } - - /* Header should be rounded to next 8k block - * 6044 = 8092 - sizeof(DpxMainHeader) */ - memset(&pad, 0, 6044); - if (fwrite(&pad, 6044, 1, dpx->file) == 0) { - if (verbose) printf("DPX: Couldn't write image header\n"); - logImageClose(dpx); - return NULL; - } - - return dpx; + DpxMainHeader header; + const char *shortFilename = NULL; + unsigned char pad[6044]; + + LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + if (dpx == NULL) { + if (verbose) + printf("DPX: Failed to malloc dpx file structure.\n"); + return NULL; + } + + dpx->width = width; + dpx->height = height; + dpx->element[0].bitsPerSample = bitsPerSample; + dpx->element[0].dataOffset = 8092; + dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f; + dpx->isMSB = 1; + dpx->numElements = 1; + + switch (bitsPerSample) { + case 8: + case 16: + dpx->element[0].packing = 0; + break; + + case 10: + case 12: + /* Packed Type A padding is the most common 10/12 bits format */ + dpx->element[0].packing = 1; + break; + + default: + if (verbose) + printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample); + logImageClose(dpx); + return NULL; + } + + if (hasAlpha == 0) { + dpx->depth = 3; + dpx->element[0].depth = 3; + dpx->element[0].descriptor = descriptor_RGB; + } + else { + dpx->depth = 4; + dpx->element[0].depth = 4; + dpx->element[0].descriptor = descriptor_RGBA; + } + + if (isLogarithmic == 0) { + dpx->element[0].transfer = transfer_Linear; + dpx->element[0].refHighQuantity = dpx->element[0].maxValue; + } + else { + dpx->element[0].transfer = transfer_PrintingDensity; + dpx->element[0].refHighQuantity = 2.048f; + } + + dpx->element[0].refLowQuantity = 0; + dpx->element[0].refLowData = 0; + dpx->element[0].refHighData = dpx->element[0].maxValue; + + if (referenceWhite > 0) + dpx->referenceWhite = referenceWhite; + else + dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; + + if (referenceBlack > 0) + dpx->referenceBlack = referenceBlack; + else + dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; + + if (gamma > 0.0f) + dpx->gamma = gamma; + else + dpx->gamma = 1.7f; + + shortFilename = strrchr(filename, '/'); + if (shortFilename == NULL) + shortFilename = filename; + else + shortFilename++; + + dpx->file = BLI_fopen(filename, "wb"); + + if (dpx->file == NULL) { + if (verbose) + printf("DPX: Couldn't open file %s\n", filename); + logImageClose(dpx); + return NULL; + } + + fillDpxMainHeader(dpx, &header, shortFilename, creator); + + if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { + if (verbose) + printf("DPX: Couldn't write image header\n"); + logImageClose(dpx); + return NULL; + } + + /* Header should be rounded to next 8k block + * 6044 = 8092 - sizeof(DpxMainHeader) */ + memset(&pad, 0, 6044); + if (fwrite(&pad, 6044, 1, dpx->file) == 0) { + if (verbose) + printf("DPX: Couldn't write image header\n"); + logImageClose(dpx); + return NULL; + } + + return dpx; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index fe9f34901b8..bf07b8e329d 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -22,7 +22,6 @@ * DPX image file format library definitions. */ - #ifndef __DPXLIB_H__ #define __DPXLIB_H__ @@ -32,126 +31,134 @@ extern "C" { #include "logImageCore.h" -#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 +#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 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]; + 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; 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]; + 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; 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]; + 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; 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]; + 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; 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]; + 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; 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]; + 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; + 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); +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 /* __DPXLIB_H__ */ diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index 3dcf1814f27..2169665cf78 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -22,7 +22,6 @@ * Cineon image file format library routines. */ - #include "logmemfile.h" #include "logImageCore.h" #include "dpxlib.h" @@ -51,13 +50,24 @@ static int logImageElementGetData(LogImageFile *dpx, LogImageElement logElement, 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 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 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); - +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 @@ -67,1409 +77,1569 @@ static int verbose = 0; void logImageSetVerbose(int verbosity) { - verbose = verbosity; - cineonSetVerbose(verbosity); - dpxSetVerbose(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)); + unsigned int magicNum = *(unsigned int *)buffer; + return (magicNum == DPX_FILE_MAGIC || magicNum == swap_uint(DPX_FILE_MAGIC, 1)); } int logImageIsCineon(const void *buffer) { - unsigned int magicNum = *(unsigned int *)buffer; - return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1)); + unsigned int magicNum = *(unsigned int *)buffer; + return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1)); } LogImageFile *logImageOpenFromFile(const char *filename, int cineon) { - unsigned int magicNum; - FILE *f = BLI_fopen(filename, "rb"); + unsigned int magicNum; + FILE *f = BLI_fopen(filename, "rb"); - (void)cineon; + (void)cineon; - if (f == NULL) - return NULL; + if (f == NULL) + return NULL; - if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) { - fclose(f); - return NULL; - } + if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) { + fclose(f); + return NULL; + } - fclose(f); + 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); + if (logImageIsDpx(&magicNum)) + return dpxOpen((const unsigned char *)filename, 0, 0); + else if (logImageIsCineon(&magicNum)) + return cineonOpen((const unsigned char *)filename, 0, 0); - return NULL; + return NULL; } 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); + if (logImageIsDpx(buffer)) + return dpxOpen(buffer, 1, size); + else if (logImageIsCineon(buffer)) + return cineonOpen(buffer, 1, size); - return NULL; + return NULL; } -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) +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); - - return NULL; + /* 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); + + return NULL; } void logImageClose(LogImageFile *logImage) { - if (logImage != NULL) { - if (logImage->file) { - fclose(logImage->file); - logImage->file = NULL; - } - MEM_freeN(logImage); - } + if (logImage != NULL) { + if (logImage->file) { + fclose(logImage->file); + logImage->file = NULL; + } + MEM_freeN(logImage); + } } void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth) { - *width = logImage->width; - *height = logImage->height; - *depth = logImage->depth; + *width = logImage->width; + *height = logImage->height; + *depth = logImage->depth; } - /* * Helper */ size_t getRowLength(size_t 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; - break; - 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; - break; - case 16: - return width * logElement.depth * 2; - - } - return 0; + /* 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; + break; + 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; + break; + case 16: + return width * logElement.depth * 2; + } + return 0; } - /* * Data writing */ int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB) { - float *elementData; - int returnValue; - - elementData = (float *)imb_alloc_pixels(logImage->width, logImage->height, logImage->depth, sizeof(float), __func__); - if (elementData == NULL) - return 1; - - if (convertRGBAToLogElement(data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) { - MEM_freeN(elementData); - return 1; - } - - 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; - - case 12: - returnValue = logImageSetData12(logImage, logImage->element[0], elementData); - break; - - case 16: - returnValue = logImageSetData16(logImage, logImage->element[0], elementData); - break; - - default: - returnValue = 1; - break; - } - - MEM_freeN(elementData); - return returnValue; + float *elementData; + int returnValue; + + elementData = (float *)imb_alloc_pixels( + logImage->width, logImage->height, logImage->depth, sizeof(float), __func__); + if (elementData == NULL) + return 1; + + if (convertRGBAToLogElement( + data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) { + MEM_freeN(elementData); + return 1; + } + + 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; + + case 12: + returnValue = logImageSetData12(logImage, logImage->element[0], elementData); + break; + + case 16: + returnValue = logImageSetData16(logImage, logImage->element[0], elementData); + break; + + default: + returnValue = 1; + break; + } + + MEM_freeN(elementData); + return returnValue; } static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned char *row; - - row = (unsigned char *)MEM_mallocN(rowLength, __func__); - if (row == NULL) { - if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); - return 1; - } - memset(row, 0, rowLength); - - for (size_t y = 0; y < logImage->height; y++) { - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned char *row; + + row = (unsigned char *)MEM_mallocN(rowLength, __func__); + if (row == NULL) { + if (verbose) + printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + memset(row, 0, rowLength); + + for (size_t y = 0; y < logImage->height; y++) { + for (size_t 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; } static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned int pixel, index; - unsigned int *row; - - row = (unsigned int *)MEM_mallocN(rowLength, __func__); - if (row == NULL) { - if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); - return 1; - } - - for (size_t y = 0; y < logImage->height; y++) { - int offset = 22; - index = 0; - pixel = 0; - - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, index; + unsigned int *row; + + row = (unsigned int *)MEM_mallocN(rowLength, __func__); + if (row == NULL) { + if (verbose) + printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (size_t y = 0; y < logImage->height; y++) { + int offset = 22; + index = 0; + pixel = 0; + + for (size_t 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; } static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned short *row; - - row = (unsigned short *)MEM_mallocN(rowLength, __func__); - if (row == NULL) { - if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); - return 1; - } - - for (size_t y = 0; y < logImage->height; y++) { - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned short *row; + + row = (unsigned short *)MEM_mallocN(rowLength, __func__); + if (row == NULL) { + if (verbose) + printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (size_t y = 0; y < logImage->height; y++) { + for (size_t 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; } static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned short *row; - - row = (unsigned short *)MEM_mallocN(rowLength, __func__); - if (row == NULL) { - if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); - return 1; - } - - for (size_t y = 0; y < logImage->height; y++) { - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned short *row; + + row = (unsigned short *)MEM_mallocN(rowLength, __func__); + if (row == NULL) { + if (verbose) + printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (size_t y = 0; y < logImage->height; y++) { + for (size_t 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; } - /* * 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] = imb_alloc_pixels(logImage->width, logImage->height, logImage->element[i].depth, sizeof(float), __func__); - if (elementData[i] == NULL) { - if (verbose) printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i); - for (j = 0; j < i; j++) - if (elementData[j] != NULL) - 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] != NULL) - 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 *)imb_alloc_pixels(logImage->width, logImage->height, mergedElement.depth, sizeof(float), __func__); - if (mergedData == NULL) { - if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n"); - for (i = 0; i < logImage->numElements; i++) - if (elementData[i] != NULL) - 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] != NULL) - MEM_freeN(elementData[i]); - - returnValue = convertLogElementToRGBA(mergedData, data, logImage, mergedElement, dataIsLinearRGB); - MEM_freeN(mergedData); - } - return returnValue; + /* 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] = imb_alloc_pixels( + logImage->width, logImage->height, logImage->element[i].depth, sizeof(float), __func__); + if (elementData[i] == NULL) { + if (verbose) + printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i); + for (j = 0; j < i; j++) + if (elementData[j] != NULL) + 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] != NULL) + 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 *)imb_alloc_pixels( + logImage->width, logImage->height, mergedElement.depth, sizeof(float), __func__); + if (mergedData == NULL) { + if (verbose) + printf("DPX/Cineon: Cannot allocate mergedData.\n"); + for (i = 0; i < logImage->numElements; i++) + if (elementData[i] != NULL) + 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] != NULL) + MEM_freeN(elementData[i]); + + returnValue = convertLogElementToRGBA( + mergedData, data, logImage, mergedElement, dataIsLinearRGB); + MEM_freeN(mergedData); + } + return returnValue; } 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); - break; - - case 12: - if (logElement.packing == 0) - return logImageElementGetData12Packed(logImage, logElement, data); - else if (logElement.packing == 1 || logElement.packing == 2) - return logImageElementGetData12(logImage, logElement, data); - break; - - case 16: - return logImageElementGetData16(logImage, logElement, data); - } - /* format not supported */ - return 1; + 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); + break; + + case 12: + if (logElement.packing == 0) + return logImageElementGetData12Packed(logImage, logElement, data); + else if (logElement.packing == 1 || logElement.packing == 2) + return logImageElementGetData12(logImage, logElement, data); + break; + + case 16: + return logImageElementGetData16(logImage, logElement, data); + } + /* format not supported */ + return 1; } static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data) { - unsigned int pixel; - - /* 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 (size_t y = 0; y < logImage->height; y++) { - for (size_t 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 (int offset = 0; offset < 32 && x + offset < logImage->width; offset++) - data[y * logImage->width * logElement.depth + x + offset] = (float)((pixel >> offset) & 0x01); - } - } - return 0; + unsigned int pixel; + + /* 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 (size_t y = 0; y < logImage->height; y++) { + for (size_t 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 (int 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) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned char pixel; - - /* extract required pixels */ - for (size_t 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", (int)(logElement.dataOffset + y * rowLength)); - return 1; - } - - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned char pixel; + + /* extract required pixels */ + for (size_t 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", (int)(logElement.dataOffset + y * rowLength)); + return 1; + } + + for (size_t 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) +static int logImageElementGetData10(LogImageFile *logImage, + LogImageElement logElement, + float *data) { - unsigned int 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; - } - - if (logImage->depth == 1 && logImage->srcFormat == format_DPX) { - for (size_t y = 0; y < logImage->height; y++) { - int offset = 32; - for (size_t 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 (size_t y = 0; y < logImage->height; y++) { - int offset = -1; - for (size_t 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; + unsigned int 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; + } + + if (logImage->depth == 1 && logImage->srcFormat == format_DPX) { + for (size_t y = 0; y < logImage->height; y++) { + int offset = 32; + for (size_t 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 (size_t y = 0; y < logImage->height; y++) { + int offset = -1; + for (size_t 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) +static int logImageElementGetData10Packed(LogImageFile *logImage, + LogImageElement logElement, + float *data) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned int pixel, oldPixel; - - /* converting bytes to pixels */ - for (size_t 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", (unsigned int)(y * rowLength + logElement.dataOffset)); - return 1; - } - - oldPixel = 0; - int offset = 0; - int offset2 = 0; - - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, oldPixel; + + /* converting bytes to pixels */ + for (size_t 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", + (unsigned int)(y * rowLength + logElement.dataOffset)); + return 1; + } + + oldPixel = 0; + int offset = 0; + int offset2 = 0; + + for (size_t 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) +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; + 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) +static int logImageElementGetData12Packed(LogImageFile *logImage, + LogImageElement logElement, + float *data) { - size_t rowLength = getRowLength(logImage->width, logElement); - unsigned int pixel, oldPixel; - - /* converting bytes to pixels */ - for (size_t 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", (unsigned int)(y * rowLength + logElement.dataOffset)); - return 1; - } - - oldPixel = 0; - int offset = 0; - int offset2 = 0; - - for (size_t 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; + size_t rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, oldPixel; + + /* converting bytes to pixels */ + for (size_t 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", + (unsigned int)(y * rowLength + logElement.dataOffset)); + return 1; + } + + oldPixel = 0; + int offset = 0; + int offset2 = 0; + + for (size_t 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) +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; + 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; - } + 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 float *getLinToLogLut(LogImageFile *logImage, LogImageElement logElement) { - float *lut; - float gain, negativeFilmGamma, offset, step; - unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); - unsigned int i; - - lut = MEM_mallocN(sizeof(float) * lutsize, "getLinToLogLut"); - - 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 < lutsize; i++) - lut[i] = (logImage->referenceWhite + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / (step / negativeFilmGamma)) / logElement.maxValue; - - return lut; + float *lut; + float gain, negativeFilmGamma, offset, step; + unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); + unsigned int i; + + lut = MEM_mallocN(sizeof(float) * lutsize, "getLinToLogLut"); + + 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 < lutsize; i++) + lut[i] = (logImage->referenceWhite + + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / + (step / negativeFilmGamma)) / + logElement.maxValue; + + return lut; } static float *getLogToLinLut(LogImageFile *logImage, LogImageElement logElement) { - float *lut; - float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip; - /* float filmGamma; unused */ - unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); - unsigned int i; - - lut = MEM_mallocN(sizeof(float) * lutsize, "getLogToLinLut"); - - /* 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 < lutsize; 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; - } - - return lut; + float *lut; + float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip; + /* float filmGamma; unused */ + unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); + unsigned int i; + + lut = MEM_mallocN(sizeof(float) * lutsize, "getLogToLinLut"); + + /* 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 < lutsize; 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; + } + + return lut; } static float *getLinToSrgbLut(LogImageElement logElement) { - float col, *lut; - unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); - unsigned int i; + float col, *lut; + unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); + unsigned int i; - lut = MEM_mallocN(sizeof(float) * lutsize, "getLogToLinLut"); + lut = MEM_mallocN(sizeof(float) * lutsize, "getLogToLinLut"); - for (i = 0; i < lutsize; 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; - } + for (i = 0; i < lutsize; 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; + } - return lut; + return lut; } static float *getSrgbToLinLut(LogImageElement logElement) { - float col, *lut; - unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); - unsigned int i; + float col, *lut; + unsigned int lutsize = (unsigned int)(logElement.maxValue + 1); + unsigned int i; - lut = MEM_mallocN(sizeof(float) * lutsize, "getLogToLinLut"); + lut = MEM_mallocN(sizeof(float) * lutsize, "getLogToLinLut"); - for (i = 0; i < lutsize; 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); - } + for (i = 0; i < lutsize; 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); + } - return lut; + return lut; } -static int convertRGBA_RGB(float *src, float *dst, LogImageFile *logImage, - LogImageElement logElement, int elementIsSource) +static int convertRGBA_RGB(float *src, + float *dst, + LogImageFile *logImage, + LogImageElement logElement, + int elementIsSource) { - unsigned int i; - float *src_ptr = src; - float *dst_ptr = dst; - - switch (logElement.transfer) { - case transfer_Unspecified: - 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: { - float *lut; - - if (elementIsSource == 1) - lut = getLogToLinLut(logImage, logElement); - else - lut = getLinToLogLut(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++; - } - - MEM_freeN(lut); - - return 0; - } - - default: - if (verbose) printf("DPX/Cineon: Unknown transfer %d.\n", logElement.transfer); - return 1; - } + unsigned int i; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_Unspecified: + 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: { + float *lut; + + if (elementIsSource == 1) + lut = getLogToLinLut(logImage, logElement); + else + lut = getLinToLogLut(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++; + } + + MEM_freeN(lut); + + return 0; + } + + default: + if (verbose) + printf("DPX/Cineon: Unknown transfer %d.\n", logElement.transfer); + return 1; + } } -static int convertRGB_RGBA(float *src, float *dst, LogImageFile *logImage, - LogImageElement logElement, int elementIsSource) +static int convertRGB_RGBA(float *src, + float *dst, + LogImageFile *logImage, + LogImageElement logElement, + int elementIsSource) { - unsigned int i; - float *src_ptr = src; - float *dst_ptr = dst; - - switch (logElement.transfer) { - case transfer_Unspecified: - 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: { - float *lut; - - if (elementIsSource == 1) - lut = getLogToLinLut(logImage, logElement); - else - lut = getLinToLogLut(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; - } - - MEM_freeN(lut); - - return 0; - } - - default: - if (verbose) printf("DPX/Cineon: Unknown transfer %d.\n", logElement.transfer); - return 1; - } + unsigned int i; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_Unspecified: + 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: { + float *lut; + + if (elementIsSource == 1) + lut = getLogToLinLut(logImage, logElement); + else + lut = getLinToLogLut(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; + } + + MEM_freeN(lut); + + return 0; + } + + default: + if (verbose) + printf("DPX/Cineon: Unknown transfer %d.\n", logElement.transfer); + return 1; + } } -static int convertRGBA_RGBA(float *src, float *dst, LogImageFile *logImage, - LogImageElement logElement, int elementIsSource) +static int convertRGBA_RGBA(float *src, + float *dst, + LogImageFile *logImage, + LogImageElement logElement, + int elementIsSource) { - unsigned int i; - float *src_ptr = src; - float *dst_ptr = dst; - - switch (logElement.transfer) { - case transfer_UserDefined: - case transfer_Linear: - case transfer_Logarithmic: { - memcpy(dst, src, 4 * (size_t)logImage->width * (size_t)logImage->height * sizeof(float)); - return 0; - } - - case transfer_PrintingDensity: { - float *lut; - - if (elementIsSource == 1) - lut = getLogToLinLut(logImage, logElement); - else - lut = getLinToLogLut(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++); - } - - MEM_freeN(lut); - - return 0; - } - - default: - return 1; - } + unsigned int i; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: { + memcpy(dst, src, 4 * (size_t)logImage->width * (size_t)logImage->height * sizeof(float)); + return 0; + } + + case transfer_PrintingDensity: { + float *lut; + + if (elementIsSource == 1) + lut = getLogToLinLut(logImage, logElement); + else + lut = getLinToLogLut(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++); + } + + MEM_freeN(lut); + + return 0; + } + + default: + return 1; + } } -static int convertABGR_RGBA(float *src, float *dst, LogImageFile *logImage, - LogImageElement logElement, int elementIsSource) +static int convertABGR_RGBA(float *src, + float *dst, + LogImageFile *logImage, + LogImageElement logElement, + int elementIsSource) { - unsigned int i; - 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: { - float *lut; - - if (elementIsSource == 1) - lut = getLogToLinLut(logImage, logElement); - else - lut = getLinToLogLut(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; - } - - MEM_freeN(lut); - - return 0; - } - - default: - return 1; - } + unsigned int i; + 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: { + float *lut; + + if (elementIsSource == 1) + lut = getLogToLinLut(logImage, logElement); + else + lut = getLinToLogLut(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; + } + + MEM_freeN(lut); + + return 0; + } + + default: + return 1; + } } -static int convertCbYCr_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +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; + 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) +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; + 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) +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; + 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) +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; + 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) +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; + 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) +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; + 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) +static int convertLogElementToRGBA( + float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int dstIsLinearRGB) { - int rvalue; - unsigned int i; - float *src_ptr; - float *dst_ptr; - - /* 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 */ - float *lut = getSrgbToLinLut(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++; - } - MEM_freeN(lut); - } - return 0; + int rvalue; + unsigned int i; + float *src_ptr; + float *dst_ptr; + + /* 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 */ + float *lut = getSrgbToLinLut(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++; + } + MEM_freeN(lut); + } + return 0; } -static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, - LogImageElement logElement, int srcIsLinearRGB) +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; - - if (srcIsLinearRGB != 0) { - /* we need to convert src to sRGB */ - srgbSrc = (float *)imb_alloc_pixels(logImage->width, logImage->height, 4, sizeof(float), __func__); - if (srgbSrc == NULL) - return 1; - - memcpy(srgbSrc, src, 4 * (size_t)logImage->width * (size_t)logImage->height * sizeof(float)); - srgbSrc_ptr = srgbSrc; - - /* convert data from Linear RGB to sRGB via lut */ - lut = getLinToSrgbLut(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++; - } - MEM_freeN(lut); - } - 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; - break; - } - - if (srcIsLinearRGB != 0) { - MEM_freeN(srgbSrc); - } - - return rvalue; + unsigned int i; + int rvalue; + float *srgbSrc; + float *srgbSrc_ptr; + float *src_ptr = src; + float *lut; + + if (srcIsLinearRGB != 0) { + /* we need to convert src to sRGB */ + srgbSrc = (float *)imb_alloc_pixels( + logImage->width, logImage->height, 4, sizeof(float), __func__); + if (srgbSrc == NULL) + return 1; + + memcpy(srgbSrc, src, 4 * (size_t)logImage->width * (size_t)logImage->height * sizeof(float)); + srgbSrc_ptr = srgbSrc; + + /* convert data from Linear RGB to sRGB via lut */ + lut = getLinToSrgbLut(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++; + } + MEM_freeN(lut); + } + 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; + break; + } + + 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 07fe6e22d40..e01c2e0f117 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -45,51 +45,50 @@ extern "C" { /* 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, + format_DPX, + format_Cineon, }; 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) */ + 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; typedef struct LogImageFile { - /* specified in header */ - int width; - int height; - int numElements; - int depth; - LogImageElement element[8]; - - /* used for log <-> lin conversion */ - float referenceBlack; - float referenceWhite; - float gamma; - - /* io stuff */ - FILE *file; - unsigned char *memBuffer; - uintptr_t memBufferSize; - unsigned char *memCursor; - - /* is the file LSB or MSB ? */ - int isMSB; - - /* DPX or Cineon ? */ - int srcFormat; + /* specified in header */ + int width; + int height; + int numElements; + int depth; + LogImageElement element[8]; + + /* used for log <-> lin conversion */ + float referenceBlack; + float referenceWhite; + float gamma; + + /* io stuff */ + FILE *file; + 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 @@ -110,19 +109,19 @@ typedef struct LogImageFile { */ 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, + 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: @@ -152,31 +151,31 @@ enum transfer { */ 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, + 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, }; /* int functions return 0 for OK */ @@ -187,9 +186,17 @@ 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); +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); /* Data handling */ @@ -205,74 +212,73 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB BLI_INLINE unsigned short swap_ushort(unsigned short x, int swap) { - if (swap != 0) - return (x >> 8) | (x << 8); - else - return x; + 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; + 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; + 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; + 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; + 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); + 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); } - #ifdef __cplusplus } #endif -#endif /* __LOGIMAGECORE_H__ */ +#endif /* __LOGIMAGECORE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/logmemfile.c b/source/blender/imbuf/intern/cineon/logmemfile.c index e67ef74951b..d7ab2855ea3 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.c +++ b/source/blender/imbuf/intern/cineon/logmemfile.c @@ -22,7 +22,6 @@ * Cineon image file format library routines. */ - #include #include #include @@ -32,92 +31,92 @@ 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 > logFile->memBufferSize) - return 1; - logFile->memCursor = (logFile->memBuffer + logFile->memBufferSize) - offset; - } - else if (origin == SEEK_CUR) { - uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; - if (pos + offset > logFile->memBufferSize) - return 1; - - logFile->memCursor += offset; - } - } - return 0; + 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 > logFile->memBufferSize) + return 1; + logFile->memCursor = (logFile->memBuffer + logFile->memBufferSize) - offset; + } + else if (origin == SEEK_CUR) { + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + offset > logFile->memBufferSize) + return 1; + + logFile->memCursor += offset; + } + } + return 0; } int logimage_fwrite(void *buffer, size_t size, unsigned int count, LogImageFile *logFile) { - 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; - } + 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, size_t size, unsigned int count, LogImageFile *logFile) { - 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; - } + 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; + 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; + *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; + 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; + *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; + 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; + *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 9b6def2a617..d0ca03193e5 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.h +++ b/source/blender/imbuf/intern/cineon/logmemfile.h @@ -22,7 +22,6 @@ * Cineon image file format library routines. */ - #ifndef __LOGMEMFILE_H__ #define __LOGMEMFILE_H__ @@ -37,4 +36,4 @@ 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__ */ +#endif /* __LOGMEMFILE_H__ */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 597421d80c6..ac35cc10920 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -97,37 +97,37 @@ static float imbuf_linear_srgb_to_xyz[3][3] = {{0.0f}}; static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER; typedef struct ColormanageProcessor { - OCIO_ConstProcessorRcPtr *processor; - CurveMapping *curve_mapping; - bool is_data_result; + OCIO_ConstProcessorRcPtr *processor; + CurveMapping *curve_mapping; + bool is_data_result; } ColormanageProcessor; static struct global_glsl_state { - /* Actual processor used for GLSL baked LUTs. */ - OCIO_ConstProcessorRcPtr *processor; - - /* Settings of processor for comparison. */ - char look[MAX_COLORSPACE_NAME]; - char view[MAX_COLORSPACE_NAME]; - char display[MAX_COLORSPACE_NAME]; - char input[MAX_COLORSPACE_NAME]; - float exposure, gamma; - - CurveMapping *curve_mapping, *orig_curve_mapping; - bool use_curve_mapping; - int curve_mapping_timestamp; - OCIO_CurveMappingSettings curve_mapping_settings; - - /* Container for GLSL state needed for OCIO module. */ - struct OCIO_GLSLDrawState *ocio_glsl_state; - struct OCIO_GLSLDrawState *transform_ocio_glsl_state; + /* Actual processor used for GLSL baked LUTs. */ + OCIO_ConstProcessorRcPtr *processor; + + /* Settings of processor for comparison. */ + char look[MAX_COLORSPACE_NAME]; + char view[MAX_COLORSPACE_NAME]; + char display[MAX_COLORSPACE_NAME]; + char input[MAX_COLORSPACE_NAME]; + float exposure, gamma; + + CurveMapping *curve_mapping, *orig_curve_mapping; + bool use_curve_mapping; + int curve_mapping_timestamp; + OCIO_CurveMappingSettings curve_mapping_settings; + + /* Container for GLSL state needed for OCIO module. */ + struct OCIO_GLSLDrawState *ocio_glsl_state; + struct OCIO_GLSLDrawState *transform_ocio_glsl_state; } global_glsl_state = {NULL}; static struct global_color_picking_state { - /* Cached processor for color picking conversion. */ - OCIO_ConstProcessorRcPtr *processor_to; - OCIO_ConstProcessorRcPtr *processor_from; - bool failed; + /* Cached processor for color picking conversion. */ + OCIO_ConstProcessorRcPtr *processor_to; + OCIO_ConstProcessorRcPtr *processor_from; + bool failed; } global_color_picking_state = {NULL}; /*********************** Color managed cache *************************/ @@ -197,1644 +197,1778 @@ static struct global_color_picking_state { * to color management cache system and keeps calls small and nice. */ typedef struct ColormanageCacheViewSettings { - int flag; - int look; - int view; - float exposure; - float gamma; - float dither; - CurveMapping *curve_mapping; + int flag; + int look; + int view; + float exposure; + float gamma; + float dither; + CurveMapping *curve_mapping; } ColormanageCacheViewSettings; typedef struct ColormanageCacheDisplaySettings { - int display; + int display; } ColormanageCacheDisplaySettings; typedef struct ColormanageCacheKey { - int view; /* view transformation used for display buffer */ - int display; /* display device name */ + int view; /* view transformation used for display buffer */ + int display; /* display device name */ } ColormanageCacheKey; typedef struct ColormanageCacheData { - int flag; /* view flags of cached buffer */ - int look; /* Additional artistics transform */ - float exposure; /* exposure value cached buffer is calculated with */ - float gamma; /* gamma value cached buffer is calculated with */ - float dither; /* dither value cached buffer is calculated with */ - CurveMapping *curve_mapping; /* curve mapping used for cached buffer */ - int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */ + int flag; /* view flags of cached buffer */ + int look; /* Additional artistics transform */ + float exposure; /* exposure value cached buffer is calculated with */ + float gamma; /* gamma value cached buffer is calculated with */ + float dither; /* dither value cached buffer is calculated with */ + CurveMapping *curve_mapping; /* curve mapping used for cached buffer */ + int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */ } ColormanageCacheData; typedef struct ColormanageCache { - struct MovieCache *moviecache; + struct MovieCache *moviecache; - ColormanageCacheData *data; + ColormanageCacheData *data; } ColormanageCache; static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf) { - if (!ibuf->colormanage_cache) - return NULL; + if (!ibuf->colormanage_cache) + return NULL; - return ibuf->colormanage_cache->moviecache; + return ibuf->colormanage_cache->moviecache; } static ColormanageCacheData *colormanage_cachedata_get(const ImBuf *ibuf) { - if (!ibuf->colormanage_cache) - return NULL; + if (!ibuf->colormanage_cache) + return NULL; - return ibuf->colormanage_cache->data; + return ibuf->colormanage_cache->data; } static unsigned int colormanage_hashhash(const void *key_v) { - const ColormanageCacheKey *key = key_v; + const ColormanageCacheKey *key = key_v; - unsigned int rval = (key->display << 16) | (key->view % 0xffff); + unsigned int rval = (key->display << 16) | (key->view % 0xffff); - return rval; + return rval; } static bool colormanage_hashcmp(const void *av, const void *bv) { - const ColormanageCacheKey *a = av; - const ColormanageCacheKey *b = bv; + const ColormanageCacheKey *a = av; + const ColormanageCacheKey *b = bv; - return ((a->view != b->view) || - (a->display != b->display)); + return ((a->view != b->view) || (a->display != b->display)); } static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) { - if (!ibuf->colormanage_cache) - ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); + if (!ibuf->colormanage_cache) + ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); - if (!ibuf->colormanage_cache->moviecache) { - struct MovieCache *moviecache; + if (!ibuf->colormanage_cache->moviecache) { + struct MovieCache *moviecache; - moviecache = IMB_moviecache_create("colormanage cache", sizeof(ColormanageCacheKey), - colormanage_hashhash, colormanage_hashcmp); + moviecache = IMB_moviecache_create("colormanage cache", + sizeof(ColormanageCacheKey), + colormanage_hashhash, + colormanage_hashcmp); - ibuf->colormanage_cache->moviecache = moviecache; - } + ibuf->colormanage_cache->moviecache = moviecache; + } - return ibuf->colormanage_cache->moviecache; + return ibuf->colormanage_cache->moviecache; } static void colormanage_cachedata_set(ImBuf *ibuf, ColormanageCacheData *data) { - if (!ibuf->colormanage_cache) - ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); + if (!ibuf->colormanage_cache) + ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); - ibuf->colormanage_cache->data = data; + ibuf->colormanage_cache->data = data; } static void colormanage_view_settings_to_cache(ImBuf *ibuf, ColormanageCacheViewSettings *cache_view_settings, const ColorManagedViewSettings *view_settings) { - int look = IMB_colormanagement_look_get_named_index(view_settings->look); - int view = IMB_colormanagement_view_get_named_index(view_settings->view_transform); + int look = IMB_colormanagement_look_get_named_index(view_settings->look); + int view = IMB_colormanagement_view_get_named_index(view_settings->view_transform); - cache_view_settings->look = look; - cache_view_settings->view = view; - cache_view_settings->exposure = view_settings->exposure; - cache_view_settings->gamma = view_settings->gamma; - cache_view_settings->dither = ibuf->dither; - cache_view_settings->flag = view_settings->flag; - cache_view_settings->curve_mapping = view_settings->curve_mapping; + cache_view_settings->look = look; + cache_view_settings->view = view; + cache_view_settings->exposure = view_settings->exposure; + cache_view_settings->gamma = view_settings->gamma; + cache_view_settings->dither = ibuf->dither; + cache_view_settings->flag = view_settings->flag; + cache_view_settings->curve_mapping = view_settings->curve_mapping; } -static void colormanage_display_settings_to_cache(ColormanageCacheDisplaySettings *cache_display_settings, - const ColorManagedDisplaySettings *display_settings) +static void colormanage_display_settings_to_cache( + ColormanageCacheDisplaySettings *cache_display_settings, + const ColorManagedDisplaySettings *display_settings) { - int display = IMB_colormanagement_display_get_named_index(display_settings->display_device); + int display = IMB_colormanagement_display_get_named_index(display_settings->display_device); - cache_display_settings->display = display; + cache_display_settings->display = display; } static void colormanage_settings_to_key(ColormanageCacheKey *key, const ColormanageCacheViewSettings *view_settings, const ColormanageCacheDisplaySettings *display_settings) { - key->view = view_settings->view; - key->display = display_settings->display; + key->view = view_settings->view; + key->display = display_settings->display; } -static ImBuf *colormanage_cache_get_ibuf(ImBuf *ibuf, ColormanageCacheKey *key, void **cache_handle) +static ImBuf *colormanage_cache_get_ibuf(ImBuf *ibuf, + ColormanageCacheKey *key, + void **cache_handle) { - ImBuf *cache_ibuf; - struct MovieCache *moviecache = colormanage_moviecache_get(ibuf); + ImBuf *cache_ibuf; + struct MovieCache *moviecache = colormanage_moviecache_get(ibuf); - if (!moviecache) { - /* if there's no moviecache it means no color management was applied on given image buffer before */ + if (!moviecache) { + /* if there's no moviecache it means no color management was applied on given image buffer before */ - return NULL; - } + return NULL; + } - *cache_handle = NULL; + *cache_handle = NULL; - cache_ibuf = IMB_moviecache_get(moviecache, key); + cache_ibuf = IMB_moviecache_get(moviecache, key); - *cache_handle = cache_ibuf; + *cache_handle = cache_ibuf; - return cache_ibuf; + return cache_ibuf; } -static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings, - const ColormanageCacheDisplaySettings *display_settings, - void **cache_handle) +static unsigned char *colormanage_cache_get( + ImBuf *ibuf, + const ColormanageCacheViewSettings *view_settings, + const ColormanageCacheDisplaySettings *display_settings, + void **cache_handle) { - ColormanageCacheKey key; - ImBuf *cache_ibuf; - int view_flag = 1 << (view_settings->view - 1); - CurveMapping *curve_mapping = view_settings->curve_mapping; - int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0; + ColormanageCacheKey key; + ImBuf *cache_ibuf; + int view_flag = 1 << (view_settings->view - 1); + CurveMapping *curve_mapping = view_settings->curve_mapping; + int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0; - colormanage_settings_to_key(&key, view_settings, display_settings); + colormanage_settings_to_key(&key, view_settings, display_settings); - /* check whether image was marked as dirty for requested transform */ - if ((ibuf->display_buffer_flags[display_settings->display - 1] & view_flag) == 0) { - return NULL; - } + /* check whether image was marked as dirty for requested transform */ + if ((ibuf->display_buffer_flags[display_settings->display - 1] & view_flag) == 0) { + return NULL; + } - cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle); + cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle); - if (cache_ibuf) { - ColormanageCacheData *cache_data; + if (cache_ibuf) { + ColormanageCacheData *cache_data; - BLI_assert(cache_ibuf->x == ibuf->x && - cache_ibuf->y == ibuf->y); + BLI_assert(cache_ibuf->x == ibuf->x && cache_ibuf->y == ibuf->y); - /* only buffers with different color space conversions are being stored - * in cache separately. buffer which were used only different exposure/gamma - * are re-suing the same cached buffer - * - * check here which exposure/gamma/curve was used for cached buffer and if they're - * different from requested buffer should be re-generated - */ - cache_data = colormanage_cachedata_get(cache_ibuf); + /* only buffers with different color space conversions are being stored + * in cache separately. buffer which were used only different exposure/gamma + * are re-suing the same cached buffer + * + * check here which exposure/gamma/curve was used for cached buffer and if they're + * different from requested buffer should be re-generated + */ + cache_data = colormanage_cachedata_get(cache_ibuf); - if (cache_data->look != view_settings->look || - cache_data->exposure != view_settings->exposure || - cache_data->gamma != view_settings->gamma || - cache_data->dither != view_settings->dither || - cache_data->flag != view_settings->flag || - cache_data->curve_mapping != curve_mapping || - cache_data->curve_mapping_timestamp != curve_mapping_timestamp) - { - *cache_handle = NULL; + if (cache_data->look != view_settings->look || + cache_data->exposure != view_settings->exposure || + cache_data->gamma != view_settings->gamma || cache_data->dither != view_settings->dither || + cache_data->flag != view_settings->flag || cache_data->curve_mapping != curve_mapping || + cache_data->curve_mapping_timestamp != curve_mapping_timestamp) { + *cache_handle = NULL; - IMB_freeImBuf(cache_ibuf); + IMB_freeImBuf(cache_ibuf); - return NULL; - } + return NULL; + } - return (unsigned char *) cache_ibuf->rect; - } + return (unsigned char *)cache_ibuf->rect; + } - return NULL; + return NULL; } -static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings, +static void colormanage_cache_put(ImBuf *ibuf, + const ColormanageCacheViewSettings *view_settings, const ColormanageCacheDisplaySettings *display_settings, - unsigned char *display_buffer, void **cache_handle) + unsigned char *display_buffer, + void **cache_handle) { - ColormanageCacheKey key; - ImBuf *cache_ibuf; - ColormanageCacheData *cache_data; - int view_flag = 1 << (view_settings->view - 1); - struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf); - CurveMapping *curve_mapping = view_settings->curve_mapping; - int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0; + ColormanageCacheKey key; + ImBuf *cache_ibuf; + ColormanageCacheData *cache_data; + int view_flag = 1 << (view_settings->view - 1); + struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf); + CurveMapping *curve_mapping = view_settings->curve_mapping; + int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0; - colormanage_settings_to_key(&key, view_settings, display_settings); + colormanage_settings_to_key(&key, view_settings, display_settings); - /* mark display buffer as valid */ - ibuf->display_buffer_flags[display_settings->display - 1] |= view_flag; + /* mark display buffer as valid */ + ibuf->display_buffer_flags[display_settings->display - 1] |= view_flag; - /* buffer itself */ - cache_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); - cache_ibuf->rect = (unsigned int *) display_buffer; + /* buffer itself */ + cache_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); + cache_ibuf->rect = (unsigned int *)display_buffer; - cache_ibuf->mall |= IB_rect; - cache_ibuf->flags |= IB_rect; + cache_ibuf->mall |= IB_rect; + cache_ibuf->flags |= IB_rect; - /* store data which is needed to check whether cached buffer could be used for color managed display settings */ - cache_data = MEM_callocN(sizeof(ColormanageCacheData), "color manage cache imbuf data"); - cache_data->look = view_settings->look; - cache_data->exposure = view_settings->exposure; - cache_data->gamma = view_settings->gamma; - cache_data->dither = view_settings->dither; - cache_data->flag = view_settings->flag; - cache_data->curve_mapping = curve_mapping; - cache_data->curve_mapping_timestamp = curve_mapping_timestamp; + /* store data which is needed to check whether cached buffer could be used for color managed display settings */ + cache_data = MEM_callocN(sizeof(ColormanageCacheData), "color manage cache imbuf data"); + cache_data->look = view_settings->look; + cache_data->exposure = view_settings->exposure; + cache_data->gamma = view_settings->gamma; + cache_data->dither = view_settings->dither; + cache_data->flag = view_settings->flag; + cache_data->curve_mapping = curve_mapping; + cache_data->curve_mapping_timestamp = curve_mapping_timestamp; - colormanage_cachedata_set(cache_ibuf, cache_data); + colormanage_cachedata_set(cache_ibuf, cache_data); - *cache_handle = cache_ibuf; + *cache_handle = cache_ibuf; - IMB_moviecache_put(moviecache, &key, cache_ibuf); + IMB_moviecache_put(moviecache, &key, cache_ibuf); } static void colormanage_cache_handle_release(void *cache_handle) { - ImBuf *cache_ibuf = cache_handle; + ImBuf *cache_ibuf = cache_handle; - IMB_freeImBuf(cache_ibuf); + IMB_freeImBuf(cache_ibuf); } /*********************** Initialization / De-initialization *************************/ -static void colormanage_role_color_space_name_get(OCIO_ConstConfigRcPtr *config, char *colorspace_name, const char *role, const char *backup_role) +static void colormanage_role_color_space_name_get(OCIO_ConstConfigRcPtr *config, + char *colorspace_name, + const char *role, + const char *backup_role) { - OCIO_ConstColorSpaceRcPtr *ociocs; + OCIO_ConstColorSpaceRcPtr *ociocs; - ociocs = OCIO_configGetColorSpace(config, role); + ociocs = OCIO_configGetColorSpace(config, role); - if (!ociocs && backup_role) - ociocs = OCIO_configGetColorSpace(config, backup_role); + if (!ociocs && backup_role) + ociocs = OCIO_configGetColorSpace(config, backup_role); - if (ociocs) { - const char *name = OCIO_colorSpaceGetName(ociocs); + if (ociocs) { + const char *name = OCIO_colorSpaceGetName(ociocs); - /* assume function was called with buffer properly allocated to MAX_COLORSPACE_NAME chars */ - BLI_strncpy(colorspace_name, name, MAX_COLORSPACE_NAME); - OCIO_colorSpaceRelease(ociocs); - } - else { - printf("Color management: Error could not find role %s role.\n", role); - } + /* assume function was called with buffer properly allocated to MAX_COLORSPACE_NAME chars */ + BLI_strncpy(colorspace_name, name, MAX_COLORSPACE_NAME); + OCIO_colorSpaceRelease(ociocs); + } + else { + printf("Color management: Error could not find role %s role.\n", role); + } } static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) { - int tot_colorspace, tot_display, tot_display_view, tot_looks; - int index, viewindex, viewindex2; - const char *name; + int tot_colorspace, tot_display, tot_display_view, tot_looks; + int index, viewindex, viewindex2; + const char *name; - /* get roles */ - colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR, NULL); - colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING, NULL); - colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT, NULL); - colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER, OCIO_ROLE_SCENE_LINEAR); - colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE, OCIO_ROLE_TEXTURE_PAINT); - colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT, OCIO_ROLE_SCENE_LINEAR); + /* get roles */ + colormanage_role_color_space_name_get( + config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR, NULL); + colormanage_role_color_space_name_get( + config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING, NULL); + colormanage_role_color_space_name_get( + config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT, NULL); + colormanage_role_color_space_name_get( + config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER, OCIO_ROLE_SCENE_LINEAR); + colormanage_role_color_space_name_get( + config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE, OCIO_ROLE_TEXTURE_PAINT); + colormanage_role_color_space_name_get( + config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT, OCIO_ROLE_SCENE_LINEAR); - /* load colorspaces */ - tot_colorspace = OCIO_configGetNumColorSpaces(config); - for (index = 0 ; index < tot_colorspace; index++) { - OCIO_ConstColorSpaceRcPtr *ocio_colorspace; - const char *description; - bool is_invertible, is_data; + /* load colorspaces */ + tot_colorspace = OCIO_configGetNumColorSpaces(config); + for (index = 0; index < tot_colorspace; index++) { + OCIO_ConstColorSpaceRcPtr *ocio_colorspace; + const char *description; + bool is_invertible, is_data; - name = OCIO_configGetColorSpaceNameByIndex(config, index); + name = OCIO_configGetColorSpaceNameByIndex(config, index); - ocio_colorspace = OCIO_configGetColorSpace(config, name); - description = OCIO_colorSpaceGetDescription(ocio_colorspace); - is_invertible = OCIO_colorSpaceIsInvertible(ocio_colorspace); - is_data = OCIO_colorSpaceIsData(ocio_colorspace); + ocio_colorspace = OCIO_configGetColorSpace(config, name); + description = OCIO_colorSpaceGetDescription(ocio_colorspace); + is_invertible = OCIO_colorSpaceIsInvertible(ocio_colorspace); + is_data = OCIO_colorSpaceIsData(ocio_colorspace); - colormanage_colorspace_add(name, description, is_invertible, is_data); + colormanage_colorspace_add(name, description, is_invertible, is_data); - OCIO_colorSpaceRelease(ocio_colorspace); - } + OCIO_colorSpaceRelease(ocio_colorspace); + } - /* load displays */ - viewindex2 = 0; - tot_display = OCIO_configGetNumDisplays(config); + /* load displays */ + viewindex2 = 0; + tot_display = OCIO_configGetNumDisplays(config); - for (index = 0 ; index < tot_display; index++) { - const char *displayname; - ColorManagedDisplay *display; + for (index = 0; index < tot_display; index++) { + const char *displayname; + ColorManagedDisplay *display; - displayname = OCIO_configGetDisplay(config, index); + displayname = OCIO_configGetDisplay(config, index); - display = colormanage_display_add(displayname); + display = colormanage_display_add(displayname); - /* load views */ - tot_display_view = OCIO_configGetNumViews(config, displayname); - for (viewindex = 0 ; viewindex < tot_display_view; viewindex++, viewindex2++) { - const char *viewname; - ColorManagedView *view; - LinkData *display_view; + /* load views */ + tot_display_view = OCIO_configGetNumViews(config, displayname); + for (viewindex = 0; viewindex < tot_display_view; viewindex++, viewindex2++) { + const char *viewname; + ColorManagedView *view; + LinkData *display_view; - viewname = OCIO_configGetView(config, displayname, viewindex); + viewname = OCIO_configGetView(config, displayname, viewindex); - /* first check if view transform with given name was already loaded */ - view = colormanage_view_get_named(viewname); + /* first check if view transform with given name was already loaded */ + view = colormanage_view_get_named(viewname); - if (!view) { - view = colormanage_view_add(viewname); - } + if (!view) { + view = colormanage_view_add(viewname); + } - display_view = BLI_genericNodeN(view); + display_view = BLI_genericNodeN(view); - BLI_addtail(&display->views, display_view); - } - } + BLI_addtail(&display->views, display_view); + } + } - global_tot_display = tot_display; + global_tot_display = tot_display; - /* load looks */ - tot_looks = OCIO_configGetNumLooks(config); - colormanage_look_add("None", "", true); - for (index = 0; index < tot_looks; index++) { - OCIO_ConstLookRcPtr *ocio_look; - const char *process_space; + /* load looks */ + tot_looks = OCIO_configGetNumLooks(config); + colormanage_look_add("None", "", true); + for (index = 0; index < tot_looks; index++) { + OCIO_ConstLookRcPtr *ocio_look; + const char *process_space; - name = OCIO_configGetLookNameByIndex(config, index); - ocio_look = OCIO_configGetLook(config, name); - process_space = OCIO_lookGetProcessSpace(ocio_look); - OCIO_lookRelease(ocio_look); + name = OCIO_configGetLookNameByIndex(config, index); + ocio_look = OCIO_configGetLook(config, name); + process_space = OCIO_lookGetProcessSpace(ocio_look); + OCIO_lookRelease(ocio_look); - colormanage_look_add(name, process_space, false); - } + colormanage_look_add(name, process_space, false); + } - /* Load luminance coefficients. */ - OCIO_configGetDefaultLumaCoefs(config, imbuf_luma_coefficients); - OCIO_configGetXYZtoRGB(config, imbuf_xyz_to_rgb); - invert_m3_m3(imbuf_rgb_to_xyz, imbuf_xyz_to_rgb); - copy_m3_m3(imbuf_xyz_to_linear_srgb, OCIO_XYZ_TO_LINEAR_SRGB); - invert_m3_m3(imbuf_linear_srgb_to_xyz, imbuf_xyz_to_linear_srgb); + /* Load luminance coefficients. */ + OCIO_configGetDefaultLumaCoefs(config, imbuf_luma_coefficients); + OCIO_configGetXYZtoRGB(config, imbuf_xyz_to_rgb); + invert_m3_m3(imbuf_rgb_to_xyz, imbuf_xyz_to_rgb); + copy_m3_m3(imbuf_xyz_to_linear_srgb, OCIO_XYZ_TO_LINEAR_SRGB); + invert_m3_m3(imbuf_linear_srgb_to_xyz, imbuf_xyz_to_linear_srgb); } static void colormanage_free_config(void) { - ColorSpace *colorspace; - ColorManagedDisplay *display; + ColorSpace *colorspace; + ColorManagedDisplay *display; - /* free color spaces */ - colorspace = global_colorspaces.first; - while (colorspace) { - ColorSpace *colorspace_next = colorspace->next; + /* free color spaces */ + colorspace = global_colorspaces.first; + while (colorspace) { + ColorSpace *colorspace_next = colorspace->next; - /* free precomputer processors */ - if (colorspace->to_scene_linear) - OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) colorspace->to_scene_linear); + /* free precomputer processors */ + if (colorspace->to_scene_linear) + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)colorspace->to_scene_linear); - if (colorspace->from_scene_linear) - OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) colorspace->from_scene_linear); + if (colorspace->from_scene_linear) + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)colorspace->from_scene_linear); - /* free color space itself */ - MEM_freeN(colorspace); + /* free color space itself */ + MEM_freeN(colorspace); - colorspace = colorspace_next; - } - BLI_listbase_clear(&global_colorspaces); - global_tot_colorspace = 0; + colorspace = colorspace_next; + } + BLI_listbase_clear(&global_colorspaces); + global_tot_colorspace = 0; - /* free displays */ - display = global_displays.first; - while (display) { - ColorManagedDisplay *display_next = display->next; + /* free displays */ + display = global_displays.first; + while (display) { + ColorManagedDisplay *display_next = display->next; - /* free precomputer processors */ - if (display->to_scene_linear) - OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) display->to_scene_linear); + /* free precomputer processors */ + if (display->to_scene_linear) + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)display->to_scene_linear); - if (display->from_scene_linear) - OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) display->from_scene_linear); + if (display->from_scene_linear) + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)display->from_scene_linear); - /* free list of views */ - BLI_freelistN(&display->views); + /* free list of views */ + BLI_freelistN(&display->views); - MEM_freeN(display); - display = display_next; - } - BLI_listbase_clear(&global_displays); - global_tot_display = 0; + MEM_freeN(display); + display = display_next; + } + BLI_listbase_clear(&global_displays); + global_tot_display = 0; - /* free views */ - BLI_freelistN(&global_views); - global_tot_view = 0; + /* free views */ + BLI_freelistN(&global_views); + global_tot_view = 0; - /* free looks */ - BLI_freelistN(&global_looks); - global_tot_looks = 0; + /* free looks */ + BLI_freelistN(&global_looks); + global_tot_looks = 0; - OCIO_exit(); + OCIO_exit(); } void colormanagement_init(void) { - const char *ocio_env; - const char *configdir; - char configfile[FILE_MAX]; - OCIO_ConstConfigRcPtr *config = NULL; + const char *ocio_env; + const char *configdir; + char configfile[FILE_MAX]; + OCIO_ConstConfigRcPtr *config = NULL; - OCIO_init(); + OCIO_init(); - ocio_env = BLI_getenv("OCIO"); + ocio_env = BLI_getenv("OCIO"); - if (ocio_env && ocio_env[0] != '\0') { - config = OCIO_configCreateFromEnv(); - if (config != NULL) { - printf("Color management: Using %s as a configuration file\n", ocio_env); - } - } + if (ocio_env && ocio_env[0] != '\0') { + config = OCIO_configCreateFromEnv(); + if (config != NULL) { + printf("Color management: Using %s as a configuration file\n", ocio_env); + } + } - if (config == NULL) { - configdir = BKE_appdir_folder_id(BLENDER_DATAFILES, "colormanagement"); + if (config == NULL) { + configdir = BKE_appdir_folder_id(BLENDER_DATAFILES, "colormanagement"); - if (configdir) { - BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE); + if (configdir) { + BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE); #ifdef WIN32 - { - /* quite a hack to support loading configuration from path with non-acii symbols */ + { + /* quite a hack to support loading configuration from path with non-acii symbols */ - char short_name[256]; - BLI_get_short_name(short_name, configfile); - config = OCIO_configCreateFromFile(short_name); - } + char short_name[256]; + BLI_get_short_name(short_name, configfile); + config = OCIO_configCreateFromFile(short_name); + } #else - config = OCIO_configCreateFromFile(configfile); + config = OCIO_configCreateFromFile(configfile); #endif - } - } + } + } - if (config == NULL) { - printf("Color management: using fallback mode for management\n"); + if (config == NULL) { + printf("Color management: using fallback mode for management\n"); - config = OCIO_configCreateFallback(); - } + config = OCIO_configCreateFallback(); + } - if (config) { - OCIO_setCurrentConfig(config); + if (config) { + OCIO_setCurrentConfig(config); - colormanage_load_config(config); + colormanage_load_config(config); - OCIO_configRelease(config); - } + OCIO_configRelease(config); + } - /* If there're no valid display/views, use fallback mode. */ - if (global_tot_display == 0 || global_tot_view == 0) { - printf("Color management: no displays/views in the config, using fallback mode instead\n"); + /* If there're no valid display/views, use fallback mode. */ + if (global_tot_display == 0 || global_tot_view == 0) { + printf("Color management: no displays/views in the config, using fallback mode instead\n"); - /* Free old config. */ - colormanage_free_config(); + /* Free old config. */ + colormanage_free_config(); - /* Initialize fallback config. */ - config = OCIO_configCreateFallback(); - colormanage_load_config(config); - } + /* Initialize fallback config. */ + config = OCIO_configCreateFallback(); + colormanage_load_config(config); + } - BLI_init_srgb_conversion(); + BLI_init_srgb_conversion(); } void colormanagement_exit(void) { - if (global_glsl_state.processor) - OCIO_processorRelease(global_glsl_state.processor); + if (global_glsl_state.processor) + OCIO_processorRelease(global_glsl_state.processor); - if (global_glsl_state.curve_mapping) - curvemapping_free(global_glsl_state.curve_mapping); + if (global_glsl_state.curve_mapping) + curvemapping_free(global_glsl_state.curve_mapping); - if (global_glsl_state.curve_mapping_settings.lut) - MEM_freeN(global_glsl_state.curve_mapping_settings.lut); + if (global_glsl_state.curve_mapping_settings.lut) + MEM_freeN(global_glsl_state.curve_mapping_settings.lut); - if (global_glsl_state.ocio_glsl_state) - OCIO_freeOGLState(global_glsl_state.ocio_glsl_state); + if (global_glsl_state.ocio_glsl_state) + OCIO_freeOGLState(global_glsl_state.ocio_glsl_state); - if (global_glsl_state.transform_ocio_glsl_state) - OCIO_freeOGLState(global_glsl_state.transform_ocio_glsl_state); + if (global_glsl_state.transform_ocio_glsl_state) + OCIO_freeOGLState(global_glsl_state.transform_ocio_glsl_state); - if (global_color_picking_state.processor_to) - OCIO_processorRelease(global_color_picking_state.processor_to); + if (global_color_picking_state.processor_to) + OCIO_processorRelease(global_color_picking_state.processor_to); - if (global_color_picking_state.processor_from) - OCIO_processorRelease(global_color_picking_state.processor_from); + if (global_color_picking_state.processor_from) + OCIO_processorRelease(global_color_picking_state.processor_from); - memset(&global_glsl_state, 0, sizeof(global_glsl_state)); - memset(&global_color_picking_state, 0, sizeof(global_color_picking_state)); + memset(&global_glsl_state, 0, sizeof(global_glsl_state)); + memset(&global_color_picking_state, 0, sizeof(global_color_picking_state)); - colormanage_free_config(); + colormanage_free_config(); } /*********************** Internal functions *************************/ void colormanage_cache_free(ImBuf *ibuf) { - if (ibuf->display_buffer_flags) { - MEM_freeN(ibuf->display_buffer_flags); + if (ibuf->display_buffer_flags) { + MEM_freeN(ibuf->display_buffer_flags); - ibuf->display_buffer_flags = NULL; - } + ibuf->display_buffer_flags = NULL; + } - if (ibuf->colormanage_cache) { - ColormanageCacheData *cache_data = colormanage_cachedata_get(ibuf); - struct MovieCache *moviecache = colormanage_moviecache_get(ibuf); + if (ibuf->colormanage_cache) { + ColormanageCacheData *cache_data = colormanage_cachedata_get(ibuf); + struct MovieCache *moviecache = colormanage_moviecache_get(ibuf); - if (cache_data) { - MEM_freeN(cache_data); - } + if (cache_data) { + MEM_freeN(cache_data); + } - if (moviecache) { - IMB_moviecache_free(moviecache); - } + if (moviecache) { + IMB_moviecache_free(moviecache); + } - MEM_freeN(ibuf->colormanage_cache); + MEM_freeN(ibuf->colormanage_cache); - ibuf->colormanage_cache = NULL; - } + ibuf->colormanage_cache = NULL; + } } -void IMB_colormanagement_display_settings_from_ctx(const bContext *C, - ColorManagedViewSettings **view_settings_r, - ColorManagedDisplaySettings **display_settings_r) +void IMB_colormanagement_display_settings_from_ctx( + const bContext *C, + ColorManagedViewSettings **view_settings_r, + ColorManagedDisplaySettings **display_settings_r) { - Scene *scene = CTX_data_scene(C); - SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + SpaceImage *sima = CTX_wm_space_image(C); - *view_settings_r = &scene->view_settings; - *display_settings_r = &scene->display_settings; + *view_settings_r = &scene->view_settings; + *display_settings_r = &scene->display_settings; - if (sima && sima->image) { - if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0) - *view_settings_r = NULL; - } + if (sima && sima->image) { + if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0) + *view_settings_r = NULL; + } } -const char *IMB_colormanagement_get_display_colorspace_name(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +const char *IMB_colormanagement_get_display_colorspace_name( + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - const char *display = display_settings->display_device; - const char *view = view_settings->view_transform; - const char *colorspace_name; + const char *display = display_settings->display_device; + const char *view = view_settings->view_transform; + const char *colorspace_name; - colorspace_name = OCIO_configGetDisplayColorSpaceName(config, display, view); + colorspace_name = OCIO_configGetDisplayColorSpaceName(config, display, view); - OCIO_configRelease(config); + OCIO_configRelease(config); - return colorspace_name; + return colorspace_name; } -static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +static ColorSpace *display_transform_get_colorspace( + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - const char *colorspace_name = IMB_colormanagement_get_display_colorspace_name(view_settings, display_settings); + const char *colorspace_name = IMB_colormanagement_get_display_colorspace_name(view_settings, + display_settings); - if (colorspace_name) - return colormanage_colorspace_get_named(colorspace_name); + if (colorspace_name) + return colormanage_colorspace_get_named(colorspace_name); - return NULL; + return NULL; } static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *look, const char *view_transform, const char *display, - float exposure, float gamma, + float exposure, + float gamma, const char *from_colorspace) { - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - OCIO_DisplayTransformRcPtr *dt; - OCIO_ConstProcessorRcPtr *processor; - ColorManagedLook *look_descr = colormanage_look_get_named(look); + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_DisplayTransformRcPtr *dt; + OCIO_ConstProcessorRcPtr *processor; + ColorManagedLook *look_descr = colormanage_look_get_named(look); - dt = OCIO_createDisplayTransform(); + dt = OCIO_createDisplayTransform(); - OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace); - OCIO_displayTransformSetView(dt, view_transform); - OCIO_displayTransformSetDisplay(dt, display); + OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace); + OCIO_displayTransformSetView(dt, view_transform); + OCIO_displayTransformSetDisplay(dt, display); - if (look_descr->is_noop == false) { - OCIO_displayTransformSetLooksOverrideEnabled(dt, true); - OCIO_displayTransformSetLooksOverride(dt, look); - } + if (look_descr->is_noop == false) { + OCIO_displayTransformSetLooksOverrideEnabled(dt, true); + OCIO_displayTransformSetLooksOverride(dt, look); + } - /* fstop exposure control */ - if (exposure != 0.0f) { - OCIO_MatrixTransformRcPtr *mt; - float gain = powf(2.0f, exposure); - const float scale4f[] = {gain, gain, gain, 1.0f}; - float m44[16], offset4[4]; + /* fstop exposure control */ + if (exposure != 0.0f) { + OCIO_MatrixTransformRcPtr *mt; + float gain = powf(2.0f, exposure); + const float scale4f[] = {gain, gain, gain, 1.0f}; + float m44[16], offset4[4]; - OCIO_matrixTransformScale(m44, offset4, scale4f); - mt = OCIO_createMatrixTransform(); - OCIO_matrixTransformSetValue(mt, m44, offset4); - OCIO_displayTransformSetLinearCC(dt, (OCIO_ConstTransformRcPtr *) mt); + OCIO_matrixTransformScale(m44, offset4, scale4f); + mt = OCIO_createMatrixTransform(); + OCIO_matrixTransformSetValue(mt, m44, offset4); + OCIO_displayTransformSetLinearCC(dt, (OCIO_ConstTransformRcPtr *)mt); - OCIO_matrixTransformRelease(mt); - } + OCIO_matrixTransformRelease(mt); + } - /* post-display gamma transform */ - if (gamma != 1.0f) { - OCIO_ExponentTransformRcPtr *et; - float exponent = 1.0f / MAX2(FLT_EPSILON, gamma); - const float exponent4f[] = {exponent, exponent, exponent, exponent}; + /* post-display gamma transform */ + if (gamma != 1.0f) { + OCIO_ExponentTransformRcPtr *et; + float exponent = 1.0f / MAX2(FLT_EPSILON, gamma); + const float exponent4f[] = {exponent, exponent, exponent, exponent}; - et = OCIO_createExponentTransform(); - OCIO_exponentTransformSetValue(et, exponent4f); - OCIO_displayTransformSetDisplayCC(dt, (OCIO_ConstTransformRcPtr *) et); + et = OCIO_createExponentTransform(); + OCIO_exponentTransformSetValue(et, exponent4f); + OCIO_displayTransformSetDisplayCC(dt, (OCIO_ConstTransformRcPtr *)et); - OCIO_exponentTransformRelease(et); - } + OCIO_exponentTransformRelease(et); + } - processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *) dt); + processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *)dt); - OCIO_displayTransformRelease(dt); - OCIO_configRelease(config); + OCIO_displayTransformRelease(dt); + OCIO_configRelease(config); - return processor; + return processor; } static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, const char *to_colorspace) { - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstProcessorRcPtr *processor; - processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace); + processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace); - OCIO_configRelease(config); + OCIO_configRelease(config); - return processor; + return processor; } static OCIO_ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace) { - if (colorspace->to_scene_linear == NULL) { - BLI_mutex_lock(&processor_lock); + if (colorspace->to_scene_linear == NULL) { + BLI_mutex_lock(&processor_lock); - if (colorspace->to_scene_linear == NULL) { - OCIO_ConstProcessorRcPtr *to_scene_linear; - to_scene_linear = create_colorspace_transform_processor(colorspace->name, global_role_scene_linear); - colorspace->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *) to_scene_linear; - } + if (colorspace->to_scene_linear == NULL) { + OCIO_ConstProcessorRcPtr *to_scene_linear; + to_scene_linear = create_colorspace_transform_processor(colorspace->name, + global_role_scene_linear); + colorspace->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *)to_scene_linear; + } - BLI_mutex_unlock(&processor_lock); - } + BLI_mutex_unlock(&processor_lock); + } - return (OCIO_ConstProcessorRcPtr *) colorspace->to_scene_linear; + return (OCIO_ConstProcessorRcPtr *)colorspace->to_scene_linear; } static OCIO_ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace) { - if (colorspace->from_scene_linear == NULL) { - BLI_mutex_lock(&processor_lock); + if (colorspace->from_scene_linear == NULL) { + BLI_mutex_lock(&processor_lock); - if (colorspace->from_scene_linear == NULL) { - OCIO_ConstProcessorRcPtr *from_scene_linear; - from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear, colorspace->name); - colorspace->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *) from_scene_linear; - } + if (colorspace->from_scene_linear == NULL) { + OCIO_ConstProcessorRcPtr *from_scene_linear; + from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear, + colorspace->name); + colorspace->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *)from_scene_linear; + } - BLI_mutex_unlock(&processor_lock); - } + BLI_mutex_unlock(&processor_lock); + } - return (OCIO_ConstProcessorRcPtr *) colorspace->from_scene_linear; + return (OCIO_ConstProcessorRcPtr *)colorspace->from_scene_linear; } static OCIO_ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display) { - if (display->from_scene_linear == NULL) { - BLI_mutex_lock(&processor_lock); + if (display->from_scene_linear == NULL) { + BLI_mutex_lock(&processor_lock); - if (display->from_scene_linear == NULL) { - const char *view_name = colormanage_view_get_default_name(display); - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - OCIO_ConstProcessorRcPtr *processor = NULL; + if (display->from_scene_linear == NULL) { + const char *view_name = colormanage_view_get_default_name(display); + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstProcessorRcPtr *processor = NULL; - if (view_name && config) { - const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name); - processor = OCIO_configGetProcessorWithNames(config, global_role_scene_linear, view_colorspace); + if (view_name && config) { + const char *view_colorspace = OCIO_configGetDisplayColorSpaceName( + config, display->name, view_name); + processor = OCIO_configGetProcessorWithNames( + config, global_role_scene_linear, view_colorspace); - OCIO_configRelease(config); - } + OCIO_configRelease(config); + } - display->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *) processor; - } + display->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *)processor; + } - BLI_mutex_unlock(&processor_lock); - } + BLI_mutex_unlock(&processor_lock); + } - return (OCIO_ConstProcessorRcPtr *) display->from_scene_linear; + return (OCIO_ConstProcessorRcPtr *)display->from_scene_linear; } static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display) { - if (display->to_scene_linear == NULL) { - BLI_mutex_lock(&processor_lock); + if (display->to_scene_linear == NULL) { + BLI_mutex_lock(&processor_lock); - if (display->to_scene_linear == NULL) { - const char *view_name = colormanage_view_get_default_name(display); - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - OCIO_ConstProcessorRcPtr *processor = NULL; + if (display->to_scene_linear == NULL) { + const char *view_name = colormanage_view_get_default_name(display); + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstProcessorRcPtr *processor = NULL; - if (view_name && config) { - const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name); - processor = OCIO_configGetProcessorWithNames(config, view_colorspace, global_role_scene_linear); + if (view_name && config) { + const char *view_colorspace = OCIO_configGetDisplayColorSpaceName( + config, display->name, view_name); + processor = OCIO_configGetProcessorWithNames( + config, view_colorspace, global_role_scene_linear); - OCIO_configRelease(config); - } + OCIO_configRelease(config); + } - display->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *) processor; - } + display->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *)processor; + } - BLI_mutex_unlock(&processor_lock); - } + BLI_mutex_unlock(&processor_lock); + } - return (OCIO_ConstProcessorRcPtr *) display->to_scene_linear; + return (OCIO_ConstProcessorRcPtr *)display->to_scene_linear; } void IMB_colormanagement_init_default_view_settings( - ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - /* First, try use "Default" view transform of the requested device. */ - ColorManagedView *default_view = colormanage_view_get_named_for_display( - display_settings->display_device, "Default"); - /* If that fails, we fall back to the default view transform of the display - * as per OCIO configuration. */ - if (default_view == NULL) { - ColorManagedDisplay *display = colormanage_display_get_named( - display_settings->display_device); - if (display != NULL) { - default_view = colormanage_view_get_default(display); - } - } - if (default_view != NULL) { - BLI_strncpy(view_settings->view_transform, - default_view->name, - sizeof(view_settings->view_transform)); - } - else { - view_settings->view_transform[0] = '\0'; - } - /* TODO(sergey): Find a way to safely/reliable un-hardcode this. */ - BLI_strncpy(view_settings->look, "None", sizeof(view_settings->look)); - /* Initialize rest of the settings. */ - view_settings->flag = 0; - view_settings->gamma = 1.0f; - view_settings->exposure = 0.0f; - view_settings->curve_mapping = NULL; + ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) +{ + /* First, try use "Default" view transform of the requested device. */ + ColorManagedView *default_view = colormanage_view_get_named_for_display( + display_settings->display_device, "Default"); + /* If that fails, we fall back to the default view transform of the display + * as per OCIO configuration. */ + if (default_view == NULL) { + ColorManagedDisplay *display = colormanage_display_get_named(display_settings->display_device); + if (display != NULL) { + default_view = colormanage_view_get_default(display); + } + } + if (default_view != NULL) { + BLI_strncpy( + view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); + } + else { + view_settings->view_transform[0] = '\0'; + } + /* TODO(sergey): Find a way to safely/reliable un-hardcode this. */ + BLI_strncpy(view_settings->look, "None", sizeof(view_settings->look)); + /* Initialize rest of the settings. */ + view_settings->flag = 0; + view_settings->gamma = 1.0f; + view_settings->exposure = 0.0f; + view_settings->curve_mapping = NULL; } static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels) { - if (channels == 1) { - pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); - } - else if (channels == 2) { - pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); - pixel[1] = curvemap_evaluateF(curve_mapping->cm, pixel[1]); - } - else { - curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); - } + if (channels == 1) { + pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); + } + else if (channels == 2) { + pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); + pixel[1] = curvemap_evaluateF(curve_mapping->cm, pixel[1]); + } + else { + curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); + } } void colorspace_set_default_role(char *colorspace, int size, int role) { - if (colorspace && colorspace[0] == '\0') { - const char *role_colorspace; + if (colorspace && colorspace[0] == '\0') { + const char *role_colorspace; - role_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + role_colorspace = IMB_colormanagement_role_colorspace_name_get(role); - BLI_strncpy(colorspace, role_colorspace, size); - } + BLI_strncpy(colorspace, role_colorspace, size); + } } void colormanage_imbuf_set_default_spaces(ImBuf *ibuf) { - ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte); + ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte); } void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { - ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); + ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); - if (colorspace && colorspace->is_data) { - ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; - return; - } + if (colorspace && colorspace->is_data) { + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + return; + } - if (ibuf->rect_float) { - const char *to_colorspace = global_role_scene_linear; + if (ibuf->rect_float) { + const char *to_colorspace = global_role_scene_linear; - if (ibuf->rect) - imb_freerectImBuf(ibuf); + if (ibuf->rect) + imb_freerectImBuf(ibuf); - IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, true); - } + IMB_colormanagement_transform( + ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, true); + } } /*********************** Generic functions *************************/ -static void colormanage_check_display_settings(ColorManagedDisplaySettings *display_settings, const char *what, +static void colormanage_check_display_settings(ColorManagedDisplaySettings *display_settings, + const char *what, const ColorManagedDisplay *default_display) { - if (display_settings->display_device[0] == '\0') { - BLI_strncpy(display_settings->display_device, default_display->name, sizeof(display_settings->display_device)); - } - else { - ColorManagedDisplay *display = colormanage_display_get_named(display_settings->display_device); + if (display_settings->display_device[0] == '\0') { + BLI_strncpy(display_settings->display_device, + default_display->name, + sizeof(display_settings->display_device)); + } + else { + ColorManagedDisplay *display = colormanage_display_get_named(display_settings->display_device); - if (!display) { - printf("Color management: display \"%s\" used by %s not found, setting to default (\"%s\").\n", - display_settings->display_device, what, default_display->name); + if (!display) { + printf( + "Color management: display \"%s\" used by %s not found, setting to default (\"%s\").\n", + display_settings->display_device, + what, + default_display->name); - BLI_strncpy(display_settings->display_device, default_display->name, - sizeof(display_settings->display_device)); - } - } + BLI_strncpy(display_settings->display_device, + default_display->name, + sizeof(display_settings->display_device)); + } + } } static void colormanage_check_view_settings(ColorManagedDisplaySettings *display_settings, - ColorManagedViewSettings *view_settings, const char *what) -{ - ColorManagedDisplay *display; - ColorManagedView *default_view = NULL; - ColorManagedLook *default_look = (ColorManagedLook *) global_looks.first; - - if (view_settings->view_transform[0] == '\0') { - display = colormanage_display_get_named(display_settings->display_device); - - if (display) - default_view = colormanage_view_get_default(display); - - if (default_view) - BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); - } - else { - ColorManagedView *view = colormanage_view_get_named(view_settings->view_transform); - - if (!view) { - display = colormanage_display_get_named(display_settings->display_device); - - if (display) - default_view = colormanage_view_get_default(display); - - if (default_view) { - printf("Color management: %s view \"%s\" not found, setting default \"%s\".\n", - what, view_settings->view_transform, default_view->name); - - BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); - } - } - } - - if (view_settings->look[0] == '\0') { - BLI_strncpy(view_settings->look, default_look->name, sizeof(view_settings->look)); - } - else { - ColorManagedLook *look = colormanage_look_get_named(view_settings->look); - if (look == NULL) { - printf("Color management: %s look \"%s\" not found, setting default \"%s\".\n", - what, view_settings->look, default_look->name); - - BLI_strncpy(view_settings->look, default_look->name, sizeof(view_settings->look)); - } - } - - /* OCIO_TODO: move to do_versions() */ - if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) { - view_settings->exposure = 0.0f; - view_settings->gamma = 1.0f; - } -} - -static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings *colorspace_settings, const char *what) -{ - if (colorspace_settings->name[0] == '\0') { - /* pass */ - } - else { - ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); - - if (!colorspace) { - printf("Color management: %s colorspace \"%s\" not found, will use default instead.\n", - what, colorspace_settings->name); - - BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); - } - } - - (void) what; + ColorManagedViewSettings *view_settings, + const char *what) +{ + ColorManagedDisplay *display; + ColorManagedView *default_view = NULL; + ColorManagedLook *default_look = (ColorManagedLook *)global_looks.first; + + if (view_settings->view_transform[0] == '\0') { + display = colormanage_display_get_named(display_settings->display_device); + + if (display) + default_view = colormanage_view_get_default(display); + + if (default_view) + BLI_strncpy(view_settings->view_transform, + default_view->name, + sizeof(view_settings->view_transform)); + } + else { + ColorManagedView *view = colormanage_view_get_named(view_settings->view_transform); + + if (!view) { + display = colormanage_display_get_named(display_settings->display_device); + + if (display) + default_view = colormanage_view_get_default(display); + + if (default_view) { + printf("Color management: %s view \"%s\" not found, setting default \"%s\".\n", + what, + view_settings->view_transform, + default_view->name); + + BLI_strncpy(view_settings->view_transform, + default_view->name, + sizeof(view_settings->view_transform)); + } + } + } + + if (view_settings->look[0] == '\0') { + BLI_strncpy(view_settings->look, default_look->name, sizeof(view_settings->look)); + } + else { + ColorManagedLook *look = colormanage_look_get_named(view_settings->look); + if (look == NULL) { + printf("Color management: %s look \"%s\" not found, setting default \"%s\".\n", + what, + view_settings->look, + default_look->name); + + BLI_strncpy(view_settings->look, default_look->name, sizeof(view_settings->look)); + } + } + + /* OCIO_TODO: move to do_versions() */ + if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) { + view_settings->exposure = 0.0f; + view_settings->gamma = 1.0f; + } +} + +static void colormanage_check_colorspace_settings( + ColorManagedColorspaceSettings *colorspace_settings, const char *what) +{ + if (colorspace_settings->name[0] == '\0') { + /* pass */ + } + else { + ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); + + if (!colorspace) { + printf("Color management: %s colorspace \"%s\" not found, will use default instead.\n", + what, + colorspace_settings->name); + + BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); + } + } + + (void)what; } void IMB_colormanagement_check_file_config(Main *bmain) { - Scene *scene; - Image *image; - MovieClip *clip; + Scene *scene; + Image *image; + MovieClip *clip; - ColorManagedDisplay *default_display; + ColorManagedDisplay *default_display; - default_display = colormanage_display_get_default(); + default_display = colormanage_display_get_default(); - if (!default_display) { - /* happens when OCIO configuration is incorrect */ - return; - } + if (!default_display) { + /* happens when OCIO configuration is incorrect */ + return; + } - for (scene = bmain->scenes.first; scene; scene = scene->id.next) { - ColorManagedColorspaceSettings *sequencer_colorspace_settings; + for (scene = bmain->scenes.first; scene; scene = scene->id.next) { + ColorManagedColorspaceSettings *sequencer_colorspace_settings; - /* check scene color management settings */ - colormanage_check_display_settings(&scene->display_settings, "scene", default_display); - colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene"); + /* check scene color management settings */ + colormanage_check_display_settings(&scene->display_settings, "scene", default_display); + colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene"); - sequencer_colorspace_settings = &scene->sequencer_colorspace_settings; + sequencer_colorspace_settings = &scene->sequencer_colorspace_settings; - colormanage_check_colorspace_settings(sequencer_colorspace_settings, "sequencer"); + colormanage_check_colorspace_settings(sequencer_colorspace_settings, "sequencer"); - if (sequencer_colorspace_settings->name[0] == '\0') { - BLI_strncpy(sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME); - } + if (sequencer_colorspace_settings->name[0] == '\0') { + BLI_strncpy( + sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME); + } - /* check sequencer strip input color space settings */ - Sequence *seq; - SEQ_BEGIN (scene->ed, seq) { - if (seq->strip) { - colormanage_check_colorspace_settings(&seq->strip->colorspace_settings, "sequencer strip"); - } - } SEQ_END; - } + /* check sequencer strip input color space settings */ + Sequence *seq; + SEQ_BEGIN (scene->ed, seq) { + if (seq->strip) { + colormanage_check_colorspace_settings(&seq->strip->colorspace_settings, "sequencer strip"); + } + } + SEQ_END; + } - /* ** check input color space settings ** */ + /* ** check input color space settings ** */ - for (image = bmain->images.first; image; image = image->id.next) { - colormanage_check_colorspace_settings(&image->colorspace_settings, "image"); - } + for (image = bmain->images.first; image; image = image->id.next) { + colormanage_check_colorspace_settings(&image->colorspace_settings, "image"); + } - for (clip = bmain->movieclips.first; clip; clip = clip->id.next) { - colormanage_check_colorspace_settings(&clip->colorspace_settings, "clip"); - } + for (clip = bmain->movieclips.first; clip; clip = clip->id.next) { + colormanage_check_colorspace_settings(&clip->colorspace_settings, "clip"); + } } void IMB_colormanagement_validate_settings(const ColorManagedDisplaySettings *display_settings, ColorManagedViewSettings *view_settings) { - ColorManagedDisplay *display; - ColorManagedView *default_view = NULL; - LinkData *view_link; + ColorManagedDisplay *display; + ColorManagedView *default_view = NULL; + LinkData *view_link; - display = colormanage_display_get_named(display_settings->display_device); + display = colormanage_display_get_named(display_settings->display_device); - default_view = colormanage_view_get_default(display); + default_view = colormanage_view_get_default(display); - for (view_link = display->views.first; view_link; view_link = view_link->next) { - ColorManagedView *view = view_link->data; + for (view_link = display->views.first; view_link; view_link = view_link->next) { + ColorManagedView *view = view_link->data; - if (STREQ(view->name, view_settings->view_transform)) - break; - } + if (STREQ(view->name, view_settings->view_transform)) + break; + } - if (view_link == NULL && default_view) - BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); + if (view_link == NULL && default_view) + BLI_strncpy( + view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); } const char *IMB_colormanagement_role_colorspace_name_get(int role) { - switch (role) { - case COLOR_ROLE_SCENE_LINEAR: - return global_role_scene_linear; - case COLOR_ROLE_COLOR_PICKING: - return global_role_color_picking; - case COLOR_ROLE_TEXTURE_PAINTING: - return global_role_texture_painting; - case COLOR_ROLE_DEFAULT_SEQUENCER: - return global_role_default_sequencer; - case COLOR_ROLE_DEFAULT_FLOAT: - return global_role_default_float; - case COLOR_ROLE_DEFAULT_BYTE: - return global_role_default_byte; - default: - printf("Unknown role was passed to %s\n", __func__); - BLI_assert(0); - break; - } - - return NULL; + switch (role) { + case COLOR_ROLE_SCENE_LINEAR: + return global_role_scene_linear; + case COLOR_ROLE_COLOR_PICKING: + return global_role_color_picking; + case COLOR_ROLE_TEXTURE_PAINTING: + return global_role_texture_painting; + case COLOR_ROLE_DEFAULT_SEQUENCER: + return global_role_default_sequencer; + case COLOR_ROLE_DEFAULT_FLOAT: + return global_role_default_float; + case COLOR_ROLE_DEFAULT_BYTE: + return global_role_default_byte; + default: + printf("Unknown role was passed to %s\n", __func__); + BLI_assert(0); + break; + } + + return NULL; } void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) { - ColorSpace *colorspace = colormanage_colorspace_get_named(name); + ColorSpace *colorspace = colormanage_colorspace_get_named(name); - if (colorspace && colorspace->is_data) - ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; - else - ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; + if (colorspace && colorspace->is_data) + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + else + ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; } void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) { - ColorSpace *colorspace = colormanage_colorspace_get_named(name); + ColorSpace *colorspace = colormanage_colorspace_get_named(name); - ibuf->float_colorspace = colorspace; + ibuf->float_colorspace = colorspace; - if (colorspace && colorspace->is_data) - ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; - else - ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; + if (colorspace && colorspace->is_data) + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + else + ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; } void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) { - ColorSpace *colorspace = colormanage_colorspace_get_named(name); + ColorSpace *colorspace = colormanage_colorspace_get_named(name); - ibuf->rect_colorspace = colorspace; + ibuf->rect_colorspace = colorspace; - if (colorspace && colorspace->is_data) - ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; - else - ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; + if (colorspace && colorspace->is_data) + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + else + ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; } const char *IMB_colormanagement_get_float_colorspace(ImBuf *ibuf) { - if (ibuf->float_colorspace) { - return ibuf->float_colorspace->name; - } - else { - return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); - } + if (ibuf->float_colorspace) { + return ibuf->float_colorspace->name; + } + else { + return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + } } const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf) { - if (ibuf->rect_colorspace) { - return ibuf->rect_colorspace->name; - } - else { - return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE); - } + if (ibuf->rect_colorspace) { + return ibuf->rect_colorspace->name; + } + else { + return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE); + } } /*********************** Threaded display buffer transform routines *************************/ typedef struct DisplayBufferThread { - ColormanageProcessor *cm_processor; + ColormanageProcessor *cm_processor; - const float *buffer; - unsigned char *byte_buffer; + const float *buffer; + unsigned char *byte_buffer; - float *display_buffer; - unsigned char *display_buffer_byte; + float *display_buffer; + unsigned char *display_buffer_byte; - int width; - int start_line; - int tot_line; + int width; + int start_line; + int tot_line; - int channels; - float dither; - bool is_data; + int channels; + float dither; + bool is_data; - const char *byte_colorspace; - const char *float_colorspace; + const char *byte_colorspace; + const char *float_colorspace; } DisplayBufferThread; typedef struct DisplayBufferInitData { - ImBuf *ibuf; - ColormanageProcessor *cm_processor; - const float *buffer; - unsigned char *byte_buffer; + ImBuf *ibuf; + ColormanageProcessor *cm_processor; + const float *buffer; + unsigned char *byte_buffer; - float *display_buffer; - unsigned char *display_buffer_byte; + float *display_buffer; + unsigned char *display_buffer_byte; - int width; + int width; - const char *byte_colorspace; - const char *float_colorspace; + const char *byte_colorspace; + const char *float_colorspace; } DisplayBufferInitData; -static void display_buffer_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +static void display_buffer_init_handle(void *handle_v, + int start_line, + int tot_line, + void *init_data_v) { - DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; - DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v; - ImBuf *ibuf = init_data->ibuf; + DisplayBufferThread *handle = (DisplayBufferThread *)handle_v; + DisplayBufferInitData *init_data = (DisplayBufferInitData *)init_data_v; + ImBuf *ibuf = init_data->ibuf; - int channels = ibuf->channels; - float dither = ibuf->dither; - bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; + int channels = ibuf->channels; + float dither = ibuf->dither; + bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; - size_t offset = ((size_t)channels) * start_line * ibuf->x; - size_t display_buffer_byte_offset = ((size_t)DISPLAY_BUFFER_CHANNELS) * start_line * ibuf->x; + size_t offset = ((size_t)channels) * start_line * ibuf->x; + size_t display_buffer_byte_offset = ((size_t)DISPLAY_BUFFER_CHANNELS) * start_line * ibuf->x; - memset(handle, 0, sizeof(DisplayBufferThread)); + memset(handle, 0, sizeof(DisplayBufferThread)); - handle->cm_processor = init_data->cm_processor; + handle->cm_processor = init_data->cm_processor; - if (init_data->buffer) - handle->buffer = init_data->buffer + offset; + if (init_data->buffer) + handle->buffer = init_data->buffer + offset; - if (init_data->byte_buffer) - handle->byte_buffer = init_data->byte_buffer + offset; + if (init_data->byte_buffer) + handle->byte_buffer = init_data->byte_buffer + offset; - if (init_data->display_buffer) - handle->display_buffer = init_data->display_buffer + offset; + if (init_data->display_buffer) + handle->display_buffer = init_data->display_buffer + offset; - if (init_data->display_buffer_byte) - handle->display_buffer_byte = init_data->display_buffer_byte + display_buffer_byte_offset; + if (init_data->display_buffer_byte) + handle->display_buffer_byte = init_data->display_buffer_byte + display_buffer_byte_offset; - handle->width = ibuf->x; + handle->width = ibuf->x; - handle->start_line = start_line; - handle->tot_line = tot_line; + handle->start_line = start_line; + handle->tot_line = tot_line; - handle->channels = channels; - handle->dither = dither; - handle->is_data = is_data; + handle->channels = channels; + handle->dither = dither; + handle->is_data = is_data; - handle->byte_colorspace = init_data->byte_colorspace; - handle->float_colorspace = init_data->float_colorspace; + handle->byte_colorspace = init_data->byte_colorspace; + handle->float_colorspace = init_data->float_colorspace; } -static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, int height, - float *linear_buffer, bool *is_straight_alpha) +static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, + int height, + float *linear_buffer, + bool *is_straight_alpha) { - int channels = handle->channels; - int width = handle->width; + int channels = handle->channels; + int width = handle->width; - size_t buffer_size = ((size_t)channels) * width * height; + size_t buffer_size = ((size_t)channels) * width * height; - bool is_data = handle->is_data; - bool is_data_display = handle->cm_processor->is_data_result; + bool is_data = handle->is_data; + bool is_data_display = handle->cm_processor->is_data_result; - if (!handle->buffer) { - unsigned char *byte_buffer = handle->byte_buffer; + if (!handle->buffer) { + unsigned char *byte_buffer = handle->byte_buffer; - const char *from_colorspace = handle->byte_colorspace; - const char *to_colorspace = global_role_scene_linear; + const char *from_colorspace = handle->byte_colorspace; + const char *to_colorspace = global_role_scene_linear; - float *fp; - unsigned char *cp; - const size_t i_last = ((size_t)width) * height; - size_t i; + float *fp; + unsigned char *cp; + const size_t i_last = ((size_t)width) * height; + size_t i; - /* first convert byte buffer to float, keep in image space */ - for (i = 0, fp = linear_buffer, cp = byte_buffer; - i != i_last; - i++, fp += channels, cp += channels) - { - if (channels == 3) { - rgb_uchar_to_float(fp, cp); - } - else if (channels == 4) { - rgba_uchar_to_float(fp, cp); - } - else { - BLI_assert(!"Buffers of 3 or 4 channels are only supported here"); - } - } + /* first convert byte buffer to float, keep in image space */ + for (i = 0, fp = linear_buffer, cp = byte_buffer; i != i_last; + i++, fp += channels, cp += channels) { + if (channels == 3) { + rgb_uchar_to_float(fp, cp); + } + else if (channels == 4) { + rgba_uchar_to_float(fp, cp); + } + else { + BLI_assert(!"Buffers of 3 or 4 channels are only supported here"); + } + } - 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, false); - } + 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, false); + } - *is_straight_alpha = true; - } - else if (handle->float_colorspace) { - /* currently float is non-linear only in sequencer, which is working - * in it's own color space even to handle float buffers. - * This color space is the same for byte and float images. - * Need to convert float buffer to linear space before applying display transform - */ + *is_straight_alpha = true; + } + else if (handle->float_colorspace) { + /* currently float is non-linear only in sequencer, which is working + * in it's own color space even to handle float buffers. + * This color space is the same for byte and float images. + * Need to convert float buffer to linear space before applying display transform + */ - const char *from_colorspace = handle->float_colorspace; - const char *to_colorspace = global_role_scene_linear; + const char *from_colorspace = handle->float_colorspace; + const char *to_colorspace = global_role_scene_linear; - memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); + memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); - if (!is_data && !is_data_display) { - IMB_colormanagement_transform(linear_buffer, width, height, channels, - from_colorspace, to_colorspace, true); - } + if (!is_data && !is_data_display) { + IMB_colormanagement_transform( + linear_buffer, width, height, channels, from_colorspace, to_colorspace, true); + } - *is_straight_alpha = false; - } - else { - /* some processors would want to modify float original buffer - * before converting it into display byte buffer, so we need to - * make sure original's ImBuf buffers wouldn't be modified by - * using duplicated buffer here - */ + *is_straight_alpha = false; + } + else { + /* some processors would want to modify float original buffer + * before converting it into display byte buffer, so we need to + * make sure original's ImBuf buffers wouldn't be modified by + * using duplicated buffer here + */ - memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); + memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); - *is_straight_alpha = false; - } + *is_straight_alpha = false; + } } static void *do_display_buffer_apply_thread(void *handle_v) { - DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; - ColormanageProcessor *cm_processor = handle->cm_processor; - float *display_buffer = handle->display_buffer; - unsigned char *display_buffer_byte = handle->display_buffer_byte; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - float dither = handle->dither; - bool is_data = handle->is_data; - - if (cm_processor == NULL) { - if (display_buffer_byte && display_buffer_byte != handle->byte_buffer) { - IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, width, height, width, width); - } - - if (display_buffer) { - IMB_buffer_float_from_byte(display_buffer, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, width, height, width, width); - } - } - else { - bool is_straight_alpha, predivide; - float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float), - "color conversion linear buffer"); - - display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha); - - predivide = is_straight_alpha == false; - - if (is_data) { - /* special case for data buffers - no color space conversions, - * only generate byte buffers - */ - } - else { - /* apply processor */ - IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, - predivide); - } - - /* copy result to output buffers */ - if (display_buffer_byte) { - /* do conversion */ - IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer, - channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - predivide, width, height, width, width); - } - - if (display_buffer) { - memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float)); - - if (is_straight_alpha && channels == 4) { - const size_t i_last = ((size_t)width) * height; - size_t i; - float *fp; - - for (i = 0, fp = display_buffer; - i != i_last; - i++, fp += channels) - { - straight_to_premul_v4(fp); - } - } - } - - MEM_freeN(linear_buffer); - } - - return NULL; -} - -static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, float *display_buffer, - unsigned char *display_buffer_byte, ColormanageProcessor *cm_processor) -{ - DisplayBufferInitData init_data; - - init_data.ibuf = ibuf; - init_data.cm_processor = cm_processor; - init_data.buffer = buffer; - init_data.byte_buffer = byte_buffer; - init_data.display_buffer = display_buffer; - init_data.display_buffer_byte = display_buffer_byte; - - if (ibuf->rect_colorspace != NULL) { - init_data.byte_colorspace = ibuf->rect_colorspace->name; - } - else { - /* happens for viewer images, which are not so simple to determine where to - * set image buffer's color spaces - */ - init_data.byte_colorspace = global_role_default_byte; - } - - if (ibuf->float_colorspace != NULL) { - /* sequencer stores float buffers in non-linear space */ - init_data.float_colorspace = ibuf->float_colorspace->name; - } - else { - init_data.float_colorspace = NULL; - } - - IMB_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, - display_buffer_init_handle, do_display_buffer_apply_thread); -} - -static bool is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + DisplayBufferThread *handle = (DisplayBufferThread *)handle_v; + ColormanageProcessor *cm_processor = handle->cm_processor; + float *display_buffer = handle->display_buffer; + unsigned char *display_buffer_byte = handle->display_buffer_byte; + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + float dither = handle->dither; + bool is_data = handle->is_data; + + if (cm_processor == NULL) { + if (display_buffer_byte && display_buffer_byte != handle->byte_buffer) { + IMB_buffer_byte_from_byte(display_buffer_byte, + handle->byte_buffer, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + width, + height, + width, + width); + } + + if (display_buffer) { + IMB_buffer_float_from_byte(display_buffer, + handle->byte_buffer, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + width, + height, + width, + width); + } + } + else { + bool is_straight_alpha, predivide; + float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float), + "color conversion linear buffer"); + + display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha); + + predivide = is_straight_alpha == false; + + if (is_data) { + /* special case for data buffers - no color space conversions, + * only generate byte buffers + */ + } + else { + /* apply processor */ + IMB_colormanagement_processor_apply( + cm_processor, linear_buffer, width, height, channels, predivide); + } + + /* copy result to output buffers */ + if (display_buffer_byte) { + /* do conversion */ + IMB_buffer_byte_from_float(display_buffer_byte, + linear_buffer, + channels, + dither, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + predivide, + width, + height, + width, + width); + } + + if (display_buffer) { + memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float)); + + if (is_straight_alpha && channels == 4) { + const size_t i_last = ((size_t)width) * height; + size_t i; + float *fp; + + for (i = 0, fp = display_buffer; i != i_last; i++, fp += channels) { + straight_to_premul_v4(fp); + } + } + } + + MEM_freeN(linear_buffer); + } + + return NULL; +} + +static void display_buffer_apply_threaded(ImBuf *ibuf, + float *buffer, + unsigned char *byte_buffer, + float *display_buffer, + unsigned char *display_buffer_byte, + ColormanageProcessor *cm_processor) +{ + DisplayBufferInitData init_data; + + init_data.ibuf = ibuf; + init_data.cm_processor = cm_processor; + init_data.buffer = buffer; + init_data.byte_buffer = byte_buffer; + init_data.display_buffer = display_buffer; + init_data.display_buffer_byte = display_buffer_byte; + + if (ibuf->rect_colorspace != NULL) { + init_data.byte_colorspace = ibuf->rect_colorspace->name; + } + else { + /* happens for viewer images, which are not so simple to determine where to + * set image buffer's color spaces + */ + init_data.byte_colorspace = global_role_default_byte; + } + + if (ibuf->float_colorspace != NULL) { + /* sequencer stores float buffers in non-linear space */ + init_data.float_colorspace = ibuf->float_colorspace->name; + } + else { + init_data.float_colorspace = NULL; + } + + IMB_processor_apply_threaded(ibuf->y, + sizeof(DisplayBufferThread), + &init_data, + display_buffer_init_handle, + do_display_buffer_apply_thread); +} + +static bool is_ibuf_rect_in_display_space(ImBuf *ibuf, + const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { - if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 && - view_settings->exposure == 0.0f && - view_settings->gamma == 1.0f) - { - const char *from_colorspace = ibuf->rect_colorspace->name; - const char *to_colorspace = IMB_colormanagement_get_display_colorspace_name(view_settings, display_settings); - ColorManagedLook *look_descr = colormanage_look_get_named(view_settings->look); - if (look_descr != NULL && !STREQ(look_descr->process_space, "")) { - return false; - } - - if (to_colorspace && STREQ(from_colorspace, to_colorspace)) - return true; - } - - return false; -} - -static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - ColormanageProcessor *cm_processor = NULL; - bool skip_transform = false; - - /* if we're going to transform byte buffer, check whether transformation would - * happen to the same color space as byte buffer itself is - * this would save byte -> float -> byte conversions making display buffer - * computation noticeable faster - */ - if (ibuf->rect_float == NULL && ibuf->rect_colorspace) { - skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings); - } - - if (skip_transform == false) - cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - - display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, - display_buffer, display_buffer_byte, cm_processor); - - if (cm_processor) - IMB_colormanagement_processor_free(cm_processor); -} - -static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, + if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 && + view_settings->exposure == 0.0f && view_settings->gamma == 1.0f) { + const char *from_colorspace = ibuf->rect_colorspace->name; + const char *to_colorspace = IMB_colormanagement_get_display_colorspace_name(view_settings, + display_settings); + ColorManagedLook *look_descr = colormanage_look_get_named(view_settings->look); + if (look_descr != NULL && !STREQ(look_descr->process_space, "")) { + return false; + } + + if (to_colorspace && STREQ(from_colorspace, to_colorspace)) + return true; + } + + return false; +} + +static void colormanage_display_buffer_process_ex( + ImBuf *ibuf, + float *display_buffer, + unsigned char *display_buffer_byte, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + ColormanageProcessor *cm_processor = NULL; + bool skip_transform = false; + + /* if we're going to transform byte buffer, check whether transformation would + * happen to the same color space as byte buffer itself is + * this would save byte -> float -> byte conversions making display buffer + * computation noticeable faster + */ + if (ibuf->rect_float == NULL && ibuf->rect_colorspace) { + skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings); + } + + if (skip_transform == false) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + + display_buffer_apply_threaded(ibuf, + ibuf->rect_float, + (unsigned char *)ibuf->rect, + display_buffer, + display_buffer_byte, + cm_processor); + + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); +} + +static void colormanage_display_buffer_process(ImBuf *ibuf, + unsigned char *display_buffer, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { - colormanage_display_buffer_process_ex(ibuf, NULL, display_buffer, view_settings, display_settings); + colormanage_display_buffer_process_ex( + ibuf, NULL, display_buffer, view_settings, display_settings); } /*********************** Threaded processor transform routines *************************/ typedef struct ProcessorTransformThread { - ColormanageProcessor *cm_processor; - unsigned char *byte_buffer; - float *float_buffer; - int width; - int start_line; - int tot_line; - int channels; - bool predivide; - bool float_from_byte; + ColormanageProcessor *cm_processor; + unsigned char *byte_buffer; + float *float_buffer; + int width; + int start_line; + int tot_line; + int channels; + bool predivide; + bool float_from_byte; } ProcessorTransformThread; typedef struct ProcessorTransformInit { - ColormanageProcessor *cm_processor; - unsigned char *byte_buffer; - float *float_buffer; - int width; - int height; - int channels; - bool predivide; - bool float_from_byte; + ColormanageProcessor *cm_processor; + unsigned char *byte_buffer; + float *float_buffer; + int width; + int height; + int channels; + bool predivide; + bool float_from_byte; } ProcessorTransformInitData; -static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +static void processor_transform_init_handle(void *handle_v, + int start_line, + int tot_line, + void *init_data_v) { - ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; - ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v; + ProcessorTransformThread *handle = (ProcessorTransformThread *)handle_v; + ProcessorTransformInitData *init_data = (ProcessorTransformInitData *)init_data_v; - const int channels = init_data->channels; - const int width = init_data->width; - const bool predivide = init_data->predivide; - const bool float_from_byte = init_data->float_from_byte; + const int channels = init_data->channels; + const int width = init_data->width; + const bool predivide = init_data->predivide; + const bool float_from_byte = init_data->float_from_byte; - const size_t offset = ((size_t)channels) * start_line * width; + const size_t offset = ((size_t)channels) * start_line * width; - memset(handle, 0, sizeof(ProcessorTransformThread)); + memset(handle, 0, sizeof(ProcessorTransformThread)); - handle->cm_processor = init_data->cm_processor; + handle->cm_processor = init_data->cm_processor; - if (init_data->byte_buffer != NULL) { - /* TODO(serge): Offset might be different for byte and float buffers. */ - handle->byte_buffer = init_data->byte_buffer + offset; - } - if (init_data->float_buffer != NULL) { - handle->float_buffer = init_data->float_buffer + offset; - } + if (init_data->byte_buffer != NULL) { + /* TODO(serge): Offset might be different for byte and float buffers. */ + handle->byte_buffer = init_data->byte_buffer + offset; + } + if (init_data->float_buffer != NULL) { + handle->float_buffer = init_data->float_buffer + offset; + } - handle->width = width; + handle->width = width; - handle->start_line = start_line; - handle->tot_line = tot_line; + handle->start_line = start_line; + handle->tot_line = tot_line; - handle->channels = channels; - handle->predivide = predivide; - handle->float_from_byte = float_from_byte; + handle->channels = channels; + handle->predivide = predivide; + handle->float_from_byte = float_from_byte; } static void *do_processor_transform_thread(void *handle_v) { - ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; - unsigned char *byte_buffer = handle->byte_buffer; - float *float_buffer = handle->float_buffer; - const int channels = handle->channels; - const int width = handle->width; - const int height = handle->tot_line; - const bool predivide = handle->predivide; - const bool float_from_byte = handle->float_from_byte; - - if (float_from_byte) { - IMB_buffer_float_from_byte(float_buffer, byte_buffer, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, - width, height, width, width); - IMB_colormanagement_processor_apply(handle->cm_processor, - float_buffer, - width, height, channels, - predivide); - IMB_premultiply_rect_float(float_buffer, 4, width, height); - } - else { - if (byte_buffer != NULL) { - IMB_colormanagement_processor_apply_byte(handle->cm_processor, - byte_buffer, - width, height, channels); - } - if (float_buffer != NULL) { - IMB_colormanagement_processor_apply(handle->cm_processor, - float_buffer, - width, height, channels, - predivide); - } - } - - return NULL; -} - -static void processor_transform_apply_threaded(unsigned char *byte_buffer, float *float_buffer, - const int width, const int height, const int channels, + ProcessorTransformThread *handle = (ProcessorTransformThread *)handle_v; + unsigned char *byte_buffer = handle->byte_buffer; + float *float_buffer = handle->float_buffer; + const int channels = handle->channels; + const int width = handle->width; + const int height = handle->tot_line; + const bool predivide = handle->predivide; + const bool float_from_byte = handle->float_from_byte; + + if (float_from_byte) { + IMB_buffer_float_from_byte(float_buffer, + byte_buffer, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + width, + height, + width, + width); + IMB_colormanagement_processor_apply( + handle->cm_processor, float_buffer, width, height, channels, predivide); + IMB_premultiply_rect_float(float_buffer, 4, width, height); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte( + handle->cm_processor, byte_buffer, width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply( + handle->cm_processor, float_buffer, width, height, channels, predivide); + } + } + + return NULL; +} + +static void processor_transform_apply_threaded(unsigned char *byte_buffer, + float *float_buffer, + const int width, + const int height, + const int channels, ColormanageProcessor *cm_processor, - const bool predivide, const bool float_from_byte) + const bool predivide, + const bool float_from_byte) { - ProcessorTransformInitData init_data; + ProcessorTransformInitData init_data; - init_data.cm_processor = cm_processor; - init_data.byte_buffer = byte_buffer; - init_data.float_buffer = float_buffer; - init_data.width = width; - init_data.height = height; - init_data.channels = channels; - init_data.predivide = predivide; - init_data.float_from_byte = float_from_byte; + init_data.cm_processor = cm_processor; + init_data.byte_buffer = byte_buffer; + init_data.float_buffer = float_buffer; + init_data.width = width; + init_data.height = height; + init_data.channels = channels; + init_data.predivide = predivide; + init_data.float_from_byte = float_from_byte; - IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data, - processor_transform_init_handle, do_processor_transform_thread); + IMB_processor_apply_threaded(height, + sizeof(ProcessorTransformThread), + &init_data, + processor_transform_init_handle, + do_processor_transform_thread); } /*********************** Color space transformation functions *************************/ /* convert the whole buffer from specified by name color space to another - internal implementation */ -static void colormanagement_transform_ex(unsigned char *byte_buffer, float *float_buffer, - int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, - bool predivide, bool do_threaded) -{ - ColormanageProcessor *cm_processor; - - if (from_colorspace[0] == '\0') { - return; - } - - if (STREQ(from_colorspace, to_colorspace)) { - /* if source and destination color spaces are identical, skip - * threading overhead and simply do nothing - */ - return; - } - - cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); - - if (do_threaded) { - processor_transform_apply_threaded(byte_buffer, float_buffer, - width, height, channels, - cm_processor, predivide, false); - } - else { - if (byte_buffer != NULL) { - IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels); - } - if (float_buffer != NULL) { - IMB_colormanagement_processor_apply(cm_processor, float_buffer, width, height, channels, predivide); - } - } - - IMB_colormanagement_processor_free(cm_processor); +static void colormanagement_transform_ex(unsigned char *byte_buffer, + float *float_buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace, + bool predivide, + bool do_threaded) +{ + ColormanageProcessor *cm_processor; + + if (from_colorspace[0] == '\0') { + return; + } + + if (STREQ(from_colorspace, to_colorspace)) { + /* if source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + + if (do_threaded) { + processor_transform_apply_threaded( + byte_buffer, float_buffer, width, height, channels, cm_processor, predivide, false); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply( + cm_processor, float_buffer, width, height, channels, predivide); + } + } + + IMB_colormanagement_processor_free(cm_processor); } /* convert the whole buffer from specified by name color space to another */ -void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, bool predivide) +void IMB_colormanagement_transform(float *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace, + bool predivide) { - colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); + colormanagement_transform_ex( + NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); } /* convert the whole buffer from specified by name color space to another * will do threaded conversion */ -void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, bool predivide) +void IMB_colormanagement_transform_threaded(float *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace, + bool predivide) { - colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); + colormanagement_transform_ex( + NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); } /* Similar to functions above, but operates on byte buffer. */ -void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace) +void IMB_colormanagement_transform_byte(unsigned char *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace) { - colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false); + colormanagement_transform_ex( + buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false); } -void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace) +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace) { - colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true); + colormanagement_transform_ex( + buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true); } /* Similar to above, but gets float buffer from display one. */ -void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, - int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace) -{ - IMB_buffer_float_from_byte(float_buffer, byte_buffer, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, - true, - width, height, width, width); - IMB_colormanagement_transform(float_buffer, - width, height, channels, - from_colorspace, to_colorspace, - true); -} -void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, - int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace) -{ - ColormanageProcessor *cm_processor; - if (from_colorspace == NULL || from_colorspace[0] == '\0') { - return; - } - if (STREQ(from_colorspace, to_colorspace)) { - /* Because this function always takes a byte buffer and returns a float buffer, it must - * always do byte-to-float conversion of some kind. To avoid threading overhead - * IMB_buffer_float_from_byte is used when color spaces are identical. See T51002. - */ - IMB_buffer_float_from_byte(float_buffer, byte_buffer, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, - width, height, width, width); - IMB_premultiply_rect_float(float_buffer, 4, width, height); - return; - } - cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); - processor_transform_apply_threaded(byte_buffer, float_buffer, - width, height, channels, - cm_processor, false, true); - IMB_colormanagement_processor_free(cm_processor); -} - -void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace) -{ - ColormanageProcessor *cm_processor; - - if (from_colorspace[0] == '\0') { - return; - } - - if (STREQ(from_colorspace, to_colorspace)) { - /* if source and destination color spaces are identical, skip - * threading overhead and simply do nothing - */ - return; - } - - cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); - - IMB_colormanagement_processor_apply_v4(cm_processor, pixel); - - IMB_colormanagement_processor_free(cm_processor); +void IMB_colormanagement_transform_from_byte(float *float_buffer, + unsigned char *byte_buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace) +{ + IMB_buffer_float_from_byte(float_buffer, + byte_buffer, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + true, + width, + height, + width, + width); + IMB_colormanagement_transform( + float_buffer, width, height, channels, from_colorspace, to_colorspace, true); +} +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, + unsigned char *byte_buffer, + int width, + int height, + int channels, + const char *from_colorspace, + const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + if (from_colorspace == NULL || from_colorspace[0] == '\0') { + return; + } + if (STREQ(from_colorspace, to_colorspace)) { + /* Because this function always takes a byte buffer and returns a float buffer, it must + * always do byte-to-float conversion of some kind. To avoid threading overhead + * IMB_buffer_float_from_byte is used when color spaces are identical. See T51002. + */ + IMB_buffer_float_from_byte(float_buffer, + byte_buffer, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + width, + height, + width, + width); + IMB_premultiply_rect_float(float_buffer, 4, width, height); + return; + } + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + processor_transform_apply_threaded( + byte_buffer, float_buffer, width, height, channels, cm_processor, false, true); + IMB_colormanagement_processor_free(cm_processor); +} + +void IMB_colormanagement_transform_v4(float pixel[4], + const char *from_colorspace, + const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + + if (from_colorspace[0] == '\0') { + return; + } + + if (STREQ(from_colorspace, to_colorspace)) { + /* if source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + + IMB_colormanagement_processor_free(cm_processor); } /* convert pixel from specified by descriptor color space to scene linear @@ -1842,84 +1976,94 @@ void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspac */ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace) { - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; - if (!colorspace) { - /* should never happen */ - printf("%s: perform conversion from unknown color space\n", __func__); - return; - } + if (!colorspace) { + /* should never happen */ + printf("%s: perform conversion from unknown color space\n", __func__); + return; + } - processor = colorspace_to_scene_linear_processor(colorspace); + processor = colorspace_to_scene_linear_processor(colorspace); - if (processor) - OCIO_processorApplyRGB(processor, pixel); + if (processor) + OCIO_processorApplyRGB(processor, pixel); } /* same as above, but converts colors in opposite direction */ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace) { - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; - if (!colorspace) { - /* should never happen */ - printf("%s: perform conversion from unknown color space\n", __func__); - return; - } + if (!colorspace) { + /* should never happen */ + printf("%s: perform conversion from unknown color space\n", __func__); + return; + } - processor = colorspace_from_scene_linear_processor(colorspace); + processor = colorspace_from_scene_linear_processor(colorspace); - if (processor) - OCIO_processorApplyRGB(processor, pixel); + if (processor) + OCIO_processorApplyRGB(processor, pixel); } -void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], bool predivide, ColorSpace *colorspace) +void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], + bool predivide, + ColorSpace *colorspace) { - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; - if (!colorspace) { - /* should never happen */ - printf("%s: perform conversion from unknown color space\n", __func__); - return; - } + if (!colorspace) { + /* should never happen */ + printf("%s: perform conversion from unknown color space\n", __func__); + return; + } - processor = colorspace_to_scene_linear_processor(colorspace); + processor = colorspace_to_scene_linear_processor(colorspace); - if (processor) { - if (predivide) - OCIO_processorApplyRGBA_predivide(processor, pixel); - else - OCIO_processorApplyRGBA(processor, pixel); - } + if (processor) { + if (predivide) + OCIO_processorApplyRGBA_predivide(processor, pixel); + else + OCIO_processorApplyRGBA(processor, pixel); + } } -void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide) +void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, + int width, + int height, + int channels, + struct ColorSpace *colorspace, + bool predivide) { - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; - if (!colorspace) { - /* should never happen */ - printf("%s: perform conversion from unknown color space\n", __func__); - return; - } + if (!colorspace) { + /* should never happen */ + printf("%s: perform conversion from unknown color space\n", __func__); + return; + } - processor = colorspace_to_scene_linear_processor(colorspace); + processor = colorspace_to_scene_linear_processor(colorspace); - if (processor) { - OCIO_PackedImageDesc *img; + if (processor) { + OCIO_PackedImageDesc *img; - img = OCIO_createOCIO_PackedImageDesc( - buffer, width, height, channels, sizeof(float), - (size_t)channels * sizeof(float), - (size_t)channels * sizeof(float) * width); + img = OCIO_createOCIO_PackedImageDesc(buffer, + width, + height, + channels, + sizeof(float), + (size_t)channels * sizeof(float), + (size_t)channels * sizeof(float) * width); - if (predivide) - OCIO_processorApply_predivide(processor, img); - else - OCIO_processorApply(processor, img); + if (predivide) + OCIO_processorApply_predivide(processor, img); + else + OCIO_processorApply(processor, img); - OCIO_PackedImageDescRelease(img); - } + OCIO_PackedImageDescRelease(img); + } } /* Conversion between color picking role. Typically we would expect such a @@ -1932,66 +2076,64 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in */ void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]) { - if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { - /* Create processor if none exists. */ - BLI_mutex_lock(&processor_lock); + if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { + /* Create processor if none exists. */ + BLI_mutex_lock(&processor_lock); - if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { - global_color_picking_state.processor_to = - create_colorspace_transform_processor(global_role_scene_linear, - global_role_color_picking); + if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { + global_color_picking_state.processor_to = create_colorspace_transform_processor( + global_role_scene_linear, global_role_color_picking); - if (!global_color_picking_state.processor_to) { - global_color_picking_state.failed = true; - } - } + if (!global_color_picking_state.processor_to) { + global_color_picking_state.failed = true; + } + } - BLI_mutex_unlock(&processor_lock); - } + BLI_mutex_unlock(&processor_lock); + } - if (global_color_picking_state.processor_to) { - OCIO_processorApplyRGB(global_color_picking_state.processor_to, pixel); - } + if (global_color_picking_state.processor_to) { + OCIO_processorApplyRGB(global_color_picking_state.processor_to, pixel); + } } void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) { - if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { - /* Create processor if none exists. */ - BLI_mutex_lock(&processor_lock); + if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { + /* Create processor if none exists. */ + BLI_mutex_lock(&processor_lock); - if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { - global_color_picking_state.processor_from = - create_colorspace_transform_processor(global_role_color_picking, - global_role_scene_linear); + if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { + global_color_picking_state.processor_from = create_colorspace_transform_processor( + global_role_color_picking, global_role_scene_linear); - if (!global_color_picking_state.processor_from) { - global_color_picking_state.failed = true; - } - } + if (!global_color_picking_state.processor_from) { + global_color_picking_state.failed = true; + } + } - BLI_mutex_unlock(&processor_lock); - } + BLI_mutex_unlock(&processor_lock); + } - if (global_color_picking_state.processor_from) { - OCIO_processorApplyRGB(global_color_picking_state.processor_from, pixel); - } + if (global_color_picking_state.processor_from) { + OCIO_processorApplyRGB(global_color_picking_state.processor_from, pixel); + } } /* Conversion between sRGB, for rare cases like hex color or copy/pasting * between UI theme and scene linear colors. */ void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3]) { - mul_m3_v3(imbuf_rgb_to_xyz, pixel); - mul_m3_v3(imbuf_xyz_to_linear_srgb, pixel); - linearrgb_to_srgb_v3_v3(pixel, pixel); + mul_m3_v3(imbuf_rgb_to_xyz, pixel); + mul_m3_v3(imbuf_xyz_to_linear_srgb, pixel); + linearrgb_to_srgb_v3_v3(pixel, pixel); } void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]) { - srgb_to_linearrgb_v3_v3(pixel, pixel); - mul_m3_v3(imbuf_linear_srgb_to_xyz, pixel); - mul_m3_v3(imbuf_xyz_to_rgb, pixel); + srgb_to_linearrgb_v3_v3(pixel, pixel); + mul_m3_v3(imbuf_linear_srgb_to_xyz, pixel); + mul_m3_v3(imbuf_xyz_to_rgb, pixel); } /* convert pixel from scene linear to display space using default view @@ -2000,65 +2142,74 @@ void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]) */ void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display) { - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; - processor = display_from_scene_linear_processor(display); + processor = display_from_scene_linear_processor(display); - if (processor) - OCIO_processorApplyRGB(processor, pixel); + if (processor) + OCIO_processorApplyRGB(processor, pixel); } /* same as above, but converts color in opposite direction */ void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display) { - OCIO_ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; - processor = display_to_scene_linear_processor(display); + processor = display_to_scene_linear_processor(display); - if (processor) - OCIO_processorApplyRGB(processor, pixel); + if (processor) + OCIO_processorApplyRGB(processor, pixel); } -void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4], - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +void IMB_colormanagement_pixel_to_display_space_v4( + float result[4], + const float pixel[4], + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - ColormanageProcessor *cm_processor; + ColormanageProcessor *cm_processor; - copy_v4_v4(result, pixel); + copy_v4_v4(result, pixel); - cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - IMB_colormanagement_processor_apply_v4(cm_processor, result); - IMB_colormanagement_processor_free(cm_processor); + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + IMB_colormanagement_processor_apply_v4(cm_processor, result); + IMB_colormanagement_processor_free(cm_processor); } -void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +void IMB_colormanagement_pixel_to_display_space_v3( + float result[3], + const float pixel[3], + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - ColormanageProcessor *cm_processor; + ColormanageProcessor *cm_processor; - copy_v3_v3(result, pixel); + copy_v3_v3(result, pixel); - cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - IMB_colormanagement_processor_apply_v3(cm_processor, result); - IMB_colormanagement_processor_free(cm_processor); + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + IMB_colormanagement_processor_apply_v3(cm_processor, result); + IMB_colormanagement_processor_free(cm_processor); } -static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, bool make_byte) +static void colormanagement_imbuf_make_display_space( + ImBuf *ibuf, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + bool make_byte) { - if (!ibuf->rect && make_byte) - imb_addrectImBuf(ibuf); + if (!ibuf->rect && make_byte) + imb_addrectImBuf(ibuf); - colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect, - view_settings, display_settings); + colormanage_display_buffer_process_ex( + ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect, view_settings, display_settings); } -void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +void IMB_colormanagement_imbuf_make_display_space( + ImBuf *ibuf, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, false); + colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, false); } /* prepare image buffer to be saved on disk, applying color management if needed @@ -2072,809 +2223,861 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage * in image format write callback and if float_colorspace is not NULL, no color * space transformation should be applied on this buffer. */ -ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, bool allocate_result, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, ImageFormatData *image_format_data) -{ - ImBuf *colormanaged_ibuf = ibuf; - bool do_colormanagement; - bool is_movie = BKE_imtype_is_movie(image_format_data->imtype); - bool requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype); - bool do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA; - - if (ibuf->rect_float && ibuf->rect && - (ibuf->userflags & (IB_DISPLAY_BUFFER_INVALID | IB_RECT_INVALID)) != 0) - { - IMB_rect_from_float(ibuf); - ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID); - } - - do_colormanagement = save_as_render && (is_movie || !requires_linear_float); - - if (do_colormanagement || do_alpha_under) { - if (allocate_result) { - colormanaged_ibuf = IMB_dupImBuf(ibuf); - } - else { - /* render pipeline is constructing image buffer itself, but it's re-using byte and float buffers from render result - * make copy of this buffers here sine this buffers would be transformed to other color space here - */ - - if (ibuf->rect && (ibuf->mall & IB_rect) == 0) { - ibuf->rect = MEM_dupallocN(ibuf->rect); - ibuf->mall |= IB_rect; - } - - if (ibuf->rect_float && (ibuf->mall & IB_rectfloat) == 0) { - ibuf->rect_float = MEM_dupallocN(ibuf->rect_float); - ibuf->mall |= IB_rectfloat; - } - } - } - - /* If we're saving from RGBA to RGB buffer then it's not - * so much useful to just ignore alpha -- it leads to bad - * artifacts especially when saving byte images. - * - * What we do here is we're overlaying our image on top of - * background color (which is currently black). - * - * This is quite much the same as what Gimp does and it - * seems to be what artists expects from saving. - * - * Do a conversion here, so image format writers could - * happily assume all the alpha tricks were made already. - * helps keep things locally here, not spreading it to - * all possible image writers we've got. - */ - if (do_alpha_under) { - float color[3] = {0, 0, 0}; - - if (colormanaged_ibuf->rect_float && colormanaged_ibuf->channels == 4) { - IMB_alpha_under_color_float(colormanaged_ibuf->rect_float, colormanaged_ibuf->x, - colormanaged_ibuf->y, color); - } - - if (colormanaged_ibuf->rect) { - IMB_alpha_under_color_byte((unsigned char *)colormanaged_ibuf->rect, - colormanaged_ibuf->x, colormanaged_ibuf->y, - color); - } - } - - if (do_colormanagement) { - bool make_byte = false; - const ImFileType *type; - - /* for proper check whether byte buffer is required by a format or not - * should be pretty safe since this image buffer is supposed to be used for - * saving only and ftype would be overwritten a bit later by BKE_imbuf_write - */ - colormanaged_ibuf->ftype = BKE_image_imtype_to_ftype(image_format_data->imtype, &colormanaged_ibuf->foptions); - - /* if file format isn't able to handle float buffer itself, - * we need to allocate byte buffer and store color managed - * image there - */ - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->save && type->ftype(type, colormanaged_ibuf)) { - if ((type->flag & IM_FTYPE_FLOAT) == 0) - make_byte = true; - - break; - } - } - - /* perform color space conversions */ - colormanagement_imbuf_make_display_space(colormanaged_ibuf, view_settings, display_settings, make_byte); - - if (colormanaged_ibuf->rect_float) { - /* float buffer isn't linear anymore, - * image format write callback should check for this flag and assume - * no space conversion should happen if ibuf->float_colorspace != NULL - */ - colormanaged_ibuf->float_colorspace = display_transform_get_colorspace(view_settings, display_settings); - } - } - - if (colormanaged_ibuf != ibuf) { - IMB_metadata_copy(colormanaged_ibuf, ibuf); - } - - return colormanaged_ibuf; -} - -void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char *display_buffer, - int width, int height, int channels, float dither, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - ColormanageProcessor *cm_processor; - size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float); - float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space"); - - /* TODO(sergey): Convert float directly to byte buffer. */ - - memcpy(display_buffer_float, buffer, float_buffer_size); - - cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - - processor_transform_apply_threaded(NULL, display_buffer_float, width, height, channels, - cm_processor, true, false); - - IMB_buffer_byte_from_float(display_buffer, display_buffer_float, - channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - true, width, height, width, width); - - MEM_freeN(display_buffer_float); - IMB_colormanagement_processor_free(cm_processor); +ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, + bool save_as_render, + bool allocate_result, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + ImageFormatData *image_format_data) +{ + ImBuf *colormanaged_ibuf = ibuf; + bool do_colormanagement; + bool is_movie = BKE_imtype_is_movie(image_format_data->imtype); + bool requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype); + bool do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA; + + if (ibuf->rect_float && ibuf->rect && + (ibuf->userflags & (IB_DISPLAY_BUFFER_INVALID | IB_RECT_INVALID)) != 0) { + IMB_rect_from_float(ibuf); + ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID); + } + + do_colormanagement = save_as_render && (is_movie || !requires_linear_float); + + if (do_colormanagement || do_alpha_under) { + if (allocate_result) { + colormanaged_ibuf = IMB_dupImBuf(ibuf); + } + else { + /* render pipeline is constructing image buffer itself, but it's re-using byte and float buffers from render result + * make copy of this buffers here sine this buffers would be transformed to other color space here + */ + + if (ibuf->rect && (ibuf->mall & IB_rect) == 0) { + ibuf->rect = MEM_dupallocN(ibuf->rect); + ibuf->mall |= IB_rect; + } + + if (ibuf->rect_float && (ibuf->mall & IB_rectfloat) == 0) { + ibuf->rect_float = MEM_dupallocN(ibuf->rect_float); + ibuf->mall |= IB_rectfloat; + } + } + } + + /* If we're saving from RGBA to RGB buffer then it's not + * so much useful to just ignore alpha -- it leads to bad + * artifacts especially when saving byte images. + * + * What we do here is we're overlaying our image on top of + * background color (which is currently black). + * + * This is quite much the same as what Gimp does and it + * seems to be what artists expects from saving. + * + * Do a conversion here, so image format writers could + * happily assume all the alpha tricks were made already. + * helps keep things locally here, not spreading it to + * all possible image writers we've got. + */ + if (do_alpha_under) { + float color[3] = {0, 0, 0}; + + if (colormanaged_ibuf->rect_float && colormanaged_ibuf->channels == 4) { + IMB_alpha_under_color_float( + colormanaged_ibuf->rect_float, colormanaged_ibuf->x, colormanaged_ibuf->y, color); + } + + if (colormanaged_ibuf->rect) { + IMB_alpha_under_color_byte((unsigned char *)colormanaged_ibuf->rect, + colormanaged_ibuf->x, + colormanaged_ibuf->y, + color); + } + } + + if (do_colormanagement) { + bool make_byte = false; + const ImFileType *type; + + /* for proper check whether byte buffer is required by a format or not + * should be pretty safe since this image buffer is supposed to be used for + * saving only and ftype would be overwritten a bit later by BKE_imbuf_write + */ + colormanaged_ibuf->ftype = BKE_image_imtype_to_ftype(image_format_data->imtype, + &colormanaged_ibuf->foptions); + + /* if file format isn't able to handle float buffer itself, + * we need to allocate byte buffer and store color managed + * image there + */ + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->save && type->ftype(type, colormanaged_ibuf)) { + if ((type->flag & IM_FTYPE_FLOAT) == 0) + make_byte = true; + + break; + } + } + + /* perform color space conversions */ + colormanagement_imbuf_make_display_space( + colormanaged_ibuf, view_settings, display_settings, make_byte); + + if (colormanaged_ibuf->rect_float) { + /* float buffer isn't linear anymore, + * image format write callback should check for this flag and assume + * no space conversion should happen if ibuf->float_colorspace != NULL + */ + colormanaged_ibuf->float_colorspace = display_transform_get_colorspace(view_settings, + display_settings); + } + } + + if (colormanaged_ibuf != ibuf) { + IMB_metadata_copy(colormanaged_ibuf, ibuf); + } + + return colormanaged_ibuf; +} + +void IMB_colormanagement_buffer_make_display_space( + float *buffer, + unsigned char *display_buffer, + int width, + int height, + int channels, + float dither, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + ColormanageProcessor *cm_processor; + size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float); + float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space"); + + /* TODO(sergey): Convert float directly to byte buffer. */ + + memcpy(display_buffer_float, buffer, float_buffer_size); + + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + + processor_transform_apply_threaded( + NULL, display_buffer_float, width, height, channels, cm_processor, true, false); + + IMB_buffer_byte_from_float(display_buffer, + display_buffer_float, + channels, + dither, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + true, + width, + height, + width, + width); + + MEM_freeN(display_buffer_float); + IMB_colormanagement_processor_free(cm_processor); } /*********************** Public display buffers interfaces *************************/ /* acquire display buffer for given image buffer using specified view and display settings */ -unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, void **cache_handle) -{ - unsigned char *display_buffer; - size_t buffer_size; - ColormanageCacheViewSettings cache_view_settings; - ColormanageCacheDisplaySettings cache_display_settings; - ColorManagedViewSettings default_view_settings; - const ColorManagedViewSettings *applied_view_settings; - - *cache_handle = NULL; - - if (!ibuf->x || !ibuf->y) - return NULL; - - if (view_settings) { - applied_view_settings = view_settings; - } - else { - /* If no view settings were specified, use default ones, which will - * attempt not to do any extra color correction. */ - IMB_colormanagement_init_default_view_settings( - &default_view_settings, display_settings); - applied_view_settings = &default_view_settings; - } - - /* early out: no float buffer and byte buffer is already in display space, - * let's just use if - */ - if (ibuf->rect_float == NULL && ibuf->rect_colorspace && ibuf->channels == 4) { - if (is_ibuf_rect_in_display_space(ibuf, applied_view_settings, display_settings)) - return (unsigned char *) ibuf->rect; - } - - colormanage_view_settings_to_cache(ibuf, &cache_view_settings, applied_view_settings); - colormanage_display_settings_to_cache(&cache_display_settings, display_settings); - - if (ibuf->invalid_rect.xmin != ibuf->invalid_rect.xmax) { - if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) { - IMB_partial_display_buffer_update_threaded(ibuf, - ibuf->rect_float, - (unsigned char *) ibuf->rect, - ibuf->x, - 0, 0, - applied_view_settings, - display_settings, - ibuf->invalid_rect.xmin, - ibuf->invalid_rect.ymin, - ibuf->invalid_rect.xmax, - ibuf->invalid_rect.ymax, - false); - } - - BLI_rcti_init(&ibuf->invalid_rect, 0, 0, 0, 0); - } - - BLI_thread_lock(LOCK_COLORMANAGE); - - /* ensure color management bit fields exists */ - if (!ibuf->display_buffer_flags) { - ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags"); - } - 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 - */ - memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); - - ibuf->userflags &= ~IB_DISPLAY_BUFFER_INVALID; - } - - display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle); - - if (display_buffer) { - BLI_thread_unlock(LOCK_COLORMANAGE); - return display_buffer; - } - - buffer_size = DISPLAY_BUFFER_CHANNELS * ((size_t)ibuf->x) * ibuf->y * sizeof(char); - display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); - - colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings); - - colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle); - - BLI_thread_unlock(LOCK_COLORMANAGE); - - return display_buffer; +unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + void **cache_handle) +{ + unsigned char *display_buffer; + size_t buffer_size; + ColormanageCacheViewSettings cache_view_settings; + ColormanageCacheDisplaySettings cache_display_settings; + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; + + *cache_handle = NULL; + + if (!ibuf->x || !ibuf->y) + return NULL; + + if (view_settings) { + applied_view_settings = view_settings; + } + else { + /* If no view settings were specified, use default ones, which will + * attempt not to do any extra color correction. */ + IMB_colormanagement_init_default_view_settings(&default_view_settings, display_settings); + applied_view_settings = &default_view_settings; + } + + /* early out: no float buffer and byte buffer is already in display space, + * let's just use if + */ + if (ibuf->rect_float == NULL && ibuf->rect_colorspace && ibuf->channels == 4) { + if (is_ibuf_rect_in_display_space(ibuf, applied_view_settings, display_settings)) + return (unsigned char *)ibuf->rect; + } + + colormanage_view_settings_to_cache(ibuf, &cache_view_settings, applied_view_settings); + colormanage_display_settings_to_cache(&cache_display_settings, display_settings); + + if (ibuf->invalid_rect.xmin != ibuf->invalid_rect.xmax) { + if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) { + IMB_partial_display_buffer_update_threaded(ibuf, + ibuf->rect_float, + (unsigned char *)ibuf->rect, + ibuf->x, + 0, + 0, + applied_view_settings, + display_settings, + ibuf->invalid_rect.xmin, + ibuf->invalid_rect.ymin, + ibuf->invalid_rect.xmax, + ibuf->invalid_rect.ymax, + false); + } + + BLI_rcti_init(&ibuf->invalid_rect, 0, 0, 0, 0); + } + + BLI_thread_lock(LOCK_COLORMANAGE); + + /* ensure color management bit fields exists */ + if (!ibuf->display_buffer_flags) { + ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, + "imbuf display_buffer_flags"); + } + 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 + */ + memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); + + ibuf->userflags &= ~IB_DISPLAY_BUFFER_INVALID; + } + + display_buffer = colormanage_cache_get( + ibuf, &cache_view_settings, &cache_display_settings, cache_handle); + + if (display_buffer) { + BLI_thread_unlock(LOCK_COLORMANAGE); + return display_buffer; + } + + buffer_size = DISPLAY_BUFFER_CHANNELS * ((size_t)ibuf->x) * ibuf->y * sizeof(char); + display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); + + colormanage_display_buffer_process( + ibuf, display_buffer, applied_view_settings, display_settings); + + colormanage_cache_put( + ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle); + + BLI_thread_unlock(LOCK_COLORMANAGE); + + return display_buffer; } /* same as IMB_display_buffer_acquire but gets view and display settings from context */ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, void **cache_handle) { - ColorManagedViewSettings *view_settings; - ColorManagedDisplaySettings *display_settings; + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; - IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); + IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); - return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); + return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); } -void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, - int channels, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, bool predivide) +void IMB_display_buffer_transform_apply(unsigned char *display_buffer, + float *linear_buffer, + int width, + int height, + int channels, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + bool predivide) { - float *buffer; - ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + float *buffer; + ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, + display_settings); - buffer = MEM_mallocN((size_t)channels * width * height * sizeof(float), "display transform temp buffer"); - memcpy(buffer, linear_buffer, (size_t)channels * width * height * sizeof(float)); + buffer = MEM_mallocN((size_t)channels * width * height * sizeof(float), + "display transform temp buffer"); + memcpy(buffer, linear_buffer, (size_t)channels * width * height * sizeof(float)); - IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); - IMB_colormanagement_processor_free(cm_processor); + IMB_colormanagement_processor_free(cm_processor); - IMB_buffer_byte_from_float(display_buffer, buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, width, height, width, width); + IMB_buffer_byte_from_float(display_buffer, + buffer, + channels, + 0.0f, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + width, + height, + width, + width); - MEM_freeN(buffer); + MEM_freeN(buffer); } void IMB_display_buffer_release(void *cache_handle) { - if (cache_handle) { - BLI_thread_lock(LOCK_COLORMANAGE); + if (cache_handle) { + BLI_thread_lock(LOCK_COLORMANAGE); - colormanage_cache_handle_release(cache_handle); + colormanage_cache_handle_release(cache_handle); - BLI_thread_unlock(LOCK_COLORMANAGE); - } + BLI_thread_unlock(LOCK_COLORMANAGE); + } } /*********************** Display functions *************************/ const char *colormanage_display_get_default_name(void) { - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - const char *display_name; + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + const char *display_name; - display_name = OCIO_configGetDefaultDisplay(config); + display_name = OCIO_configGetDefaultDisplay(config); - OCIO_configRelease(config); + OCIO_configRelease(config); - return display_name; + return display_name; } ColorManagedDisplay *colormanage_display_get_default(void) { - const char *display_name = colormanage_display_get_default_name(); + const char *display_name = colormanage_display_get_default_name(); - if (display_name[0] == '\0') - return NULL; + if (display_name[0] == '\0') + return NULL; - return colormanage_display_get_named(display_name); + return colormanage_display_get_named(display_name); } ColorManagedDisplay *colormanage_display_add(const char *name) { - ColorManagedDisplay *display; - int index = 0; + ColorManagedDisplay *display; + int index = 0; - if (global_displays.last) { - ColorManagedDisplay *last_display = global_displays.last; + if (global_displays.last) { + ColorManagedDisplay *last_display = global_displays.last; - index = last_display->index; - } + index = last_display->index; + } - display = MEM_callocN(sizeof(ColorManagedDisplay), "ColorManagedDisplay"); + display = MEM_callocN(sizeof(ColorManagedDisplay), "ColorManagedDisplay"); - display->index = index + 1; + display->index = index + 1; - BLI_strncpy(display->name, name, sizeof(display->name)); + BLI_strncpy(display->name, name, sizeof(display->name)); - BLI_addtail(&global_displays, display); + BLI_addtail(&global_displays, display); - return display; + return display; } ColorManagedDisplay *colormanage_display_get_named(const char *name) { - ColorManagedDisplay *display; + ColorManagedDisplay *display; - for (display = global_displays.first; display; display = display->next) { - if (STREQ(display->name, name)) - return display; - } + for (display = global_displays.first; display; display = display->next) { + if (STREQ(display->name, name)) + return display; + } - return NULL; + return NULL; } ColorManagedDisplay *colormanage_display_get_indexed(int index) { - /* display indices are 1-based */ - return BLI_findlink(&global_displays, index - 1); + /* display indices are 1-based */ + return BLI_findlink(&global_displays, index - 1); } int IMB_colormanagement_display_get_named_index(const char *name) { - ColorManagedDisplay *display; + ColorManagedDisplay *display; - display = colormanage_display_get_named(name); + display = colormanage_display_get_named(name); - if (display) { - return display->index; - } + if (display) { + return display->index; + } - return 0; + return 0; } const char *IMB_colormanagement_display_get_indexed_name(int index) { - ColorManagedDisplay *display; + ColorManagedDisplay *display; - display = colormanage_display_get_indexed(index); + display = colormanage_display_get_indexed(index); - if (display) { - return display->name; - } + if (display) { + return display->name; + } - return NULL; + return NULL; } const char *IMB_colormanagement_display_get_default_name(void) { - ColorManagedDisplay *display = colormanage_display_get_default(); + ColorManagedDisplay *display = colormanage_display_get_default(); - return display->name; + return display->name; } /* used by performance-critical pixel processing areas, such as color widgets */ ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name) { - return colormanage_display_get_named(name); + return colormanage_display_get_named(name); } const char *IMB_colormanagement_display_get_none_name(void) { - if (colormanage_display_get_named("None") != NULL) - return "None"; + if (colormanage_display_get_named("None") != NULL) + return "None"; - return colormanage_display_get_default_name(); + return colormanage_display_get_default_name(); } const char *IMB_colormanagement_display_get_default_view_transform_name( - struct ColorManagedDisplay *display) + struct ColorManagedDisplay *display) { - return colormanage_view_get_default_name(display); + return colormanage_view_get_default_name(display); } /*********************** View functions *************************/ const char *colormanage_view_get_default_name(const ColorManagedDisplay *display) { - OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - const char *name; + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + const char *name; - name = OCIO_configGetDefaultView(config, display->name); + name = OCIO_configGetDefaultView(config, display->name); - OCIO_configRelease(config); + OCIO_configRelease(config); - return name; + return name; } ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display) { - const char *name = colormanage_view_get_default_name(display); + const char *name = colormanage_view_get_default_name(display); - if (!name || name[0] == '\0') - return NULL; + if (!name || name[0] == '\0') + return NULL; - return colormanage_view_get_named(name); + return colormanage_view_get_named(name); } ColorManagedView *colormanage_view_add(const char *name) { - ColorManagedView *view; - int index = global_tot_view; + ColorManagedView *view; + int index = global_tot_view; - view = MEM_callocN(sizeof(ColorManagedView), "ColorManagedView"); - view->index = index + 1; - BLI_strncpy(view->name, name, sizeof(view->name)); + view = MEM_callocN(sizeof(ColorManagedView), "ColorManagedView"); + view->index = index + 1; + BLI_strncpy(view->name, name, sizeof(view->name)); - BLI_addtail(&global_views, view); + BLI_addtail(&global_views, view); - global_tot_view++; + global_tot_view++; - return view; + return view; } ColorManagedView *colormanage_view_get_named(const char *name) { - ColorManagedView *view; + ColorManagedView *view; - for (view = global_views.first; view; view = view->next) { - if (STREQ(view->name, name)) - return view; - } + for (view = global_views.first; view; view = view->next) { + if (STREQ(view->name, name)) + return view; + } - return NULL; + return NULL; } ColorManagedView *colormanage_view_get_indexed(int index) { - /* view transform indices are 1-based */ - return BLI_findlink(&global_views, index - 1); + /* view transform indices are 1-based */ + return BLI_findlink(&global_views, index - 1); } -ColorManagedView *colormanage_view_get_named_for_display( - const char *display_name, const char *name) +ColorManagedView *colormanage_view_get_named_for_display(const char *display_name, + const char *name) { - ColorManagedDisplay *display = colormanage_display_get_named(display_name); - if (display == NULL) { - return NULL; - } - LISTBASE_FOREACH(LinkData *, view_link, &display->views) { - ColorManagedView *view = view_link->data; - if (STRCASEEQ(name, view->name)) { - return view; - } - } - return NULL; + ColorManagedDisplay *display = colormanage_display_get_named(display_name); + if (display == NULL) { + return NULL; + } + LISTBASE_FOREACH (LinkData *, view_link, &display->views) { + ColorManagedView *view = view_link->data; + if (STRCASEEQ(name, view->name)) { + return view; + } + } + return NULL; } int IMB_colormanagement_view_get_named_index(const char *name) { - ColorManagedView *view = colormanage_view_get_named(name); + ColorManagedView *view = colormanage_view_get_named(name); - if (view) { - return view->index; - } + if (view) { + return view->index; + } - return 0; + return 0; } const char *IMB_colormanagement_view_get_indexed_name(int index) { - ColorManagedView *view = colormanage_view_get_indexed(index); + ColorManagedView *view = colormanage_view_get_indexed(index); - if (view) { - return view->name; - } + if (view) { + return view->name; + } - return NULL; + return NULL; } const char *IMB_colormanagement_view_get_default_name(const char *display_name) { - ColorManagedDisplay *display = colormanage_display_get_named(display_name); - ColorManagedView *view = NULL; + ColorManagedDisplay *display = colormanage_display_get_named(display_name); + ColorManagedView *view = NULL; - if (display) - view = colormanage_view_get_default(display); + if (display) + view = colormanage_view_get_default(display); - if (view) - return view->name; + if (view) + return view->name; - return NULL; + return NULL; } /*********************** Color space functions *************************/ static void colormanage_description_strip(char *description) { - int i, n; + int i, n; - for (i = (int)strlen(description) - 1; i >= 0; i--) { - if (ELEM(description[i], '\r', '\n')) { - description[i] = '\0'; - } - else { - break; - } - } + for (i = (int)strlen(description) - 1; i >= 0; i--) { + if (ELEM(description[i], '\r', '\n')) { + description[i] = '\0'; + } + else { + break; + } + } - for (i = 0, n = strlen(description); i < n; i++) { - if (ELEM(description[i], '\r', '\n')) { - description[i] = ' '; - } - } + for (i = 0, n = strlen(description); i < n; i++) { + if (ELEM(description[i], '\r', '\n')) { + description[i] = ' '; + } + } } -ColorSpace *colormanage_colorspace_add(const char *name, const char *description, bool is_invertible, bool is_data) +ColorSpace *colormanage_colorspace_add(const char *name, + const char *description, + bool is_invertible, + bool is_data) { - ColorSpace *colorspace, *prev_space; - int counter = 1; + ColorSpace *colorspace, *prev_space; + int counter = 1; - colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace"); + colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace"); - BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); + BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); - if (description) { - BLI_strncpy(colorspace->description, description, sizeof(colorspace->description)); + if (description) { + BLI_strncpy(colorspace->description, description, sizeof(colorspace->description)); - colormanage_description_strip(colorspace->description); - } + colormanage_description_strip(colorspace->description); + } - colorspace->is_invertible = is_invertible; - colorspace->is_data = is_data; + colorspace->is_invertible = is_invertible; + colorspace->is_data = is_data; - for (prev_space = global_colorspaces.first; prev_space; prev_space = prev_space->next) { - if (BLI_strcasecmp(prev_space->name, colorspace->name) > 0) - break; + for (prev_space = global_colorspaces.first; prev_space; prev_space = prev_space->next) { + if (BLI_strcasecmp(prev_space->name, colorspace->name) > 0) + break; - prev_space->index = counter++; - } + prev_space->index = counter++; + } - if (!prev_space) - BLI_addtail(&global_colorspaces, colorspace); - else - BLI_insertlinkbefore(&global_colorspaces, prev_space, colorspace); + if (!prev_space) + BLI_addtail(&global_colorspaces, colorspace); + else + BLI_insertlinkbefore(&global_colorspaces, prev_space, colorspace); - colorspace->index = counter++; - for (; prev_space; prev_space = prev_space->next) { - prev_space->index = counter++; - } + colorspace->index = counter++; + for (; prev_space; prev_space = prev_space->next) { + prev_space->index = counter++; + } - global_tot_colorspace++; + global_tot_colorspace++; - return colorspace; + return colorspace; } ColorSpace *colormanage_colorspace_get_named(const char *name) { - ColorSpace *colorspace; + ColorSpace *colorspace; - for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { - if (STREQ(colorspace->name, name)) - return colorspace; - } + for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { + if (STREQ(colorspace->name, name)) + return colorspace; + } - return NULL; + return NULL; } ColorSpace *colormanage_colorspace_get_roled(int role) { - const char *role_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + const char *role_colorspace = IMB_colormanagement_role_colorspace_name_get(role); - return colormanage_colorspace_get_named(role_colorspace); + return colormanage_colorspace_get_named(role_colorspace); } ColorSpace *colormanage_colorspace_get_indexed(int index) { - /* color space indices are 1-based */ - return BLI_findlink(&global_colorspaces, index - 1); + /* color space indices are 1-based */ + return BLI_findlink(&global_colorspaces, index - 1); } int IMB_colormanagement_colorspace_get_named_index(const char *name) { - ColorSpace *colorspace; + ColorSpace *colorspace; - colorspace = colormanage_colorspace_get_named(name); + colorspace = colormanage_colorspace_get_named(name); - if (colorspace) { - return colorspace->index; - } + if (colorspace) { + return colorspace->index; + } - return 0; + return 0; } const char *IMB_colormanagement_colorspace_get_indexed_name(int index) { - ColorSpace *colorspace; + ColorSpace *colorspace; - colorspace = colormanage_colorspace_get_indexed(index); + colorspace = colormanage_colorspace_get_indexed(index); - if (colorspace) { - return colorspace->name; - } + if (colorspace) { + return colorspace->name; + } - return ""; + return ""; } -void IMB_colormanagement_colorspace_from_ibuf_ftype(ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf) +void IMB_colormanagement_colorspace_from_ibuf_ftype( + ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf) { - /* Don't modify non-color data space, it does not change with file type. */ - ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); + /* Don't modify non-color data space, it does not change with file type. */ + ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); - if (colorspace && colorspace->is_data) { - return; - } + if (colorspace && colorspace->is_data) { + return; + } - /* Get color space from file type. */ - const ImFileType *type; + /* Get color space from file type. */ + const ImFileType *type; - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->save && type->ftype(type, ibuf)) { - const char *role_colorspace; + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->save && type->ftype(type, ibuf)) { + const char *role_colorspace; - role_colorspace = IMB_colormanagement_role_colorspace_name_get(type->default_save_role); + role_colorspace = IMB_colormanagement_role_colorspace_name_get(type->default_save_role); - BLI_strncpy(colorspace_settings->name, role_colorspace, sizeof(colorspace_settings->name)); - } - } + BLI_strncpy(colorspace_settings->name, role_colorspace, sizeof(colorspace_settings->name)); + } + } } /*********************** Looks functions *************************/ ColorManagedLook *colormanage_look_add(const char *name, const char *process_space, bool is_noop) { - ColorManagedLook *look; - int index = global_tot_looks; + ColorManagedLook *look; + int index = global_tot_looks; - look = MEM_callocN(sizeof(ColorManagedLook), "ColorManagedLook"); - look->index = index + 1; - BLI_strncpy(look->name, name, sizeof(look->name)); - BLI_strncpy(look->ui_name, name, sizeof(look->ui_name)); - BLI_strncpy(look->process_space, process_space, sizeof(look->process_space)); - look->is_noop = is_noop; + look = MEM_callocN(sizeof(ColorManagedLook), "ColorManagedLook"); + look->index = index + 1; + BLI_strncpy(look->name, name, sizeof(look->name)); + BLI_strncpy(look->ui_name, name, sizeof(look->ui_name)); + BLI_strncpy(look->process_space, process_space, sizeof(look->process_space)); + look->is_noop = is_noop; - /* Detect view specific looks. */ - const char *separator_offset = strstr(look->name, " - "); - if (separator_offset) { - BLI_strncpy(look->view, look->name, separator_offset - look->name + 1); - BLI_strncpy(look->ui_name, separator_offset + strlen(" - "), sizeof(look->ui_name)); - } + /* Detect view specific looks. */ + const char *separator_offset = strstr(look->name, " - "); + if (separator_offset) { + BLI_strncpy(look->view, look->name, separator_offset - look->name + 1); + BLI_strncpy(look->ui_name, separator_offset + strlen(" - "), sizeof(look->ui_name)); + } - BLI_addtail(&global_looks, look); + BLI_addtail(&global_looks, look); - global_tot_looks++; + global_tot_looks++; - return look; + return look; } ColorManagedLook *colormanage_look_get_named(const char *name) { - ColorManagedLook *look; + ColorManagedLook *look; - for (look = global_looks.first; look; look = look->next) { - if (STREQ(look->name, name)) { - return look; - } - } + for (look = global_looks.first; look; look = look->next) { + if (STREQ(look->name, name)) { + return look; + } + } - return NULL; + return NULL; } ColorManagedLook *colormanage_look_get_indexed(int index) { - /* look indices are 1-based */ - return BLI_findlink(&global_looks, index - 1); + /* look indices are 1-based */ + return BLI_findlink(&global_looks, index - 1); } int IMB_colormanagement_look_get_named_index(const char *name) { - ColorManagedLook *look; + ColorManagedLook *look; - look = colormanage_look_get_named(name); + look = colormanage_look_get_named(name); - if (look) { - return look->index; - } + if (look) { + return look->index; + } - return 0; + return 0; } const char *IMB_colormanagement_look_get_indexed_name(int index) { - ColorManagedLook *look; + ColorManagedLook *look; - look = colormanage_look_get_indexed(index); + look = colormanage_look_get_indexed(index); - if (look) { - return look->name; - } + if (look) { + return look->name; + } - return NULL; + return NULL; } /*********************** RNA helper functions *************************/ void IMB_colormanagement_display_items_add(EnumPropertyItem **items, int *totitem) { - ColorManagedDisplay *display; + ColorManagedDisplay *display; - for (display = global_displays.first; display; display = display->next) { - EnumPropertyItem item; + for (display = global_displays.first; display; display = display->next) { + EnumPropertyItem item; - item.value = display->index; - item.name = display->name; - item.identifier = display->name; - item.icon = 0; - item.description = ""; + item.value = display->index; + item.name = display->name; + item.identifier = display->name; + item.icon = 0; + item.description = ""; - RNA_enum_item_add(items, totitem, &item); - } + RNA_enum_item_add(items, totitem, &item); + } } -static void colormanagement_view_item_add(EnumPropertyItem **items, int *totitem, ColorManagedView *view) +static void colormanagement_view_item_add(EnumPropertyItem **items, + int *totitem, + ColorManagedView *view) { - EnumPropertyItem item; + EnumPropertyItem item; - item.value = view->index; - item.name = view->name; - item.identifier = view->name; - item.icon = 0; - item.description = ""; + item.value = view->index; + item.name = view->name; + item.identifier = view->name; + item.icon = 0; + item.description = ""; - RNA_enum_item_add(items, totitem, &item); + RNA_enum_item_add(items, totitem, &item); } -void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, const char *display_name) +void IMB_colormanagement_view_items_add(EnumPropertyItem **items, + int *totitem, + const char *display_name) { - ColorManagedDisplay *display = colormanage_display_get_named(display_name); - ColorManagedView *view; + ColorManagedDisplay *display = colormanage_display_get_named(display_name); + ColorManagedView *view; - if (display) { - LinkData *display_view; + if (display) { + LinkData *display_view; - for (display_view = display->views.first; display_view; display_view = display_view->next) { - view = display_view->data; + for (display_view = display->views.first; display_view; display_view = display_view->next) { + view = display_view->data; - colormanagement_view_item_add(items, totitem, view); - } - } + colormanagement_view_item_add(items, totitem, view); + } + } } -void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem, const char *view_name) +void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, + int *totitem, + const char *view_name) { - ColorManagedLook *look; - const char *view_filter = NULL; + ColorManagedLook *look; + const char *view_filter = NULL; - /* Test if this view transform is limited to specific looks. */ - for (look = global_looks.first; look; look = look->next) { - if (STREQ(look->view, view_name)) { - view_filter = view_name; - } - } + /* Test if this view transform is limited to specific looks. */ + for (look = global_looks.first; look; look = look->next) { + if (STREQ(look->view, view_name)) { + view_filter = view_name; + } + } - for (look = global_looks.first; look; look = look->next) { - if (!look->is_noop && view_filter && !STREQ(look->view, view_filter)) { - continue; - } + for (look = global_looks.first; look; look = look->next) { + if (!look->is_noop && view_filter && !STREQ(look->view, view_filter)) { + continue; + } - EnumPropertyItem item; + EnumPropertyItem item; - item.value = look->index; - item.name = look->ui_name; - item.identifier = look->name; - item.icon = 0; - item.description = ""; + item.value = look->index; + item.name = look->ui_name; + item.identifier = look->name; + item.icon = 0; + item.description = ""; - RNA_enum_item_add(items, totitem, &item); - } + RNA_enum_item_add(items, totitem, &item); + } } void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *totitem) { - ColorSpace *colorspace; + ColorSpace *colorspace; - for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { - EnumPropertyItem item; + for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { + EnumPropertyItem item; - if (!colorspace->is_invertible) - continue; + if (!colorspace->is_invertible) + continue; - item.value = colorspace->index; - item.name = colorspace->name; - item.identifier = colorspace->name; - item.icon = 0; - item.description = colorspace->description; + item.value = colorspace->index; + item.name = colorspace->name; + item.identifier = colorspace->name; + item.icon = 0; + item.description = colorspace->description; - RNA_enum_item_add(items, totitem, &item); - } + RNA_enum_item_add(items, totitem, &item); + } } /*********************** Partial display buffer update *************************/ @@ -2896,633 +3099,684 @@ static void partial_buffer_update_rect(ImBuf *ibuf, const unsigned char *byte_buffer, int display_stride, int linear_stride, - int linear_offset_x, int linear_offset_y, + int linear_offset_x, + int linear_offset_y, ColormanageProcessor *cm_processor, - const int xmin, const int ymin, - const int xmax, const int ymax) -{ - int x, y; - int channels = ibuf->channels; - float dither = ibuf->dither; - ColorSpace *rect_colorspace = ibuf->rect_colorspace; - float *display_buffer_float = NULL; - const int width = xmax - xmin; - const int height = ymax - ymin; - bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; - - if (dither != 0.0f) { - /* cm_processor is NULL in cases byte_buffer's space matches display - * buffer's space - * in this case we could skip extra transform and only apply dither - * use 4 channels for easier byte->float->byte conversion here so - * (this is only needed to apply dither, in other cases we'll convert - * byte buffer to display directly) - */ - if (!cm_processor) - channels = 4; - - display_buffer_float = MEM_callocN((size_t)channels * width * height * sizeof(float), "display buffer for dither"); - } - - if (cm_processor) { - for (y = ymin; y < ymax; y++) { - for (x = xmin; x < xmax; x++) { - size_t display_index = ((size_t)y * display_stride + x) * 4; - size_t linear_index = ((size_t)(y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; - float pixel[4]; - - if (linear_buffer) { - if (channels == 4) { - copy_v4_v4(pixel, (float *) linear_buffer + linear_index); - } - else if (channels == 3) { - copy_v3_v3(pixel, (float *) linear_buffer + linear_index); - pixel[3] = 1.0f; - } - else if (channels == 1) { - pixel[0] = linear_buffer[linear_index]; - } - else { - BLI_assert(!"Unsupported number of channels in partial buffer update"); - } - } - else if (byte_buffer) { - rgba_uchar_to_float(pixel, byte_buffer + linear_index); - IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); - straight_to_premul_v4(pixel); - } - - if (!is_data) { - IMB_colormanagement_processor_apply_pixel(cm_processor, pixel, channels); - } - - if (display_buffer_float) { - size_t index = ((size_t)(y - ymin) * width + (x - xmin)) * channels; - - if (channels == 4) { - copy_v4_v4(display_buffer_float + index, pixel); - } - else if (channels == 3) { - copy_v3_v3(display_buffer_float + index, pixel); - } - else /* if (channels == 1) */ { - display_buffer_float[index] = pixel[0]; - } - } - else { - if (channels == 4) { - float pixel_straight[4]; - premul_to_straight_v4_v4(pixel_straight, pixel); - rgba_float_to_uchar(display_buffer + display_index, pixel_straight); - } - else if (channels == 3) { - rgb_float_to_uchar(display_buffer + display_index, pixel); - display_buffer[display_index + 3] = 255; - } - else /* if (channels == 1) */ { - display_buffer[display_index] = - display_buffer[display_index + 1] = - display_buffer[display_index + 2] = - display_buffer[display_index + 3] = unit_float_to_uchar_clamp(pixel[0]); - } - } - } - } - } - else { - if (display_buffer_float) { - /* huh, for dither we need float buffer first, no cheaper way. currently */ - IMB_buffer_float_from_byte(display_buffer_float, byte_buffer, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, true, - width, height, width, display_stride); - } - else { - int i; - - for (i = ymin; i < ymax; i++) { - size_t byte_offset = ((size_t)linear_stride * i + xmin) * 4; - size_t display_offset = ((size_t)display_stride * i + xmin) * 4; - - memcpy(display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width); - } - } - } - - if (display_buffer_float) { - size_t display_index = ((size_t)ymin * display_stride + xmin) * channels; - - IMB_buffer_byte_from_float(display_buffer + display_index, display_buffer_float, channels, dither, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, true, width, height, display_stride, width); - - MEM_freeN(display_buffer_float); - } + const int xmin, + const int ymin, + const int xmax, + const int ymax) +{ + int x, y; + int channels = ibuf->channels; + float dither = ibuf->dither; + ColorSpace *rect_colorspace = ibuf->rect_colorspace; + float *display_buffer_float = NULL; + const int width = xmax - xmin; + const int height = ymax - ymin; + bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; + + if (dither != 0.0f) { + /* cm_processor is NULL in cases byte_buffer's space matches display + * buffer's space + * in this case we could skip extra transform and only apply dither + * use 4 channels for easier byte->float->byte conversion here so + * (this is only needed to apply dither, in other cases we'll convert + * byte buffer to display directly) + */ + if (!cm_processor) + channels = 4; + + display_buffer_float = MEM_callocN((size_t)channels * width * height * sizeof(float), + "display buffer for dither"); + } + + if (cm_processor) { + for (y = ymin; y < ymax; y++) { + for (x = xmin; x < xmax; x++) { + size_t display_index = ((size_t)y * display_stride + x) * 4; + size_t linear_index = ((size_t)(y - linear_offset_y) * linear_stride + + (x - linear_offset_x)) * + channels; + float pixel[4]; + + if (linear_buffer) { + if (channels == 4) { + copy_v4_v4(pixel, (float *)linear_buffer + linear_index); + } + else if (channels == 3) { + copy_v3_v3(pixel, (float *)linear_buffer + linear_index); + pixel[3] = 1.0f; + } + else if (channels == 1) { + pixel[0] = linear_buffer[linear_index]; + } + else { + BLI_assert(!"Unsupported number of channels in partial buffer update"); + } + } + else if (byte_buffer) { + rgba_uchar_to_float(pixel, byte_buffer + linear_index); + IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); + straight_to_premul_v4(pixel); + } + + if (!is_data) { + IMB_colormanagement_processor_apply_pixel(cm_processor, pixel, channels); + } + + if (display_buffer_float) { + size_t index = ((size_t)(y - ymin) * width + (x - xmin)) * channels; + + if (channels == 4) { + copy_v4_v4(display_buffer_float + index, pixel); + } + else if (channels == 3) { + copy_v3_v3(display_buffer_float + index, pixel); + } + else /* if (channels == 1) */ { + display_buffer_float[index] = pixel[0]; + } + } + else { + if (channels == 4) { + float pixel_straight[4]; + premul_to_straight_v4_v4(pixel_straight, pixel); + rgba_float_to_uchar(display_buffer + display_index, pixel_straight); + } + else if (channels == 3) { + rgb_float_to_uchar(display_buffer + display_index, pixel); + display_buffer[display_index + 3] = 255; + } + else /* if (channels == 1) */ { + display_buffer[display_index] = display_buffer[display_index + 1] = + display_buffer[display_index + 2] = display_buffer[display_index + 3] = + unit_float_to_uchar_clamp(pixel[0]); + } + } + } + } + } + else { + if (display_buffer_float) { + /* huh, for dither we need float buffer first, no cheaper way. currently */ + IMB_buffer_float_from_byte(display_buffer_float, + byte_buffer, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + true, + width, + height, + width, + display_stride); + } + else { + int i; + + for (i = ymin; i < ymax; i++) { + size_t byte_offset = ((size_t)linear_stride * i + xmin) * 4; + size_t display_offset = ((size_t)display_stride * i + xmin) * 4; + + memcpy( + display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width); + } + } + } + + if (display_buffer_float) { + size_t display_index = ((size_t)ymin * display_stride + xmin) * channels; + + IMB_buffer_byte_from_float(display_buffer + display_index, + display_buffer_float, + channels, + dither, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + true, + width, + height, + display_stride, + width); + + MEM_freeN(display_buffer_float); + } } typedef struct PartialThreadData { - ImBuf *ibuf; - unsigned char *display_buffer; - const float *linear_buffer; - const unsigned char *byte_buffer; - int display_stride; - int linear_stride; - int linear_offset_x, linear_offset_y; - ColormanageProcessor *cm_processor; - int xmin, ymin, xmax; + ImBuf *ibuf; + unsigned char *display_buffer; + const float *linear_buffer; + const unsigned char *byte_buffer; + int display_stride; + int linear_stride; + int linear_offset_x, linear_offset_y; + ColormanageProcessor *cm_processor; + int xmin, ymin, xmax; } PartialThreadData; static void partial_buffer_update_rect_thread_do(void *data_v, int start_scanline, int num_scanlines) { - PartialThreadData *data = (PartialThreadData *)data_v; - int ymin = data->ymin + start_scanline; - partial_buffer_update_rect(data->ibuf, - data->display_buffer, - data->linear_buffer, - data->byte_buffer, - data->display_stride, - data->linear_stride, - data->linear_offset_x, - data->linear_offset_y, - data->cm_processor, - data->xmin, - ymin, - data->xmax, - ymin + num_scanlines); -} - -static void imb_partial_display_buffer_update_ex(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, - bool copy_display_to_byte_buffer, - bool do_threads) -{ - ColormanageCacheViewSettings cache_view_settings; - ColormanageCacheDisplaySettings cache_display_settings; - void *cache_handle = NULL; - unsigned char *display_buffer = NULL; - int buffer_width = ibuf->x; - - if (ibuf->display_buffer_flags) { - int view_flag, display_index; - - colormanage_view_settings_to_cache(ibuf, &cache_view_settings, view_settings); - colormanage_display_settings_to_cache(&cache_display_settings, display_settings); - - view_flag = 1 << (cache_view_settings.view - 1); - display_index = cache_display_settings.display - 1; - - BLI_thread_lock(LOCK_COLORMANAGE); - - if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) { - display_buffer = colormanage_cache_get(ibuf, - &cache_view_settings, - &cache_display_settings, - &cache_handle); - } - - /* In some rare cases buffer's dimension could be changing directly from - * different thread - * this i.e. happens when image editor acquires render result - */ - buffer_width = ibuf->x; - - /* Mark all other buffers as invalid. */ - memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); - ibuf->display_buffer_flags[display_index] |= view_flag; - - BLI_thread_unlock(LOCK_COLORMANAGE); - } - - if (display_buffer == NULL) { - if (copy_display_to_byte_buffer) { - display_buffer = (unsigned char *) ibuf->rect; - } - } - - if (display_buffer) { - ColormanageProcessor *cm_processor = NULL; - bool skip_transform = false; - - /* Byte buffer is assumed to be in imbuf's rect space, so if byte buffer - * is known we could skip display->linear->display conversion in case - * display color space matches imbuf's rect space. - * - * But if there's a float buffer it's likely operation was performed on - * it first and byte buffer is likely to be out of date here. - */ - if (linear_buffer == NULL && byte_buffer != NULL) { - skip_transform = is_ibuf_rect_in_display_space(ibuf, - view_settings, - display_settings); - } - - if (!skip_transform) { - cm_processor = IMB_colormanagement_display_processor_new( - view_settings, display_settings); - } - - if (do_threads) { - PartialThreadData data; - data.ibuf = ibuf; - data.display_buffer = display_buffer; - data.linear_buffer = linear_buffer; - data.byte_buffer = byte_buffer; - data.display_stride = buffer_width; - data.linear_stride = stride; - data.linear_offset_x = offset_x; - data.linear_offset_y = offset_y; - data.cm_processor = cm_processor; - data.xmin = xmin; - data.ymin = ymin; - data.xmax = xmax; - IMB_processor_apply_threaded_scanlines( - ymax - ymin, partial_buffer_update_rect_thread_do, &data); - } - else { - partial_buffer_update_rect(ibuf, - display_buffer, linear_buffer, byte_buffer, - buffer_width, - stride, - offset_x, offset_y, - cm_processor, - xmin, ymin, xmax, ymax); - } - - if (cm_processor) { - IMB_colormanagement_processor_free(cm_processor); - } - - IMB_display_buffer_release(cache_handle); - } - - if (copy_display_to_byte_buffer && (unsigned char *) ibuf->rect != display_buffer) { - int y; - for (y = ymin; y < ymax; y++) { - size_t index = (size_t)y * buffer_width * 4; - memcpy((unsigned char *)ibuf->rect + index, - display_buffer + index, - (size_t)(xmax - xmin) * 4); - } - } + PartialThreadData *data = (PartialThreadData *)data_v; + int ymin = data->ymin + start_scanline; + partial_buffer_update_rect(data->ibuf, + data->display_buffer, + data->linear_buffer, + data->byte_buffer, + data->display_stride, + data->linear_stride, + data->linear_offset_x, + data->linear_offset_y, + data->cm_processor, + data->xmin, + ymin, + data->xmax, + ymin + num_scanlines); +} + +static void imb_partial_display_buffer_update_ex( + 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, + bool copy_display_to_byte_buffer, + bool do_threads) +{ + ColormanageCacheViewSettings cache_view_settings; + ColormanageCacheDisplaySettings cache_display_settings; + void *cache_handle = NULL; + unsigned char *display_buffer = NULL; + int buffer_width = ibuf->x; + + if (ibuf->display_buffer_flags) { + int view_flag, display_index; + + colormanage_view_settings_to_cache(ibuf, &cache_view_settings, view_settings); + colormanage_display_settings_to_cache(&cache_display_settings, display_settings); + + view_flag = 1 << (cache_view_settings.view - 1); + display_index = cache_display_settings.display - 1; + + BLI_thread_lock(LOCK_COLORMANAGE); + + if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) { + display_buffer = colormanage_cache_get( + ibuf, &cache_view_settings, &cache_display_settings, &cache_handle); + } + + /* In some rare cases buffer's dimension could be changing directly from + * different thread + * this i.e. happens when image editor acquires render result + */ + buffer_width = ibuf->x; + + /* Mark all other buffers as invalid. */ + memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); + ibuf->display_buffer_flags[display_index] |= view_flag; + + BLI_thread_unlock(LOCK_COLORMANAGE); + } + + if (display_buffer == NULL) { + if (copy_display_to_byte_buffer) { + display_buffer = (unsigned char *)ibuf->rect; + } + } + + if (display_buffer) { + ColormanageProcessor *cm_processor = NULL; + bool skip_transform = false; + + /* Byte buffer is assumed to be in imbuf's rect space, so if byte buffer + * is known we could skip display->linear->display conversion in case + * display color space matches imbuf's rect space. + * + * But if there's a float buffer it's likely operation was performed on + * it first and byte buffer is likely to be out of date here. + */ + if (linear_buffer == NULL && byte_buffer != NULL) { + skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings); + } + + if (!skip_transform) { + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + } + + if (do_threads) { + PartialThreadData data; + data.ibuf = ibuf; + data.display_buffer = display_buffer; + data.linear_buffer = linear_buffer; + data.byte_buffer = byte_buffer; + data.display_stride = buffer_width; + data.linear_stride = stride; + data.linear_offset_x = offset_x; + data.linear_offset_y = offset_y; + data.cm_processor = cm_processor; + data.xmin = xmin; + data.ymin = ymin; + data.xmax = xmax; + IMB_processor_apply_threaded_scanlines( + ymax - ymin, partial_buffer_update_rect_thread_do, &data); + } + else { + partial_buffer_update_rect(ibuf, + display_buffer, + linear_buffer, + byte_buffer, + buffer_width, + stride, + offset_x, + offset_y, + cm_processor, + xmin, + ymin, + xmax, + ymax); + } + + if (cm_processor) { + IMB_colormanagement_processor_free(cm_processor); + } + + IMB_display_buffer_release(cache_handle); + } + + if (copy_display_to_byte_buffer && (unsigned char *)ibuf->rect != display_buffer) { + int y; + for (y = ymin; y < ymax; y++) { + size_t index = (size_t)y * buffer_width * 4; + memcpy( + (unsigned char *)ibuf->rect + index, display_buffer + index, (size_t)(xmax - xmin) * 4); + } + } } 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, + 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, bool copy_display_to_byte_buffer) { - imb_partial_display_buffer_update_ex(ibuf, - linear_buffer, - byte_buffer, - stride, - offset_x, offset_y, - view_settings, - display_settings, - xmin, ymin, - xmax, ymax, - copy_display_to_byte_buffer, - false); - -} - -void IMB_partial_display_buffer_update_threaded(struct ImBuf *ibuf, - const float *linear_buffer, - const unsigned char *byte_buffer, - 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, - bool copy_display_to_byte_buffer) -{ - int width = xmax - xmin; - int height = ymax - ymin; - bool do_threads = (((size_t)width) * height >= 64 * 64); - imb_partial_display_buffer_update_ex(ibuf, - linear_buffer, - byte_buffer, - stride, - offset_x, offset_y, - view_settings, - display_settings, - xmin, ymin, - xmax, ymax, - copy_display_to_byte_buffer, - do_threads); + imb_partial_display_buffer_update_ex(ibuf, + linear_buffer, + byte_buffer, + stride, + offset_x, + offset_y, + view_settings, + display_settings, + xmin, + ymin, + xmax, + ymax, + copy_display_to_byte_buffer, + false); +} + +void IMB_partial_display_buffer_update_threaded( + struct ImBuf *ibuf, + const float *linear_buffer, + const unsigned char *byte_buffer, + 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, + bool copy_display_to_byte_buffer) +{ + int width = xmax - xmin; + int height = ymax - ymin; + bool do_threads = (((size_t)width) * height >= 64 * 64); + imb_partial_display_buffer_update_ex(ibuf, + linear_buffer, + byte_buffer, + stride, + offset_x, + offset_y, + view_settings, + display_settings, + xmin, + ymin, + xmax, + ymax, + copy_display_to_byte_buffer, + do_threads); } void IMB_partial_display_buffer_update_delayed(ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax) { - if (ibuf->invalid_rect.xmin == ibuf->invalid_rect.xmax) { - BLI_rcti_init(&ibuf->invalid_rect, xmin, xmax, ymin, ymax); - } - else { - rcti rect; - BLI_rcti_init(&rect, xmin, xmax, ymin, ymax); - BLI_rcti_union(&ibuf->invalid_rect, &rect); - } + if (ibuf->invalid_rect.xmin == ibuf->invalid_rect.xmax) { + BLI_rcti_init(&ibuf->invalid_rect, xmin, xmax, ymin, ymax); + } + else { + rcti rect; + BLI_rcti_init(&rect, xmin, xmax, ymin, ymax); + BLI_rcti_union(&ibuf->invalid_rect, &rect); + } } /*********************** Pixel processor functions *************************/ -ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +ColormanageProcessor *IMB_colormanagement_display_processor_new( + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - ColormanageProcessor *cm_processor; - ColorManagedViewSettings default_view_settings; - const ColorManagedViewSettings *applied_view_settings; - ColorSpace *display_space; + ColormanageProcessor *cm_processor; + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; + ColorSpace *display_space; - cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); + cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); - if (view_settings) { - applied_view_settings = view_settings; - } - else { - IMB_colormanagement_init_default_view_settings( - &default_view_settings, display_settings); - applied_view_settings = &default_view_settings; - } + if (view_settings) { + applied_view_settings = view_settings; + } + else { + IMB_colormanagement_init_default_view_settings(&default_view_settings, display_settings); + applied_view_settings = &default_view_settings; + } - display_space = display_transform_get_colorspace(applied_view_settings, display_settings); - if (display_space) - cm_processor->is_data_result = display_space->is_data; + display_space = display_transform_get_colorspace(applied_view_settings, display_settings); + if (display_space) + cm_processor->is_data_result = display_space->is_data; - cm_processor->processor = create_display_buffer_processor(applied_view_settings->look, - applied_view_settings->view_transform, - display_settings->display_device, - applied_view_settings->exposure, - applied_view_settings->gamma, - global_role_scene_linear); + cm_processor->processor = create_display_buffer_processor(applied_view_settings->look, + applied_view_settings->view_transform, + display_settings->display_device, + applied_view_settings->exposure, + applied_view_settings->gamma, + global_role_scene_linear); - 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; + return cm_processor; } -ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace) +ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, + const char *to_colorspace) { - ColormanageProcessor *cm_processor; - ColorSpace *color_space; + ColormanageProcessor *cm_processor; + ColorSpace *color_space; - cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); + 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; + 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); + cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); - return cm_processor; + return cm_processor; } void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor, float pixel[4]) { - if (cm_processor->curve_mapping) - curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); + if (cm_processor->curve_mapping) + curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); - if (cm_processor->processor) - OCIO_processorApplyRGBA(cm_processor->processor, pixel); + if (cm_processor->processor) + OCIO_processorApplyRGBA(cm_processor->processor, pixel); } -void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_processor, float pixel[4]) +void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_processor, + float pixel[4]) { - if (cm_processor->curve_mapping) - curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); + if (cm_processor->curve_mapping) + curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); - if (cm_processor->processor) - OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel); + if (cm_processor->processor) + OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel); } void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3]) { - if (cm_processor->curve_mapping) - curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); - - if (cm_processor->processor) - OCIO_processorApplyRGB(cm_processor->processor, pixel); -} - -void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, float *pixel, int channels) -{ - if (channels == 4) { - IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel); - } - else if (channels == 3) { - IMB_colormanagement_processor_apply_v3(cm_processor, pixel); - } - else if (channels == 1) { - if (cm_processor->curve_mapping) { - curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, 1); - } - } - else { - BLI_assert(!"Incorrect number of channels passed to IMB_colormanagement_processor_apply_pixel"); - } -} - -void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height, - int channels, bool predivide) -{ - /* apply curve mapping */ - if (cm_processor->curve_mapping) { - int x, y; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float *pixel = buffer + channels * (((size_t)y) * width + x); - - curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels); - } - } - } - - if (cm_processor->processor && channels >= 3) { - OCIO_PackedImageDesc *img; - - /* apply OCIO processor */ - img = OCIO_createOCIO_PackedImageDesc( - buffer, width, height, channels, sizeof(float), - (size_t)channels * sizeof(float), - (size_t)channels * sizeof(float) * width); - - if (predivide) - OCIO_processorApply_predivide(cm_processor->processor, img); - else - OCIO_processorApply(cm_processor->processor, img); - - OCIO_PackedImageDescRelease(img); - } -} - -void IMB_colormanagement_processor_apply_byte(ColormanageProcessor *cm_processor, - unsigned char *buffer, - int width, int height, int channels) -{ - /* TODO(sergey): Would be nice to support arbitrary channels configurations, - * but for now it's not so important. - */ - BLI_assert(channels == 4); - float pixel[4]; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - size_t offset = channels * (((size_t)y) * width + x); - rgba_uchar_to_float(pixel, buffer + offset); - IMB_colormanagement_processor_apply_v4(cm_processor, pixel); - rgba_float_to_uchar(buffer + offset, pixel); - } - } + if (cm_processor->curve_mapping) + curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); + + if (cm_processor->processor) + OCIO_processorApplyRGB(cm_processor->processor, pixel); +} + +void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, + float *pixel, + int channels) +{ + if (channels == 4) { + IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel); + } + else if (channels == 3) { + IMB_colormanagement_processor_apply_v3(cm_processor, pixel); + } + else if (channels == 1) { + if (cm_processor->curve_mapping) { + curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, 1); + } + } + else { + BLI_assert( + !"Incorrect number of channels passed to IMB_colormanagement_processor_apply_pixel"); + } +} + +void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, + float *buffer, + int width, + int height, + int channels, + bool predivide) +{ + /* apply curve mapping */ + if (cm_processor->curve_mapping) { + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = buffer + channels * (((size_t)y) * width + x); + + curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels); + } + } + } + + if (cm_processor->processor && channels >= 3) { + OCIO_PackedImageDesc *img; + + /* apply OCIO processor */ + img = OCIO_createOCIO_PackedImageDesc(buffer, + width, + height, + channels, + sizeof(float), + (size_t)channels * sizeof(float), + (size_t)channels * sizeof(float) * width); + + if (predivide) + OCIO_processorApply_predivide(cm_processor->processor, img); + else + OCIO_processorApply(cm_processor->processor, img); + + OCIO_PackedImageDescRelease(img); + } +} + +void IMB_colormanagement_processor_apply_byte( + ColormanageProcessor *cm_processor, unsigned char *buffer, int width, int height, int channels) +{ + /* TODO(sergey): Would be nice to support arbitrary channels configurations, + * but for now it's not so important. + */ + BLI_assert(channels == 4); + float pixel[4]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + size_t offset = channels * (((size_t)y) * width + x); + rgba_uchar_to_float(pixel, buffer + offset); + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + rgba_float_to_uchar(buffer + offset, pixel); + } + } } void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { - if (cm_processor->curve_mapping) - curvemapping_free(cm_processor->curve_mapping); - if (cm_processor->processor) - OCIO_processorRelease(cm_processor->processor); + if (cm_processor->curve_mapping) + curvemapping_free(cm_processor->curve_mapping); + if (cm_processor->processor) + OCIO_processorRelease(cm_processor->processor); - MEM_freeN(cm_processor); + MEM_freeN(cm_processor); } /* **** OpenGL drawing routines using GLSL for color space transform ***** */ -static bool check_glsl_display_processor_changed(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, - const char *from_colorspace) +static bool check_glsl_display_processor_changed( + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + const char *from_colorspace) { - return !(global_glsl_state.exposure == view_settings->exposure && - global_glsl_state.gamma == view_settings->gamma && - STREQ(global_glsl_state.look, view_settings->look) && - STREQ(global_glsl_state.view, view_settings->view_transform) && - STREQ(global_glsl_state.display, display_settings->display_device) && - STREQ(global_glsl_state.input, from_colorspace)); + return !(global_glsl_state.exposure == view_settings->exposure && + global_glsl_state.gamma == view_settings->gamma && + STREQ(global_glsl_state.look, view_settings->look) && + STREQ(global_glsl_state.view, view_settings->view_transform) && + STREQ(global_glsl_state.display, display_settings->display_device) && + STREQ(global_glsl_state.input, from_colorspace)); } static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping, OCIO_CurveMappingSettings *curve_mapping_settings) { - int i; + int i; - curvemapping_initialize(curve_mapping); - curvemapping_premultiply(curve_mapping, false); - curvemapping_table_RGBA(curve_mapping, - &curve_mapping_settings->lut, - &curve_mapping_settings->lut_size); + curvemapping_initialize(curve_mapping); + curvemapping_premultiply(curve_mapping, false); + curvemapping_table_RGBA( + curve_mapping, &curve_mapping_settings->lut, &curve_mapping_settings->lut_size); - for (i = 0; i < 4; i++) { - CurveMap *cuma = curve_mapping->cm + i; - curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != 0; - curve_mapping_settings->range[i] = cuma->range; - curve_mapping_settings->mintable[i] = cuma->mintable; - curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0]; - curve_mapping_settings->ext_in_y[i] = cuma->ext_in[1]; - curve_mapping_settings->ext_out_x[i] = cuma->ext_out[0]; - curve_mapping_settings->ext_out_y[i] = cuma->ext_out[1]; - curve_mapping_settings->first_x[i] = cuma->table[0].x; - curve_mapping_settings->first_y[i] = cuma->table[0].y; - curve_mapping_settings->last_x[i] = cuma->table[CM_TABLE].x; - curve_mapping_settings->last_y[i] = cuma->table[CM_TABLE].y; - } + for (i = 0; i < 4; i++) { + CurveMap *cuma = curve_mapping->cm + i; + curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != + 0; + curve_mapping_settings->range[i] = cuma->range; + curve_mapping_settings->mintable[i] = cuma->mintable; + curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0]; + curve_mapping_settings->ext_in_y[i] = cuma->ext_in[1]; + curve_mapping_settings->ext_out_x[i] = cuma->ext_out[0]; + curve_mapping_settings->ext_out_y[i] = cuma->ext_out[1]; + curve_mapping_settings->first_x[i] = cuma->table[0].x; + curve_mapping_settings->first_y[i] = cuma->table[0].y; + curve_mapping_settings->last_x[i] = cuma->table[CM_TABLE].x; + curve_mapping_settings->last_y[i] = cuma->table[CM_TABLE].y; + } - copy_v3_v3(curve_mapping_settings->black, curve_mapping->black); - copy_v3_v3(curve_mapping_settings->bwmul, curve_mapping->bwmul); + copy_v3_v3(curve_mapping_settings->black, curve_mapping->black); + copy_v3_v3(curve_mapping_settings->bwmul, curve_mapping->bwmul); - curve_mapping_settings->cache_id = (size_t) curve_mapping; + curve_mapping_settings->cache_id = (size_t)curve_mapping; } static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const char *from_colorspace) { - bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0; - bool need_update = false; - - need_update = global_glsl_state.processor == NULL || - check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace) || - use_curve_mapping != global_glsl_state.use_curve_mapping; - - if (use_curve_mapping && need_update == false) { - need_update |= view_settings->curve_mapping->changed_timestamp != global_glsl_state.curve_mapping_timestamp || - view_settings->curve_mapping != global_glsl_state.orig_curve_mapping; - } - - /* Update state if there's no processor yet or - * processor settings has been changed. - */ - if (need_update) { - OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings; - CurveMapping *new_curve_mapping = NULL; - - /* Store settings of processor for further comparison. */ - BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME); - BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME); - BLI_strncpy(global_glsl_state.display, display_settings->display_device, MAX_COLORSPACE_NAME); - BLI_strncpy(global_glsl_state.input, from_colorspace, MAX_COLORSPACE_NAME); - global_glsl_state.exposure = view_settings->exposure; - global_glsl_state.gamma = view_settings->gamma; - - /* We're using curve mapping's address as a cache ID, - * so we need to make sure re-allocation gives new address here. - * We do this by allocating new curve mapping before freeing ol one. - */ - if (use_curve_mapping) { - new_curve_mapping = curvemapping_copy(view_settings->curve_mapping); - } - - if (global_glsl_state.curve_mapping) { - curvemapping_free(global_glsl_state.curve_mapping); - MEM_freeN(curve_mapping_settings->lut); - global_glsl_state.curve_mapping = NULL; - curve_mapping_settings->lut = NULL; - } - - /* Fill in OCIO's curve mapping settings. */ - if (use_curve_mapping) { - curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings); - - global_glsl_state.curve_mapping = new_curve_mapping; - global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp; - global_glsl_state.orig_curve_mapping = view_settings->curve_mapping; - global_glsl_state.use_curve_mapping = true; - } - else { - global_glsl_state.orig_curve_mapping = NULL; - global_glsl_state.use_curve_mapping = false; - } - - /* Free old processor, if any. */ - if (global_glsl_state.processor) - OCIO_processorRelease(global_glsl_state.processor); - - /* We're using display OCIO processor, no RGB curves yet. */ - global_glsl_state.processor = - create_display_buffer_processor(global_glsl_state.look, - global_glsl_state.view, - global_glsl_state.display, - global_glsl_state.exposure, - global_glsl_state.gamma, - global_glsl_state.input); - } + bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0; + bool need_update = false; + + need_update = global_glsl_state.processor == NULL || + check_glsl_display_processor_changed( + view_settings, display_settings, from_colorspace) || + use_curve_mapping != global_glsl_state.use_curve_mapping; + + if (use_curve_mapping && need_update == false) { + need_update |= view_settings->curve_mapping->changed_timestamp != + global_glsl_state.curve_mapping_timestamp || + view_settings->curve_mapping != global_glsl_state.orig_curve_mapping; + } + + /* Update state if there's no processor yet or + * processor settings has been changed. + */ + if (need_update) { + OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings; + CurveMapping *new_curve_mapping = NULL; + + /* Store settings of processor for further comparison. */ + BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME); + BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME); + BLI_strncpy(global_glsl_state.display, display_settings->display_device, MAX_COLORSPACE_NAME); + BLI_strncpy(global_glsl_state.input, from_colorspace, MAX_COLORSPACE_NAME); + global_glsl_state.exposure = view_settings->exposure; + global_glsl_state.gamma = view_settings->gamma; + + /* We're using curve mapping's address as a cache ID, + * so we need to make sure re-allocation gives new address here. + * We do this by allocating new curve mapping before freeing ol one. + */ + if (use_curve_mapping) { + new_curve_mapping = curvemapping_copy(view_settings->curve_mapping); + } + + if (global_glsl_state.curve_mapping) { + curvemapping_free(global_glsl_state.curve_mapping); + MEM_freeN(curve_mapping_settings->lut); + global_glsl_state.curve_mapping = NULL; + curve_mapping_settings->lut = NULL; + } + + /* Fill in OCIO's curve mapping settings. */ + if (use_curve_mapping) { + curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings); + + global_glsl_state.curve_mapping = new_curve_mapping; + global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp; + global_glsl_state.orig_curve_mapping = view_settings->curve_mapping; + global_glsl_state.use_curve_mapping = true; + } + else { + global_glsl_state.orig_curve_mapping = NULL; + global_glsl_state.use_curve_mapping = false; + } + + /* Free old processor, if any. */ + if (global_glsl_state.processor) + OCIO_processorRelease(global_glsl_state.processor); + + /* We're using display OCIO processor, no RGB curves yet. */ + global_glsl_state.processor = create_display_buffer_processor(global_glsl_state.look, + global_glsl_state.view, + global_glsl_state.display, + global_glsl_state.exposure, + global_glsl_state.gamma, + global_glsl_state.input); + } } bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings)) { - return OCIO_supportGLSLDraw(); + return OCIO_supportGLSLDraw(); } /** @@ -3538,73 +3792,82 @@ bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSE * This is low-level function, use glaDrawImBuf_glsl_ctx if you * only need to display given image buffer */ -bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, - struct ColorSpace *from_colorspace, - float dither, bool predivide) -{ - ColorManagedViewSettings default_view_settings; - const ColorManagedViewSettings *applied_view_settings; - - if (view_settings) { - applied_view_settings = view_settings; - } - else { - /* If no view settings were specified, use default ones, which will - * attempt not to do any extra color correction. */ - IMB_colormanagement_init_default_view_settings( - &default_view_settings, display_settings); - applied_view_settings = &default_view_settings; - } - - /* Make sure OCIO processor is up-to-date. */ - update_glsl_display_processor(applied_view_settings, display_settings, - from_colorspace ? from_colorspace->name : global_role_scene_linear); - - if (global_glsl_state.processor == NULL) { - /* Happens when requesting non-existing color space or LUT in the - * configuration file does not exist. - */ - return false; - } - - return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, - global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL, - dither, predivide); +bool IMB_colormanagement_setup_glsl_draw_from_space( + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + struct ColorSpace *from_colorspace, + float dither, + bool predivide) +{ + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; + + if (view_settings) { + applied_view_settings = view_settings; + } + else { + /* If no view settings were specified, use default ones, which will + * attempt not to do any extra color correction. */ + IMB_colormanagement_init_default_view_settings(&default_view_settings, display_settings); + applied_view_settings = &default_view_settings; + } + + /* Make sure OCIO processor is up-to-date. */ + update_glsl_display_processor(applied_view_settings, + display_settings, + from_colorspace ? from_colorspace->name : + global_role_scene_linear); + + if (global_glsl_state.processor == NULL) { + /* Happens when requesting non-existing color space or LUT in the + * configuration file does not exist. + */ + return false; + } + + return OCIO_setupGLSLDraw( + &global_glsl_state.ocio_glsl_state, + global_glsl_state.processor, + global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL, + dither, + predivide); } /* Configures GLSL shader for conversion from scene linear to display space */ bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - float dither, bool predivide) + float dither, + bool predivide) { - return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - NULL, dither, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space( + view_settings, display_settings, NULL, dither, predivide); } /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const bContext *C, struct ColorSpace *from_colorspace, - float dither, bool predivide) +bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const bContext *C, + struct ColorSpace *from_colorspace, + float dither, + bool predivide) { - ColorManagedViewSettings *view_settings; - ColorManagedDisplaySettings *display_settings; + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; - IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); + IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); - return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, - dither, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space( + view_settings, display_settings, from_colorspace, dither, predivide); } /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, float dither, bool predivide) { - return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, dither, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, dither, predivide); } /* Finish GLSL-based display space conversion */ void IMB_colormanagement_finish_glsl_draw(void) { - if (global_glsl_state.ocio_glsl_state != NULL) { - OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state); - } + if (global_glsl_state.ocio_glsl_state != NULL) { + OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state); + } } diff --git a/source/blender/imbuf/intern/colormanagement_inline.c b/source/blender/imbuf/intern/colormanagement_inline.c index 2200c1d8c52..42c90b8414f 100644 --- a/source/blender/imbuf/intern/colormanagement_inline.c +++ b/source/blender/imbuf/intern/colormanagement_inline.c @@ -40,29 +40,29 @@ float IMB_colormanagement_get_luminance(const float rgb[3]) { - return dot_v3v3(imbuf_luma_coefficients, rgb); + return dot_v3v3(imbuf_luma_coefficients, rgb); } /* Byte equivalent of IMB_colormanagement_get_luminance(). */ unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3]) { - float rgbf[3]; - float val; + float rgbf[3]; + float val; - rgb_uchar_to_float(rgbf, rgb); - val = dot_v3v3(imbuf_luma_coefficients, rgbf); + rgb_uchar_to_float(rgbf, rgb); + val = dot_v3v3(imbuf_luma_coefficients, rgbf); - return unit_float_to_uchar_clamp(val); + return unit_float_to_uchar_clamp(val); } void IMB_colormangement_xyz_to_rgb(float rgb[3], const float xyz[3]) { - mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, xyz); + mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, xyz); } void IMB_colormangement_rgb_to_xyz(float xyz[3], const float rgb[3]) { - mul_v3_m3v3(xyz, imbuf_rgb_to_xyz, rgb); + mul_v3_m3v3(xyz, imbuf_rgb_to_xyz, rgb); } -#endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */ +#endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */ diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index aae769d9882..9211f6a7ba6 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -55,607 +54,599 @@ #include /*---------------------------------------------------------------------------- - BlockDXT1 + BlockDXT1 ----------------------------------------------------------------------------*/ uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const { - // Does bit expansion before interpolation. - color_array[0].b = (col0.b << 3) | (col0.b >> 2); - color_array[0].g = (col0.g << 2) | (col0.g >> 4); - color_array[0].r = (col0.r << 3) | (col0.r >> 2); - color_array[0].a = 0xFF; - - // @@ Same as above, but faster? -// Color32 c; -// c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000); -// c.u |= (c.u >> 5) & 0x070007; -// c.u |= (c.u >> 6) & 0x000300; -// color_array[0].u = c.u; - - color_array[1].r = (col1.r << 3) | (col1.r >> 2); - color_array[1].g = (col1.g << 2) | (col1.g >> 4); - color_array[1].b = (col1.b << 3) | (col1.b >> 2); - color_array[1].a = 0xFF; - - // @@ Same as above, but faster? -// c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000); -// c.u |= (c.u >> 5) & 0x070007; -// c.u |= (c.u >> 6) & 0x000300; -// color_array[1].u = c.u; - - if ( col0.u > col1.u ) { - // Four-color block: derive the other two colors. - color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; - color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; - color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; - color_array[2].a = 0xFF; - - color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; - color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; - color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; - color_array[3].a = 0xFF; - - return 4; - } - else { - // Three-color block: derive the other color. - color_array[2].r = (color_array[0].r + color_array[1].r) / 2; - color_array[2].g = (color_array[0].g + color_array[1].g) / 2; - color_array[2].b = (color_array[0].b + color_array[1].b) / 2; - color_array[2].a = 0xFF; - - // Set all components to 0 to match DXT specs. - color_array[3].r = 0x00; // color_array[2].r; - color_array[3].g = 0x00; // color_array[2].g; - color_array[3].b = 0x00; // color_array[2].b; - color_array[3].a = 0x00; - - return 3; - } + // Does bit expansion before interpolation. + color_array[0].b = (col0.b << 3) | (col0.b >> 2); + color_array[0].g = (col0.g << 2) | (col0.g >> 4); + color_array[0].r = (col0.r << 3) | (col0.r >> 2); + color_array[0].a = 0xFF; + + // @@ Same as above, but faster? + // Color32 c; + // c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000); + // c.u |= (c.u >> 5) & 0x070007; + // c.u |= (c.u >> 6) & 0x000300; + // color_array[0].u = c.u; + + color_array[1].r = (col1.r << 3) | (col1.r >> 2); + color_array[1].g = (col1.g << 2) | (col1.g >> 4); + color_array[1].b = (col1.b << 3) | (col1.b >> 2); + color_array[1].a = 0xFF; + + // @@ Same as above, but faster? + // c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000); + // c.u |= (c.u >> 5) & 0x070007; + // c.u |= (c.u >> 6) & 0x000300; + // color_array[1].u = c.u; + + if (col0.u > col1.u) { + // Four-color block: derive the other two colors. + color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; + color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; + color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; + color_array[2].a = 0xFF; + + color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; + color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; + color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; + color_array[3].a = 0xFF; + + return 4; + } + else { + // Three-color block: derive the other color. + color_array[2].r = (color_array[0].r + color_array[1].r) / 2; + color_array[2].g = (color_array[0].g + color_array[1].g) / 2; + color_array[2].b = (color_array[0].b + color_array[1].b) / 2; + color_array[2].a = 0xFF; + + // Set all components to 0 to match DXT specs. + color_array[3].r = 0x00; // color_array[2].r; + color_array[3].g = 0x00; // color_array[2].g; + color_array[3].b = 0x00; // color_array[2].b; + color_array[3].a = 0x00; + + return 3; + } } - uint BlockDXT1::evaluatePaletteNV5x(Color32 color_array[4]) const { - // Does bit expansion before interpolation. - color_array[0].b = (3 * col0.b * 22) / 8; - color_array[0].g = (col0.g << 2) | (col0.g >> 4); - color_array[0].r = (3 * col0.r * 22) / 8; - color_array[0].a = 0xFF; - - color_array[1].r = (3 * col1.r * 22) / 8; - color_array[1].g = (col1.g << 2) | (col1.g >> 4); - color_array[1].b = (3 * col1.b * 22) / 8; - color_array[1].a = 0xFF; - - int gdiff = color_array[1].g - color_array[0].g; - - if ( col0.u > col1.u ) { - // Four-color block: derive the other two colors. - color_array[2].r = ((2 * col0.r + col1.r) * 22) / 8; - color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 80) / 256; - color_array[2].b = ((2 * col0.b + col1.b) * 22) / 8; - color_array[2].a = 0xFF; - - color_array[3].r = ((2 * col1.r + col0.r) * 22) / 8; - color_array[3].g = (256 * color_array[1].g - gdiff / 4 + 128 - gdiff * 80) / 256; - color_array[3].b = ((2 * col1.b + col0.b) * 22) / 8; - color_array[3].a = 0xFF; - - return 4; - } - else { - // Three-color block: derive the other color. - color_array[2].r = ((col0.r + col1.r) * 33) / 8; - color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 128) / 256; - color_array[2].b = ((col0.b + col1.b) * 33) / 8; - color_array[2].a = 0xFF; - - // Set all components to 0 to match DXT specs. - color_array[3].r = 0x00; // color_array[2].r; - color_array[3].g = 0x00; // color_array[2].g; - color_array[3].b = 0x00; // color_array[2].b; - color_array[3].a = 0x00; - - return 3; - } + // Does bit expansion before interpolation. + color_array[0].b = (3 * col0.b * 22) / 8; + color_array[0].g = (col0.g << 2) | (col0.g >> 4); + color_array[0].r = (3 * col0.r * 22) / 8; + color_array[0].a = 0xFF; + + color_array[1].r = (3 * col1.r * 22) / 8; + color_array[1].g = (col1.g << 2) | (col1.g >> 4); + color_array[1].b = (3 * col1.b * 22) / 8; + color_array[1].a = 0xFF; + + int gdiff = color_array[1].g - color_array[0].g; + + if (col0.u > col1.u) { + // Four-color block: derive the other two colors. + color_array[2].r = ((2 * col0.r + col1.r) * 22) / 8; + color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 80) / 256; + color_array[2].b = ((2 * col0.b + col1.b) * 22) / 8; + color_array[2].a = 0xFF; + + color_array[3].r = ((2 * col1.r + col0.r) * 22) / 8; + color_array[3].g = (256 * color_array[1].g - gdiff / 4 + 128 - gdiff * 80) / 256; + color_array[3].b = ((2 * col1.b + col0.b) * 22) / 8; + color_array[3].a = 0xFF; + + return 4; + } + else { + // Three-color block: derive the other color. + color_array[2].r = ((col0.r + col1.r) * 33) / 8; + color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 128) / 256; + color_array[2].b = ((col0.b + col1.b) * 33) / 8; + color_array[2].a = 0xFF; + + // Set all components to 0 to match DXT specs. + color_array[3].r = 0x00; // color_array[2].r; + color_array[3].g = 0x00; // color_array[2].g; + color_array[3].b = 0x00; // color_array[2].b; + color_array[3].a = 0x00; + + return 3; + } } // Evaluate palette assuming 3 color block. void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const { - color_array[0].b = (col0.b << 3) | (col0.b >> 2); - color_array[0].g = (col0.g << 2) | (col0.g >> 4); - color_array[0].r = (col0.r << 3) | (col0.r >> 2); - color_array[0].a = 0xFF; + color_array[0].b = (col0.b << 3) | (col0.b >> 2); + color_array[0].g = (col0.g << 2) | (col0.g >> 4); + color_array[0].r = (col0.r << 3) | (col0.r >> 2); + color_array[0].a = 0xFF; - color_array[1].r = (col1.r << 3) | (col1.r >> 2); - color_array[1].g = (col1.g << 2) | (col1.g >> 4); - color_array[1].b = (col1.b << 3) | (col1.b >> 2); - color_array[1].a = 0xFF; + color_array[1].r = (col1.r << 3) | (col1.r >> 2); + color_array[1].g = (col1.g << 2) | (col1.g >> 4); + color_array[1].b = (col1.b << 3) | (col1.b >> 2); + color_array[1].a = 0xFF; - // Three-color block: derive the other color. - color_array[2].r = (color_array[0].r + color_array[1].r) / 2; - color_array[2].g = (color_array[0].g + color_array[1].g) / 2; - color_array[2].b = (color_array[0].b + color_array[1].b) / 2; - color_array[2].a = 0xFF; + // Three-color block: derive the other color. + color_array[2].r = (color_array[0].r + color_array[1].r) / 2; + color_array[2].g = (color_array[0].g + color_array[1].g) / 2; + color_array[2].b = (color_array[0].b + color_array[1].b) / 2; + color_array[2].a = 0xFF; - // Set all components to 0 to match DXT specs. - color_array[3].r = 0x00; // color_array[2].r; - color_array[3].g = 0x00; // color_array[2].g; - color_array[3].b = 0x00; // color_array[2].b; - color_array[3].a = 0x00; + // Set all components to 0 to match DXT specs. + color_array[3].r = 0x00; // color_array[2].r; + color_array[3].g = 0x00; // color_array[2].g; + color_array[3].b = 0x00; // color_array[2].b; + color_array[3].a = 0x00; } // Evaluate palette assuming 4 color block. void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const { - color_array[0].b = (col0.b << 3) | (col0.b >> 2); - color_array[0].g = (col0.g << 2) | (col0.g >> 4); - color_array[0].r = (col0.r << 3) | (col0.r >> 2); - color_array[0].a = 0xFF; + color_array[0].b = (col0.b << 3) | (col0.b >> 2); + color_array[0].g = (col0.g << 2) | (col0.g >> 4); + color_array[0].r = (col0.r << 3) | (col0.r >> 2); + color_array[0].a = 0xFF; - color_array[1].r = (col1.r << 3) | (col1.r >> 2); - color_array[1].g = (col1.g << 2) | (col1.g >> 4); - color_array[1].b = (col1.b << 3) | (col1.b >> 2); - color_array[1].a = 0xFF; + color_array[1].r = (col1.r << 3) | (col1.r >> 2); + color_array[1].g = (col1.g << 2) | (col1.g >> 4); + color_array[1].b = (col1.b << 3) | (col1.b >> 2); + color_array[1].a = 0xFF; - // Four-color block: derive the other two colors. - color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; - color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; - color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; - color_array[2].a = 0xFF; + // Four-color block: derive the other two colors. + color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; + color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; + color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; + color_array[2].a = 0xFF; - color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; - color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; - color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; - color_array[3].a = 0xFF; + color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; + color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; + color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; + color_array[3].a = 0xFF; } - void BlockDXT1::decodeBlock(ColorBlock *block) const { - // Decode color block. - Color32 color_array[4]; - evaluatePalette(color_array); + // Decode color block. + Color32 color_array[4]; + evaluatePalette(color_array); - // Write color block. - for ( uint j = 0; j < 4; j++ ) { - for ( uint i = 0; i < 4; i++ ) { - uint idx = (row[j] >> (2 * i)) & 3; - block->color(i, j) = color_array[idx]; - } - } + // Write color block. + for (uint j = 0; j < 4; j++) { + for (uint i = 0; i < 4; i++) { + uint idx = (row[j] >> (2 * i)) & 3; + block->color(i, j) = color_array[idx]; + } + } } void BlockDXT1::decodeBlockNV5x(ColorBlock *block) const { - // Decode color block. - Color32 color_array[4]; - evaluatePaletteNV5x(color_array); + // Decode color block. + Color32 color_array[4]; + evaluatePaletteNV5x(color_array); - // Write color block. - for ( uint j = 0; j < 4; j++ ) { - for ( uint i = 0; i < 4; i++ ) { - uint idx = (row[j] >> (2 * i)) & 3; - block->color(i, j) = color_array[idx]; - } - } + // Write color block. + for (uint j = 0; j < 4; j++) { + for (uint i = 0; i < 4; i++) { + uint idx = (row[j] >> (2 * i)) & 3; + block->color(i, j) = color_array[idx]; + } + } } void BlockDXT1::setIndices(int *idx) { - indices = 0; - for (uint i = 0; i < 16; i++) { - indices |= (idx[i] & 3) << (2 * i); - } + indices = 0; + for (uint i = 0; i < 16; i++) { + indices |= (idx[i] & 3) << (2 * i); + } } - /// Flip DXT1 block vertically. inline void BlockDXT1::flip4() { - swap(row[0], row[3]); - swap(row[1], row[2]); + swap(row[0], row[3]); + swap(row[1], row[2]); } /// Flip half DXT1 block vertically. inline void BlockDXT1::flip2() { - swap(row[0], row[1]); + swap(row[0], row[1]); } - /*---------------------------------------------------------------------------- - BlockDXT3 + BlockDXT3 ----------------------------------------------------------------------------*/ void BlockDXT3::decodeBlock(ColorBlock *block) const { - // Decode color. - color.decodeBlock(block); + // Decode color. + color.decodeBlock(block); - // Decode alpha. - alpha.decodeBlock(block); + // Decode alpha. + alpha.decodeBlock(block); } void BlockDXT3::decodeBlockNV5x(ColorBlock *block) const { - color.decodeBlockNV5x(block); - alpha.decodeBlock(block); + color.decodeBlockNV5x(block); + alpha.decodeBlock(block); } void AlphaBlockDXT3::decodeBlock(ColorBlock *block) const { - block->color(0x0).a = (alpha0 << 4) | alpha0; - block->color(0x1).a = (alpha1 << 4) | alpha1; - block->color(0x2).a = (alpha2 << 4) | alpha2; - block->color(0x3).a = (alpha3 << 4) | alpha3; - block->color(0x4).a = (alpha4 << 4) | alpha4; - block->color(0x5).a = (alpha5 << 4) | alpha5; - block->color(0x6).a = (alpha6 << 4) | alpha6; - block->color(0x7).a = (alpha7 << 4) | alpha7; - block->color(0x8).a = (alpha8 << 4) | alpha8; - block->color(0x9).a = (alpha9 << 4) | alpha9; - block->color(0xA).a = (alphaA << 4) | alphaA; - block->color(0xB).a = (alphaB << 4) | alphaB; - block->color(0xC).a = (alphaC << 4) | alphaC; - block->color(0xD).a = (alphaD << 4) | alphaD; - block->color(0xE).a = (alphaE << 4) | alphaE; - block->color(0xF).a = (alphaF << 4) | alphaF; + block->color(0x0).a = (alpha0 << 4) | alpha0; + block->color(0x1).a = (alpha1 << 4) | alpha1; + block->color(0x2).a = (alpha2 << 4) | alpha2; + block->color(0x3).a = (alpha3 << 4) | alpha3; + block->color(0x4).a = (alpha4 << 4) | alpha4; + block->color(0x5).a = (alpha5 << 4) | alpha5; + block->color(0x6).a = (alpha6 << 4) | alpha6; + block->color(0x7).a = (alpha7 << 4) | alpha7; + block->color(0x8).a = (alpha8 << 4) | alpha8; + block->color(0x9).a = (alpha9 << 4) | alpha9; + block->color(0xA).a = (alphaA << 4) | alphaA; + block->color(0xB).a = (alphaB << 4) | alphaB; + block->color(0xC).a = (alphaC << 4) | alphaC; + block->color(0xD).a = (alphaD << 4) | alphaD; + block->color(0xE).a = (alphaE << 4) | alphaE; + block->color(0xF).a = (alphaF << 4) | alphaF; } /// Flip DXT3 alpha block vertically. void AlphaBlockDXT3::flip4() { - swap(row[0], row[3]); - swap(row[1], row[2]); + swap(row[0], row[3]); + swap(row[1], row[2]); } /// Flip half DXT3 alpha block vertically. void AlphaBlockDXT3::flip2() { - swap(row[0], row[1]); + swap(row[0], row[1]); } /// Flip DXT3 block vertically. void BlockDXT3::flip4() { - alpha.flip4(); - color.flip4(); + alpha.flip4(); + color.flip4(); } /// Flip half DXT3 block vertically. void BlockDXT3::flip2() { - alpha.flip2(); - color.flip2(); + alpha.flip2(); + color.flip2(); } - /*---------------------------------------------------------------------------- - BlockDXT5 + BlockDXT5 ----------------------------------------------------------------------------*/ void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const { - if (alpha0() > alpha1()) { - evaluatePalette8(alpha); - } - else { - evaluatePalette6(alpha); - } + if (alpha0() > alpha1()) { + evaluatePalette8(alpha); + } + else { + evaluatePalette6(alpha); + } } void AlphaBlockDXT5::evaluatePalette8(uint8 alpha[8]) const { - // 8-alpha block: derive the other six alphas. - // Bit code 000 = alpha0, 001 = alpha1, others are interpolated. - alpha[0] = alpha0(); - alpha[1] = alpha1(); - alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7; // bit code 010 - alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7; // bit code 011 - alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7; // bit code 100 - alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7; // bit code 101 - alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7; // bit code 110 - alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7; // bit code 111 + // 8-alpha block: derive the other six alphas. + // Bit code 000 = alpha0, 001 = alpha1, others are interpolated. + alpha[0] = alpha0(); + alpha[1] = alpha1(); + alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7; // bit code 010 + alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7; // bit code 011 + alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7; // bit code 100 + alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7; // bit code 101 + alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7; // bit code 110 + alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7; // bit code 111 } void AlphaBlockDXT5::evaluatePalette6(uint8 alpha[8]) const { - // 6-alpha block. - // Bit code 000 = alpha0, 001 = alpha1, others are interpolated. - alpha[0] = alpha0(); - alpha[1] = alpha1(); - alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5; // Bit code 010 - alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5; // Bit code 011 - alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5; // Bit code 100 - alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5; // Bit code 101 - alpha[6] = 0x00; // Bit code 110 - alpha[7] = 0xFF; // Bit code 111 + // 6-alpha block. + // Bit code 000 = alpha0, 001 = alpha1, others are interpolated. + alpha[0] = alpha0(); + alpha[1] = alpha1(); + alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5; // Bit code 010 + alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5; // Bit code 011 + alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5; // Bit code 100 + alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5; // Bit code 101 + alpha[6] = 0x00; // Bit code 110 + alpha[7] = 0xFF; // Bit code 111 } void AlphaBlockDXT5::indices(uint8 index_array[16]) const { - index_array[0x0] = bits0(); - index_array[0x1] = bits1(); - index_array[0x2] = bits2(); - index_array[0x3] = bits3(); - index_array[0x4] = bits4(); - index_array[0x5] = bits5(); - index_array[0x6] = bits6(); - index_array[0x7] = bits7(); - index_array[0x8] = bits8(); - index_array[0x9] = bits9(); - index_array[0xA] = bitsA(); - index_array[0xB] = bitsB(); - index_array[0xC] = bitsC(); - index_array[0xD] = bitsD(); - index_array[0xE] = bitsE(); - index_array[0xF] = bitsF(); + index_array[0x0] = bits0(); + index_array[0x1] = bits1(); + index_array[0x2] = bits2(); + index_array[0x3] = bits3(); + index_array[0x4] = bits4(); + index_array[0x5] = bits5(); + index_array[0x6] = bits6(); + index_array[0x7] = bits7(); + index_array[0x8] = bits8(); + index_array[0x9] = bits9(); + index_array[0xA] = bitsA(); + index_array[0xB] = bitsB(); + index_array[0xC] = bitsC(); + index_array[0xD] = bitsD(); + index_array[0xE] = bitsE(); + index_array[0xF] = bitsF(); } uint AlphaBlockDXT5::index(uint index) const { - int offset = (3 * index + 16); - return uint((this->u >> offset) & 0x7); + int offset = (3 * index + 16); + return uint((this->u >> offset) & 0x7); } void AlphaBlockDXT5::setIndex(uint index, uint value) { - int offset = (3 * index + 16); - uint64 mask = uint64(0x7) << offset; - this->u = (this->u & ~mask) | (uint64(value) << offset); + int offset = (3 * index + 16); + uint64 mask = uint64(0x7) << offset; + this->u = (this->u & ~mask) | (uint64(value) << offset); } void AlphaBlockDXT5::decodeBlock(ColorBlock *block) const { - uint8 alpha_array[8]; - evaluatePalette(alpha_array); + uint8 alpha_array[8]; + evaluatePalette(alpha_array); - uint8 index_array[16]; - indices(index_array); + uint8 index_array[16]; + indices(index_array); - for (uint i = 0; i < 16; i++) { - block->color(i).a = alpha_array[index_array[i]]; - } + for (uint i = 0; i < 16; i++) { + block->color(i).a = alpha_array[index_array[i]]; + } } void AlphaBlockDXT5::flip4() { - uint64 *b = (uint64 *)this; + uint64 *b = (uint64 *)this; - // @@ The masks might have to be byte swapped. - uint64 tmp = (*b & (uint64)(0x000000000000FFFFLL)); - tmp |= (*b & (uint64)(0x000000000FFF0000LL)) << 36; - tmp |= (*b & (uint64)(0x000000FFF0000000LL)) << 12; - tmp |= (*b & (uint64)(0x000FFF0000000000LL)) >> 12; - tmp |= (*b & (uint64)(0xFFF0000000000000LL)) >> 36; + // @@ The masks might have to be byte swapped. + uint64 tmp = (*b & (uint64)(0x000000000000FFFFLL)); + tmp |= (*b & (uint64)(0x000000000FFF0000LL)) << 36; + tmp |= (*b & (uint64)(0x000000FFF0000000LL)) << 12; + tmp |= (*b & (uint64)(0x000FFF0000000000LL)) >> 12; + tmp |= (*b & (uint64)(0xFFF0000000000000LL)) >> 36; - *b = tmp; + *b = tmp; } void AlphaBlockDXT5::flip2() { - uint *b = (uint *)this; + uint *b = (uint *)this; - // @@ The masks might have to be byte swapped. - uint tmp = (*b & 0xFF000000); - tmp |= (*b & 0x00000FFF) << 12; - tmp |= (*b & 0x00FFF000) >> 12; + // @@ The masks might have to be byte swapped. + uint tmp = (*b & 0xFF000000); + tmp |= (*b & 0x00000FFF) << 12; + tmp |= (*b & 0x00FFF000) >> 12; - *b = tmp; + *b = tmp; } void BlockDXT5::decodeBlock(ColorBlock *block) const { - // Decode color. - color.decodeBlock(block); + // Decode color. + color.decodeBlock(block); - // Decode alpha. - alpha.decodeBlock(block); + // Decode alpha. + alpha.decodeBlock(block); } void BlockDXT5::decodeBlockNV5x(ColorBlock *block) const { - // Decode color. - color.decodeBlockNV5x(block); + // Decode color. + color.decodeBlockNV5x(block); - // Decode alpha. - alpha.decodeBlock(block); + // Decode alpha. + alpha.decodeBlock(block); } /// Flip DXT5 block vertically. void BlockDXT5::flip4() { - alpha.flip4(); - color.flip4(); + alpha.flip4(); + color.flip4(); } /// Flip half DXT5 block vertically. void BlockDXT5::flip2() { - alpha.flip2(); - color.flip2(); + alpha.flip2(); + color.flip2(); } - /// Decode ATI1 block. void BlockATI1::decodeBlock(ColorBlock *block) const { - uint8 alpha_array[8]; - alpha.evaluatePalette(alpha_array); + uint8 alpha_array[8]; + alpha.evaluatePalette(alpha_array); - uint8 index_array[16]; - alpha.indices(index_array); + uint8 index_array[16]; + alpha.indices(index_array); - for (uint i = 0; i < 16; i++) { - Color32 & c = block->color(i); - c.b = c.g = c.r = alpha_array[index_array[i]]; - c.a = 255; - } + for (uint i = 0; i < 16; i++) { + Color32 &c = block->color(i); + c.b = c.g = c.r = alpha_array[index_array[i]]; + c.a = 255; + } } /// Flip ATI1 block vertically. void BlockATI1::flip4() { - alpha.flip4(); + alpha.flip4(); } /// Flip half ATI1 block vertically. void BlockATI1::flip2() { - alpha.flip2(); + alpha.flip2(); } - /// Decode ATI2 block. void BlockATI2::decodeBlock(ColorBlock *block) const { - uint8 alpha_array[8]; - uint8 index_array[16]; + uint8 alpha_array[8]; + uint8 index_array[16]; - x.evaluatePalette(alpha_array); - x.indices(index_array); + x.evaluatePalette(alpha_array); + x.indices(index_array); - for (uint i = 0; i < 16; i++) { - Color32 & c = block->color(i); - c.r = alpha_array[index_array[i]]; - } + for (uint i = 0; i < 16; i++) { + Color32 &c = block->color(i); + c.r = alpha_array[index_array[i]]; + } - y.evaluatePalette(alpha_array); - y.indices(index_array); + y.evaluatePalette(alpha_array); + y.indices(index_array); - for (uint i = 0; i < 16; i++) { - Color32 & c = block->color(i); - c.g = alpha_array[index_array[i]]; - c.b = 0; - c.a = 255; - } + for (uint i = 0; i < 16; i++) { + Color32 &c = block->color(i); + c.g = alpha_array[index_array[i]]; + c.b = 0; + c.a = 255; + } } /// Flip ATI2 block vertically. void BlockATI2::flip4() { - x.flip4(); - y.flip4(); + x.flip4(); + y.flip4(); } /// Flip half ATI2 block vertically. void BlockATI2::flip2() { - x.flip2(); - y.flip2(); + x.flip2(); + y.flip2(); } - void BlockCTX1::evaluatePalette(Color32 color_array[4]) const { - // Does bit expansion before interpolation. - color_array[0].b = 0x00; - color_array[0].g = col0[1]; - color_array[0].r = col0[0]; - color_array[0].a = 0xFF; + // Does bit expansion before interpolation. + color_array[0].b = 0x00; + color_array[0].g = col0[1]; + color_array[0].r = col0[0]; + color_array[0].a = 0xFF; - color_array[1].r = 0x00; - color_array[1].g = col0[1]; - color_array[1].b = col1[0]; - color_array[1].a = 0xFF; + color_array[1].r = 0x00; + color_array[1].g = col0[1]; + color_array[1].b = col1[0]; + color_array[1].a = 0xFF; - color_array[2].r = 0x00; - color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; - color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; - color_array[2].a = 0xFF; + color_array[2].r = 0x00; + color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; + color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; + color_array[2].a = 0xFF; - color_array[3].r = 0x00; - color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; - color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; - color_array[3].a = 0xFF; + color_array[3].r = 0x00; + color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; + color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; + color_array[3].a = 0xFF; } void BlockCTX1::decodeBlock(ColorBlock *block) const { - // Decode color block. - Color32 color_array[4]; - evaluatePalette(color_array); + // Decode color block. + Color32 color_array[4]; + evaluatePalette(color_array); - // Write color block. - for ( uint j = 0; j < 4; j++ ) { - for ( uint i = 0; i < 4; i++ ) { - uint idx = (row[j] >> (2 * i)) & 3; - block->color(i, j) = color_array[idx]; - } - } + // Write color block. + for (uint j = 0; j < 4; j++) { + for (uint i = 0; i < 4; i++) { + uint idx = (row[j] >> (2 * i)) & 3; + block->color(i, j) = color_array[idx]; + } + } } void BlockCTX1::setIndices(int *idx) { - indices = 0; - for (uint i = 0; i < 16; i++) { - indices |= (idx[i] & 3) << (2 * i); - } + indices = 0; + for (uint i = 0; i < 16; i++) { + indices |= (idx[i] & 3) << (2 * i); + } } - /// Flip CTX1 block vertically. inline void BlockCTX1::flip4() { - swap(row[0], row[3]); - swap(row[1], row[2]); + swap(row[0], row[3]); + swap(row[1], row[2]); } /// Flip half CTX1 block vertically. inline void BlockCTX1::flip2() { - swap(row[0], row[1]); + swap(row[0], row[1]); } -void mem_read(Stream & mem, BlockDXT1 & block) +void mem_read(Stream &mem, BlockDXT1 &block) { - mem_read(mem, block.col0.u); - mem_read(mem, block.col1.u); - mem_read(mem, block.indices); + mem_read(mem, block.col0.u); + mem_read(mem, block.col1.u); + mem_read(mem, block.indices); } -void mem_read(Stream & mem, AlphaBlockDXT3 & block) +void mem_read(Stream &mem, AlphaBlockDXT3 &block) { - for (unsigned int i = 0; i < 4; i++) mem_read(mem, block.row[i]); + for (unsigned int i = 0; i < 4; i++) + mem_read(mem, block.row[i]); } -void mem_read(Stream & mem, BlockDXT3 & block) +void mem_read(Stream &mem, BlockDXT3 &block) { - mem_read(mem, block.alpha); - mem_read(mem, block.color); + mem_read(mem, block.alpha); + mem_read(mem, block.color); } -void mem_read(Stream & mem, AlphaBlockDXT5 & block) +void mem_read(Stream &mem, AlphaBlockDXT5 &block) { - mem_read(mem, block.u); + mem_read(mem, block.u); } -void mem_read(Stream & mem, BlockDXT5 & block) +void mem_read(Stream &mem, BlockDXT5 &block) { - mem_read(mem, block.alpha); - mem_read(mem, block.color); + mem_read(mem, block.alpha); + mem_read(mem, block.color); } -void mem_read(Stream & mem, BlockATI1 & block) +void mem_read(Stream &mem, BlockATI1 &block) { - mem_read(mem, block.alpha); + mem_read(mem, block.alpha); } -void mem_read(Stream & mem, BlockATI2 & block) +void mem_read(Stream &mem, BlockATI2 &block) { - mem_read(mem, block.x); - mem_read(mem, block.y); + mem_read(mem, block.x); + mem_read(mem, block.y); } -void mem_read(Stream & mem, BlockCTX1 & block) +void mem_read(Stream &mem, BlockCTX1 &block) { - mem_read(mem, block.col0[0]); - mem_read(mem, block.col0[1]); - mem_read(mem, block.col1[0]); - mem_read(mem, block.col1[1]); - mem_read(mem, block.indices); + mem_read(mem, block.col0[0]); + mem_read(mem, block.col0[1]); + mem_read(mem, block.col1[0]); + mem_read(mem, block.col1[1]); + mem_read(mem, block.indices); } diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 82ec5b45d4e..c13fa42dcdc 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -59,202 +58,252 @@ /// DXT1 block. struct BlockDXT1 { - Color16 col0; - Color16 col1; - union { - uint8 row[4]; - uint indices; - }; + Color16 col0; + Color16 col1; + union { + uint8 row[4]; + uint indices; + }; - bool isFourColorMode() const; + bool isFourColorMode() const; - uint evaluatePalette(Color32 color_array[4]) const; - uint evaluatePaletteNV5x(Color32 color_array[4]) const; + uint evaluatePalette(Color32 color_array[4]) const; + uint evaluatePaletteNV5x(Color32 color_array[4]) const; - void evaluatePalette3(Color32 color_array[4]) const; - void evaluatePalette4(Color32 color_array[4]) const; + void evaluatePalette3(Color32 color_array[4]) const; + void evaluatePalette4(Color32 color_array[4]) const; - void decodeBlock(ColorBlock * block) const; - void decodeBlockNV5x(ColorBlock * block) const; + void decodeBlock(ColorBlock *block) const; + void decodeBlockNV5x(ColorBlock *block) const; - void setIndices(int * idx); + void setIndices(int *idx); - void flip4(); - void flip2(); + void flip4(); + void flip2(); }; /// Return true if the block uses four color mode, false otherwise. inline bool BlockDXT1::isFourColorMode() const { - return col0.u > col1.u; + return col0.u > col1.u; } - /// DXT3 alpha block with explicit alpha. struct AlphaBlockDXT3 { - union { - struct { - uint alpha0 : 4; - uint alpha1 : 4; - uint alpha2 : 4; - uint alpha3 : 4; - uint alpha4 : 4; - uint alpha5 : 4; - uint alpha6 : 4; - uint alpha7 : 4; - uint alpha8 : 4; - uint alpha9 : 4; - uint alphaA : 4; - uint alphaB : 4; - uint alphaC : 4; - uint alphaD : 4; - uint alphaE : 4; - uint alphaF : 4; - }; - uint16 row[4]; - }; - - void decodeBlock(ColorBlock * block) const; - - void flip4(); - void flip2(); + union { + struct { + uint alpha0 : 4; + uint alpha1 : 4; + uint alpha2 : 4; + uint alpha3 : 4; + uint alpha4 : 4; + uint alpha5 : 4; + uint alpha6 : 4; + uint alpha7 : 4; + uint alpha8 : 4; + uint alpha9 : 4; + uint alphaA : 4; + uint alphaB : 4; + uint alphaC : 4; + uint alphaD : 4; + uint alphaE : 4; + uint alphaF : 4; + }; + uint16 row[4]; + }; + + void decodeBlock(ColorBlock *block) const; + + void flip4(); + void flip2(); }; - /// DXT3 block. struct BlockDXT3 { - AlphaBlockDXT3 alpha; - BlockDXT1 color; + AlphaBlockDXT3 alpha; + BlockDXT1 color; - void decodeBlock(ColorBlock * block) const; - void decodeBlockNV5x(ColorBlock * block) const; + void decodeBlock(ColorBlock *block) const; + void decodeBlockNV5x(ColorBlock *block) const; - void flip4(); - void flip2(); + void flip4(); + void flip2(); }; - /// DXT5 alpha block. struct AlphaBlockDXT5 { - // uint64 unions do not compile on all platforms + // uint64 unions do not compile on all platforms #if 0 - union { - struct { - uint64 alpha0 : 8; // 8 - uint64 alpha1 : 8; // 16 - uint64 bits0 : 3; // 3 - 19 - uint64 bits1 : 3; // 6 - 22 - uint64 bits2 : 3; // 9 - 25 - uint64 bits3 : 3; // 12 - 28 - uint64 bits4 : 3; // 15 - 31 - uint64 bits5 : 3; // 18 - 34 - uint64 bits6 : 3; // 21 - 37 - uint64 bits7 : 3; // 24 - 40 - uint64 bits8 : 3; // 27 - 43 - uint64 bits9 : 3; // 30 - 46 - uint64 bitsA : 3; // 33 - 49 - uint64 bitsB : 3; // 36 - 52 - uint64 bitsC : 3; // 39 - 55 - uint64 bitsD : 3; // 42 - 58 - uint64 bitsE : 3; // 45 - 61 - uint64 bitsF : 3; // 48 - 64 - }; - uint64 u; - }; + union { + struct { + uint64 alpha0 : 8; // 8 + uint64 alpha1 : 8; // 16 + uint64 bits0 : 3; // 3 - 19 + uint64 bits1 : 3; // 6 - 22 + uint64 bits2 : 3; // 9 - 25 + uint64 bits3 : 3; // 12 - 28 + uint64 bits4 : 3; // 15 - 31 + uint64 bits5 : 3; // 18 - 34 + uint64 bits6 : 3; // 21 - 37 + uint64 bits7 : 3; // 24 - 40 + uint64 bits8 : 3; // 27 - 43 + uint64 bits9 : 3; // 30 - 46 + uint64 bitsA : 3; // 33 - 49 + uint64 bitsB : 3; // 36 - 52 + uint64 bitsC : 3; // 39 - 55 + uint64 bitsD : 3; // 42 - 58 + uint64 bitsE : 3; // 45 - 61 + uint64 bitsF : 3; // 48 - 64 + }; + uint64 u; + }; #endif - 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; } - - void evaluatePalette(uint8 alpha[8]) const; - void evaluatePalette8(uint8 alpha[8]) const; - void evaluatePalette6(uint8 alpha[8]) const; - void indices(uint8 index_array[16]) const; - - uint index(uint index) const; - void setIndex(uint index, uint value); - - void decodeBlock(ColorBlock * block) const; - - void flip4(); - void flip2(); + 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; + } + + void evaluatePalette(uint8 alpha[8]) const; + void evaluatePalette8(uint8 alpha[8]) const; + void evaluatePalette6(uint8 alpha[8]) const; + void indices(uint8 index_array[16]) const; + + uint index(uint index) const; + void setIndex(uint index, uint value); + + void decodeBlock(ColorBlock *block) const; + + void flip4(); + void flip2(); }; - /// DXT5 block. struct BlockDXT5 { - AlphaBlockDXT5 alpha; - BlockDXT1 color; + AlphaBlockDXT5 alpha; + BlockDXT1 color; - void decodeBlock(ColorBlock * block) const; - void decodeBlockNV5x(ColorBlock * block) const; + void decodeBlock(ColorBlock *block) const; + void decodeBlockNV5x(ColorBlock *block) const; - void flip4(); - void flip2(); + void flip4(); + void flip2(); }; /// ATI1 block. struct BlockATI1 { - AlphaBlockDXT5 alpha; + AlphaBlockDXT5 alpha; - void decodeBlock(ColorBlock * block) const; + void decodeBlock(ColorBlock *block) const; - void flip4(); - void flip2(); + void flip4(); + void flip2(); }; /// ATI2 block. struct BlockATI2 { - AlphaBlockDXT5 x; - AlphaBlockDXT5 y; + AlphaBlockDXT5 x; + AlphaBlockDXT5 y; - void decodeBlock(ColorBlock * block) const; + void decodeBlock(ColorBlock *block) const; - void flip4(); - void flip2(); + void flip4(); + void flip2(); }; /// CTX1 block. struct BlockCTX1 { - uint8 col0[2]; - uint8 col1[2]; - union { - uint8 row[4]; - uint indices; - }; + uint8 col0[2]; + uint8 col1[2]; + union { + uint8 row[4]; + uint indices; + }; - void evaluatePalette(Color32 color_array[4]) const; - void setIndices(int * idx); + void evaluatePalette(Color32 color_array[4]) const; + void setIndices(int *idx); - void decodeBlock(ColorBlock * block) const; + void decodeBlock(ColorBlock *block) const; - void flip4(); - void flip2(); + void flip4(); + void flip2(); }; -void mem_read(Stream & mem, BlockDXT1 & block); -void mem_read(Stream & mem, AlphaBlockDXT3 & block); -void mem_read(Stream & mem, BlockDXT3 & block); -void mem_read(Stream & mem, AlphaBlockDXT5 & block); -void mem_read(Stream & mem, BlockDXT5 & block); -void mem_read(Stream & mem, BlockATI1 & block); -void mem_read(Stream & mem, BlockATI2 & block); -void mem_read(Stream & mem, BlockCTX1 & block); +void mem_read(Stream &mem, BlockDXT1 &block); +void mem_read(Stream &mem, AlphaBlockDXT3 &block); +void mem_read(Stream &mem, BlockDXT3 &block); +void mem_read(Stream &mem, AlphaBlockDXT5 &block); +void mem_read(Stream &mem, BlockDXT5 &block); +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 c68608f4cff..2ec1ea9eb36 100644 --- a/source/blender/imbuf/intern/dds/CMakeLists.txt +++ b/source/blender/imbuf/intern/dds/CMakeLists.txt @@ -19,14 +19,14 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - .. - ../.. - ../../../blenkernel - ../../../blenlib - ../../../makesdna - ../../../../../intern/guardedalloc - ../../../../../intern/utfconv + . + .. + ../.. + ../../../blenkernel + ../../../blenlib + ../../../makesdna + ../../../../../intern/guardedalloc + ../../../../../intern/utfconv ) set(INC_SYS @@ -34,31 +34,31 @@ 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.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 + BlockDXT.cpp + ColorBlock.cpp + DirectDrawSurface.cpp + FlipDXT.cpp + Image.cpp + Stream.cpp + dds_api.cpp ) set(LIB ) if(WITH_IMAGE_DDS) - add_definitions(-DWITH_DDS) + add_definitions(-DWITH_DDS) endif() blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h index da7b77c2854..16432ffa715 100644 --- a/source/blender/imbuf/intern/dds/Color.h +++ b/source/blender/imbuf/intern/dds/Color.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -32,62 +31,79 @@ #define __COLOR_H__ /// 32 bit color stored as BGRA. -class Color32 -{ -public: - Color32() { } - Color32(const Color32 & c) : u(c.u) { } - Color32(unsigned char R, unsigned char G, unsigned char B) { setRGBA(R, G, B, 0xFF); } - Color32(unsigned char R, unsigned char G, unsigned char B, unsigned char A) { setRGBA( R, G, B, A); } - //Color32(unsigned char c[4]) { setRGBA(c[0], c[1], c[2], c[3]); } - //Color32(float R, float G, float B) { setRGBA(uint(R*255), uint(G*255), uint(B*255), 0xFF); } - //Color32(float R, float G, float B, float A) { setRGBA(uint(R*255), uint(G*255), uint(B*255), uint(A*255)); } - Color32(unsigned int U) : u(U) { } +class Color32 { + public: + Color32() + { + } + Color32(const Color32 &c) : u(c.u) + { + } + Color32(unsigned char R, unsigned char G, unsigned char B) + { + setRGBA(R, G, B, 0xFF); + } + Color32(unsigned char R, unsigned char G, unsigned char B, unsigned char A) + { + setRGBA(R, G, B, A); + } + //Color32(unsigned char c[4]) { setRGBA(c[0], c[1], c[2], c[3]); } + //Color32(float R, float G, float B) { setRGBA(uint(R*255), uint(G*255), uint(B*255), 0xFF); } + //Color32(float R, float G, float B, float A) { setRGBA(uint(R*255), uint(G*255), uint(B*255), uint(A*255)); } + Color32(unsigned int U) : u(U) + { + } - void setRGBA(unsigned char R, unsigned char G, unsigned char B, unsigned char A) - { - r = R; - g = G; - b = B; - a = A; - } + void setRGBA(unsigned char R, unsigned char G, unsigned char B, unsigned char A) + { + r = R; + g = G; + b = B; + a = A; + } - void setBGRA(unsigned char B, unsigned char G, unsigned char R, unsigned char A = 0xFF) - { - r = R; - g = G; - b = B; - a = A; - } + void setBGRA(unsigned char B, unsigned char G, unsigned char R, unsigned char A = 0xFF) + { + r = R; + g = G; + b = B; + a = A; + } - operator unsigned int () const { - return u; - } + operator unsigned int() const + { + return u; + } - union { - struct { - unsigned char b, g, r, a; - }; - unsigned int u; - }; + union { + struct { + unsigned char b, g, r, a; + }; + unsigned int u; + }; }; /// 16 bit 565 BGR color. -class Color16 -{ -public: - Color16() { } - Color16(const Color16 & c) : u(c.u) { } - explicit Color16(unsigned short U) : u(U) { } +class Color16 { + public: + Color16() + { + } + Color16(const Color16 &c) : u(c.u) + { + } + explicit Color16(unsigned short U) : u(U) + { + } - union { - struct { - unsigned short b : 5; - unsigned short g : 6; - unsigned short r : 5; - }; - unsigned short u; - }; + union { + struct { + unsigned short b : 5; + unsigned short g : 6; + unsigned short r : 5; + }; + unsigned short u; + }; }; -#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 e0c1c168d50..73397cd036e 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -33,20 +32,19 @@ #include #if 0 - // Get approximate luminance. - inline static uint colorLuminance(Color32 c) - { - return c.r + c.g + c.b; - } - - // Get the euclidean distance between the given colors. - inline static uint colorDistance(Color32 c0, Color32 c1) - { - return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b); - } + // Get approximate luminance. + inline static uint colorLuminance(Color32 c) + { + return c.r + c.g + c.b; + } + + // Get the euclidean distance between the given colors. + inline static uint colorDistance(Color32 c0, Color32 c1) + { + return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b); + } #endif - /// Default constructor. ColorBlock::ColorBlock() { @@ -55,138 +53,143 @@ ColorBlock::ColorBlock() /// Init the color block from an array of colors. ColorBlock::ColorBlock(const uint *linearImage) { - for (uint i = 0; i < 16; i++) { - color(i) = Color32(linearImage[i]); - } + for (uint i = 0; i < 16; i++) { + color(i) = Color32(linearImage[i]); + } } /// Init the color block with the contents of the given block. -ColorBlock::ColorBlock(const ColorBlock & block) +ColorBlock::ColorBlock(const ColorBlock &block) { - for (uint i = 0; i < 16; i++) { - color(i) = block.color(i); - } + for (uint i = 0; i < 16; i++) { + color(i) = block.color(i); + } } - /// Initialize this color block. ColorBlock::ColorBlock(const Image *img, uint x, uint y) { - init(img, x, y); + init(img, x, y); } void ColorBlock::init(const Image *img, uint x, uint y) { - init(img->width(), img->height(), (const uint *)img->pixels(), x, y); + init(img->width(), img->height(), (const uint *)img->pixels(), x, y); } void ColorBlock::init(uint w, uint h, const uint *data, uint x, uint y) { - const uint bw = MIN(w - x, 4U); - const uint bh = MIN(h - y, 4U); + const uint bw = MIN(w - x, 4U); + const uint bh = MIN(h - y, 4U); - // Blocks that are smaller than 4x4 are handled by repeating the pixels. - // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :( - // @@ Ideally we should zero the weights of the pixels out of range. + // Blocks that are smaller than 4x4 are handled by repeating the pixels. + // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :( + // @@ Ideally we should zero the weights of the pixels out of range. - for (uint i = 0; i < 4; i++) { - const int by = i % bh; + for (uint i = 0; i < 4; i++) { + const int by = i % bh; - for (uint e = 0; e < 4; e++) { - const int bx = e % bw; - const uint idx = (y + by) * w + x + bx; + for (uint e = 0; e < 4; e++) { + const int bx = e % bw; + const uint idx = (y + by) * w + x + bx; - color(e, i).u = data[idx]; - } - } + color(e, i).u = data[idx]; + } + } } void ColorBlock::init(uint w, uint h, const float *data, uint x, uint y) { - const uint bw = MIN(w - x, 4U); - const uint bh = MIN(h - y, 4U); - - // Blocks that are smaller than 4x4 are handled by repeating the pixels. - // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :( - // @@ Ideally we should zero the weights of the pixels out of range. - - uint srcPlane = w * h; - - for (uint i = 0; i < 4; i++) { - const uint by = i % bh; - - for (uint e = 0; e < 4; e++) { - const uint bx = e % bw; - const uint idx = ((y + by) * w + x + bx); - - Color32 & c = color(e, i); - c.r = uint8(255 * CLAMP(data[idx + 0 * srcPlane], 0.0f, 1.0f)); // @@ Is this the right way to quantize floats to bytes? - c.g = uint8(255 * CLAMP(data[idx + 1 * srcPlane], 0.0f, 1.0f)); - c.b = uint8(255 * CLAMP(data[idx + 2 * srcPlane], 0.0f, 1.0f)); - c.a = uint8(255 * CLAMP(data[idx + 3 * srcPlane], 0.0f, 1.0f)); - } - } + const uint bw = MIN(w - x, 4U); + const uint bh = MIN(h - y, 4U); + + // Blocks that are smaller than 4x4 are handled by repeating the pixels. + // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :( + // @@ Ideally we should zero the weights of the pixels out of range. + + uint srcPlane = w * h; + + for (uint i = 0; i < 4; i++) { + const uint by = i % bh; + + for (uint e = 0; e < 4; e++) { + const uint bx = e % bw; + const uint idx = ((y + by) * w + x + bx); + + Color32 &c = color(e, i); + c.r = uint8(255 * CLAMP(data[idx + 0 * srcPlane], + 0.0f, + 1.0f)); // @@ Is this the right way to quantize floats to bytes? + c.g = uint8(255 * CLAMP(data[idx + 1 * srcPlane], 0.0f, 1.0f)); + c.b = uint8(255 * CLAMP(data[idx + 2 * srcPlane], 0.0f, 1.0f)); + c.a = uint8(255 * CLAMP(data[idx + 3 * srcPlane], 0.0f, 1.0f)); + } + } } static inline uint8 component(Color32 c, uint i) { - if (i == 0) return c.r; - if (i == 1) return c.g; - if (i == 2) return c.b; - if (i == 3) return c.a; - if (i == 4) return 0xFF; - return 0; + if (i == 0) + return c.r; + if (i == 1) + return c.g; + if (i == 2) + return c.b; + if (i == 3) + return c.a; + if (i == 4) + return 0xFF; + return 0; } void ColorBlock::swizzle(uint x, uint y, uint z, uint w) { - for (int i = 0; i < 16; i++) { - Color32 c = m_color[i]; - m_color[i].r = component(c, x); - m_color[i].g = component(c, y); - m_color[i].b = component(c, z); - m_color[i].a = component(c, w); - } + for (int i = 0; i < 16; i++) { + Color32 c = m_color[i]; + m_color[i].r = component(c, x); + m_color[i].g = component(c, y); + m_color[i].b = component(c, z); + m_color[i].a = component(c, w); + } } - /// Returns true if the block has a single color. -bool ColorBlock::isSingleColor(Color32 mask/*= Color32(0xFF, 0xFF, 0xFF, 0x00)*/) const +bool ColorBlock::isSingleColor(Color32 mask /*= Color32(0xFF, 0xFF, 0xFF, 0x00)*/) const { - uint u = m_color[0].u & mask.u; + uint u = m_color[0].u & mask.u; - for (int i = 1; i < 16; i++) { - if (u != (m_color[i].u & mask.u)) { - return false; - } - } + for (int i = 1; i < 16; i++) { + if (u != (m_color[i].u & mask.u)) { + return false; + } + } - return true; + return true; } #if 0 /// Returns true if the block has a single color, ignoring transparent pixels. bool ColorBlock::isSingleColorNoAlpha() const { - Color32 c; - int i; - for (i = 0; i < 16; i++) - { - if (m_color[i].a != 0) c = m_color[i]; - } - - Color32 mask(0xFF, 0xFF, 0xFF, 0x00); - uint u = c.u & mask.u; - - for (; i < 16; i++) - { - if (u != (m_color[i].u & mask.u)) - { - return false; - } - } - - return true; + Color32 c; + int i; + for (i = 0; i < 16; i++) + { + if (m_color[i].a != 0) c = m_color[i]; + } + + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = c.u & mask.u; + + for (; i < 16; i++) + { + if (u != (m_color[i].u & mask.u)) + { + return false; + } + } + + return true; } #endif @@ -194,24 +197,24 @@ bool ColorBlock::isSingleColorNoAlpha() const /// Count number of unique colors in this color block. uint ColorBlock::countUniqueColors() const { - uint count = 0; - - // @@ This does not have to be o(n^2) - for (int i = 0; i < 16; i++) - { - bool unique = true; - for (int j = 0; j < i; j++) { - if ( m_color[i] != m_color[j] ) { - unique = false; - } - } - - if ( unique ) { - count++; - } - } - - return count; + uint count = 0; + + // @@ This does not have to be o(n^2) + for (int i = 0; i < 16; i++) + { + bool unique = true; + for (int j = 0; j < i; j++) { + if ( m_color[i] != m_color[j] ) { + unique = false; + } + } + + if ( unique ) { + count++; + } + } + + return count; } #endif @@ -219,27 +222,28 @@ uint ColorBlock::countUniqueColors() const /// Get average color of the block. Color32 ColorBlock::averageColor() const { - uint r, g, b, a; - r = g = b = a = 0; + uint r, g, b, a; + r = g = b = a = 0; - for (uint i = 0; i < 16; i++) { - r += m_color[i].r; - g += m_color[i].g; - b += m_color[i].b; - a += m_color[i].a; - } + for (uint i = 0; i < 16; i++) { + r += m_color[i].r; + g += m_color[i].g; + b += m_color[i].b; + a += m_color[i].a; + } - return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16)); + return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16)); } #endif /// Return true if the block is not fully opaque. bool ColorBlock::hasAlpha() const { - for (uint i = 0; i < 16; i++) { - if (m_color[i].a != 255) return true; - } - return false; + for (uint i = 0; i < 16; i++) { + if (m_color[i].a != 255) + return true; + } + return false; } #if 0 @@ -247,121 +251,121 @@ bool ColorBlock::hasAlpha() const /// Get diameter color range. void ColorBlock::diameterRange(Color32 *start, Color32 *end) const { - Color32 c0, c1; - uint best_dist = 0; - - for (int i = 0; i < 16; i++) { - for (int j = i+1; j < 16; j++) { - uint dist = colorDistance(m_color[i], m_color[j]); - if ( dist > best_dist ) { - best_dist = dist; - c0 = m_color[i]; - c1 = m_color[j]; - } - } - } - - *start = c0; - *end = c1; + Color32 c0, c1; + uint best_dist = 0; + + for (int i = 0; i < 16; i++) { + for (int j = i+1; j < 16; j++) { + uint dist = colorDistance(m_color[i], m_color[j]); + if ( dist > best_dist ) { + best_dist = dist; + c0 = m_color[i]; + c1 = m_color[j]; + } + } + } + + *start = c0; + *end = c1; } /// Get luminance color range. void ColorBlock::luminanceRange(Color32 *start, Color32 *end) const { - Color32 minColor, maxColor; - uint minLuminance, maxLuminance; - - maxLuminance = minLuminance = colorLuminance(m_color[0]); - - for (uint i = 1; i < 16; i++) - { - uint luminance = colorLuminance(m_color[i]); - - if (luminance > maxLuminance) { - maxLuminance = luminance; - maxColor = m_color[i]; - } - else if (luminance < minLuminance) { - minLuminance = luminance; - minColor = m_color[i]; - } - } - - *start = minColor; - *end = maxColor; + Color32 minColor, maxColor; + uint minLuminance, maxLuminance; + + maxLuminance = minLuminance = colorLuminance(m_color[0]); + + for (uint i = 1; i < 16; i++) + { + uint luminance = colorLuminance(m_color[i]); + + if (luminance > maxLuminance) { + maxLuminance = luminance; + maxColor = m_color[i]; + } + else if (luminance < minLuminance) { + minLuminance = luminance; + minColor = m_color[i]; + } + } + + *start = minColor; + *end = maxColor; } /// Get color range based on the bounding box. void ColorBlock::boundsRange(Color32 *start, Color32 *end) const { - Color32 minColor(255, 255, 255); - Color32 maxColor(0, 0, 0); - - for (uint i = 0; i < 16; i++) - { - if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; } - if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; } - if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; } - if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; } - if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; } - if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; } - } - - // Offset range by 1/16 of the extents - Color32 inset; - inset.r = (maxColor.r - minColor.r) >> 4; - inset.g = (maxColor.g - minColor.g) >> 4; - inset.b = (maxColor.b - minColor.b) >> 4; - - minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255; - minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255; - minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255; - - maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0; - maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0; - maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0; - - *start = minColor; - *end = maxColor; + Color32 minColor(255, 255, 255); + Color32 maxColor(0, 0, 0); + + for (uint i = 0; i < 16; i++) + { + if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; } + if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; } + if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; } + if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; } + if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; } + if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; } + } + + // Offset range by 1/16 of the extents + Color32 inset; + inset.r = (maxColor.r - minColor.r) >> 4; + inset.g = (maxColor.g - minColor.g) >> 4; + inset.b = (maxColor.b - minColor.b) >> 4; + + minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255; + minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255; + minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255; + + maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0; + maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0; + maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0; + + *start = minColor; + *end = maxColor; } /// Get color range based on the bounding box. void ColorBlock::boundsRangeAlpha(Color32 *start, Color32 *end) const { - Color32 minColor(255, 255, 255, 255); - Color32 maxColor(0, 0, 0, 0); - - for (uint i = 0; i < 16; i++) - { - if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; } - if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; } - if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; } - if (m_color[i].a < minColor.a) { minColor.a = m_color[i].a; } - if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; } - if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; } - if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; } - if (m_color[i].a > maxColor.a) { maxColor.a = m_color[i].a; } - } - - // Offset range by 1/16 of the extents - Color32 inset; - inset.r = (maxColor.r - minColor.r) >> 4; - inset.g = (maxColor.g - minColor.g) >> 4; - inset.b = (maxColor.b - minColor.b) >> 4; - inset.a = (maxColor.a - minColor.a) >> 4; - - minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255; - minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255; - minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255; - minColor.a = (minColor.a + inset.a <= 255) ? minColor.a + inset.a : 255; - - maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0; - maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0; - maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0; - maxColor.a = (maxColor.a >= inset.a) ? maxColor.a - inset.a : 0; - - *start = minColor; - *end = maxColor; + Color32 minColor(255, 255, 255, 255); + Color32 maxColor(0, 0, 0, 0); + + for (uint i = 0; i < 16; i++) + { + if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; } + if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; } + if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; } + if (m_color[i].a < minColor.a) { minColor.a = m_color[i].a; } + if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; } + if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; } + if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; } + if (m_color[i].a > maxColor.a) { maxColor.a = m_color[i].a; } + } + + // Offset range by 1/16 of the extents + Color32 inset; + inset.r = (maxColor.r - minColor.r) >> 4; + inset.g = (maxColor.g - minColor.g) >> 4; + inset.b = (maxColor.b - minColor.b) >> 4; + inset.a = (maxColor.a - minColor.a) >> 4; + + minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255; + minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255; + minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255; + minColor.a = (minColor.a + inset.a <= 255) ? minColor.a + inset.a : 255; + + maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0; + maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0; + maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0; + maxColor.a = (maxColor.a >= inset.a) ? maxColor.a - inset.a : 0; + + *start = minColor; + *end = maxColor; } #endif @@ -369,21 +373,21 @@ void ColorBlock::boundsRangeAlpha(Color32 *start, Color32 *end) const /// Sort colors by abosolute value in their 16 bit representation. void ColorBlock::sortColorsByAbsoluteValue() { - // Dummy selection sort. - for ( uint a = 0; a < 16; a++ ) { - uint max = a; - Color16 cmax(m_color[a]); - - for ( uint b = a+1; b < 16; b++ ) { - Color16 cb(m_color[b]); - - if ( cb.u > cmax.u ) { - max = b; - cmax = cb; - } - } - swap( m_color[a], m_color[max] ); - } + // Dummy selection sort. + for ( uint a = 0; a < 16; a++ ) { + uint max = a; + Color16 cmax(m_color[a]); + + for ( uint b = a+1; b < 16; b++ ) { + Color16 cb(m_color[b]); + + if ( cb.u > cmax.u ) { + max = b; + cmax = cb; + } + } + swap( m_color[a], m_color[max] ); + } } #endif @@ -392,29 +396,29 @@ void ColorBlock::sortColorsByAbsoluteValue() void ColorBlock::computeRange(Vector3::Arg axis, Color32 *start, Color32 *end) const { - int mini, maxi; - mini = maxi = 0; - - 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++) - { - const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b); - - float val = dot(vec, axis); - if ( val < min ) { - mini = i; - min = val; - } - else if ( val > max ) { - maxi = i; - max = val; - } - } - - *start = m_color[mini]; - *end = m_color[maxi]; + int mini, maxi; + mini = maxi = 0; + + 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++) + { + const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b); + + float val = dot(vec, axis); + if ( val < min ) { + mini = i; + min = val; + } + else if ( val > max ) { + maxi = i; + max = val; + } + } + + *start = m_color[mini]; + *end = m_color[maxi]; } #endif @@ -422,24 +426,24 @@ void ColorBlock::computeRange(Vector3::Arg axis, Color32 *start, Color32 *end) c /// Sort colors in the given axis. void ColorBlock::sortColors(const Vector3 & axis) { - float luma_array[16]; - - for (uint i = 0; i < 16; i++) { - const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b); - luma_array[i] = dot(vec, axis); - } - - // Dummy selection sort. - for ( uint a = 0; a < 16; a++ ) { - uint min = a; - for ( uint b = a+1; b < 16; b++ ) { - if ( luma_array[b] < luma_array[min] ) { - min = b; - } - } - swap( luma_array[a], luma_array[min] ); - swap( m_color[a], m_color[min] ); - } + float luma_array[16]; + + for (uint i = 0; i < 16; i++) { + const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b); + luma_array[i] = dot(vec, axis); + } + + // Dummy selection sort. + for ( uint a = 0; a < 16; a++ ) { + uint min = a; + for ( uint b = a+1; b < 16; b++ ) { + if ( luma_array[b] < luma_array[min] ) { + min = b; + } + } + swap( luma_array[a], luma_array[min] ); + swap( m_color[a], m_color[min] ); + } } #endif @@ -447,14 +451,14 @@ void ColorBlock::sortColors(const Vector3 & axis) /// Get the volume of the color block. float ColorBlock::volume() const { - Box bounds; - bounds.clearBounds(); + Box bounds; + bounds.clearBounds(); - for (int i = 0; i < 16; i++) { - const Vector3 point(m_color[i].r, m_color[i].g, m_color[i].b); - bounds.addPointToBounds(point); - } + for (int i = 0; i < 16; i++) { + const Vector3 point(m_color[i].r, m_color[i].g, m_color[i].b); + bounds.addPointToBounds(point); + } - return bounds.volume(); + return bounds.volume(); } #endif diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 66d1ed4e2c5..2e8a6bbda7f 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -36,65 +35,61 @@ /// Uncompressed 4x4 color block. struct ColorBlock { - ColorBlock(); - ColorBlock(const uint * linearImage); - ColorBlock(const ColorBlock & block); - ColorBlock(const Image *img, uint x, uint y); - - void init(const Image *img, uint x, uint y); - void init(uint w, uint h, const uint * data, uint x, uint y); - void init(uint w, uint h, const float * data, uint x, uint y); - - void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0 + ColorBlock(); + ColorBlock(const uint *linearImage); + ColorBlock(const ColorBlock &block); + ColorBlock(const Image *img, uint x, uint y); - bool isSingleColor(Color32 mask = Color32(0xFF, 0xFF, 0xFF, 0x00)) const; - bool hasAlpha() const; + void init(const Image *img, uint x, uint y); + void init(uint w, uint h, const uint *data, uint x, uint y); + void init(uint w, uint h, const float *data, uint x, uint y); + void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0 - // Accessors - const Color32 * colors() const; + bool isSingleColor(Color32 mask = Color32(0xFF, 0xFF, 0xFF, 0x00)) const; + bool hasAlpha() const; - Color32 color(uint i) const; - Color32 & color(uint i); + // Accessors + const Color32 *colors() const; - Color32 color(uint x, uint y) const; - Color32 & color(uint x, uint y); + Color32 color(uint i) const; + Color32 &color(uint i); -private: - - Color32 m_color[4 * 4]; + Color32 color(uint x, uint y) const; + Color32 &color(uint x, uint y); + private: + Color32 m_color[4 * 4]; }; - /// Get pointer to block colors. -inline const Color32 * ColorBlock::colors() const +inline const Color32 *ColorBlock::colors() const { - return m_color; + return m_color; } /// Get block color. inline Color32 ColorBlock::color(uint i) const { - return m_color[i]; + return m_color[i]; } /// Get block color. -inline Color32 & ColorBlock::color(uint i) +inline Color32 &ColorBlock::color(uint i) { - return m_color[i]; + return m_color[i]; } /// Get block color. inline Color32 ColorBlock::color(uint x, uint y) const { - return m_color[y * 4 + x]; + return m_color[y * 4 + x]; } /// Get block color. -inline Color32 & ColorBlock::color(uint x, uint y) +inline Color32 &ColorBlock::color(uint x, uint y) { - return m_color[y * 4 + x]; + 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 1a7d087ec2e..56f5d54cf42 100644 --- a/source/blender/imbuf/intern/dds/Common.h +++ b/source/blender/imbuf/intern/dds/Common.h @@ -18,39 +18,36 @@ * \ingroup imbdds */ - #ifndef __COMMON_H__ #define __COMMON_H__ #ifndef MIN -#define MIN(a,b) ((a) <= (b) ? (a) : (b)) +# define MIN(a, b) ((a) <= (b) ? (a) : (b)) #endif #ifndef MAX -#define MAX(a,b) ((a) >= (b) ? (a) : (b)) +# define MAX(a, b) ((a) >= (b) ? (a) : (b)) #endif #ifndef CLAMP -#define CLAMP(x,a,b) MIN(MAX((x), (a)), (b)) +# define CLAMP(x, a, b) MIN(MAX((x), (a)), (b)) #endif -template -inline void -swap(T & a, T & b) +template 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; -typedef unsigned short uint16; -typedef unsigned int uint; -typedef unsigned int uint32; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint; +typedef unsigned int uint32; typedef unsigned long long uint64; // copied from nvtt src/nvimage/nvimage.h inline uint computePitch(uint w, uint bitsize, uint alignment) { - return ((w * bitsize + 8 * alignment - 1) / (8 * alignment)) * alignment; + return ((w * bitsize + 8 * alignment - 1) / (8 * alignment)) * alignment; } #endif diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 76de84cdee5..3db9b65c461 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -53,17 +52,17 @@ #include #include -#include // printf +#include // printf #include // malloc -#include // sqrt +#include // sqrt #include /*** declarations ***/ #if !defined(DDS_MAKEFOURCC) -# define DDS_MAKEFOURCC(ch0, ch1, ch2, ch3) \ - (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \ - (uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 )) +# define DDS_MAKEFOURCC(ch0, ch1, ch2, ch3) \ + (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | (uint(uint8(ch2)) << 16) | \ + (uint(uint8(ch3)) << 24)) #endif static const uint FOURCC_NVTT = DDS_MAKEFOURCC('N', 'V', 'T', 'T'); @@ -159,727 +158,716 @@ static const uint DDPF_ALPHAPREMULT = 0x00008000U; static const uint DDPF_NORMAL = 0x80000000U; static const uint DDPF_SRGB = 0x40000000U; - // DX10 formats. - enum DXGI_FORMAT - { - DXGI_FORMAT_UNKNOWN = 0, - - DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, - DXGI_FORMAT_R32G32B32A32_FLOAT = 2, - DXGI_FORMAT_R32G32B32A32_UINT = 3, - DXGI_FORMAT_R32G32B32A32_SINT = 4, - - DXGI_FORMAT_R32G32B32_TYPELESS = 5, - DXGI_FORMAT_R32G32B32_FLOAT = 6, - DXGI_FORMAT_R32G32B32_UINT = 7, - DXGI_FORMAT_R32G32B32_SINT = 8, - - DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, - DXGI_FORMAT_R16G16B16A16_FLOAT = 10, - DXGI_FORMAT_R16G16B16A16_UNORM = 11, - DXGI_FORMAT_R16G16B16A16_UINT = 12, - DXGI_FORMAT_R16G16B16A16_SNORM = 13, - DXGI_FORMAT_R16G16B16A16_SINT = 14, - - DXGI_FORMAT_R32G32_TYPELESS = 15, - DXGI_FORMAT_R32G32_FLOAT = 16, - DXGI_FORMAT_R32G32_UINT = 17, - DXGI_FORMAT_R32G32_SINT = 18, - - DXGI_FORMAT_R32G8X24_TYPELESS = 19, - DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, - DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, - DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, - - DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, - DXGI_FORMAT_R10G10B10A2_UNORM = 24, - DXGI_FORMAT_R10G10B10A2_UINT = 25, - - DXGI_FORMAT_R11G11B10_FLOAT = 26, - - DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, - DXGI_FORMAT_R8G8B8A8_UNORM = 28, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, - DXGI_FORMAT_R8G8B8A8_UINT = 30, - DXGI_FORMAT_R8G8B8A8_SNORM = 31, - DXGI_FORMAT_R8G8B8A8_SINT = 32, - - DXGI_FORMAT_R16G16_TYPELESS = 33, - DXGI_FORMAT_R16G16_FLOAT = 34, - DXGI_FORMAT_R16G16_UNORM = 35, - DXGI_FORMAT_R16G16_UINT = 36, - DXGI_FORMAT_R16G16_SNORM = 37, - DXGI_FORMAT_R16G16_SINT = 38, - - DXGI_FORMAT_R32_TYPELESS = 39, - DXGI_FORMAT_D32_FLOAT = 40, - DXGI_FORMAT_R32_FLOAT = 41, - DXGI_FORMAT_R32_UINT = 42, - DXGI_FORMAT_R32_SINT = 43, - - DXGI_FORMAT_R24G8_TYPELESS = 44, - DXGI_FORMAT_D24_UNORM_S8_UINT = 45, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, - DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, - - DXGI_FORMAT_R8G8_TYPELESS = 48, - DXGI_FORMAT_R8G8_UNORM = 49, - DXGI_FORMAT_R8G8_UINT = 50, - DXGI_FORMAT_R8G8_SNORM = 51, - DXGI_FORMAT_R8G8_SINT = 52, - - DXGI_FORMAT_R16_TYPELESS = 53, - DXGI_FORMAT_R16_FLOAT = 54, - DXGI_FORMAT_D16_UNORM = 55, - DXGI_FORMAT_R16_UNORM = 56, - DXGI_FORMAT_R16_UINT = 57, - DXGI_FORMAT_R16_SNORM = 58, - DXGI_FORMAT_R16_SINT = 59, - - DXGI_FORMAT_R8_TYPELESS = 60, - DXGI_FORMAT_R8_UNORM = 61, - DXGI_FORMAT_R8_UINT = 62, - DXGI_FORMAT_R8_SNORM = 63, - DXGI_FORMAT_R8_SINT = 64, - DXGI_FORMAT_A8_UNORM = 65, - - DXGI_FORMAT_R1_UNORM = 66, - - DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, - - DXGI_FORMAT_R8G8_B8G8_UNORM = 68, - DXGI_FORMAT_G8R8_G8B8_UNORM = 69, - - DXGI_FORMAT_BC1_TYPELESS = 70, - DXGI_FORMAT_BC1_UNORM = 71, - DXGI_FORMAT_BC1_UNORM_SRGB = 72, - - DXGI_FORMAT_BC2_TYPELESS = 73, - DXGI_FORMAT_BC2_UNORM = 74, - DXGI_FORMAT_BC2_UNORM_SRGB = 75, - - DXGI_FORMAT_BC3_TYPELESS = 76, - DXGI_FORMAT_BC3_UNORM = 77, - DXGI_FORMAT_BC3_UNORM_SRGB = 78, - - DXGI_FORMAT_BC4_TYPELESS = 79, - DXGI_FORMAT_BC4_UNORM = 80, - DXGI_FORMAT_BC4_SNORM = 81, - - DXGI_FORMAT_BC5_TYPELESS = 82, - DXGI_FORMAT_BC5_UNORM = 83, - DXGI_FORMAT_BC5_SNORM = 84, - - DXGI_FORMAT_B5G6R5_UNORM = 85, - DXGI_FORMAT_B5G5R5A1_UNORM = 86, - 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, - }; - - enum D3D10_RESOURCE_DIMENSION - { - D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, - D3D10_RESOURCE_DIMENSION_BUFFER = 1, - D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, - D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, - D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, - }; - - - static const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) - { -#define CASE(format) case DXGI_FORMAT_##format: return #format - switch (dxgiFormat) - { - CASE(UNKNOWN); - - CASE(R32G32B32A32_TYPELESS); - CASE(R32G32B32A32_FLOAT); - CASE(R32G32B32A32_UINT); - CASE(R32G32B32A32_SINT); - - CASE(R32G32B32_TYPELESS); - CASE(R32G32B32_FLOAT); - CASE(R32G32B32_UINT); - CASE(R32G32B32_SINT); - - CASE(R16G16B16A16_TYPELESS); - CASE(R16G16B16A16_FLOAT); - CASE(R16G16B16A16_UNORM); - CASE(R16G16B16A16_UINT); - CASE(R16G16B16A16_SNORM); - CASE(R16G16B16A16_SINT); - - CASE(R32G32_TYPELESS); - CASE(R32G32_FLOAT); - CASE(R32G32_UINT); - CASE(R32G32_SINT); - - CASE(R32G8X24_TYPELESS); - CASE(D32_FLOAT_S8X24_UINT); - CASE(R32_FLOAT_X8X24_TYPELESS); - CASE(X32_TYPELESS_G8X24_UINT); - - CASE(R10G10B10A2_TYPELESS); - CASE(R10G10B10A2_UNORM); - CASE(R10G10B10A2_UINT); - - CASE(R11G11B10_FLOAT); - - CASE(R8G8B8A8_TYPELESS); - CASE(R8G8B8A8_UNORM); - CASE(R8G8B8A8_UNORM_SRGB); - CASE(R8G8B8A8_UINT); - CASE(R8G8B8A8_SNORM); - CASE(R8G8B8A8_SINT); - - CASE(R16G16_TYPELESS); - CASE(R16G16_FLOAT); - CASE(R16G16_UNORM); - CASE(R16G16_UINT); - CASE(R16G16_SNORM); - CASE(R16G16_SINT); - - CASE(R32_TYPELESS); - CASE(D32_FLOAT); - CASE(R32_FLOAT); - CASE(R32_UINT); - CASE(R32_SINT); - - CASE(R24G8_TYPELESS); - CASE(D24_UNORM_S8_UINT); - CASE(R24_UNORM_X8_TYPELESS); - CASE(X24_TYPELESS_G8_UINT); - - CASE(R8G8_TYPELESS); - CASE(R8G8_UNORM); - CASE(R8G8_UINT); - CASE(R8G8_SNORM); - CASE(R8G8_SINT); - - CASE(R16_TYPELESS); - CASE(R16_FLOAT); - CASE(D16_UNORM); - CASE(R16_UNORM); - CASE(R16_UINT); - CASE(R16_SNORM); - CASE(R16_SINT); - - CASE(R8_TYPELESS); - CASE(R8_UNORM); - CASE(R8_UINT); - CASE(R8_SNORM); - CASE(R8_SINT); - CASE(A8_UNORM); - - CASE(R1_UNORM); - - CASE(R9G9B9E5_SHAREDEXP); - - CASE(R8G8_B8G8_UNORM); - CASE(G8R8_G8B8_UNORM); - - CASE(BC1_TYPELESS); - CASE(BC1_UNORM); - CASE(BC1_UNORM_SRGB); - - CASE(BC2_TYPELESS); - CASE(BC2_UNORM); - CASE(BC2_UNORM_SRGB); - - CASE(BC3_TYPELESS); - CASE(BC3_UNORM); - CASE(BC3_UNORM_SRGB); - - CASE(BC4_TYPELESS); - CASE(BC4_UNORM); - CASE(BC4_SNORM); - - CASE(BC5_TYPELESS); - CASE(BC5_UNORM); - CASE(BC5_SNORM); - - CASE(B5G6R5_UNORM); - CASE(B5G5R5A1_UNORM); - CASE(B8G8R8A8_UNORM); - CASE(B8G8R8X8_UNORM); - - default: - return "UNKNOWN"; - } +// DX10 formats. +enum DXGI_FORMAT { + DXGI_FORMAT_UNKNOWN = 0, + + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + + DXGI_FORMAT_R11G11B10_FLOAT = 26, + + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + + DXGI_FORMAT_R1_UNORM = 66, + + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + 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, +}; + +enum D3D10_RESOURCE_DIMENSION { + D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, + D3D10_RESOURCE_DIMENSION_BUFFER = 1, + D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, + D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, + D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, +}; + +static const char *getDxgiFormatString(DXGI_FORMAT dxgiFormat) +{ +#define CASE(format) \ + case DXGI_FORMAT_##format: \ + return #format + switch (dxgiFormat) { + CASE(UNKNOWN); + + CASE(R32G32B32A32_TYPELESS); + CASE(R32G32B32A32_FLOAT); + CASE(R32G32B32A32_UINT); + CASE(R32G32B32A32_SINT); + + CASE(R32G32B32_TYPELESS); + CASE(R32G32B32_FLOAT); + CASE(R32G32B32_UINT); + CASE(R32G32B32_SINT); + + CASE(R16G16B16A16_TYPELESS); + CASE(R16G16B16A16_FLOAT); + CASE(R16G16B16A16_UNORM); + CASE(R16G16B16A16_UINT); + CASE(R16G16B16A16_SNORM); + CASE(R16G16B16A16_SINT); + + CASE(R32G32_TYPELESS); + CASE(R32G32_FLOAT); + CASE(R32G32_UINT); + CASE(R32G32_SINT); + + CASE(R32G8X24_TYPELESS); + CASE(D32_FLOAT_S8X24_UINT); + CASE(R32_FLOAT_X8X24_TYPELESS); + CASE(X32_TYPELESS_G8X24_UINT); + + CASE(R10G10B10A2_TYPELESS); + CASE(R10G10B10A2_UNORM); + CASE(R10G10B10A2_UINT); + + CASE(R11G11B10_FLOAT); + + CASE(R8G8B8A8_TYPELESS); + CASE(R8G8B8A8_UNORM); + CASE(R8G8B8A8_UNORM_SRGB); + CASE(R8G8B8A8_UINT); + CASE(R8G8B8A8_SNORM); + CASE(R8G8B8A8_SINT); + + CASE(R16G16_TYPELESS); + CASE(R16G16_FLOAT); + CASE(R16G16_UNORM); + CASE(R16G16_UINT); + CASE(R16G16_SNORM); + CASE(R16G16_SINT); + + CASE(R32_TYPELESS); + CASE(D32_FLOAT); + CASE(R32_FLOAT); + CASE(R32_UINT); + CASE(R32_SINT); + + CASE(R24G8_TYPELESS); + CASE(D24_UNORM_S8_UINT); + CASE(R24_UNORM_X8_TYPELESS); + CASE(X24_TYPELESS_G8_UINT); + + CASE(R8G8_TYPELESS); + CASE(R8G8_UNORM); + CASE(R8G8_UINT); + CASE(R8G8_SNORM); + CASE(R8G8_SINT); + + CASE(R16_TYPELESS); + CASE(R16_FLOAT); + CASE(D16_UNORM); + CASE(R16_UNORM); + CASE(R16_UINT); + CASE(R16_SNORM); + CASE(R16_SINT); + + CASE(R8_TYPELESS); + CASE(R8_UNORM); + CASE(R8_UINT); + CASE(R8_SNORM); + CASE(R8_SINT); + CASE(A8_UNORM); + + CASE(R1_UNORM); + + CASE(R9G9B9E5_SHAREDEXP); + + CASE(R8G8_B8G8_UNORM); + CASE(G8R8_G8B8_UNORM); + + CASE(BC1_TYPELESS); + CASE(BC1_UNORM); + CASE(BC1_UNORM_SRGB); + + CASE(BC2_TYPELESS); + CASE(BC2_UNORM); + CASE(BC2_UNORM_SRGB); + + CASE(BC3_TYPELESS); + CASE(BC3_UNORM); + CASE(BC3_UNORM_SRGB); + + CASE(BC4_TYPELESS); + CASE(BC4_UNORM); + CASE(BC4_SNORM); + + CASE(BC5_TYPELESS); + CASE(BC5_UNORM); + CASE(BC5_SNORM); + + CASE(B5G6R5_UNORM); + CASE(B5G5R5A1_UNORM); + CASE(B8G8R8A8_UNORM); + CASE(B8G8R8X8_UNORM); + + default: + return "UNKNOWN"; + } #undef CASE - } - - static const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) - { - switch (resourceDimension) - { - default: - case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; - case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; - case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; - case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; - case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; - } - } +} + +static const char *getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) +{ + switch (resourceDimension) { + default: + case D3D10_RESOURCE_DIMENSION_UNKNOWN: + return "UNKNOWN"; + case D3D10_RESOURCE_DIMENSION_BUFFER: + return "BUFFER"; + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: + return "TEXTURE1D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: + return "TEXTURE2D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: + return "TEXTURE3D"; + } +} /*** implementation ***/ -void mem_read(Stream & mem, DDSPixelFormat & pf) +void mem_read(Stream &mem, DDSPixelFormat &pf) { - mem_read(mem, pf.size); - mem_read(mem, pf.flags); - mem_read(mem, pf.fourcc); - mem_read(mem, pf.bitcount); - mem_read(mem, pf.rmask); - mem_read(mem, pf.gmask); - mem_read(mem, pf.bmask); - mem_read(mem, pf.amask); + mem_read(mem, pf.size); + mem_read(mem, pf.flags); + mem_read(mem, pf.fourcc); + mem_read(mem, pf.bitcount); + mem_read(mem, pf.rmask); + mem_read(mem, pf.gmask); + mem_read(mem, pf.bmask); + mem_read(mem, pf.amask); } -void mem_read(Stream & mem, DDSCaps & caps) +void mem_read(Stream &mem, DDSCaps &caps) { - mem_read(mem, caps.caps1); - mem_read(mem, caps.caps2); - mem_read(mem, caps.caps3); - mem_read(mem, caps.caps4); + mem_read(mem, caps.caps1); + mem_read(mem, caps.caps2); + mem_read(mem, caps.caps3); + mem_read(mem, caps.caps4); } -void mem_read(Stream & mem, DDSHeader10 & header) +void mem_read(Stream &mem, DDSHeader10 &header) { - mem_read(mem, header.dxgiFormat); - mem_read(mem, header.resourceDimension); - mem_read(mem, header.miscFlag); - mem_read(mem, header.arraySize); - mem_read(mem, header.reserved); + mem_read(mem, header.dxgiFormat); + mem_read(mem, header.resourceDimension); + mem_read(mem, header.miscFlag); + mem_read(mem, header.arraySize); + mem_read(mem, header.reserved); } -void mem_read(Stream & mem, DDSHeader & header) +void mem_read(Stream &mem, DDSHeader &header) { - mem_read(mem, header.fourcc); - mem_read(mem, header.size); - mem_read(mem, header.flags); - mem_read(mem, header.height); - mem_read(mem, header.width); - mem_read(mem, header.pitch); - mem_read(mem, header.depth); - mem_read(mem, header.mipmapcount); - for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]); - mem_read(mem, header.pf); - mem_read(mem, header.caps); - mem_read(mem, header.notused); - - if (header.hasDX10Header()) - { - mem_read(mem, header.header10); - } + mem_read(mem, header.fourcc); + mem_read(mem, header.size); + mem_read(mem, header.flags); + mem_read(mem, header.height); + mem_read(mem, header.width); + mem_read(mem, header.pitch); + mem_read(mem, header.depth); + mem_read(mem, header.mipmapcount); + for (uint i = 0; i < 11; i++) + mem_read(mem, header.reserved[i]); + mem_read(mem, header.pf); + mem_read(mem, header.caps); + mem_read(mem, header.notused); + + if (header.hasDX10Header()) { + mem_read(mem, header.header10); + } } -namespace -{ +namespace { struct FormatDescriptor { - uint format; - uint bitcount; - uint rmask; - uint gmask; - uint bmask; - uint amask; + 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 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 +} // 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; - } - } - - return 0; + 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; } - - DDSHeader::DDSHeader() { - this->fourcc = FOURCC_DDS; - this->size = 124; - this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT); - this->height = 0; - this->width = 0; - this->pitch = 0; - this->depth = 0; - this->mipmapcount = 0; - 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[10] = (2 << 16) | (1 << 8) | (0); // major.minor.revision - - this->pf.size = 32; - this->pf.flags = 0; - this->pf.fourcc = 0; - this->pf.bitcount = 0; - this->pf.rmask = 0; - this->pf.gmask = 0; - this->pf.bmask = 0; - this->pf.amask = 0; - this->caps.caps1 = DDSCAPS_TEXTURE; - this->caps.caps2 = 0; - this->caps.caps3 = 0; - this->caps.caps4 = 0; - this->notused = 0; - - this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN; - this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN; - this->header10.miscFlag = 0; - this->header10.arraySize = 0; - this->header10.reserved = 0; + this->fourcc = FOURCC_DDS; + this->size = 124; + this->flags = (DDSD_CAPS | DDSD_PIXELFORMAT); + this->height = 0; + this->width = 0; + this->pitch = 0; + this->depth = 0; + this->mipmapcount = 0; + 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[10] = (2 << 16) | (1 << 8) | (0); // major.minor.revision + + this->pf.size = 32; + this->pf.flags = 0; + this->pf.fourcc = 0; + this->pf.bitcount = 0; + this->pf.rmask = 0; + this->pf.gmask = 0; + this->pf.bmask = 0; + this->pf.amask = 0; + this->caps.caps1 = DDSCAPS_TEXTURE; + this->caps.caps2 = 0; + this->caps.caps3 = 0; + this->caps.caps4 = 0; + this->notused = 0; + + this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN; + this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN; + this->header10.miscFlag = 0; + this->header10.arraySize = 0; + this->header10.reserved = 0; } void DDSHeader::setWidth(uint w) { - this->flags |= DDSD_WIDTH; - this->width = w; + this->flags |= DDSD_WIDTH; + this->width = w; } void DDSHeader::setHeight(uint h) { - this->flags |= DDSD_HEIGHT; - this->height = h; + this->flags |= DDSD_HEIGHT; + this->height = h; } void DDSHeader::setDepth(uint d) { - this->flags |= DDSD_DEPTH; - this->depth = d; + this->flags |= DDSD_DEPTH; + this->depth = d; } void DDSHeader::setMipmapCount(uint count) { - if (count == 0 || count == 1) - { - this->flags &= ~DDSD_MIPMAPCOUNT; - this->mipmapcount = 1; - - if (this->caps.caps2 == 0) { - this->caps.caps1 = DDSCAPS_TEXTURE; - } - else { - this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; - } - } - else - { - this->flags |= DDSD_MIPMAPCOUNT; - this->mipmapcount = count; - - this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; - } + if (count == 0 || count == 1) { + this->flags &= ~DDSD_MIPMAPCOUNT; + this->mipmapcount = 1; + + if (this->caps.caps2 == 0) { + this->caps.caps1 = DDSCAPS_TEXTURE; + } + else { + this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; + } + } + else { + this->flags |= DDSD_MIPMAPCOUNT; + this->mipmapcount = count; + + this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + } } void DDSHeader::setTexture2D() { - this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; - this->header10.arraySize = 1; + this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; + this->header10.arraySize = 1; } void DDSHeader::setTexture3D() { - this->caps.caps2 = DDSCAPS2_VOLUME; + this->caps.caps2 = DDSCAPS2_VOLUME; - this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; - this->header10.arraySize = 1; + this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; + this->header10.arraySize = 1; } void DDSHeader::setTextureCube() { - this->caps.caps1 |= DDSCAPS_COMPLEX; - this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES; + this->caps.caps1 |= DDSCAPS_COMPLEX; + this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES; - this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; - this->header10.arraySize = 6; + this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; + this->header10.arraySize = 6; } void DDSHeader::setLinearSize(uint size) { - this->flags &= ~DDSD_PITCH; - this->flags |= DDSD_LINEARSIZE; - this->pitch = size; + this->flags &= ~DDSD_PITCH; + this->flags |= DDSD_LINEARSIZE; + this->pitch = size; } void DDSHeader::setPitch(uint pitch) { - this->flags &= ~DDSD_LINEARSIZE; - this->flags |= DDSD_PITCH; - this->pitch = pitch; + this->flags &= ~DDSD_LINEARSIZE; + this->flags |= DDSD_PITCH; + this->pitch = pitch; } void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3) { - // set fourcc pixel format. - this->pf.flags = DDPF_FOURCC; - this->pf.fourcc = DDS_MAKEFOURCC(c0, c1, c2, c3); - - this->pf.bitcount = 0; - this->pf.rmask = 0; - this->pf.gmask = 0; - this->pf.bmask = 0; - this->pf.amask = 0; + // set fourcc pixel format. + this->pf.flags = DDPF_FOURCC; + this->pf.fourcc = DDS_MAKEFOURCC(c0, c1, c2, c3); + + this->pf.bitcount = 0; + this->pf.rmask = 0; + this->pf.gmask = 0; + this->pf.bmask = 0; + this->pf.amask = 0; } void DDSHeader::setFormatCode(uint32 code) { - // set fourcc pixel format. - this->pf.flags = DDPF_FOURCC; - this->pf.fourcc = code; - - this->pf.bitcount = 0; - this->pf.rmask = 0; - this->pf.gmask = 0; - this->pf.bmask = 0; - this->pf.amask = 0; + // set fourcc pixel format. + this->pf.flags = DDPF_FOURCC; + this->pf.fourcc = code; + + this->pf.bitcount = 0; + this->pf.rmask = 0; + this->pf.gmask = 0; + this->pf.bmask = 0; + this->pf.amask = 0; } void DDSHeader::setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3) { - this->pf.bitcount = DDS_MAKEFOURCC(c0, c1, c2, c3); + this->pf.bitcount = DDS_MAKEFOURCC(c0, c1, c2, c3); } - void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { - // Make sure the masks are correct. - if ((rmask & gmask) || - (rmask & bmask) || - (rmask & amask) || - (gmask & bmask) || - (gmask & amask) || - (bmask & amask)) - { - printf("DDS: bad RGBA masks, pixel format not set\n"); - return; - } - - if (rmask != 0 || gmask != 0 || bmask != 0) - { - if (gmask == 0 && bmask == 0) - { - this->pf.flags = DDPF_LUMINANCE; - } - else - { - this->pf.flags = DDPF_RGB; - } - - if (amask != 0) { - this->pf.flags |= DDPF_ALPHAPIXELS; - } - } - else if (amask != 0) - { - this->pf.flags |= DDPF_ALPHA; - } - - if (bitcount == 0) - { - // Compute bit count from the masks. - uint total = rmask | gmask | bmask | amask; - while (total != 0) { - bitcount++; - total >>= 1; - } - } - - // 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 (!(bitcount > 0 && bitcount <= 32)) { - printf("DDS: bad bit count, pixel format not set\n"); - return; - } - this->pf.bitcount = bitcount; - this->pf.rmask = rmask; - this->pf.gmask = gmask; - this->pf.bmask = bmask; - this->pf.amask = amask; + // Make sure the masks are correct. + if ((rmask & gmask) || (rmask & bmask) || (rmask & amask) || (gmask & bmask) || + (gmask & amask) || (bmask & amask)) { + printf("DDS: bad RGBA masks, pixel format not set\n"); + return; + } + + if (rmask != 0 || gmask != 0 || bmask != 0) { + if (gmask == 0 && bmask == 0) { + this->pf.flags = DDPF_LUMINANCE; + } + else { + this->pf.flags = DDPF_RGB; + } + + if (amask != 0) { + this->pf.flags |= DDPF_ALPHAPIXELS; + } + } + else if (amask != 0) { + this->pf.flags |= DDPF_ALPHA; + } + + if (bitcount == 0) { + // Compute bit count from the masks. + uint total = rmask | gmask | bmask | amask; + while (total != 0) { + bitcount++; + total >>= 1; + } + } + + // 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 (!(bitcount > 0 && bitcount <= 32)) { + printf("DDS: bad bit count, pixel format not set\n"); + return; + } + this->pf.bitcount = bitcount; + this->pf.rmask = rmask; + this->pf.gmask = gmask; + this->pf.bmask = bmask; + this->pf.amask = amask; } void DDSHeader::setDX10Format(uint format) { - //this->pf.flags = 0; - this->pf.fourcc = FOURCC_DX10; - this->header10.dxgiFormat = format; + //this->pf.flags = 0; + this->pf.fourcc = FOURCC_DX10; + this->header10.dxgiFormat = format; } void DDSHeader::setNormalFlag(bool b) { - if (b) this->pf.flags |= DDPF_NORMAL; - else this->pf.flags &= ~DDPF_NORMAL; + if (b) + this->pf.flags |= DDPF_NORMAL; + else + this->pf.flags &= ~DDPF_NORMAL; } 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) { - if (b) this->pf.flags |= DDPF_ALPHAPIXELS; - else this->pf.flags &= ~DDPF_ALPHAPIXELS; + if (b) + this->pf.flags |= DDPF_ALPHAPIXELS; + else + this->pf.flags &= ~DDPF_ALPHAPIXELS; } void DDSHeader::setUserVersion(int version) { - this->reserved[7] = FOURCC_UVER; - this->reserved[8] = version; + this->reserved[7] = FOURCC_UVER; + this->reserved[8] = version; } #if 0 void DDSHeader::swapBytes() { - this->fourcc = POSH_LittleU32(this->fourcc); - this->size = POSH_LittleU32(this->size); - this->flags = POSH_LittleU32(this->flags); - this->height = POSH_LittleU32(this->height); - this->width = POSH_LittleU32(this->width); - this->pitch = POSH_LittleU32(this->pitch); - this->depth = POSH_LittleU32(this->depth); - this->mipmapcount = POSH_LittleU32(this->mipmapcount); - - for (int i = 0; i < 11; i++) { - this->reserved[i] = POSH_LittleU32(this->reserved[i]); - } - - this->pf.size = POSH_LittleU32(this->pf.size); - this->pf.flags = POSH_LittleU32(this->pf.flags); - this->pf.fourcc = POSH_LittleU32(this->pf.fourcc); - this->pf.bitcount = POSH_LittleU32(this->pf.bitcount); - this->pf.rmask = POSH_LittleU32(this->pf.rmask); - this->pf.gmask = POSH_LittleU32(this->pf.gmask); - this->pf.bmask = POSH_LittleU32(this->pf.bmask); - this->pf.amask = POSH_LittleU32(this->pf.amask); - this->caps.caps1 = POSH_LittleU32(this->caps.caps1); - this->caps.caps2 = POSH_LittleU32(this->caps.caps2); - this->caps.caps3 = POSH_LittleU32(this->caps.caps3); - this->caps.caps4 = POSH_LittleU32(this->caps.caps4); - this->notused = POSH_LittleU32(this->notused); - - this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat); - this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension); - this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag); - this->header10.arraySize = POSH_LittleU32(this->header10.arraySize); - this->header10.reserved = POSH_LittleU32(this->header10.reserved); + this->fourcc = POSH_LittleU32(this->fourcc); + this->size = POSH_LittleU32(this->size); + this->flags = POSH_LittleU32(this->flags); + this->height = POSH_LittleU32(this->height); + this->width = POSH_LittleU32(this->width); + this->pitch = POSH_LittleU32(this->pitch); + this->depth = POSH_LittleU32(this->depth); + this->mipmapcount = POSH_LittleU32(this->mipmapcount); + + for (int i = 0; i < 11; i++) { + this->reserved[i] = POSH_LittleU32(this->reserved[i]); + } + + this->pf.size = POSH_LittleU32(this->pf.size); + this->pf.flags = POSH_LittleU32(this->pf.flags); + this->pf.fourcc = POSH_LittleU32(this->pf.fourcc); + this->pf.bitcount = POSH_LittleU32(this->pf.bitcount); + this->pf.rmask = POSH_LittleU32(this->pf.rmask); + this->pf.gmask = POSH_LittleU32(this->pf.gmask); + this->pf.bmask = POSH_LittleU32(this->pf.bmask); + this->pf.amask = POSH_LittleU32(this->pf.amask); + this->caps.caps1 = POSH_LittleU32(this->caps.caps1); + this->caps.caps2 = POSH_LittleU32(this->caps.caps2); + this->caps.caps3 = POSH_LittleU32(this->caps.caps3); + this->caps.caps4 = POSH_LittleU32(this->caps.caps4); + this->notused = POSH_LittleU32(this->notused); + + this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat); + this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension); + this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag); + this->header10.arraySize = POSH_LittleU32(this->header10.arraySize); + this->header10.reserved = POSH_LittleU32(this->header10.reserved); } #endif bool DDSHeader::hasDX10Header() const { - return this->pf.fourcc == FOURCC_DX10; + return this->pf.fourcc == FOURCC_DX10; } 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() { - mem_read(stream, header); + mem_read(stream, header); - // some ATI2 compressed normal maps do not have their - // normal flag set, so force it here (the original nvtt don't do - // this, but the decompressor has a -forcenormal flag) - if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true); + // some ATI2 compressed normal maps do not have their + // normal flag set, so force it here (the original nvtt don't do + // this, but the decompressor has a -forcenormal flag) + if (header.pf.fourcc == FOURCC_ATI2) + header.setNormalFlag(true); } DirectDrawSurface::~DirectDrawSurface() @@ -888,666 +876,642 @@ DirectDrawSurface::~DirectDrawSurface() bool DirectDrawSurface::isValid() const { - if (header.fourcc != FOURCC_DDS || header.size != 124) - { - return false; - } + if (header.fourcc != FOURCC_DDS || header.size != 124) { + return false; + } - const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); - if ( (header.flags & required) != required ) { - return false; - } + const uint required = (DDSD_WIDTH | DDSD_HEIGHT /*|DDSD_CAPS|DDSD_PIXELFORMAT*/); + if ((header.flags & required) != required) { + return false; + } - if (header.pf.size != 32) { - return false; - } + if (header.pf.size != 32) { + return false; + } - /* in some files DDSCAPS_TEXTURE is missing: silently ignore */ + /* in some files DDSCAPS_TEXTURE is missing: silently ignore */ #if 0 - if (!(header.caps.caps1 & DDSCAPS_TEXTURE)) { - return false; - } + if (!(header.caps.caps1 & DDSCAPS_TEXTURE)) { + return false; + } #endif - return true; + return true; } bool DirectDrawSurface::isSupported() const { - if (header.hasDX10Header()) - { - if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) - { - return true; - } - - return false; - } - else - { - if (header.pf.flags & DDPF_FOURCC) - { - if (header.pf.fourcc != FOURCC_DXT1 && - header.pf.fourcc != FOURCC_DXT2 && - header.pf.fourcc != FOURCC_DXT3 && - header.pf.fourcc != FOURCC_DXT4 && - header.pf.fourcc != FOURCC_DXT5 && - header.pf.fourcc != FOURCC_RXGB && - header.pf.fourcc != FOURCC_ATI1 && - header.pf.fourcc != FOURCC_ATI2) - { - // Unknown fourcc code. - return false; - } - } - else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)) - { - // All RGB and luminance formats are supported now. - } - else - { - return false; - } - - if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) - { - // Cubemaps must contain all faces. - return false; - } - - if (isTexture3D()) - { - // @@ 3D textures not supported yet. - return false; - } - } - - return true; + if (header.hasDX10Header()) { + if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM || + header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM || + header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM || + header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM || + header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) { + return true; + } + + return false; + } + else { + if (header.pf.flags & DDPF_FOURCC) { + if (header.pf.fourcc != FOURCC_DXT1 && header.pf.fourcc != FOURCC_DXT2 && + header.pf.fourcc != FOURCC_DXT3 && header.pf.fourcc != FOURCC_DXT4 && + header.pf.fourcc != FOURCC_DXT5 && header.pf.fourcc != FOURCC_RXGB && + header.pf.fourcc != FOURCC_ATI1 && header.pf.fourcc != FOURCC_ATI2) { + // Unknown fourcc code. + return false; + } + } + else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)) { + // All RGB and luminance formats are supported now. + } + else { + return false; + } + + if (isTextureCube() && + (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) { + // Cubemaps must contain all faces. + return false; + } + + if (isTexture3D()) { + // @@ 3D textures not supported yet. + return false; + } + } + + return true; } bool DirectDrawSurface::hasAlpha() const { - if (header.hasDX10Header()) - { - /* TODO: Update hasAlpha to handle all DX10 formats. */ - return - header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM; - } - else - { - if (header.pf.flags & DDPF_RGB) - { - return header.pf.amask != 0; - } - else if (header.pf.flags & DDPF_FOURCC) - { - if (header.pf.fourcc == FOURCC_RXGB || - header.pf.fourcc == FOURCC_ATI1 || - header.pf.fourcc == FOURCC_ATI2 || - header.pf.flags & DDPF_NORMAL) - { - return false; - } - else - { - // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) - return true; - } - } - - return false; - } + if (header.hasDX10Header()) { + /* TODO: Update hasAlpha to handle all DX10 formats. */ + return header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM || + header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM || + header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM; + } + else { + if (header.pf.flags & DDPF_RGB) { + return header.pf.amask != 0; + } + else if (header.pf.flags & DDPF_FOURCC) { + if (header.pf.fourcc == FOURCC_RXGB || header.pf.fourcc == FOURCC_ATI1 || + header.pf.fourcc == FOURCC_ATI2 || header.pf.flags & DDPF_NORMAL) { + return false; + } + else { + // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) + return true; + } + } + + return false; + } } uint DirectDrawSurface::mipmapCount() const { - if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount; - else return 1; + if (header.flags & DDSD_MIPMAPCOUNT) + return header.mipmapcount; + else + return 1; } uint DirectDrawSurface::fourCC() const { - return header.pf.fourcc; + return header.pf.fourcc; } uint DirectDrawSurface::width() const { - if (header.flags & DDSD_WIDTH) return header.width; - else return 1; + if (header.flags & DDSD_WIDTH) + return header.width; + else + return 1; } uint DirectDrawSurface::height() const { - if (header.flags & DDSD_HEIGHT) return header.height; - else return 1; + if (header.flags & DDSD_HEIGHT) + return header.height; + else + return 1; } uint DirectDrawSurface::depth() const { - if (header.flags & DDSD_DEPTH) return header.depth; - else return 1; + if (header.flags & DDSD_DEPTH) + return header.depth; + else + return 1; } bool DirectDrawSurface::isTexture1D() const { - if (header.hasDX10Header()) - { - return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; - } - return false; + if (header.hasDX10Header()) { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + return false; } bool DirectDrawSurface::isTexture2D() const { - if (header.hasDX10Header()) - { - return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; - } - else - { - return !isTexture3D() && !isTextureCube(); - } + if (header.hasDX10Header()) { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; + } + else { + return !isTexture3D() && !isTextureCube(); + } } bool DirectDrawSurface::isTexture3D() const { - if (header.hasDX10Header()) - { - return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; - } - else - { - return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; - } + if (header.hasDX10Header()) { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; + } + else { + return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; + } } bool DirectDrawSurface::isTextureCube() const { - return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; + return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } void DirectDrawSurface::setNormalFlag(bool b) { - header.setNormalFlag(b); + header.setNormalFlag(b); } void DirectDrawSurface::setHasAlphaFlag(bool b) { - header.setHasAlphaFlag(b); + header.setHasAlphaFlag(b); } void DirectDrawSurface::setUserVersion(int version) { - header.setUserVersion(version); + header.setUserVersion(version); } void DirectDrawSurface::mipmap(Image *img, uint face, uint mipmap) { - stream.seek(offset(face, mipmap)); - - uint w = width(); - uint h = height(); - - // Compute width and height. - for (uint m = 0; m < mipmap; m++) - { - w = MAX(1U, w / 2); - h = MAX(1U, h / 2); - } - - img->allocate(w, h); - - if (hasAlpha()) - { - img->setFormat(Image::Format_ARGB); - } - else - { - img->setFormat(Image::Format_RGB); - } - - if (header.hasDX10Header()) - { - // So far only block formats supported. - readBlockImage(img); - } - else - { - if (header.pf.flags & DDPF_RGB) - { - readLinearImage(img); - } - else if (header.pf.flags & DDPF_FOURCC) - { - readBlockImage(img); - } - } + stream.seek(offset(face, mipmap)); + + uint w = width(); + uint h = height(); + + // Compute width and height. + for (uint m = 0; m < mipmap; m++) { + w = MAX(1U, w / 2); + h = MAX(1U, h / 2); + } + + img->allocate(w, h); + + if (hasAlpha()) { + img->setFormat(Image::Format_ARGB); + } + else { + img->setFormat(Image::Format_RGB); + } + + if (header.hasDX10Header()) { + // So far only block formats supported. + readBlockImage(img); + } + else { + if (header.pf.flags & DDPF_RGB) { + readLinearImage(img); + } + else if (header.pf.flags & DDPF_FOURCC) { + readBlockImage(img); + } + } } // It was easier to copy this function from upstream than to resync. // This should be removed if a resync ever occurs. void *DirectDrawSurface::readData(uint &rsize) { - uint header_size = 128; // sizeof(DDSHeader); - if (header.hasDX10Header()) - { - header_size += 20; // sizeof(DDSHeader10); - } + uint header_size = 128; // sizeof(DDSHeader); + if (header.hasDX10Header()) { + header_size += 20; // sizeof(DDSHeader10); + } - uint size = stream.size - header_size; - rsize = size; + uint size = stream.size - header_size; + rsize = size; - unsigned char *data = (unsigned char *)malloc(sizeof(*data) * size); + unsigned char *data = (unsigned char *)malloc(sizeof(*data) * size); - stream.seek(header_size); - mem_read(stream, data, size); + stream.seek(header_size); + mem_read(stream, data, size); - if (stream.failed) { - free(data); - data = NULL; - rsize = 0; - } + if (stream.failed) { + free(data); + data = NULL; + rsize = 0; + } - // Maybe check if size == rsize? assert() isn't in this scope... + // Maybe check if size == rsize? assert() isn't in this scope... - return data; + return data; } void DirectDrawSurface::readLinearImage(Image *img) { - const uint w = img->width(); - const uint h = img->height(); + const uint w = img->width(); + const uint h = img->height(); - uint rshift, rsize; - PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize); + uint rshift, rsize; + PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize); - uint gshift, gsize; - PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize); + uint gshift, gsize; + PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize); - uint bshift, bsize; - PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize); + uint bshift, bsize; + PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize); - uint ashift, asize; - PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize); + uint ashift, asize; + PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize); - uint byteCount = (header.pf.bitcount + 7) / 8; + uint byteCount = (header.pf.bitcount + 7) / 8; - if (byteCount > 4) - { - /* just in case... we could have segfaults later on if byteCount > 4 */ - printf("DDS: bitcount too large"); - return; - } + if (byteCount > 4) { + /* just in case... we could have segfaults later on if byteCount > 4 */ + printf("DDS: bitcount too large"); + return; + } - // Read linear RGB images. - for (uint y = 0; y < h; y++) - { - for (uint x = 0; x < w; x++) - { - uint c = 0; - mem_read(stream, (unsigned char *)(&c), byteCount); + // Read linear RGB images. + for (uint y = 0; y < h; y++) { + for (uint x = 0; x < w; x++) { + uint c = 0; + mem_read(stream, (unsigned char *)(&c), byteCount); - Color32 pixel(0, 0, 0, 0xFF); - pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8); - pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8); - pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8); - pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8); + Color32 pixel(0, 0, 0, 0xFF); + pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8); + pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8); + pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8); + pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8); - img->pixel(x, y) = pixel; - } - } + img->pixel(x, y) = pixel; + } + } } void DirectDrawSurface::readBlockImage(Image *img) { - const uint w = img->width(); - const uint h = img->height(); - - const uint bw = (w + 3) / 4; - const uint bh = (h + 3) / 4; - - for (uint by = 0; by < bh; by++) - { - for (uint bx = 0; bx < bw; bx++) - { - ColorBlock block; - - // Read color block. - readBlock(&block); - - // Write color block. - for (uint y = 0; y < MIN(4U, h-4*by); y++) - { - for (uint x = 0; x < MIN(4U, w-4*bx); x++) - { - img->pixel(4*bx+x, 4*by+y) = block.color(x, y); - } - } - } - } + const uint w = img->width(); + const uint h = img->height(); + + const uint bw = (w + 3) / 4; + const uint bh = (h + 3) / 4; + + for (uint by = 0; by < bh; by++) { + for (uint bx = 0; bx < bw; bx++) { + ColorBlock block; + + // Read color block. + readBlock(&block); + + // Write color block. + for (uint y = 0; y < MIN(4U, h - 4 * by); y++) { + for (uint x = 0; x < MIN(4U, w - 4 * bx); x++) { + img->pixel(4 * bx + x, 4 * by + y) = block.color(x, y); + } + } + } + } } static Color32 buildNormal(uint8 x, uint8 y) { - float nx = 2 * (x / 255.0f) - 1; - float ny = 2 * (y / 255.0f) - 1; - float nz = 0.0f; - if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny); - uint8 z = CLAMP(int(255.0f * (nz + 1) / 2.0f), 0, 255); - - return Color32(x, y, z); + float nx = 2 * (x / 255.0f) - 1; + float ny = 2 * (y / 255.0f) - 1; + float nz = 0.0f; + if (1 - nx * nx - ny * ny > 0) + nz = sqrt(1 - nx * nx - ny * ny); + uint8 z = CLAMP(int(255.0f * (nz + 1) / 2.0f), 0, 255); + + return Color32(x, y, z); } - void DirectDrawSurface::readBlock(ColorBlock *rgba) { - uint fourcc = header.pf.fourcc; - - // Map DX10 block formats to fourcc codes. - if (header.hasDX10Header()) - { - if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1; - if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3; - if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5; - if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1; - if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2; - } - - - if (fourcc == FOURCC_DXT1) - { - BlockDXT1 block; - mem_read(stream, block); - block.decodeBlock(rgba); - } - else if (fourcc == FOURCC_DXT2 || - 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) - { - BlockDXT5 block; - mem_read(stream, block); - block.decodeBlock(rgba); - - if (fourcc == FOURCC_RXGB) - { - // Swap R & A. - for (int i = 0; i < 16; i++) - { - Color32 & c = rgba->color(i); - uint tmp = c.r; - c.r = c.a; - c.a = tmp; - } - } - } - else if (fourcc == FOURCC_ATI1) - { - BlockATI1 block; - mem_read(stream, block); - block.decodeBlock(rgba); - } - else if (fourcc == FOURCC_ATI2) - { - BlockATI2 block; - mem_read(stream, block); - block.decodeBlock(rgba); - } - - // If normal flag set, convert to normal. - if (header.pf.flags & DDPF_NORMAL) - { - if (fourcc == FOURCC_ATI2) - { - for (int i = 0; i < 16; i++) - { - Color32 & c = rgba->color(i); - c = buildNormal(c.r, c.g); - } - } - else if (fourcc == FOURCC_DXT5) - { - for (int i = 0; i < 16; i++) - { - Color32 & c = rgba->color(i); - c = buildNormal(c.a, c.g); - } - } - } + uint fourcc = header.pf.fourcc; + + // Map DX10 block formats to fourcc codes. + if (header.hasDX10Header()) { + if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) + fourcc = FOURCC_DXT1; + if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) + fourcc = FOURCC_DXT3; + if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) + fourcc = FOURCC_DXT5; + if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) + fourcc = FOURCC_ATI1; + if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) + fourcc = FOURCC_ATI2; + } + + if (fourcc == FOURCC_DXT1) { + BlockDXT1 block; + mem_read(stream, block); + block.decodeBlock(rgba); + } + else if (fourcc == FOURCC_DXT2 || 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) { + BlockDXT5 block; + mem_read(stream, block); + block.decodeBlock(rgba); + + if (fourcc == FOURCC_RXGB) { + // Swap R & A. + for (int i = 0; i < 16; i++) { + Color32 &c = rgba->color(i); + uint tmp = c.r; + c.r = c.a; + c.a = tmp; + } + } + } + else if (fourcc == FOURCC_ATI1) { + BlockATI1 block; + mem_read(stream, block); + block.decodeBlock(rgba); + } + else if (fourcc == FOURCC_ATI2) { + BlockATI2 block; + mem_read(stream, block); + block.decodeBlock(rgba); + } + + // If normal flag set, convert to normal. + if (header.pf.flags & DDPF_NORMAL) { + if (fourcc == FOURCC_ATI2) { + for (int i = 0; i < 16; i++) { + Color32 &c = rgba->color(i); + c = buildNormal(c.r, c.g); + } + } + else if (fourcc == FOURCC_DXT5) { + for (int i = 0; i < 16; i++) { + Color32 &c = rgba->color(i); + c = buildNormal(c.a, c.g); + } + } + } } - uint DirectDrawSurface::blockSize() const { - switch (header.pf.fourcc) - { - case FOURCC_DXT1: - case FOURCC_ATI1: - return 8; - case FOURCC_DXT2: - case FOURCC_DXT3: - case FOURCC_DXT4: - case FOURCC_DXT5: - case FOURCC_RXGB: - case FOURCC_ATI2: - return 16; - case FOURCC_DX10: - switch (header.header10.dxgiFormat) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - return 8; - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - return 16; - }; - }; - - // Not a block image. - return 0; + switch (header.pf.fourcc) { + case FOURCC_DXT1: + case FOURCC_ATI1: + return 8; + case FOURCC_DXT2: + case FOURCC_DXT3: + case FOURCC_DXT4: + case FOURCC_DXT5: + case FOURCC_RXGB: + case FOURCC_ATI2: + return 16; + case FOURCC_DX10: + switch (header.header10.dxgiFormat) { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return 8; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + return 16; + }; + }; + + // Not a block image. + return 0; } uint DirectDrawSurface::mipmapSize(uint mipmap) const { - uint w = width(); - uint h = height(); - uint d = depth(); - - for (uint m = 0; m < mipmap; m++) - { - w = MAX(1U, w / 2); - h = MAX(1U, h / 2); - d = MAX(1U, d / 2); - } - - if (header.pf.flags & DDPF_FOURCC) - { - // @@ How are 3D textures aligned? - w = (w + 3) / 4; - h = (h + 3) / 4; - return blockSize() * w * h; - } - else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE)) - { - uint pitch = computePitch(w, header.pf.bitcount, 8); // Assuming 8 bit alignment, which is the same D3DX expects. - - return pitch * h * d; - } - else { - printf("DDS: mipmap format not supported\n"); - return(0); - }; + uint w = width(); + uint h = height(); + uint d = depth(); + + for (uint m = 0; m < mipmap; m++) { + w = MAX(1U, w / 2); + h = MAX(1U, h / 2); + d = MAX(1U, d / 2); + } + + if (header.pf.flags & DDPF_FOURCC) { + // @@ How are 3D textures aligned? + w = (w + 3) / 4; + h = (h + 3) / 4; + return blockSize() * w * h; + } + else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE)) { + uint pitch = computePitch( + w, header.pf.bitcount, 8); // Assuming 8 bit alignment, which is the same D3DX expects. + + return pitch * h * d; + } + else { + printf("DDS: mipmap format not supported\n"); + return (0); + }; } uint DirectDrawSurface::faceSize() const { - const uint count = mipmapCount(); - uint size = 0; + const uint count = mipmapCount(); + uint size = 0; - for (uint m = 0; m < count; m++) - { - size += mipmapSize(m); - } + for (uint m = 0; m < count; m++) { + size += mipmapSize(m); + } - return size; + return size; } uint DirectDrawSurface::offset(const uint face, const uint mipmap) { - uint size = 128; // sizeof(DDSHeader); + uint size = 128; // sizeof(DDSHeader); - if (header.hasDX10Header()) - { - size += 20; // sizeof(DDSHeader10); - } + if (header.hasDX10Header()) { + size += 20; // sizeof(DDSHeader10); + } - if (face != 0) - { - size += face * faceSize(); - } + if (face != 0) { + size += face * faceSize(); + } - for (uint m = 0; m < mipmap; m++) - { - size += mipmapSize(m); - } + for (uint m = 0; m < mipmap; m++) { + size += mipmapSize(m); + } - return size; + return size; } - void DirectDrawSurface::printInfo() const { - printf("Flags: 0x%.8X\n", header.flags); - if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n"); - if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n"); - if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n"); - if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n"); - if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n"); - if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n"); - if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n"); - if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n"); - - printf("Height: %u\n", header.height); - printf("Width: %u\n", header.width); - printf("Depth: %u\n", header.depth); - if (header.flags & DDSD_PITCH) printf("Pitch: %u\n", header.pitch); - else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %u\n", header.pitch); - printf("Mipmap count: %u\n", header.mipmapcount); - - 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_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"); - if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n"); - if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n"); - 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", - (int)((header.pf.fourcc >> 0) & 0xFF), - (int)((header.pf.fourcc >> 8) & 0xFF), - (int)((header.pf.fourcc >> 16) & 0xFF), - (int)((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", - (int)(header.pf.bitcount >> 0) & 0xFF, - (int)(header.pf.bitcount >> 8) & 0xFF, - (int)(header.pf.bitcount >> 16) & 0xFF, - (int)(header.pf.bitcount >> 24) & 0xFF, - header.pf.bitcount); - } - else - { - printf("\tBit count: %u\n", header.pf.bitcount); - } - - printf("\tRed mask: 0x%.8X\n", header.pf.rmask); - printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); - printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); - printf("\tAlpha mask: 0x%.8X\n", header.pf.amask); - - printf("Caps:\n"); - printf("\tCaps 1: 0x%.8X\n", header.caps.caps1); - if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n"); - if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n"); - if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n"); - - printf("\tCaps 2: 0x%.8X\n", header.caps.caps2); - if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n"); - else if (header.caps.caps2 & DDSCAPS2_CUBEMAP) - { - printf("\t\tDDSCAPS2_CUBEMAP\n"); - if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n"); - else { - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n"); - if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n"); - } - } - - printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); - printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); - - if (header.hasDX10Header()) - { - printf("DX10 Header:\n"); - printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); - printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); - printf("\tMisc flag: %u\n", header.header10.miscFlag); - printf("\tArray size: %u\n", header.header10.arraySize); - } - - if (header.reserved[9] == FOURCC_NVTT) - { - int major = (header.reserved[10] >> 16) & 0xFF; - int minor = (header.reserved[10] >> 8) & 0xFF; - int revision= header.reserved[10] & 0xFF; - - printf("Version:\n"); - 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]); - } + printf("Flags: 0x%.8X\n", header.flags); + if (header.flags & DDSD_CAPS) + printf("\tDDSD_CAPS\n"); + if (header.flags & DDSD_PIXELFORMAT) + printf("\tDDSD_PIXELFORMAT\n"); + if (header.flags & DDSD_WIDTH) + printf("\tDDSD_WIDTH\n"); + if (header.flags & DDSD_HEIGHT) + printf("\tDDSD_HEIGHT\n"); + if (header.flags & DDSD_DEPTH) + printf("\tDDSD_DEPTH\n"); + if (header.flags & DDSD_PITCH) + printf("\tDDSD_PITCH\n"); + if (header.flags & DDSD_LINEARSIZE) + printf("\tDDSD_LINEARSIZE\n"); + if (header.flags & DDSD_MIPMAPCOUNT) + printf("\tDDSD_MIPMAPCOUNT\n"); + + printf("Height: %u\n", header.height); + printf("Width: %u\n", header.width); + printf("Depth: %u\n", header.depth); + if (header.flags & DDSD_PITCH) + printf("Pitch: %u\n", header.pitch); + else if (header.flags & DDSD_LINEARSIZE) + printf("Linear size: %u\n", header.pitch); + printf("Mipmap count: %u\n", header.mipmapcount); + + 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_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"); + if (header.pf.flags & DDPF_PALETTEINDEXED1) + printf("\t\tDDPF_PALETTEINDEXED1\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED2) + printf("\t\tDDPF_PALETTEINDEXED2\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED4) + printf("\t\tDDPF_PALETTEINDEXED4\n"); + if (header.pf.flags & DDPF_PALETTEINDEXED8) + printf("\t\tDDPF_PALETTEINDEXED8\n"); + 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", + (int)((header.pf.fourcc >> 0) & 0xFF), + (int)((header.pf.fourcc >> 8) & 0xFF), + (int)((header.pf.fourcc >> 16) & 0xFF), + (int)((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", + (int)(header.pf.bitcount >> 0) & 0xFF, + (int)(header.pf.bitcount >> 8) & 0xFF, + (int)(header.pf.bitcount >> 16) & 0xFF, + (int)(header.pf.bitcount >> 24) & 0xFF, + header.pf.bitcount); + } + else { + printf("\tBit count: %u\n", header.pf.bitcount); + } + + printf("\tRed mask: 0x%.8X\n", header.pf.rmask); + printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); + printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); + printf("\tAlpha mask: 0x%.8X\n", header.pf.amask); + + printf("Caps:\n"); + printf("\tCaps 1: 0x%.8X\n", header.caps.caps1); + if (header.caps.caps1 & DDSCAPS_COMPLEX) + printf("\t\tDDSCAPS_COMPLEX\n"); + if (header.caps.caps1 & DDSCAPS_TEXTURE) + printf("\t\tDDSCAPS_TEXTURE\n"); + if (header.caps.caps1 & DDSCAPS_MIPMAP) + printf("\t\tDDSCAPS_MIPMAP\n"); + + printf("\tCaps 2: 0x%.8X\n", header.caps.caps2); + if (header.caps.caps2 & DDSCAPS2_VOLUME) + printf("\t\tDDSCAPS2_VOLUME\n"); + else if (header.caps.caps2 & DDSCAPS2_CUBEMAP) { + printf("\t\tDDSCAPS2_CUBEMAP\n"); + if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) + printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n"); + else { + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) + printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) + printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) + printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) + printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) + printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n"); + if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) + printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n"); + } + } + + printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); + printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); + + if (header.hasDX10Header()) { + printf("DX10 Header:\n"); + printf("\tDXGI Format: %u (%s)\n", + header.header10.dxgiFormat, + getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); + printf("\tResource dimension: %u (%s)\n", + header.header10.resourceDimension, + getD3d10ResourceDimensionString( + (D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); + printf("\tMisc flag: %u\n", header.header10.miscFlag); + printf("\tArray size: %u\n", header.header10.arraySize); + } + + if (header.reserved[9] == FOURCC_NVTT) { + int major = (header.reserved[10] >> 16) & 0xFF; + int minor = (header.reserved[10] >> 8) & 0xFF; + int revision = header.reserved[10] & 0xFF; + + printf("Version:\n"); + 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]); + } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index 8166e6b0831..54bd1ad2dcd 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -58,136 +57,132 @@ #include struct DDSPixelFormat { - uint size; - uint flags; - uint fourcc; - uint bitcount; - uint rmask; - uint gmask; - uint bmask; - uint amask; + uint size; + uint flags; + uint fourcc; + uint bitcount; + uint rmask; + uint gmask; + uint bmask; + uint amask; }; struct DDSCaps { - uint caps1; - uint caps2; - uint caps3; - uint caps4; + uint caps1; + uint caps2; + uint caps3; + uint caps4; }; /// DDS file header for DX10. struct DDSHeader10 { - uint dxgiFormat; - uint resourceDimension; - uint miscFlag; - uint arraySize; - uint reserved; + uint dxgiFormat; + uint resourceDimension; + uint miscFlag; + uint arraySize; + uint reserved; }; /// DDS file header. struct DDSHeader { - uint fourcc; - uint size; - uint flags; - uint height; - uint width; - uint pitch; - uint depth; - uint mipmapcount; - uint reserved[11]; - DDSPixelFormat pf; - DDSCaps caps; - uint notused; - DDSHeader10 header10; - - - // Helper methods. - DDSHeader(); - - void setWidth(uint w); - void setHeight(uint h); - void setDepth(uint d); - void setMipmapCount(uint count); - void setTexture2D(); - void setTexture3D(); - void setTextureCube(); - void setLinearSize(uint size); - void setPitch(uint pitch); - void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3); - void setFormatCode(uint code); - void setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3); - void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); - void setDX10Format(uint format); - void setNormalFlag(bool b); - void setSrgbFlag(bool b); - void setHasAlphaFlag(bool b); - void setUserVersion(int version); - - /*void swapBytes();*/ - - bool hasDX10Header() const; - uint signature() const; - uint toolVersion() const; - uint userVersion() const; - bool isNormalMap() const; - bool isSrgb() const; - bool hasAlpha() const; - uint d3d9Format() const; + uint fourcc; + uint size; + uint flags; + uint height; + uint width; + uint pitch; + uint depth; + uint mipmapcount; + uint reserved[11]; + DDSPixelFormat pf; + DDSCaps caps; + uint notused; + DDSHeader10 header10; + + // Helper methods. + DDSHeader(); + + void setWidth(uint w); + void setHeight(uint h); + void setDepth(uint d); + void setMipmapCount(uint count); + void setTexture2D(); + void setTexture3D(); + void setTextureCube(); + void setLinearSize(uint size); + void setPitch(uint pitch); + void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3); + void setFormatCode(uint code); + void setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3); + void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); + void setDX10Format(uint format); + void setNormalFlag(bool b); + void setSrgbFlag(bool b); + void setHasAlphaFlag(bool b); + void setUserVersion(int version); + + /*void swapBytes();*/ + + bool hasDX10Header() const; + uint signature() const; + uint toolVersion() const; + uint userVersion() const; + bool isNormalMap() const; + bool isSrgb() const; + bool hasAlpha() const; + uint d3d9Format() const; }; /// DirectDraw Surface. (DDS) -class DirectDrawSurface -{ -public: - DirectDrawSurface(unsigned char *mem, uint size); - ~DirectDrawSurface(); - - bool isValid() const; - bool isSupported() const; - - bool hasAlpha() const; - - uint mipmapCount() const; - uint fourCC() const; - uint width() const; - uint height() const; - uint depth() const; - bool isTexture1D() const; - bool isTexture2D() const; - bool isTexture3D() const; - bool isTextureCube() const; - - void setNormalFlag(bool b); - void setHasAlphaFlag(bool b); - void setUserVersion(int version); - - void mipmap(Image *img, uint f, uint m); - void *readData(uint &size); - // void mipmap(FloatImage *img, uint f, uint m); - - void printInfo() const; - -private: - - uint blockSize() const; - uint faceSize() const; - uint mipmapSize(uint m) const; - - uint offset(uint f, uint m); - - void readLinearImage(Image * img); - void readBlockImage(Image * img); - void readBlock(ColorBlock * rgba); - - -private: - Stream stream; // memory where DDS file resides - DDSHeader header; +class DirectDrawSurface { + public: + DirectDrawSurface(unsigned char *mem, uint size); + ~DirectDrawSurface(); + + bool isValid() const; + bool isSupported() const; + + bool hasAlpha() const; + + uint mipmapCount() const; + uint fourCC() const; + uint width() const; + uint height() const; + uint depth() const; + bool isTexture1D() const; + bool isTexture2D() const; + bool isTexture3D() const; + bool isTextureCube() const; + + void setNormalFlag(bool b); + void setHasAlphaFlag(bool b); + void setUserVersion(int version); + + void mipmap(Image *img, uint f, uint m); + void *readData(uint &size); + // void mipmap(FloatImage *img, uint f, uint m); + + void printInfo() const; + + private: + uint blockSize() const; + uint faceSize() const; + uint mipmapSize(uint m) const; + + uint offset(uint f, uint m); + + void readLinearImage(Image *img); + void readBlockImage(Image *img); + void readBlock(ColorBlock *rgba); + + private: + Stream stream; // memory where DDS file resides + DDSHeader header; }; -void mem_read(Stream & mem, DDSPixelFormat & pf); -void mem_read(Stream & mem, DDSCaps & caps); -void mem_read(Stream & mem, DDSHeader & header); -void mem_read(Stream & mem, DDSHeader10 & header); +void mem_read(Stream &mem, DDSPixelFormat &pf); +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 index 50488b923db..0660d5ce5cc 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -50,207 +50,205 @@ 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; + // 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; + // 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); + // 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); + // 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) >> 16; - block[5] = line_1_0 & 0xff; - block[6] = (line_1_0 & 0xff00) >> 8; - block[7] = (line_1_0 & 0xff0000) >> 16; - - // And flip the DXT1 block using the above function. - FlipDXT1BlockFull(block + 8); + // 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) >> 16; + block[5] = line_1_0 & 0xff; + block[6] = (line_1_0 & 0xff00) >> 8; + block[7] = (line_1_0 & 0xff0000) >> 16; + + // 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) >> 16; - FlipDXT1BlockHalf(block + 8); + // 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) >> 16; + 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) +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; + // 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 index 7d70395f1fa..b7056742430 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.h +++ b/source/blender/imbuf/intern/dds/FlipDXT.h @@ -20,6 +20,7 @@ #include "BLI_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); +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.cpp b/source/blender/imbuf/intern/dds/Image.cpp index 642194fa39b..6f0fff75818 100644 --- a/source/blender/imbuf/intern/dds/Image.cpp +++ b/source/blender/imbuf/intern/dds/Image.cpp @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -31,7 +30,7 @@ #include #include -#include // printf +#include // printf Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL) { @@ -39,87 +38,86 @@ Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL) Image::~Image() { - free(); + free(); } void Image::allocate(uint w, uint h) { - free(); - m_width = w; - m_height = h; - m_data = new Color32[w * h]; + free(); + m_width = w; + m_height = h; + m_data = new Color32[w * h]; } void Image::free() { - if (m_data) delete [] m_data; - m_data = NULL; + if (m_data) + delete[] m_data; + m_data = NULL; } - uint Image::width() const { - return m_width; + return m_width; } uint Image::height() const { - return m_height; + return m_height; } -const Color32 * Image::scanline(uint h) const +const Color32 *Image::scanline(uint h) const { - if (h >= m_height) { - printf("DDS: scanline beyond dimensions of image\n"); - return m_data; - } - return m_data + h * m_width; + if (h >= m_height) { + printf("DDS: scanline beyond dimensions of image\n"); + return m_data; + } + return m_data + h * m_width; } Color32 *Image::scanline(uint h) { - if (h >= m_height) { - printf("DDS: scanline beyond dimensions of image\n"); - return m_data; - } - return m_data + h * m_width; + if (h >= m_height) { + printf("DDS: scanline beyond dimensions of image\n"); + return m_data; + } + return m_data + h * m_width; } const Color32 *Image::pixels() const { - return m_data; + return m_data; } Color32 *Image::pixels() { - return m_data; + return m_data; } -const Color32 & Image::pixel(uint idx) const +const Color32 &Image::pixel(uint idx) const { - if (idx >= m_width * m_height) { - printf("DDS: pixel beyond dimensions of image\n"); - return m_data[0]; - } - return m_data[idx]; + if (idx >= m_width * m_height) { + printf("DDS: pixel beyond dimensions of image\n"); + return m_data[0]; + } + return m_data[idx]; } -Color32 & Image::pixel(uint idx) +Color32 &Image::pixel(uint idx) { - if (idx >= m_width * m_height) { - printf("DDS: pixel beyond dimensions of image\n"); - return m_data[0]; - } - return m_data[idx]; + if (idx >= m_width * m_height) { + printf("DDS: pixel beyond dimensions of image\n"); + return m_data[0]; + } + return m_data[idx]; } - Image::Format Image::format() const { - return m_format; + return m_format; } void Image::setFormat(Image::Format f) { - m_format = f; + m_format = f; } diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h index fa8cacd3142..b6191b7e96c 100644 --- a/source/blender/imbuf/intern/dds/Image.h +++ b/source/blender/imbuf/intern/dds/Image.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -35,64 +34,60 @@ #include /// 32 bit RGBA image. -class Image -{ -public: +class Image { + public: + enum Format { + Format_RGB, + Format_ARGB, + }; - enum Format - { - Format_RGB, - Format_ARGB, - }; + Image(); + ~Image(); - Image(); - ~Image(); - - void allocate(uint w, uint h); + void allocate(uint w, uint h); #if 0 - bool load(const char *name); + bool load(const char *name); - void wrap(void *data, uint w, uint h); - void unwrap(); + void wrap(void *data, uint w, uint h); + void unwrap(); #endif - uint width() const; - uint height() const; + uint width() const; + uint height() const; - const Color32 *scanline(uint h) const; - Color32 *scanline(uint h); + const Color32 *scanline(uint h) const; + Color32 *scanline(uint h); - const Color32 *pixels() const; - Color32 *pixels(); + const Color32 *pixels() const; + Color32 *pixels(); - const Color32 & pixel(uint idx) const; - Color32 & pixel(uint idx); + const Color32 &pixel(uint idx) const; + Color32 &pixel(uint idx); - const Color32 & pixel(uint x, uint y) const; - Color32 & pixel(uint x, uint y); + const Color32 &pixel(uint x, uint y) const; + Color32 &pixel(uint x, uint y); - Format format() const; - void setFormat(Format f); + Format format() const; + void setFormat(Format f); -private: - void free(); + private: + void free(); -private: - uint m_width; - uint m_height; - Format m_format; - Color32 *m_data; + private: + uint m_width; + uint m_height; + Format m_format; + Color32 *m_data; }; - -inline const Color32 & Image::pixel(uint x, uint y) const +inline const Color32 &Image::pixel(uint x, uint y) const { - return pixel(y * width() + x); + return pixel(y * width() + x); } -inline Color32 & Image::pixel(uint x, uint y) +inline Color32 &Image::pixel(uint x, uint y) { - return pixel(y * width() + x); + 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 7c50245858f..07912b86f47 100644 --- a/source/blender/imbuf/intern/dds/PixelFormat.h +++ b/source/blender/imbuf/intern/dds/PixelFormat.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) @@ -54,79 +53,78 @@ #include - namespace PixelFormat - { - - // Convert component \a c having \a inbits to the returned value having \a outbits. - inline uint convert(uint c, uint inbits, uint outbits) - { - if (inbits == 0) { - return 0; - } - else if (inbits >= outbits) { - // truncate - return c >> (inbits - outbits); - } - else { - // bitexpand - return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); - } - } - - // Get pixel component shift and size given its mask. - inline void maskShiftAndSize(uint mask, uint *shift, uint *size) - { - if (!mask) { - *shift = 0; - *size = 0; - return; - } - - *shift = 0; - while ((mask & 1) == 0) { - ++(*shift); - mask >>= 1; - } - - *size = 0; - while ((mask & 1) == 1) { - ++(*size); - mask >>= 1; - } - } - - 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; - } +namespace PixelFormat { + +// Convert component \a c having \a inbits to the returned value having \a outbits. +inline uint convert(uint c, uint inbits, uint outbits) +{ + if (inbits == 0) { + return 0; + } + else if (inbits >= outbits) { + // truncate + return c >> (inbits - outbits); + } + else { + // bitexpand + return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); + } +} + +// Get pixel component shift and size given its mask. +inline void maskShiftAndSize(uint mask, uint *shift, uint *size) +{ + if (!mask) { + *shift = 0; + *size = 0; + return; + } + + *shift = 0; + while ((mask & 1) == 0) { + ++(*shift); + mask >>= 1; + } + + *size = 0; + while ((mask & 1) == 1) { + ++(*size); + mask >>= 1; + } +} + +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; - } + 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 +} // namespace PixelFormat -#endif /* __PIXELFORMAT_H__ */ +#endif /* __PIXELFORMAT_H__ */ diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp index 993fa7734ba..271717f165c 100644 --- a/source/blender/imbuf/intern/dds/Stream.cpp +++ b/source/blender/imbuf/intern/dds/Stream.cpp @@ -18,86 +18,85 @@ * \ingroup imbdds */ - #include -#include // printf -#include // memcpy +#include // printf +#include // memcpy static const char *msg_error_seek = "DDS: trying to seek beyond end of stream (corrupt file?)"; static const char *msg_error_read = "DDS: trying to read beyond end of stream (corrupt file?)"; unsigned int Stream::seek(unsigned int p) { - if (p > size) { - set_failed(msg_error_seek); - } - else { - pos = p; - } + if (p > size) { + set_failed(msg_error_seek); + } + else { + pos = p; + } - return pos; + return pos; } -unsigned int mem_read(Stream & mem, unsigned long long & i) +unsigned int mem_read(Stream &mem, unsigned long long &i) { - if (mem.pos + 8 > mem.size) { - mem.set_failed(msg_error_seek); - return(0); - } - memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian - mem.pos += 8; - return(8); + if (mem.pos + 8 > mem.size) { + mem.set_failed(msg_error_seek); + return (0); + } + memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian + mem.pos += 8; + return (8); } -unsigned int mem_read(Stream & mem, unsigned int & i) +unsigned int mem_read(Stream &mem, unsigned int &i) { - if (mem.pos + 4 > mem.size) { - mem.set_failed(msg_error_read); - return(0); - } - memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian - mem.pos += 4; - return(4); + if (mem.pos + 4 > mem.size) { + mem.set_failed(msg_error_read); + return (0); + } + memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian + mem.pos += 4; + return (4); } -unsigned int mem_read(Stream & mem, unsigned short & i) +unsigned int mem_read(Stream &mem, unsigned short &i) { - if (mem.pos + 2 > mem.size) { - mem.set_failed(msg_error_read); - return(0); - } - memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian - mem.pos += 2; - return(2); + if (mem.pos + 2 > mem.size) { + mem.set_failed(msg_error_read); + return (0); + } + memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian + mem.pos += 2; + return (2); } -unsigned int mem_read(Stream & mem, unsigned char & i) +unsigned int mem_read(Stream &mem, unsigned char &i) { - if (mem.pos + 1 > mem.size) { - mem.set_failed(msg_error_read); - return(0); - } - i = (mem.mem + mem.pos)[0]; - mem.pos += 1; - return(1); + if (mem.pos + 1 > mem.size) { + mem.set_failed(msg_error_read); + return (0); + } + i = (mem.mem + mem.pos)[0]; + mem.pos += 1; + return (1); } -unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt) +unsigned int mem_read(Stream &mem, unsigned char *i, unsigned int cnt) { - if (mem.pos + cnt > mem.size) { - mem.set_failed(msg_error_read); - return(0); - } - memcpy(i, mem.mem + mem.pos, cnt); - mem.pos += cnt; - return(cnt); + if (mem.pos + cnt > mem.size) { + mem.set_failed(msg_error_read); + return (0); + } + memcpy(i, mem.mem + mem.pos, cnt); + mem.pos += cnt; + return (cnt); } void Stream::set_failed(const char *msg) { - if (!failed) { - puts(msg); - failed = true; - } + if (!failed) { + puts(msg); + failed = true; + } } diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index b9fba2ef8b2..35662e8f24e 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -18,26 +18,27 @@ * \ingroup imbdds */ - /* simple memory stream functions with buffer overflow check */ #ifndef __STREAM_H__ #define __STREAM_H__ struct Stream { - unsigned char *mem; // location in memory - unsigned int size; // size - unsigned int pos; // current position - bool failed; // error occured when seeking - Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0), failed(false) {} - unsigned int seek(unsigned int p); - void set_failed(const char *msg); + unsigned char *mem; // location in memory + unsigned int size; // size + unsigned int pos; // current position + bool failed; // error occured when seeking + Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0), failed(false) + { + } + unsigned int seek(unsigned int p); + void set_failed(const char *msg); }; -unsigned int mem_read(Stream & mem, unsigned long long & i); -unsigned int mem_read(Stream & mem, unsigned int & i); -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); +unsigned int mem_read(Stream &mem, unsigned long long &i); +unsigned int mem_read(Stream &mem, unsigned int &i); +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 fa88f81b55a..6a76e231e37 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -18,7 +18,6 @@ * \ingroup imbdds */ - extern "C" { #include "BLI_utildefines.h" } @@ -28,11 +27,11 @@ extern "C" { #include #include #include -#include // printf +#include // printf #include -#if defined (WIN32) -#include "utfconv.h" +#if defined(WIN32) +# include "utfconv.h" #endif extern "C" { @@ -47,138 +46,149 @@ extern "C" { int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/) { - return(0); /* todo: finish this function */ + return (0); /* todo: finish this function */ - /* check image buffer */ - if (ibuf == 0) return (0); - if (ibuf->rect == 0) return (0); + /* check image buffer */ + if (ibuf == 0) + return (0); + if (ibuf->rect == 0) + return (0); - /* open file for writing */ - std::ofstream fildes; + /* open file for writing */ + std::ofstream fildes; -#if defined (WIN32) - wchar_t *wname = alloc_utf16_from_8(name, 0); - fildes.open(wname); - free(wname); +#if defined(WIN32) + wchar_t *wname = alloc_utf16_from_8(name, 0); + fildes.open(wname); + free(wname); #else - fildes.open(name); + fildes.open(name); #endif - /* write header */ - fildes << "DDS "; - fildes.close(); + /* write header */ + fildes << "DDS "; + fildes.close(); - return(1); + return (1); } -int imb_is_a_dds(const unsigned char *mem) // note: use at most first 32 bytes +int imb_is_a_dds(const unsigned char *mem) // note: use at most first 32 bytes { - /* heuristic check to see if mem contains a DDS file */ - /* header.fourcc == FOURCC_DDS */ - if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) return(0); - /* header.size == 124 */ - if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) return(0); - return(1); + /* heuristic check to see if mem contains a DDS file */ + /* header.fourcc == FOURCC_DDS */ + if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) + return (0); + /* header.size == 124 */ + if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) + return (0); + return (1); } -struct ImBuf *imb_load_dds(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +struct ImBuf *imb_load_dds(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - struct ImBuf *ibuf = NULL; - DirectDrawSurface dds((unsigned char *)mem, size); /* reads header */ - unsigned char bits_per_pixel; - unsigned int *rect; - Image img; - unsigned int numpixels = 0; - int col; - unsigned char *cp = (unsigned char *) &col; - Color32 pixel; - Color32 *pixels = 0; - - /* OCIO_TODO: never was able to save DDS, so can't test loading - * but profile used to be set to sRGB and can't see rect_float here, so - * default byte space should work fine - */ - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - if (!imb_is_a_dds(mem)) - return (0); - - /* check if DDS is valid and supported */ - if (!dds.isValid()) { - /* no need to print error here, just testing if it is a DDS */ - if (flags & IB_test) - return (0); - - printf("DDS: not valid; header follows\n"); - dds.printInfo(); - return(0); - } - if (!dds.isSupported()) { - printf("DDS: format not supported\n"); - return(0); - } - if ((dds.width() > 65535) || (dds.height() > 65535)) { - printf("DDS: dimensions too large\n"); - return(0); - } - - /* convert DDS into ImBuf */ - dds.mipmap(&img, 0, 0); /* load first face, first mipmap */ - pixels = img.pixels(); - numpixels = dds.width() * dds.height(); - bits_per_pixel = 24; - if (img.format() == Image::Format_ARGB) { - /* check that there is effectively an alpha channel */ - for (unsigned int i = 0; i < numpixels; i++) { - pixel = pixels[i]; - if (pixel.a != 255) { - bits_per_pixel = 32; - break; - } - } - } - ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0); - if (ibuf == 0) return(0); /* memory allocation failed */ - - ibuf->ftype = IMB_FTYPE_DDS; - ibuf->dds_data.fourcc = dds.fourCC(); - ibuf->dds_data.nummipmaps = dds.mipmapCount(); - - if ((flags & IB_test) == 0) { - if (!imb_addrectImBuf(ibuf)) return(ibuf); - if (ibuf->rect == 0) return(ibuf); - - rect = ibuf->rect; - cp[3] = 0xff; /* default alpha if alpha channel is not present */ - - for (unsigned int i = 0; i < numpixels; i++) { - pixel = pixels[i]; - cp[0] = pixel.r; /* set R component of col */ - cp[1] = pixel.g; /* set G component of col */ - cp[2] = pixel.b; /* set B component of col */ - if (dds.hasAlpha()) - cp[3] = pixel.a; /* set A component of col */ - rect[i] = col; - } - - if (ibuf->dds_data.fourcc != FOURCC_DDS) { - ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size); - - /* flip compressed texture */ - if (ibuf->dds_data.data) { - 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); - } - - return(ibuf); + struct ImBuf *ibuf = NULL; + DirectDrawSurface dds((unsigned char *)mem, size); /* reads header */ + unsigned char bits_per_pixel; + unsigned int *rect; + Image img; + unsigned int numpixels = 0; + int col; + unsigned char *cp = (unsigned char *)&col; + Color32 pixel; + Color32 *pixels = 0; + + /* OCIO_TODO: never was able to save DDS, so can't test loading + * but profile used to be set to sRGB and can't see rect_float here, so + * default byte space should work fine + */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + if (!imb_is_a_dds(mem)) + return (0); + + /* check if DDS is valid and supported */ + if (!dds.isValid()) { + /* no need to print error here, just testing if it is a DDS */ + if (flags & IB_test) + return (0); + + printf("DDS: not valid; header follows\n"); + dds.printInfo(); + return (0); + } + if (!dds.isSupported()) { + printf("DDS: format not supported\n"); + return (0); + } + if ((dds.width() > 65535) || (dds.height() > 65535)) { + printf("DDS: dimensions too large\n"); + return (0); + } + + /* convert DDS into ImBuf */ + dds.mipmap(&img, 0, 0); /* load first face, first mipmap */ + pixels = img.pixels(); + numpixels = dds.width() * dds.height(); + bits_per_pixel = 24; + if (img.format() == Image::Format_ARGB) { + /* check that there is effectively an alpha channel */ + for (unsigned int i = 0; i < numpixels; i++) { + pixel = pixels[i]; + if (pixel.a != 255) { + bits_per_pixel = 32; + break; + } + } + } + ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0); + if (ibuf == 0) + return (0); /* memory allocation failed */ + + ibuf->ftype = IMB_FTYPE_DDS; + ibuf->dds_data.fourcc = dds.fourCC(); + ibuf->dds_data.nummipmaps = dds.mipmapCount(); + + if ((flags & IB_test) == 0) { + if (!imb_addrectImBuf(ibuf)) + return (ibuf); + if (ibuf->rect == 0) + return (ibuf); + + rect = ibuf->rect; + cp[3] = 0xff; /* default alpha if alpha channel is not present */ + + for (unsigned int i = 0; i < numpixels; i++) { + pixel = pixels[i]; + cp[0] = pixel.r; /* set R component of col */ + cp[1] = pixel.g; /* set G component of col */ + cp[2] = pixel.b; /* set B component of col */ + if (dds.hasAlpha()) + cp[3] = pixel.a; /* set A component of col */ + rect[i] = col; + } + + if (ibuf->dds_data.fourcc != FOURCC_DDS) { + ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size); + + /* flip compressed texture */ + if (ibuf->dds_data.data) { + 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); + } + + return (ibuf); } -} // extern "C" +} // extern "C" diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h index cbe19ab3e90..12db8aa6416 100644 --- a/source/blender/imbuf/intern/dds/dds_api.h +++ b/source/blender/imbuf/intern/dds/dds_api.h @@ -18,7 +18,6 @@ * \ingroup imbdds */ - #ifndef __DDS_API_H__ #define __DDS_API_H__ @@ -28,9 +27,12 @@ extern "C" { #include "../../IMB_imbuf.h" -int imb_is_a_dds(const unsigned char *mem); /* use only first 32 bytes of mem */ -int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_dds(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +int imb_is_a_dds(const unsigned char *mem); /* use only first 32 bytes of mem */ +int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags); +struct ImBuf *imb_load_dds(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index d1997e4612d..fb8dcffe9d4 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -33,469 +33,495 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" - #include "MEM_guardedalloc.h" /************************* Floyd-Steinberg dithering *************************/ typedef struct DitherContext { - float dither; + float dither; } DitherContext; static DitherContext *create_dither_context(float dither) { - DitherContext *di; + DitherContext *di; - di = MEM_mallocN(sizeof(DitherContext), "dithering context"); - di->dither = dither; + di = MEM_mallocN(sizeof(DitherContext), "dithering context"); + di->dither = dither; - return di; + return di; } static void clear_dither_context(DitherContext *di) { - MEM_freeN(di); + MEM_freeN(di); } - /************************* Generic Buffer Conversion *************************/ MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4]) { - b[0] = unit_ushort_to_uchar(us[0]); - b[1] = unit_ushort_to_uchar(us[1]); - b[2] = unit_ushort_to_uchar(us[2]); - b[3] = unit_ushort_to_uchar(us[3]); + b[0] = unit_ushort_to_uchar(us[0]); + b[1] = unit_ushort_to_uchar(us[1]); + b[2] = unit_ushort_to_uchar(us[2]); + b[3] = unit_ushort_to_uchar(us[3]); } MINLINE unsigned char ftochar(float value) { - return unit_float_to_uchar_clamp(value); + return unit_float_to_uchar_clamp(value); } -MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t) +MINLINE void ushort_to_byte_dither_v4( + uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t) { #define USHORTTOFLOAT(val) ((float)val / 65535.0f) - float dither_value = dither_random_value(s, t) * 0.005f * di->dither; + float dither_value = dither_random_value(s, t) * 0.005f * di->dither; - b[0] = ftochar(dither_value + USHORTTOFLOAT(us[0])); - b[1] = ftochar(dither_value + USHORTTOFLOAT(us[1])); - b[2] = ftochar(dither_value + USHORTTOFLOAT(us[2])); - b[3] = unit_ushort_to_uchar(us[3]); + b[0] = ftochar(dither_value + USHORTTOFLOAT(us[0])); + b[1] = ftochar(dither_value + USHORTTOFLOAT(us[1])); + b[2] = ftochar(dither_value + USHORTTOFLOAT(us[2])); + b[3] = unit_ushort_to_uchar(us[3]); #undef USHORTTOFLOAT } -MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di, float s, float t) +MINLINE void float_to_byte_dither_v4( + uchar b[4], const float f[4], DitherContext *di, float s, float t) { - float dither_value = dither_random_value(s, t) * 0.005f * di->dither; + float dither_value = dither_random_value(s, t) * 0.005f * di->dither; - b[0] = ftochar(dither_value + f[0]); - b[1] = ftochar(dither_value + f[1]); - b[2] = ftochar(dither_value + f[2]); - b[3] = unit_float_to_uchar_clamp(f[3]); + b[0] = ftochar(dither_value + f[0]); + b[1] = ftochar(dither_value + f[1]); + b[2] = ftochar(dither_value + f[2]); + b[3] = unit_float_to_uchar_clamp(f[3]); } /* float to byte pixels, output 4-channel RGBA */ -void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, - int channels_from, float dither, int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from) +void IMB_buffer_byte_from_float(uchar *rect_to, + const float *rect_from, + int channels_from, + float dither, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from) { - float tmp[4]; - int x, y; - DitherContext *di = NULL; - float inv_width = 1.0f / width; - float inv_height = 1.0f / height; - - /* we need valid profiles */ - BLI_assert(profile_to != IB_PROFILE_NONE); - BLI_assert(profile_from != IB_PROFILE_NONE); - - if (dither) - di = create_dither_context(dither); - - for (y = 0; y < height; y++) { - float t = y * inv_height; - - if (channels_from == 1) { - /* single channel input */ - const float *from = rect_from + ((size_t)stride_from) * y; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from++, to += 4) - to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); - } - else if (channels_from == 3) { - /* RGB input */ - const float *from = rect_from + ((size_t)stride_from) * y * 3; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - if (profile_to == profile_from) { - /* no color space conversion */ - for (x = 0; x < width; x++, from += 3, to += 4) { - rgb_float_to_uchar(to, from); - to[3] = 255; - } - } - else if (profile_to == IB_PROFILE_SRGB) { - /* convert from linear to sRGB */ - for (x = 0; x < width; x++, from += 3, to += 4) { - linearrgb_to_srgb_v3_v3(tmp, from); - rgb_float_to_uchar(to, tmp); - to[3] = 255; - } - } - else if (profile_to == IB_PROFILE_LINEAR_RGB) { - /* convert from sRGB to linear */ - for (x = 0; x < width; x++, from += 3, to += 4) { - srgb_to_linearrgb_v3_v3(tmp, from); - rgb_float_to_uchar(to, tmp); - to[3] = 255; - } - } - } - else if (channels_from == 4) { - /* RGBA input */ - const float *from = rect_from + ((size_t)stride_from) * y * 4; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - if (profile_to == profile_from) { - float straight[4]; - - /* no color space conversion */ - if (dither && predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4_v4(straight, from); - float_to_byte_dither_v4(to, straight, di, (float) x * inv_width, t); - } - } - else if (dither) { - for (x = 0; x < width; x++, from += 4, to += 4) - float_to_byte_dither_v4(to, from, di, (float) x * inv_width, t); - } - else if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4_v4(straight, from); - rgba_float_to_uchar(to, straight); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) - rgba_float_to_uchar(to, from); - } - } - else if (profile_to == IB_PROFILE_SRGB) { - /* convert from linear to sRGB */ - unsigned short us[4]; - float straight[4]; - - if (dither && predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4_v4(straight, from); - linearrgb_to_srgb_ushort4(us, from); - ushort_to_byte_dither_v4(to, us, di, (float) x * inv_width, t); - } - } - else if (dither) { - for (x = 0; x < width; x++, from += 4, to += 4) { - linearrgb_to_srgb_ushort4(us, from); - ushort_to_byte_dither_v4(to, us, di, (float) x * inv_width, t); - } - } - else if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4_v4(straight, from); - linearrgb_to_srgb_ushort4(us, from); - ushort_to_byte_v4(to, us); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) { - linearrgb_to_srgb_ushort4(us, from); - ushort_to_byte_v4(to, us); - } - } - } - else if (profile_to == IB_PROFILE_LINEAR_RGB) { - /* convert from sRGB to linear */ - if (dither && predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - srgb_to_linearrgb_predivide_v4(tmp, from); - float_to_byte_dither_v4(to, tmp, di, (float) x * inv_width, t); - } - } - else if (dither) { - for (x = 0; x < width; x++, from += 4, to += 4) { - srgb_to_linearrgb_v4(tmp, from); - float_to_byte_dither_v4(to, tmp, di, (float) x * inv_width, t); - } - } - else if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - srgb_to_linearrgb_predivide_v4(tmp, from); - rgba_float_to_uchar(to, tmp); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) { - srgb_to_linearrgb_v4(tmp, from); - rgba_float_to_uchar(to, tmp); - } - } - } - } - } - - if (dither) - clear_dither_context(di); + float tmp[4]; + int x, y; + DitherContext *di = NULL; + float inv_width = 1.0f / width; + float inv_height = 1.0f / height; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + if (dither) + di = create_dither_context(dither); + + for (y = 0; y < height; y++) { + float t = y * inv_height; + + if (channels_from == 1) { + /* single channel input */ + const float *from = rect_from + ((size_t)stride_from) * y; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from++, to += 4) + to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); + } + else if (channels_from == 3) { + /* RGB input */ + const float *from = rect_from + ((size_t)stride_from) * y * 3; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + if (profile_to == profile_from) { + /* no color space conversion */ + for (x = 0; x < width; x++, from += 3, to += 4) { + rgb_float_to_uchar(to, from); + to[3] = 255; + } + } + else if (profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + for (x = 0; x < width; x++, from += 3, to += 4) { + linearrgb_to_srgb_v3_v3(tmp, from); + rgb_float_to_uchar(to, tmp); + to[3] = 255; + } + } + else if (profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert from sRGB to linear */ + for (x = 0; x < width; x++, from += 3, to += 4) { + srgb_to_linearrgb_v3_v3(tmp, from); + rgb_float_to_uchar(to, tmp); + to[3] = 255; + } + } + } + else if (channels_from == 4) { + /* RGBA input */ + const float *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + if (profile_to == profile_from) { + float straight[4]; + + /* no color space conversion */ + if (dither && predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + premul_to_straight_v4_v4(straight, from); + float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t); + } + } + else if (dither) { + for (x = 0; x < width; x++, from += 4, to += 4) + float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t); + } + else if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + premul_to_straight_v4_v4(straight, from); + rgba_float_to_uchar(to, straight); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) + rgba_float_to_uchar(to, from); + } + } + else if (profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + unsigned short us[4]; + float straight[4]; + + if (dither && predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + premul_to_straight_v4_v4(straight, from); + linearrgb_to_srgb_ushort4(us, from); + ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t); + } + } + else if (dither) { + for (x = 0; x < width; x++, from += 4, to += 4) { + linearrgb_to_srgb_ushort4(us, from); + ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t); + } + } + else if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + premul_to_straight_v4_v4(straight, from); + linearrgb_to_srgb_ushort4(us, from); + ushort_to_byte_v4(to, us); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) { + linearrgb_to_srgb_ushort4(us, from); + ushort_to_byte_v4(to, us); + } + } + } + else if (profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert from sRGB to linear */ + if (dither && predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + srgb_to_linearrgb_predivide_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t); + } + } + else if (dither) { + for (x = 0; x < width; x++, from += 4, to += 4) { + srgb_to_linearrgb_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t); + } + } + else if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + srgb_to_linearrgb_predivide_v4(tmp, from); + rgba_float_to_uchar(to, tmp); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) { + srgb_to_linearrgb_v4(tmp, from); + rgba_float_to_uchar(to, tmp); + } + } + } + } + } + + if (dither) + clear_dither_context(di); } - /* float to byte pixels, output 4-channel RGBA */ -void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, - int channels_from, float dither, bool predivide, - int width, int height, int stride_to, int stride_from, char *mask) +void IMB_buffer_byte_from_float_mask(uchar *rect_to, + const float *rect_from, + int channels_from, + float dither, + bool predivide, + int width, + int height, + int stride_to, + int stride_from, + char *mask) { - int x, y; - DitherContext *di = NULL; - float inv_width = 1.0f / width, - inv_height = 1.0f / height; - - if (dither) - di = create_dither_context(dither); - - for (y = 0; y < height; y++) { - float t = y * inv_height; - - if (channels_from == 1) { - /* single channel input */ - const float *from = rect_from + ((size_t)stride_from) * y; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from++, to += 4) - if (*mask++ == FILTER_MASK_USED) - to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); - } - else if (channels_from == 3) { - /* RGB input */ - const float *from = rect_from + ((size_t)stride_from) * y * 3; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from += 3, to += 4) { - if (*mask++ == FILTER_MASK_USED) { - rgb_float_to_uchar(to, from); - to[3] = 255; - } - } - } - else if (channels_from == 4) { - /* RGBA input */ - const float *from = rect_from + ((size_t)stride_from) * y * 4; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - float straight[4]; - - if (dither && predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - if (*mask++ == FILTER_MASK_USED) { - premul_to_straight_v4_v4(straight, from); - float_to_byte_dither_v4(to, straight, di, (float) x * inv_width, t); - } - } - } - else if (dither) { - for (x = 0; x < width; x++, from += 4, to += 4) - if (*mask++ == FILTER_MASK_USED) - float_to_byte_dither_v4(to, from, di, (float) x * inv_width, t); - } - else if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - if (*mask++ == FILTER_MASK_USED) { - premul_to_straight_v4_v4(straight, from); - rgba_float_to_uchar(to, straight); - } - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) - if (*mask++ == FILTER_MASK_USED) - rgba_float_to_uchar(to, from); - } - } - } - - if (dither) - clear_dither_context(di); + int x, y; + DitherContext *di = NULL; + float inv_width = 1.0f / width, inv_height = 1.0f / height; + + if (dither) + di = create_dither_context(dither); + + for (y = 0; y < height; y++) { + float t = y * inv_height; + + if (channels_from == 1) { + /* single channel input */ + const float *from = rect_from + ((size_t)stride_from) * y; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from++, to += 4) + if (*mask++ == FILTER_MASK_USED) + to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); + } + else if (channels_from == 3) { + /* RGB input */ + const float *from = rect_from + ((size_t)stride_from) * y * 3; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from += 3, to += 4) { + if (*mask++ == FILTER_MASK_USED) { + rgb_float_to_uchar(to, from); + to[3] = 255; + } + } + } + else if (channels_from == 4) { + /* RGBA input */ + const float *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + float straight[4]; + + if (dither && predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + if (*mask++ == FILTER_MASK_USED) { + premul_to_straight_v4_v4(straight, from); + float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t); + } + } + } + else if (dither) { + for (x = 0; x < width; x++, from += 4, to += 4) + if (*mask++ == FILTER_MASK_USED) + float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t); + } + else if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + if (*mask++ == FILTER_MASK_USED) { + premul_to_straight_v4_v4(straight, from); + rgba_float_to_uchar(to, straight); + } + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) + if (*mask++ == FILTER_MASK_USED) + rgba_float_to_uchar(to, from); + } + } + } + + if (dither) + clear_dither_context(di); } /* byte to float pixels, input and output 4-channel RGBA */ -void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, - int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from) +void IMB_buffer_float_from_byte(float *rect_to, + const uchar *rect_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from) { - float tmp[4]; - int x, y; - - /* we need valid profiles */ - BLI_assert(profile_to != IB_PROFILE_NONE); - BLI_assert(profile_from != IB_PROFILE_NONE); - - /* RGBA input */ - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 4; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - if (profile_to == profile_from) { - /* no color space conversion */ - for (x = 0; x < width; x++, from += 4, to += 4) - rgba_uchar_to_float(to, from); - } - else if (profile_to == IB_PROFILE_LINEAR_RGB) { - /* convert sRGB to linear */ - if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - srgb_to_linearrgb_uchar4_predivide(to, from); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) { - srgb_to_linearrgb_uchar4(to, from); - } - } - } - else if (profile_to == IB_PROFILE_SRGB) { - /* convert linear to sRGB */ - if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - rgba_uchar_to_float(tmp, from); - linearrgb_to_srgb_predivide_v4(to, tmp); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) { - rgba_uchar_to_float(tmp, from); - linearrgb_to_srgb_v4(to, tmp); - } - } - } - } + float tmp[4]; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + /* RGBA input */ + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + if (profile_to == profile_from) { + /* no color space conversion */ + for (x = 0; x < width; x++, from += 4, to += 4) + rgba_uchar_to_float(to, from); + } + else if (profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert sRGB to linear */ + if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + srgb_to_linearrgb_uchar4_predivide(to, from); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) { + srgb_to_linearrgb_uchar4(to, from); + } + } + } + else if (profile_to == IB_PROFILE_SRGB) { + /* convert linear to sRGB */ + if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + rgba_uchar_to_float(tmp, from); + linearrgb_to_srgb_predivide_v4(to, tmp); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) { + rgba_uchar_to_float(tmp, from); + linearrgb_to_srgb_v4(to, tmp); + } + } + } + } } /* float to float pixels, output 4-channel RGBA */ -void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, - int channels_from, int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from) +void IMB_buffer_float_from_float(float *rect_to, + const float *rect_from, + int channels_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from) { - int x, y; - - /* we need valid profiles */ - BLI_assert(profile_to != IB_PROFILE_NONE); - BLI_assert(profile_from != IB_PROFILE_NONE); - - if (channels_from == 1) { - /* single channel input */ - for (y = 0; y < height; y++) { - const float *from = rect_from + ((size_t)stride_from) * y; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from++, to += 4) - to[0] = to[1] = to[2] = to[3] = from[0]; - } - } - else if (channels_from == 3) { - /* RGB input */ - for (y = 0; y < height; y++) { - const float *from = rect_from + ((size_t)stride_from) * y * 3; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - if (profile_to == profile_from) { - /* no color space conversion */ - for (x = 0; x < width; x++, from += 3, to += 4) { - copy_v3_v3(to, from); - to[3] = 1.0f; - } - } - else if (profile_to == IB_PROFILE_LINEAR_RGB) { - /* convert from sRGB to linear */ - for (x = 0; x < width; x++, from += 3, to += 4) { - srgb_to_linearrgb_v3_v3(to, from); - to[3] = 1.0f; - } - } - else if (profile_to == IB_PROFILE_SRGB) { - /* convert from linear to sRGB */ - for (x = 0; x < width; x++, from += 3, to += 4) { - linearrgb_to_srgb_v3_v3(to, from); - to[3] = 1.0f; - } - } - } - } - else if (channels_from == 4) { - /* RGBA input */ - for (y = 0; y < height; y++) { - const float *from = rect_from + ((size_t)stride_from) * y * 4; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - if (profile_to == profile_from) { - /* same profile, copy */ - memcpy(to, from, sizeof(float) * ((size_t)4) * width); - } - else if (profile_to == IB_PROFILE_LINEAR_RGB) { - /* convert to sRGB to linear */ - if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) - srgb_to_linearrgb_predivide_v4(to, from); - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) - srgb_to_linearrgb_v4(to, from); - } - } - else if (profile_to == IB_PROFILE_SRGB) { - /* convert from linear to sRGB */ - if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) - linearrgb_to_srgb_predivide_v4(to, from); - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) - linearrgb_to_srgb_v4(to, from); - } - } - } - } + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + if (channels_from == 1) { + /* single channel input */ + for (y = 0; y < height; y++) { + const float *from = rect_from + ((size_t)stride_from) * y; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from++, to += 4) + to[0] = to[1] = to[2] = to[3] = from[0]; + } + } + else if (channels_from == 3) { + /* RGB input */ + for (y = 0; y < height; y++) { + const float *from = rect_from + ((size_t)stride_from) * y * 3; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + if (profile_to == profile_from) { + /* no color space conversion */ + for (x = 0; x < width; x++, from += 3, to += 4) { + copy_v3_v3(to, from); + to[3] = 1.0f; + } + } + else if (profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert from sRGB to linear */ + for (x = 0; x < width; x++, from += 3, to += 4) { + srgb_to_linearrgb_v3_v3(to, from); + to[3] = 1.0f; + } + } + else if (profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + for (x = 0; x < width; x++, from += 3, to += 4) { + linearrgb_to_srgb_v3_v3(to, from); + to[3] = 1.0f; + } + } + } + } + else if (channels_from == 4) { + /* RGBA input */ + for (y = 0; y < height; y++) { + const float *from = rect_from + ((size_t)stride_from) * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + if (profile_to == profile_from) { + /* same profile, copy */ + memcpy(to, from, sizeof(float) * ((size_t)4) * width); + } + else if (profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert to sRGB to linear */ + if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) + srgb_to_linearrgb_predivide_v4(to, from); + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) + srgb_to_linearrgb_v4(to, from); + } + } + else if (profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) + linearrgb_to_srgb_predivide_v4(to, from); + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) + linearrgb_to_srgb_v4(to, from); + } + } + } + } } typedef struct FloatToFloatThreadData { - float *rect_to; - const float *rect_from; - int channels_from; - int profile_to; - int profile_from; - bool predivide; - int width; - int stride_to; - int stride_from; + float *rect_to; + const float *rect_from; + int channels_from; + int profile_to; + int profile_from; + bool predivide; + int width; + int stride_to; + int stride_from; } FloatToFloatThreadData; static void imb_buffer_float_from_float_thread_do(void *data_v, int start_scanline, int num_scanlines) { - FloatToFloatThreadData *data = (FloatToFloatThreadData *)data_v; - size_t offset_from = ((size_t)start_scanline) * data->stride_from * data->channels_from; - size_t offset_to = ((size_t)start_scanline) * data->stride_to * data->channels_from; - IMB_buffer_float_from_float(data->rect_to + offset_to, - data->rect_from + offset_from, - data->channels_from, - data->profile_to, - data->profile_from, - data->predivide, - data->width, - num_scanlines, - data->stride_to, - data->stride_from); + FloatToFloatThreadData *data = (FloatToFloatThreadData *)data_v; + size_t offset_from = ((size_t)start_scanline) * data->stride_from * data->channels_from; + size_t offset_to = ((size_t)start_scanline) * data->stride_to * data->channels_from; + IMB_buffer_float_from_float(data->rect_to + offset_to, + data->rect_from + offset_from, + data->channels_from, + data->profile_to, + data->profile_from, + data->predivide, + data->width, + num_scanlines, + data->stride_to, + data->stride_from); } void IMB_buffer_float_from_float_threaded(float *rect_to, @@ -509,183 +535,209 @@ void IMB_buffer_float_from_float_threaded(float *rect_to, int stride_to, int stride_from) { - if (((size_t)width) * height < 64 * 64) { - IMB_buffer_float_from_float(rect_to, - rect_from, - channels_from, - profile_to, - profile_from, - predivide, - width, - height, - stride_to, - stride_from); - } - else { - FloatToFloatThreadData data; - data.rect_to = rect_to; - data.rect_from = rect_from; - data.channels_from = channels_from; - data.profile_to = profile_to; - data.profile_from = profile_from; - data.predivide = predivide; - data.width = width; - data.stride_to = stride_to; - data.stride_from = stride_from; - IMB_processor_apply_threaded_scanlines( - height, imb_buffer_float_from_float_thread_do, &data); - } + if (((size_t)width) * height < 64 * 64) { + IMB_buffer_float_from_float(rect_to, + rect_from, + channels_from, + profile_to, + profile_from, + predivide, + width, + height, + stride_to, + stride_from); + } + else { + FloatToFloatThreadData data; + data.rect_to = rect_to; + data.rect_from = rect_from; + data.channels_from = channels_from; + data.profile_to = profile_to; + data.profile_from = profile_from; + data.predivide = predivide; + data.width = width; + data.stride_to = stride_to; + data.stride_from = stride_from; + IMB_processor_apply_threaded_scanlines(height, imb_buffer_float_from_float_thread_do, &data); + } } /* float to float pixels, output 4-channel RGBA */ -void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, int channels_from, - int width, int height, int stride_to, int stride_from, char *mask) +void IMB_buffer_float_from_float_mask(float *rect_to, + const float *rect_from, + int channels_from, + int width, + int height, + int stride_to, + int stride_from, + char *mask) { - int x, y; - - if (channels_from == 1) { - /* single channel input */ - for (y = 0; y < height; y++) { - const float *from = rect_from + ((size_t)stride_from) * y; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from++, to += 4) - if (*mask++ == FILTER_MASK_USED) - to[0] = to[1] = to[2] = to[3] = from[0]; - } - } - else if (channels_from == 3) { - /* RGB input */ - for (y = 0; y < height; y++) { - const float *from = rect_from + ((size_t)stride_from) * y * 3; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from += 3, to += 4) { - if (*mask++ == FILTER_MASK_USED) { - copy_v3_v3(to, from); - to[3] = 1.0f; - } - } - } - } - else if (channels_from == 4) { - /* RGBA input */ - for (y = 0; y < height; y++) { - const float *from = rect_from + ((size_t)stride_from) * y * 4; - float *to = rect_to + ((size_t)stride_to) * y * 4; - - for (x = 0; x < width; x++, from += 4, to += 4) - if (*mask++ == FILTER_MASK_USED) - copy_v4_v4(to, from); - } - } + int x, y; + + if (channels_from == 1) { + /* single channel input */ + for (y = 0; y < height; y++) { + const float *from = rect_from + ((size_t)stride_from) * y; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from++, to += 4) + if (*mask++ == FILTER_MASK_USED) + to[0] = to[1] = to[2] = to[3] = from[0]; + } + } + else if (channels_from == 3) { + /* RGB input */ + for (y = 0; y < height; y++) { + const float *from = rect_from + ((size_t)stride_from) * y * 3; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from += 3, to += 4) { + if (*mask++ == FILTER_MASK_USED) { + copy_v3_v3(to, from); + to[3] = 1.0f; + } + } + } + } + else if (channels_from == 4) { + /* RGBA input */ + for (y = 0; y < height; y++) { + const float *from = rect_from + ((size_t)stride_from) * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; + + for (x = 0; x < width; x++, from += 4, to += 4) + if (*mask++ == FILTER_MASK_USED) + copy_v4_v4(to, from); + } + } } /* byte to byte pixels, input and output 4-channel RGBA */ -void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, - int profile_to, int profile_from, bool predivide, - int width, int height, int stride_to, int stride_from) +void IMB_buffer_byte_from_byte(uchar *rect_to, + const uchar *rect_from, + int profile_to, + int profile_from, + bool predivide, + int width, + int height, + int stride_to, + int stride_from) { - float tmp[4]; - int x, y; - - /* we need valid profiles */ - BLI_assert(profile_to != IB_PROFILE_NONE); - BLI_assert(profile_from != IB_PROFILE_NONE); - - /* always RGBA input */ - for (y = 0; y < height; y++) { - const uchar *from = rect_from + ((size_t)stride_from) * y * 4; - uchar *to = rect_to + ((size_t)stride_to) * y * 4; - - if (profile_to == profile_from) { - /* same profile, copy */ - memcpy(to, from, sizeof(uchar) * 4 * width); - } - else if (profile_to == IB_PROFILE_LINEAR_RGB) { - /* convert to sRGB to linear */ - if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - rgba_uchar_to_float(tmp, from); - srgb_to_linearrgb_predivide_v4(tmp, tmp); - rgba_float_to_uchar(to, tmp); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) { - rgba_uchar_to_float(tmp, from); - srgb_to_linearrgb_v4(tmp, tmp); - rgba_float_to_uchar(to, tmp); - } - } - } - else if (profile_to == IB_PROFILE_SRGB) { - /* convert from linear to sRGB */ - if (predivide) { - for (x = 0; x < width; x++, from += 4, to += 4) { - rgba_uchar_to_float(tmp, from); - linearrgb_to_srgb_predivide_v4(tmp, tmp); - rgba_float_to_uchar(to, tmp); - } - } - else { - for (x = 0; x < width; x++, from += 4, to += 4) { - rgba_uchar_to_float(tmp, from); - linearrgb_to_srgb_v4(tmp, tmp); - rgba_float_to_uchar(to, tmp); - } - } - } - } + float tmp[4]; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + /* always RGBA input */ + for (y = 0; y < height; y++) { + const uchar *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; + + if (profile_to == profile_from) { + /* same profile, copy */ + memcpy(to, from, sizeof(uchar) * 4 * width); + } + else if (profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert to sRGB to linear */ + if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + rgba_uchar_to_float(tmp, from); + srgb_to_linearrgb_predivide_v4(tmp, tmp); + rgba_float_to_uchar(to, tmp); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) { + rgba_uchar_to_float(tmp, from); + srgb_to_linearrgb_v4(tmp, tmp); + rgba_float_to_uchar(to, tmp); + } + } + } + else if (profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if (predivide) { + for (x = 0; x < width; x++, from += 4, to += 4) { + rgba_uchar_to_float(tmp, from); + linearrgb_to_srgb_predivide_v4(tmp, tmp); + rgba_float_to_uchar(to, tmp); + } + } + else { + for (x = 0; x < width; x++, from += 4, to += 4) { + rgba_uchar_to_float(tmp, from); + linearrgb_to_srgb_v4(tmp, tmp); + rgba_float_to_uchar(to, tmp); + } + } + } + } } /****************************** ImBuf Conversion *****************************/ void IMB_rect_from_float(ImBuf *ibuf) { - float *buffer; - const char *from_colorspace; - - /* verify we have a float buffer */ - if (ibuf->rect_float == NULL) - return; - - /* create byte rect if it didn't exist yet */ - if (ibuf->rect == NULL) { - if (imb_addrectImBuf(ibuf) == 0) - return; - } - - if (ibuf->float_colorspace == NULL) - from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); - else - from_colorspace = ibuf->float_colorspace->name; - - buffer = MEM_dupallocN(ibuf->rect_float); - - /* first make float buffer in byte space */ - IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, true); - - /* convert from float's premul alpha to byte's straight alpha */ - IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y); - - /* convert float to byte */ - IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); - - MEM_freeN(buffer); - - /* ensure user flag is reset */ - ibuf->userflags &= ~IB_RECT_INVALID; + float *buffer; + const char *from_colorspace; + + /* verify we have a float buffer */ + if (ibuf->rect_float == NULL) + return; + + /* create byte rect if it didn't exist yet */ + if (ibuf->rect == NULL) { + if (imb_addrectImBuf(ibuf) == 0) + return; + } + + if (ibuf->float_colorspace == NULL) + from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + else + from_colorspace = ibuf->float_colorspace->name; + + buffer = MEM_dupallocN(ibuf->rect_float); + + /* first make float buffer in byte space */ + IMB_colormanagement_transform(buffer, + ibuf->x, + ibuf->y, + ibuf->channels, + from_colorspace, + ibuf->rect_colorspace->name, + true); + + /* convert from float's premul alpha to byte's straight alpha */ + IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y); + + /* convert float to byte */ + IMB_buffer_byte_from_float((unsigned char *)ibuf->rect, + buffer, + ibuf->channels, + ibuf->dither, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + ibuf->x, + ibuf->y, + ibuf->x, + ibuf->x); + + MEM_freeN(buffer); + + /* ensure user flag is reset */ + ibuf->userflags &= ~IB_RECT_INVALID; } typedef struct PartialThreadData { - ImBuf *ibuf; - float *buffer; - uchar *rect_byte; - const float *rect_float; - int width; - bool is_data; + ImBuf *ibuf; + float *buffer; + uchar *rect_byte; + const float *rect_float; + int width; + bool is_data; } PartialThreadData; static void partial_rect_from_float_slice(float *buffer, @@ -696,128 +748,145 @@ static void partial_rect_from_float_slice(float *buffer, const int h, const bool is_data) { - const int profile_from = IB_PROFILE_LINEAR_RGB; - 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); - - /* and do color space conversion to byte */ - IMB_buffer_byte_from_float(rect_byte, rect_float, - 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, true, - w, h, ibuf->x, w); - } - else { - IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_SRGB, profile_from, true, - w, h, w, ibuf->x); - - IMB_buffer_float_unpremultiply(buffer, w, h); - /* 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); - } + const int profile_from = IB_PROFILE_LINEAR_RGB; + 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); + + /* and do color space conversion to byte */ + IMB_buffer_byte_from_float(rect_byte, + rect_float, + 4, + ibuf->dither, + IB_PROFILE_SRGB, + profile_from, + true, + w, + h, + ibuf->x, + w); + } + else { + IMB_buffer_float_from_float( + buffer, rect_float, ibuf->channels, IB_PROFILE_SRGB, profile_from, true, w, h, w, ibuf->x); + + IMB_buffer_float_unpremultiply(buffer, w, h); + /* 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); + } } -static void partial_rect_from_float_thread_do(void *data_v, - int start_scanline, - int num_scanlines) +static void partial_rect_from_float_thread_do(void *data_v, int start_scanline, int num_scanlines) { - PartialThreadData *data = (PartialThreadData *)data_v; - ImBuf *ibuf = data->ibuf; - size_t global_offset = ((size_t)ibuf->x) * start_scanline; - size_t local_offset = ((size_t)data->width) * start_scanline; - partial_rect_from_float_slice(data->buffer + local_offset * ibuf->channels, - data->rect_byte + global_offset * 4, - ibuf, - data->rect_float + global_offset * ibuf->channels, - data->width, - num_scanlines, - data->is_data); + PartialThreadData *data = (PartialThreadData *)data_v; + ImBuf *ibuf = data->ibuf; + size_t global_offset = ((size_t)ibuf->x) * start_scanline; + size_t local_offset = ((size_t)data->width) * start_scanline; + partial_rect_from_float_slice(data->buffer + local_offset * ibuf->channels, + data->rect_byte + global_offset * 4, + ibuf, + data->rect_float + global_offset * ibuf->channels, + data->width, + num_scanlines, + data->is_data); } /* 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, bool is_data) +void IMB_partial_rect_from_float( + ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data) { - const float *rect_float; - uchar *rect_byte; - - /* verify we have a float buffer */ - if (ibuf->rect_float == NULL || buffer == NULL) - return; - - /* create byte rect if it didn't exist yet */ - if (ibuf->rect == NULL) - imb_addrectImBuf(ibuf); - - /* do conversion */ - rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels; - rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4; - - if (((size_t)w) * h < 64 * 64) { - partial_rect_from_float_slice( - buffer, rect_byte, ibuf, rect_float, w, h, is_data); - } - else { - PartialThreadData data; - data.ibuf = ibuf; - data.buffer = buffer; - data.rect_byte = rect_byte; - data.rect_float = rect_float; - data.width = w; - data.is_data = is_data; - IMB_processor_apply_threaded_scanlines( - h, partial_rect_from_float_thread_do, &data); - } - - /* ensure user flag is reset */ - ibuf->userflags &= ~IB_RECT_INVALID; + const float *rect_float; + uchar *rect_byte; + + /* verify we have a float buffer */ + if (ibuf->rect_float == NULL || buffer == NULL) + return; + + /* create byte rect if it didn't exist yet */ + if (ibuf->rect == NULL) + imb_addrectImBuf(ibuf); + + /* do conversion */ + rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels; + rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4; + + if (((size_t)w) * h < 64 * 64) { + partial_rect_from_float_slice(buffer, rect_byte, ibuf, rect_float, w, h, is_data); + } + else { + PartialThreadData data; + data.ibuf = ibuf; + data.buffer = buffer; + data.rect_byte = rect_byte; + data.rect_float = rect_float; + data.width = w; + data.is_data = is_data; + IMB_processor_apply_threaded_scanlines(h, partial_rect_from_float_thread_do, &data); + } + + /* ensure user flag is reset */ + ibuf->userflags &= ~IB_RECT_INVALID; } void IMB_float_from_rect(ImBuf *ibuf) { - float *rect_float; - - /* verify if we byte and float buffers */ - if (ibuf->rect == NULL) - return; - - /* allocate float buffer outside of image buffer, - * so work-in-progress color space conversion doesn't - * interfere with other parts of blender - */ - rect_float = ibuf->rect_float; - if (rect_float == NULL) { - size_t size; - - size = ((size_t)ibuf->x) * ibuf->y; - size = size * 4 * sizeof(float); - ibuf->channels = 4; - - rect_float = MEM_mapallocN(size, "IMB_float_from_rect"); - - if (rect_float == NULL) - return; - } - - /* first, create float buffer in non-linear space */ - IMB_buffer_float_from_byte(rect_float, (unsigned char *) ibuf->rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); - - /* then make float be in linear space */ - IMB_colormanagement_colorspace_to_scene_linear(rect_float, ibuf->x, ibuf->y, ibuf->channels, - ibuf->rect_colorspace, false); - - /* byte buffer is straight alpha, float should always be premul */ - IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y); - - if (ibuf->rect_float == NULL) { - ibuf->rect_float = rect_float; - ibuf->mall |= IB_rectfloat; - ibuf->flags |= IB_rectfloat; - } + float *rect_float; + + /* verify if we byte and float buffers */ + if (ibuf->rect == NULL) + return; + + /* allocate float buffer outside of image buffer, + * so work-in-progress color space conversion doesn't + * interfere with other parts of blender + */ + rect_float = ibuf->rect_float; + if (rect_float == NULL) { + size_t size; + + size = ((size_t)ibuf->x) * ibuf->y; + size = size * 4 * sizeof(float); + ibuf->channels = 4; + + rect_float = MEM_mapallocN(size, "IMB_float_from_rect"); + + if (rect_float == NULL) + return; + } + + /* first, create float buffer in non-linear space */ + IMB_buffer_float_from_byte(rect_float, + (unsigned char *)ibuf->rect, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + ibuf->x, + ibuf->y, + ibuf->x, + ibuf->x); + + /* then make float be in linear space */ + IMB_colormanagement_colorspace_to_scene_linear( + rect_float, ibuf->x, ibuf->y, ibuf->channels, ibuf->rect_colorspace, false); + + /* byte buffer is straight alpha, float should always be premul */ + IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y); + + if (ibuf->rect_float == NULL) { + ibuf->rect_float = rect_float; + ibuf->mall |= IB_rectfloat; + ibuf->flags |= IB_rectfloat; + } } /**************************** Color to Grayscale *****************************/ @@ -825,72 +894,72 @@ void IMB_float_from_rect(ImBuf *ibuf) /* no profile conversion */ void IMB_color_to_bw(ImBuf *ibuf) { - float *rct_fl = ibuf->rect_float; - uchar *rct = (uchar *)ibuf->rect; - size_t i; - - if (rct_fl) { - for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) - rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl); - } - - if (rct) { - for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4) - rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct); - } + float *rct_fl = ibuf->rect_float; + uchar *rct = (uchar *)ibuf->rect; + size_t i; + + if (rct_fl) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) + rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl); + } + + if (rct) { + for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4) + rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct); + } } void IMB_buffer_float_clamp(float *buf, int width, int height) { - size_t i, total = ((size_t)width) * height * 4; - for (i = 0; i < total; i++) { - buf[i] = min_ff(1.0, buf[i]); - } + size_t i, total = ((size_t)width) * height * 4; + for (i = 0; i < total; i++) { + buf[i] = min_ff(1.0, buf[i]); + } } void IMB_buffer_float_unpremultiply(float *buf, int width, int height) { - size_t total = ((size_t)width) * height; - float *fp = buf; - while (total--) { - premul_to_straight_v4(fp); - fp += 4; - } + size_t total = ((size_t)width) * height; + float *fp = buf; + while (total--) { + premul_to_straight_v4(fp); + fp += 4; + } } void IMB_buffer_float_premultiply(float *buf, int width, int height) { - size_t total = ((size_t)width) * height; - float *fp = buf; - while (total--) { - straight_to_premul_v4(fp); - fp += 4; - } + size_t total = ((size_t)width) * height; + float *fp = buf; + while (total--) { + straight_to_premul_v4(fp); + fp += 4; + } } /**************************** alter saturation *****************************/ void IMB_saturation(ImBuf *ibuf, float sat) { - size_t i; - unsigned char *rct = (unsigned char *)ibuf->rect; - float *rct_fl = ibuf->rect_float; - float hsv[3]; - - if (rct) { - float rgb[3]; - for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) { - rgb_uchar_to_float(rgb, rct); - rgb_to_hsv_v(rgb, hsv); - hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2); - rgb_float_to_uchar(rct, rgb); - } - } - - if (rct_fl) { - for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) { - rgb_to_hsv_v(rct_fl, hsv); - hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2); - } - } + size_t i; + unsigned char *rct = (unsigned char *)ibuf->rect; + float *rct_fl = ibuf->rect_float; + float hsv[3]; + + if (rct) { + float rgb[3]; + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) { + rgb_uchar_to_float(rgb, rct); + rgb_to_hsv_v(rgb, hsv); + hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2); + rgb_float_to_uchar(rct, rgb); + } + } + + if (rct_fl) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) { + rgb_to_hsv_v(rct_fl, hsv); + hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2); + } + } } diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index e02141b6038..7056e901f65 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -18,7 +18,6 @@ * \ingroup imbuf */ - #include #include "BLI_utildefines.h" @@ -30,74 +29,218 @@ #include "IMB_colormanagement.h" #ifdef WITH_OPENIMAGEIO -#include "oiio/openimageio_api.h" +# include "oiio/openimageio_api.h" #endif #ifdef WITH_OPENEXR -#include "openexr/openexr_api.h" +# include "openexr/openexr_api.h" #endif #ifdef WITH_DDS -#include "dds/dds_api.h" +# include "dds/dds_api.h" #endif static int imb_ftype_default(const ImFileType *type, ImBuf *ibuf) { - return (ibuf->ftype == type->filetype); + return (ibuf->ftype == type->filetype); } static int imb_ftype_iris(const ImFileType *type, ImBuf *ibuf) { - (void)type; - return (ibuf->ftype == IMB_FTYPE_IMAGIC); + (void)type; + return (ibuf->ftype == IMB_FTYPE_IMAGIC); } const ImFileType IMB_FILE_TYPES[] = { - {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, IMB_FTYPE_JPG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, IMB_FTYPE_PNG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, IMB_FTYPE_BMP, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_targa, NULL, imb_ftype_default, imb_loadtarga, NULL, imb_savetarga, NULL, 0, IMB_FTYPE_TGA, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_iris, NULL, imb_ftype_iris, imb_loadiris, NULL, imb_saveiris, NULL, 0, IMB_FTYPE_IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_jpeg, + NULL, + imb_ftype_default, + imb_load_jpeg, + NULL, + imb_savejpeg, + NULL, + 0, + IMB_FTYPE_JPG, + COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_png, + NULL, + imb_ftype_default, + imb_loadpng, + NULL, + imb_savepng, + NULL, + 0, + IMB_FTYPE_PNG, + COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_bmp, + NULL, + imb_ftype_default, + imb_bmp_decode, + NULL, + imb_savebmp, + NULL, + 0, + IMB_FTYPE_BMP, + COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_targa, + NULL, + imb_ftype_default, + imb_loadtarga, + NULL, + imb_savetarga, + NULL, + 0, + IMB_FTYPE_TGA, + COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_iris, + NULL, + imb_ftype_iris, + imb_loadiris, + NULL, + imb_saveiris, + NULL, + 0, + IMB_FTYPE_IMAGIC, + COLOR_ROLE_DEFAULT_BYTE}, #ifdef WITH_CINEON - {NULL, NULL, imb_is_dpx, NULL, imb_ftype_default, imb_load_dpx, NULL, imb_save_dpx, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_DPX, COLOR_ROLE_DEFAULT_FLOAT}, - {NULL, NULL, imb_is_cineon, NULL, imb_ftype_default, imb_load_cineon, NULL, imb_save_cineon, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_CINEON, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, + NULL, + imb_is_dpx, + NULL, + imb_ftype_default, + imb_load_dpx, + NULL, + imb_save_dpx, + NULL, + IM_FTYPE_FLOAT, + IMB_FTYPE_DPX, + COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, + NULL, + imb_is_cineon, + NULL, + imb_ftype_default, + imb_load_cineon, + NULL, + imb_save_cineon, + NULL, + IM_FTYPE_FLOAT, + IMB_FTYPE_CINEON, + COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_TIFF - {imb_inittiff, NULL, imb_is_a_tiff, NULL, imb_ftype_default, imb_loadtiff, NULL, imb_savetiff, imb_loadtiletiff, 0, IMB_FTYPE_TIF, COLOR_ROLE_DEFAULT_BYTE}, + {imb_inittiff, + NULL, + imb_is_a_tiff, + NULL, + imb_ftype_default, + imb_loadtiff, + NULL, + imb_savetiff, + imb_loadtiletiff, + 0, + IMB_FTYPE_TIF, + COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_HDR - {NULL, NULL, imb_is_a_hdr, NULL, imb_ftype_default, imb_loadhdr, NULL, imb_savehdr, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_RADHDR, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, + NULL, + imb_is_a_hdr, + NULL, + imb_ftype_default, + imb_loadhdr, + NULL, + imb_savehdr, + NULL, + IM_FTYPE_FLOAT, + IMB_FTYPE_RADHDR, + COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENEXR - {imb_initopenexr, imb_exitopenexr, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_OPENEXR, COLOR_ROLE_DEFAULT_FLOAT}, + {imb_initopenexr, + imb_exitopenexr, + imb_is_a_openexr, + NULL, + imb_ftype_default, + imb_load_openexr, + NULL, + imb_save_openexr, + NULL, + IM_FTYPE_FLOAT, + IMB_FTYPE_OPENEXR, + COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENJPEG - {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_load_jp2, NULL, imb_save_jp2, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_JP2, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_jp2, + NULL, + imb_ftype_default, + imb_load_jp2, + NULL, + imb_save_jp2, + NULL, + IM_FTYPE_FLOAT, + IMB_FTYPE_JP2, + COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_DDS - {NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, IMB_FTYPE_DDS, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, + NULL, + imb_is_a_dds, + NULL, + imb_ftype_default, + imb_load_dds, + NULL, + NULL, + NULL, + 0, + IMB_FTYPE_DDS, + COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_OPENIMAGEIO - {NULL, NULL, NULL, imb_is_a_photoshop, imb_ftype_default, NULL, imb_load_photoshop, NULL, NULL, IM_FTYPE_FLOAT, IMB_FTYPE_PSD, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, + NULL, + NULL, + imb_is_a_photoshop, + imb_ftype_default, + NULL, + imb_load_photoshop, + NULL, + NULL, + IM_FTYPE_FLOAT, + IMB_FTYPE_PSD, + COLOR_ROLE_DEFAULT_FLOAT}, #endif - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}, + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}, }; -const ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1]; +const ImFileType *IMB_FILE_TYPES_LAST = + &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1]; void imb_filetypes_init(void) { - const ImFileType *type; + const ImFileType *type; - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) - if (type->init) - type->init(); + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) + if (type->init) + type->init(); } void imb_filetypes_exit(void) { - const ImFileType *type; + const ImFileType *type; - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) - if (type->exit) - type->exit(); + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) + if (type->exit) + type->exit(); } diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 673d4aae59f..2d7e90db34e 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -35,353 +35,380 @@ static void filtrow(unsigned char *point, int x) { - unsigned int c1, c2, c3, error; - - if (x > 1) { - c1 = c2 = *point; - error = 2; - for (x--; x > 0; x--) { - c3 = point[4]; - c1 += (c2 << 1) + c3 + error; - error = c1 & 3; - *point = c1 >> 2; - point += 4; - c1 = c2; - c2 = c3; - } - *point = (c1 + (c2 << 1) + c2 + error) >> 2; - } + unsigned int c1, c2, c3, error; + + if (x > 1) { + c1 = c2 = *point; + error = 2; + for (x--; x > 0; x--) { + c3 = point[4]; + c1 += (c2 << 1) + c3 + error; + error = c1 & 3; + *point = c1 >> 2; + point += 4; + c1 = c2; + c2 = c3; + } + *point = (c1 + (c2 << 1) + c2 + error) >> 2; + } } static void filtrowf(float *point, int x) { - float c1, c2, c3; - - if (x > 1) { - c1 = c2 = *point; - for (x--; x > 0; x--) { - c3 = point[4]; - c1 += (c2 * 2) + c3; - *point = 0.25f * c1; - point += 4; - c1 = c2; - c2 = c3; - } - *point = 0.25f * (c1 + (c2 * 2) + c2); - } + float c1, c2, c3; + + if (x > 1) { + c1 = c2 = *point; + for (x--; x > 0; x--) { + c3 = point[4]; + c1 += (c2 * 2) + c3; + *point = 0.25f * c1; + point += 4; + c1 = c2; + c2 = c3; + } + *point = 0.25f * (c1 + (c2 * 2) + c2); + } } - - static void filtcolum(unsigned char *point, int y, int skip) { - unsigned int c1, c2, c3, error; - unsigned char *point2; - - if (y > 1) { - c1 = c2 = *point; - point2 = point; - error = 2; - for (y--; y > 0; y--) { - point2 += skip; - c3 = *point2; - c1 += (c2 << 1) + c3 + error; - error = c1 & 3; - *point = c1 >> 2; - point = point2; - c1 = c2; - c2 = c3; - } - *point = (c1 + (c2 << 1) + c2 + error) >> 2; - } + unsigned int c1, c2, c3, error; + unsigned char *point2; + + if (y > 1) { + c1 = c2 = *point; + point2 = point; + error = 2; + for (y--; y > 0; y--) { + point2 += skip; + c3 = *point2; + c1 += (c2 << 1) + c3 + error; + error = c1 & 3; + *point = c1 >> 2; + point = point2; + c1 = c2; + c2 = c3; + } + *point = (c1 + (c2 << 1) + c2 + error) >> 2; + } } static void filtcolumf(float *point, int y, int skip) { - float c1, c2, c3, *point2; - - if (y > 1) { - c1 = c2 = *point; - point2 = point; - for (y--; y > 0; y--) { - point2 += skip; - c3 = *point2; - c1 += (c2 * 2) + c3; - *point = 0.25f * c1; - point = point2; - c1 = c2; - c2 = c3; - } - *point = 0.25f * (c1 + (c2 * 2) + c2); - } + float c1, c2, c3, *point2; + + if (y > 1) { + c1 = c2 = *point; + point2 = point; + for (y--; y > 0; y--) { + point2 += skip; + c3 = *point2; + c1 += (c2 * 2) + c3; + *point = 0.25f * c1; + point = point2; + c1 = c2; + c2 = c3; + } + *point = 0.25f * (c1 + (c2 * 2) + c2); + } } void IMB_filtery(struct ImBuf *ibuf) { - unsigned char *point; - float *pointf; - int x, y, skip; - - point = (unsigned char *)ibuf->rect; - pointf = ibuf->rect_float; - - x = ibuf->x; - y = ibuf->y; - skip = x << 2; - - for (; x > 0; x--) { - if (point) { - if (ibuf->planes > 24) filtcolum(point, y, skip); - point++; - filtcolum(point, y, skip); - point++; - filtcolum(point, y, skip); - point++; - filtcolum(point, y, skip); - point++; - } - if (pointf) { - if (ibuf->planes > 24) filtcolumf(pointf, y, skip); - pointf++; - filtcolumf(pointf, y, skip); - pointf++; - filtcolumf(pointf, y, skip); - pointf++; - filtcolumf(pointf, y, skip); - pointf++; - } - } + unsigned char *point; + float *pointf; + int x, y, skip; + + point = (unsigned char *)ibuf->rect; + pointf = ibuf->rect_float; + + x = ibuf->x; + y = ibuf->y; + skip = x << 2; + + for (; x > 0; x--) { + if (point) { + if (ibuf->planes > 24) + filtcolum(point, y, skip); + point++; + filtcolum(point, y, skip); + point++; + filtcolum(point, y, skip); + point++; + filtcolum(point, y, skip); + point++; + } + if (pointf) { + if (ibuf->planes > 24) + filtcolumf(pointf, y, skip); + pointf++; + filtcolumf(pointf, y, skip); + pointf++; + filtcolumf(pointf, y, skip); + pointf++; + filtcolumf(pointf, y, skip); + pointf++; + } + } } - void imb_filterx(struct ImBuf *ibuf) { - unsigned char *point; - float *pointf; - int x, y, skip; - - point = (unsigned char *)ibuf->rect; - pointf = ibuf->rect_float; - - x = ibuf->x; - y = ibuf->y; - skip = (x << 2) - 3; - - for (; y > 0; y--) { - if (point) { - if (ibuf->planes > 24) filtrow(point, x); - point++; - filtrow(point, x); - point++; - filtrow(point, x); - point++; - filtrow(point, x); - point += skip; - } - if (pointf) { - if (ibuf->planes > 24) filtrowf(pointf, x); - pointf++; - filtrowf(pointf, x); - pointf++; - filtrowf(pointf, x); - pointf++; - filtrowf(pointf, x); - pointf += skip; - } - } + unsigned char *point; + float *pointf; + int x, y, skip; + + point = (unsigned char *)ibuf->rect; + pointf = ibuf->rect_float; + + x = ibuf->x; + y = ibuf->y; + skip = (x << 2) - 3; + + for (; y > 0; y--) { + if (point) { + if (ibuf->planes > 24) + filtrow(point, x); + point++; + filtrow(point, x); + point++; + filtrow(point, x); + point++; + filtrow(point, x); + point += skip; + } + if (pointf) { + if (ibuf->planes > 24) + filtrowf(pointf, x); + pointf++; + filtrowf(pointf, x); + pointf++; + filtrowf(pointf, x); + pointf++; + filtrowf(pointf, x); + pointf += skip; + } + } } static void imb_filterN(ImBuf *out, ImBuf *in) { - BLI_assert(out->channels == in->channels); - BLI_assert(out->x == in->x && out->y == in->y); - - const int channels = in->channels; - const int rowlen = in->x; - - if (in->rect && out->rect) { - for (int y = 0; y < in->y; y++) { - /* setup rows */ - const char *row2 = (const char *)in->rect + y * channels * rowlen; - const char *row1 = (y == 0) ? row2 : row2 - channels * rowlen; - const char *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen; - - char *cp = (char *)out->rect + y * channels * rowlen; - - for (int x = 0; x < rowlen; x++) { - const char *r11, *r13, *r21, *r23, *r31, *r33; - - if (x == 0) { - r11 = row1; - r21 = row2; - r31 = row3; - } - else { - r11 = row1 - channels; - r21 = row2 - channels; - r31 = row3 - channels; - } - - if (x == rowlen - 1) { - r13 = row1; - r23 = row2; - r33 = row3; - } - else { - r13 = row1 + channels; - r23 = row2 + channels; - r33 = row3 + channels; - } - - cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) >> 4; - cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) >> 4; - cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) >> 4; - cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) >> 4; - cp += channels; row1 += channels; row2 += channels; row3 += channels; - } - } - } - - if (in->rect_float && out->rect_float) { - for (int y = 0; y < in->y; y++) { - /* setup rows */ - const float *row2 = (const float *)in->rect_float + y * channels * rowlen; - const float *row1 = (y == 0) ? row2 : row2 - channels * rowlen; - const float *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen; - - float *cp = (float *)out->rect_float + y * channels * rowlen; - - for (int x = 0; x < rowlen; x++) { - const float *r11, *r13, *r21, *r23, *r31, *r33; - - if (x == 0) { - r11 = row1; - r21 = row2; - r31 = row3; - } - else { - r11 = row1 - channels; - r21 = row2 - channels; - r31 = row3 - channels; - } - - if (x == rowlen - 1) { - r13 = row1; - r23 = row2; - r33 = row3; - } - else { - r13 = row1 + channels; - r23 = row2 + channels; - r33 = row3 + channels; - } - - cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) * (1.0f / 16.0f); - cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) * (1.0f / 16.0f); - cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) * (1.0f / 16.0f); - cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) * (1.0f / 16.0f); - cp += channels; row1 += channels; row2 += channels; row3 += channels; - } - } - } + BLI_assert(out->channels == in->channels); + BLI_assert(out->x == in->x && out->y == in->y); + + const int channels = in->channels; + const int rowlen = in->x; + + if (in->rect && out->rect) { + for (int y = 0; y < in->y; y++) { + /* setup rows */ + const char *row2 = (const char *)in->rect + y * channels * rowlen; + const char *row1 = (y == 0) ? row2 : row2 - channels * rowlen; + const char *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen; + + char *cp = (char *)out->rect + y * channels * rowlen; + + for (int x = 0; x < rowlen; x++) { + const char *r11, *r13, *r21, *r23, *r31, *r33; + + if (x == 0) { + r11 = row1; + r21 = row2; + r31 = row3; + } + else { + r11 = row1 - channels; + r21 = row2 - channels; + r31 = row3 - channels; + } + + if (x == rowlen - 1) { + r13 = row1; + r23 = row2; + r33 = row3; + } + else { + r13 = row1 + channels; + r23 = row2 + channels; + r33 = row3 + channels; + } + + cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + + 2 * row3[0] + r33[0]) >> + 4; + cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + + 2 * row3[1] + r33[1]) >> + 4; + cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + + 2 * row3[2] + r33[2]) >> + 4; + cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + + 2 * row3[3] + r33[3]) >> + 4; + cp += channels; + row1 += channels; + row2 += channels; + row3 += channels; + } + } + } + + if (in->rect_float && out->rect_float) { + for (int y = 0; y < in->y; y++) { + /* setup rows */ + const float *row2 = (const float *)in->rect_float + y * channels * rowlen; + const float *row1 = (y == 0) ? row2 : row2 - channels * rowlen; + const float *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen; + + float *cp = (float *)out->rect_float + y * channels * rowlen; + + for (int x = 0; x < rowlen; x++) { + const float *r11, *r13, *r21, *r23, *r31, *r33; + + if (x == 0) { + r11 = row1; + r21 = row2; + r31 = row3; + } + else { + r11 = row1 - channels; + r21 = row2 - channels; + r31 = row3 - channels; + } + + if (x == rowlen - 1) { + r13 = row1; + r23 = row2; + r33 = row3; + } + else { + r13 = row1 + channels; + r23 = row2 + channels; + r33 = row3 + channels; + } + + cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + + 2 * row3[0] + r33[0]) * + (1.0f / 16.0f); + cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + + 2 * row3[1] + r33[1]) * + (1.0f / 16.0f); + cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + + 2 * row3[2] + r33[2]) * + (1.0f / 16.0f); + cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + + 2 * row3[3] + r33[3]) * + (1.0f / 16.0f); + cp += channels; + row1 += channels; + row2 += channels; + row3 += channels; + } + } + } } void IMB_filter(struct ImBuf *ibuf) { - IMB_filtery(ibuf); - imb_filterx(ibuf); + IMB_filtery(ibuf); + imb_filterx(ibuf); } void IMB_mask_filter_extend(char *mask, int width, int height) { - const char *row1, *row2, *row3; - int rowlen, x, y; - char *temprect; - - rowlen = width; - - /* make a copy, to prevent flooding */ - temprect = MEM_dupallocN(mask); - - for (y = 1; y <= height; y++) { - /* setup rows */ - row1 = (char *)(temprect + (y - 2) * rowlen); - row2 = row1 + rowlen; - row3 = row2 + rowlen; - if (y == 1) - row1 = row2; - else if (y == height) - row3 = row2; - - for (x = 0; x < rowlen; x++) { - if (mask[((y - 1) * rowlen) + x] == 0) { - if (*row1 || *row2 || *row3 || *(row1 + 1) || *(row3 + 1) ) { - mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN; - } - else if ((x != rowlen - 1) && (*(row1 + 2) || *(row2 + 2) || *(row3 + 2)) ) { - mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN; - } - } - - if (x != 0) { - row1++; row2++; row3++; - } - } - } - - MEM_freeN(temprect); + const char *row1, *row2, *row3; + int rowlen, x, y; + char *temprect; + + rowlen = width; + + /* make a copy, to prevent flooding */ + temprect = MEM_dupallocN(mask); + + for (y = 1; y <= height; y++) { + /* setup rows */ + row1 = (char *)(temprect + (y - 2) * rowlen); + row2 = row1 + rowlen; + row3 = row2 + rowlen; + if (y == 1) + row1 = row2; + else if (y == height) + row3 = row2; + + for (x = 0; x < rowlen; x++) { + if (mask[((y - 1) * rowlen) + x] == 0) { + if (*row1 || *row2 || *row3 || *(row1 + 1) || *(row3 + 1)) { + mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN; + } + else if ((x != rowlen - 1) && (*(row1 + 2) || *(row2 + 2) || *(row3 + 2))) { + mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN; + } + } + + if (x != 0) { + row1++; + row2++; + row3++; + } + } + } + + MEM_freeN(temprect); } void IMB_mask_clear(ImBuf *ibuf, char *mask, int val) { - int x, y; - if (ibuf->rect_float) { - for (x = 0; x < ibuf->x; x++) { - for (y = 0; y < ibuf->y; y++) { - if (mask[ibuf->x * y + x] == val) { - float *col = ibuf->rect_float + 4 * (ibuf->x * y + x); - col[0] = col[1] = col[2] = col[3] = 0.0f; - } - } - } - } - else { - /* char buffer */ - for (x = 0; x < ibuf->x; x++) { - for (y = 0; y < ibuf->y; y++) { - if (mask[ibuf->x * y + x] == val) { - char *col = (char *)(ibuf->rect + ibuf->x * y + x); - col[0] = col[1] = col[2] = col[3] = 0; - } - } - } - } + int x, y; + if (ibuf->rect_float) { + for (x = 0; x < ibuf->x; x++) { + for (y = 0; y < ibuf->y; y++) { + if (mask[ibuf->x * y + x] == val) { + float *col = ibuf->rect_float + 4 * (ibuf->x * y + x); + col[0] = col[1] = col[2] = col[3] = 0.0f; + } + } + } + } + else { + /* char buffer */ + for (x = 0; x < ibuf->x; x++) { + for (y = 0; y < ibuf->y; y++) { + if (mask[ibuf->x * y + x] == val) { + char *col = (char *)(ibuf->rect + ibuf->x * y + x); + col[0] = col[1] = col[2] = col[3] = 0; + } + } + } + } } static int filter_make_index(const int x, const int y, const int w, const int h) { - if (x < 0 || x >= w || y < 0 || y >= h) return -1; /* return bad index */ - else return y * w + x; + if (x < 0 || x >= w || y < 0 || y >= h) + return -1; /* return bad index */ + else + return y * w + x; } -static int check_pixel_assigned(const void *buffer, const char *mask, const int index, const int depth, const bool is_float) +static int check_pixel_assigned( + const void *buffer, const char *mask, const int index, const int depth, const bool is_float) { - int res = 0; - - if (index >= 0) { - const int alpha_index = depth * index + (depth - 1); - - if (mask != NULL) { - res = mask[index] != 0 ? 1 : 0; - } - else if ((is_float && ((const float *) buffer)[alpha_index] != 0.0f) || - (!is_float && ((const unsigned char *) buffer)[alpha_index] != 0) ) - { - res = 1; - } - } - - return res; + int res = 0; + + if (index >= 0) { + const int alpha_index = depth * index + (depth - 1); + + if (mask != NULL) { + res = mask[index] != 0 ? 1 : 0; + } + else if ((is_float && ((const float *)buffer)[alpha_index] != 0.0f) || + (!is_float && ((const unsigned char *)buffer)[alpha_index] != 0)) { + res = 1; + } + } + + return res; } /* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 1.0 @@ -390,299 +417,310 @@ static int check_pixel_assigned(const void *buffer, const char *mask, const int * */ void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter) { - const int width = ibuf->x; - const int height = ibuf->y; - const int depth = 4; /* always 4 channels */ - const int chsize = ibuf->rect_float ? sizeof(float) : sizeof(unsigned char); - const size_t bsize = ((size_t)width) * height * depth * chsize; - const bool is_float = (ibuf->rect_float != NULL); - void *dstbuf = (void *) MEM_dupallocN(ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect); - char *dstmask = mask == NULL ? NULL : (char *) MEM_dupallocN(mask); - void *srcbuf = ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect; - char *srcmask = mask; - int cannot_early_out = 1, r, n, k, i, j, c; - float weight[25]; - - /* build a weights buffer */ - n = 1; + const int width = ibuf->x; + const int height = ibuf->y; + const int depth = 4; /* always 4 channels */ + const int chsize = ibuf->rect_float ? sizeof(float) : sizeof(unsigned char); + const size_t bsize = ((size_t)width) * height * depth * chsize; + const bool is_float = (ibuf->rect_float != NULL); + void *dstbuf = (void *)MEM_dupallocN(ibuf->rect_float ? (void *)ibuf->rect_float : + (void *)ibuf->rect); + char *dstmask = mask == NULL ? NULL : (char *)MEM_dupallocN(mask); + void *srcbuf = ibuf->rect_float ? (void *)ibuf->rect_float : (void *)ibuf->rect; + char *srcmask = mask; + int cannot_early_out = 1, r, n, k, i, j, c; + float weight[25]; + + /* build a weights buffer */ + n = 1; #if 0 - k = 0; - for (i = -n; i <= n; i++) - for (j = -n; j <= n; j++) - weight[k++] = sqrt((float) i * i + j * j); + k = 0; + for (i = -n; i <= n; i++) + for (j = -n; j <= n; j++) + weight[k++] = sqrt((float) i * i + j * j); #endif - weight[0] = 1; weight[1] = 2; weight[2] = 1; - weight[3] = 2; weight[4] = 0; weight[5] = 2; - weight[6] = 1; weight[7] = 2; weight[8] = 1; - - /* run passes */ - for (r = 0; cannot_early_out == 1 && r < filter; r++) { - int x, y; - cannot_early_out = 0; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - const int index = filter_make_index(x, y, width, height); - - /* only update unassigned pixels */ - if (!check_pixel_assigned(srcbuf, srcmask, index, depth, is_float)) { - float tmp[4]; - float wsum = 0; - float acc[4] = {0, 0, 0, 0}; - k = 0; - - if (check_pixel_assigned(srcbuf, srcmask, filter_make_index(x - 1, y, width, height), depth, is_float) || - check_pixel_assigned(srcbuf, srcmask, filter_make_index(x + 1, y, width, height), depth, is_float) || - check_pixel_assigned(srcbuf, srcmask, filter_make_index(x, y - 1, width, height), depth, is_float) || - check_pixel_assigned(srcbuf, srcmask, filter_make_index(x, y + 1, width, height), depth, is_float)) - { - for (i = -n; i <= n; i++) { - for (j = -n; j <= n; j++) { - if (i != 0 || j != 0) { - const int tmpindex = filter_make_index(x + i, y + j, width, height); - - if (check_pixel_assigned(srcbuf, srcmask, tmpindex, depth, is_float)) { - if (is_float) { - for (c = 0; c < depth; c++) - tmp[c] = ((const float *) srcbuf)[depth * tmpindex + c]; - } - else { - for (c = 0; c < depth; c++) - tmp[c] = (float) ((const unsigned char *) srcbuf)[depth * tmpindex + c]; - } - - wsum += weight[k]; - - for (c = 0; c < depth; c++) - acc[c] += weight[k] * tmp[c]; - } - } - k++; - } - } - - if (wsum != 0) { - for (c = 0; c < depth; c++) - acc[c] /= wsum; - - if (is_float) { - for (c = 0; c < depth; c++) - ((float *) dstbuf)[depth * index + c] = acc[c]; - } - else { - for (c = 0; c < depth; c++) { - ((unsigned char *) dstbuf)[depth * index + c] = acc[c] > 255 ? 255 : (acc[c] < 0 ? 0 : ((unsigned char) (acc[c] + 0.5f))); - } - } - - if (dstmask != NULL) dstmask[index] = FILTER_MASK_MARGIN; /* assigned */ - cannot_early_out = 1; - } - } - } - } - } - - /* keep the original buffer up to date. */ - memcpy(srcbuf, dstbuf, bsize); - if (dstmask != NULL) { - memcpy(srcmask, dstmask, ((size_t)width) * height); - } - } - - /* free memory */ - MEM_freeN(dstbuf); - if (dstmask != NULL) MEM_freeN(dstmask); + weight[0] = 1; + weight[1] = 2; + weight[2] = 1; + weight[3] = 2; + weight[4] = 0; + weight[5] = 2; + weight[6] = 1; + weight[7] = 2; + weight[8] = 1; + + /* run passes */ + for (r = 0; cannot_early_out == 1 && r < filter; r++) { + int x, y; + cannot_early_out = 0; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + const int index = filter_make_index(x, y, width, height); + + /* only update unassigned pixels */ + if (!check_pixel_assigned(srcbuf, srcmask, index, depth, is_float)) { + float tmp[4]; + float wsum = 0; + float acc[4] = {0, 0, 0, 0}; + k = 0; + + if (check_pixel_assigned( + srcbuf, srcmask, filter_make_index(x - 1, y, width, height), depth, is_float) || + check_pixel_assigned( + srcbuf, srcmask, filter_make_index(x + 1, y, width, height), depth, is_float) || + check_pixel_assigned( + srcbuf, srcmask, filter_make_index(x, y - 1, width, height), depth, is_float) || + check_pixel_assigned( + srcbuf, srcmask, filter_make_index(x, y + 1, width, height), depth, is_float)) { + for (i = -n; i <= n; i++) { + for (j = -n; j <= n; j++) { + if (i != 0 || j != 0) { + const int tmpindex = filter_make_index(x + i, y + j, width, height); + + if (check_pixel_assigned(srcbuf, srcmask, tmpindex, depth, is_float)) { + if (is_float) { + for (c = 0; c < depth; c++) + tmp[c] = ((const float *)srcbuf)[depth * tmpindex + c]; + } + else { + for (c = 0; c < depth; c++) + tmp[c] = (float)((const unsigned char *)srcbuf)[depth * tmpindex + c]; + } + + wsum += weight[k]; + + for (c = 0; c < depth; c++) + acc[c] += weight[k] * tmp[c]; + } + } + k++; + } + } + + if (wsum != 0) { + for (c = 0; c < depth; c++) + acc[c] /= wsum; + + if (is_float) { + for (c = 0; c < depth; c++) + ((float *)dstbuf)[depth * index + c] = acc[c]; + } + else { + for (c = 0; c < depth; c++) { + ((unsigned char *)dstbuf)[depth * index + c] = + acc[c] > 255 ? 255 : (acc[c] < 0 ? 0 : ((unsigned char)(acc[c] + 0.5f))); + } + } + + if (dstmask != NULL) + dstmask[index] = FILTER_MASK_MARGIN; /* assigned */ + cannot_early_out = 1; + } + } + } + } + } + + /* keep the original buffer up to date. */ + memcpy(srcbuf, dstbuf, bsize); + if (dstmask != NULL) { + memcpy(srcmask, dstmask, ((size_t)width) * height); + } + } + + /* free memory */ + MEM_freeN(dstbuf); + if (dstmask != NULL) + MEM_freeN(dstmask); } /* threadsafe version, only recreates existing maps */ void IMB_remakemipmap(ImBuf *ibuf, int use_filter) { - ImBuf *hbuf = ibuf; - int curmap = 0; + ImBuf *hbuf = ibuf; + int curmap = 0; - ibuf->miptot = 1; + ibuf->miptot = 1; - while (curmap < IMB_MIPMAP_LEVELS) { + while (curmap < IMB_MIPMAP_LEVELS) { - if (ibuf->mipmap[curmap]) { + if (ibuf->mipmap[curmap]) { - if (use_filter) { - ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags); - imb_filterN(nbuf, hbuf); - imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf); - IMB_freeImBuf(nbuf); - } - else - imb_onehalf_no_alloc(ibuf->mipmap[curmap], hbuf); - } + if (use_filter) { + ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags); + imb_filterN(nbuf, hbuf); + imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf); + IMB_freeImBuf(nbuf); + } + else + imb_onehalf_no_alloc(ibuf->mipmap[curmap], hbuf); + } - ibuf->miptot = curmap + 2; - hbuf = ibuf->mipmap[curmap]; - if (hbuf) - hbuf->miplevel = curmap + 1; + ibuf->miptot = curmap + 2; + hbuf = ibuf->mipmap[curmap]; + if (hbuf) + hbuf->miplevel = curmap + 1; - if (!hbuf || (hbuf->x <= 2 && hbuf->y <= 2)) - break; + if (!hbuf || (hbuf->x <= 2 && hbuf->y <= 2)) + break; - curmap++; - } + curmap++; + } } /* frees too (if there) and recreates new data */ void IMB_makemipmap(ImBuf *ibuf, int use_filter) { - ImBuf *hbuf = ibuf; - int curmap = 0; + ImBuf *hbuf = ibuf; + int curmap = 0; - imb_freemipmapImBuf(ibuf); + imb_freemipmapImBuf(ibuf); - /* no mipmap for non RGBA images */ - if (ibuf->rect_float && ibuf->channels < 4) - return; + /* no mipmap for non RGBA images */ + if (ibuf->rect_float && ibuf->channels < 4) + return; - ibuf->miptot = 1; + ibuf->miptot = 1; - while (curmap < IMB_MIPMAP_LEVELS) { - if (use_filter) { - ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags); - imb_filterN(nbuf, hbuf); - ibuf->mipmap[curmap] = IMB_onehalf(nbuf); - IMB_freeImBuf(nbuf); - } - else - ibuf->mipmap[curmap] = IMB_onehalf(hbuf); + while (curmap < IMB_MIPMAP_LEVELS) { + if (use_filter) { + ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags); + imb_filterN(nbuf, hbuf); + ibuf->mipmap[curmap] = IMB_onehalf(nbuf); + IMB_freeImBuf(nbuf); + } + else + ibuf->mipmap[curmap] = IMB_onehalf(hbuf); - ibuf->miptot = curmap + 2; - hbuf = ibuf->mipmap[curmap]; - hbuf->miplevel = curmap + 1; + ibuf->miptot = curmap + 2; + hbuf = ibuf->mipmap[curmap]; + hbuf->miplevel = curmap + 1; - if (hbuf->x < 2 && hbuf->y < 2) - break; + if (hbuf->x < 2 && hbuf->y < 2) + break; - curmap++; - } + curmap++; + } } ImBuf *IMB_getmipmap(ImBuf *ibuf, int level) { - CLAMP(level, 0, ibuf->miptot - 1); - return (level == 0) ? ibuf : ibuf->mipmap[level - 1]; + CLAMP(level, 0, ibuf->miptot - 1); + return (level == 0) ? ibuf : ibuf->mipmap[level - 1]; } void IMB_premultiply_rect(unsigned int *rect, char planes, int w, int h) { - char *cp; - int x, y, val; - - if (planes == 24) { /* put alpha at 255 */ - cp = (char *)(rect); - - for (y = 0; y < h; y++) - for (x = 0; x < w; x++, cp += 4) - cp[3] = 255; - } - else { - cp = (char *)(rect); - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++, cp += 4) { - val = cp[3]; - cp[0] = (cp[0] * val) >> 8; - cp[1] = (cp[1] * val) >> 8; - cp[2] = (cp[2] * val) >> 8; - } - } - } + char *cp; + int x, y, val; + + if (planes == 24) { /* put alpha at 255 */ + cp = (char *)(rect); + + for (y = 0; y < h; y++) + for (x = 0; x < w; x++, cp += 4) + cp[3] = 255; + } + else { + cp = (char *)(rect); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, cp += 4) { + val = cp[3]; + cp[0] = (cp[0] * val) >> 8; + cp[1] = (cp[1] * val) >> 8; + cp[2] = (cp[2] * val) >> 8; + } + } + } } void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h) { - float val, *cp; - int x, y; - - if (channels == 4) { - cp = rect_float; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++, cp += 4) { - val = cp[3]; - cp[0] = cp[0] * val; - cp[1] = cp[1] * val; - cp[2] = cp[2] * val; - } - } - } - + float val, *cp; + int x, y; + + if (channels == 4) { + cp = rect_float; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, cp += 4) { + val = cp[3]; + cp[0] = cp[0] * val; + cp[1] = cp[1] * val; + cp[2] = cp[2] * val; + } + } + } } void IMB_premultiply_alpha(ImBuf *ibuf) { - if (ibuf == NULL) - return; + if (ibuf == NULL) + return; - if (ibuf->rect) - IMB_premultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y); + if (ibuf->rect) + IMB_premultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y); - if (ibuf->rect_float) - IMB_premultiply_rect_float(ibuf->rect_float, ibuf->channels, ibuf->x, ibuf->y); + if (ibuf->rect_float) + IMB_premultiply_rect_float(ibuf->rect_float, ibuf->channels, ibuf->x, ibuf->y); } void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h) { - char *cp; - int x, y; - float val; - - if (planes == 24) { /* put alpha at 255 */ - cp = (char *)(rect); - - for (y = 0; y < h; y++) - for (x = 0; x < w; x++, cp += 4) - cp[3] = 255; - } - else { - cp = (char *)(rect); - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++, cp += 4) { - val = cp[3] != 0 ? 1.0f / (float)cp[3] : 1.0f; - cp[0] = unit_float_to_uchar_clamp(cp[0] * val); - cp[1] = unit_float_to_uchar_clamp(cp[1] * val); - cp[2] = unit_float_to_uchar_clamp(cp[2] * val); - } - } - } + char *cp; + int x, y; + float val; + + if (planes == 24) { /* put alpha at 255 */ + cp = (char *)(rect); + + for (y = 0; y < h; y++) + for (x = 0; x < w; x++, cp += 4) + cp[3] = 255; + } + else { + cp = (char *)(rect); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, cp += 4) { + val = cp[3] != 0 ? 1.0f / (float)cp[3] : 1.0f; + cp[0] = unit_float_to_uchar_clamp(cp[0] * val); + cp[1] = unit_float_to_uchar_clamp(cp[1] * val); + cp[2] = unit_float_to_uchar_clamp(cp[2] * val); + } + } + } } void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h) { - float val, *fp; - int x, y; - - if (channels == 4) { - fp = rect_float; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++, fp += 4) { - val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f; - fp[0] = fp[0] * val; - fp[1] = fp[1] * val; - fp[2] = fp[2] * val; - } - } - } - + float val, *fp; + int x, y; + + if (channels == 4) { + fp = rect_float; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, fp += 4) { + val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f; + fp[0] = fp[0] * val; + fp[1] = fp[1] * val; + fp[2] = fp[2] * val; + } + } + } } void IMB_unpremultiply_alpha(ImBuf *ibuf) { - if (ibuf == NULL) - return; + if (ibuf == NULL) + return; - if (ibuf->rect) - IMB_unpremultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y); + if (ibuf->rect) + IMB_unpremultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y); - if (ibuf->rect_float) - IMB_unpremultiply_rect_float(ibuf->rect_float, ibuf->channels, ibuf->x, ibuf->y); + if (ibuf->rect_float) + IMB_unpremultiply_rect_float(ibuf->rect_float, ibuf->channels, ibuf->x, ibuf->y); } diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 1e48c4fd428..58253bde3e3 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -42,86 +42,88 @@ /* Only this one is used liberally here, and in imbuf */ void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf) { - size_t size; - unsigned char rt, *cp = (unsigned char *)ibuf->rect; - float rtf, *cpf = ibuf->rect_float; - - if (ibuf->rect) { - size = ibuf->x * ibuf->y; - - while (size-- > 0) { - rt = cp[0]; - cp[0] = cp[3]; - cp[3] = rt; - rt = cp[1]; - cp[1] = cp[2]; - cp[2] = rt; - cp += 4; - } - } - - if (ibuf->rect_float) { - size = ibuf->x * ibuf->y; - - while (size-- > 0) { - rtf = cpf[0]; - cpf[0] = cpf[3]; - cpf[3] = rtf; - rtf = cpf[1]; - cpf[1] = cpf[2]; - cpf[2] = rtf; - cpf += 4; - } - } + size_t size; + unsigned char rt, *cp = (unsigned char *)ibuf->rect; + float rtf, *cpf = ibuf->rect_float; + + if (ibuf->rect) { + size = ibuf->x * ibuf->y; + + while (size-- > 0) { + rt = cp[0]; + cp[0] = cp[3]; + cp[3] = rt; + rt = cp[1]; + cp[1] = cp[2]; + cp[2] = rt; + cp += 4; + } + } + + if (ibuf->rect_float) { + size = ibuf->x * ibuf->y; + + while (size-- > 0) { + rtf = cpf[0]; + cpf[0] = cpf[3]; + cpf[3] = rtf; + rtf = cpf[1]; + cpf[1] = cpf[2]; + cpf[2] = rtf; + cpf += 4; + } + } } static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float **outF, int x, int y) { - size_t offset = ((size_t)ibuf->x) * y * 4 + 4 * x; + size_t offset = ((size_t)ibuf->x) * y * 4 + 4 * x; - if (ibuf->rect) - *outI = (unsigned char *)ibuf->rect + offset; + if (ibuf->rect) + *outI = (unsigned char *)ibuf->rect + offset; - if (ibuf->rect_float) - *outF = ibuf->rect_float + offset; + if (ibuf->rect_float) + *outF = ibuf->rect_float + offset; } /* BICUBIC Interpolation */ -void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) +void bicubic_interpolation_color( + struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - if (outF) { - BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); - } - else { - BLI_bicubic_interpolation_char((unsigned char *) in->rect, outI, in->x, in->y, 4, u, v); - } + if (outF) { + BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); + } + else { + BLI_bicubic_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); + } } - void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) { - unsigned char *outI = NULL; - float *outF = NULL; + unsigned char *outI = NULL; + float *outF = NULL; - if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { - return; - } + if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { + return; + } - pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ + pixel_from_buffer( + out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ - bicubic_interpolation_color(in, outI, outF, u, v); + bicubic_interpolation_color(in, outI, outF, u, v); } /* BILINEAR INTERPOLATION */ -void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) +void bilinear_interpolation_color( + struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - if (outF) { - BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); - } - else { - BLI_bilinear_interpolation_char((unsigned char *) in->rect, outI, in->x, in->y, 4, u, v); - } + if (outF) { + BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); + } + else { + BLI_bilinear_interpolation_char((unsigned char *)in->rect, outI, in->x, in->y, 4, u, v); + } } /* function assumes out to be zero'ed, only does RGBA */ @@ -130,345 +132,356 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float /* Note about wrapping, the u/v still needs to be within the image bounds, * just the interpolation is wrapped. * This the same as bilinear_interpolation_color except it wraps rather than using empty and emptyI */ -void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) +void bilinear_interpolation_color_wrap( + struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - float *row1, *row2, *row3, *row4, a, b; - unsigned char *row1I, *row2I, *row3I, *row4I; - float a_b, ma_b, a_mb, ma_mb; - int y1, y2, x1, x2; - - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)floor(u); - x2 = (int)ceil(u); - y1 = (int)floor(v); - y2 = (int)ceil(v); - - /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { - return; - } - - /* wrap interpolation pixels - main difference from bilinear_interpolation_color */ - if (x1 < 0) x1 = in->x + x1; - if (y1 < 0) y1 = in->y + y1; - - if (x2 >= in->x) x2 = x2 - in->x; - if (y2 >= in->y) y2 = y2 - in->y; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - if (outF) { - /* sample including outside of edges of image */ - row1 = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1; - row2 = in->rect_float + ((size_t)in->x) * y2 * 4 + 4 * x1; - row3 = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x2; - row4 = in->rect_float + ((size_t)in->x) * y2 * 4 + 4 * x2; - - outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; - - /* clamp here or else we can easily get off-range */ - CLAMP(outF[0], 0.0f, 1.0f); - CLAMP(outF[1], 0.0f, 1.0f); - CLAMP(outF[2], 0.0f, 1.0f); - CLAMP(outF[3], 0.0f, 1.0f); - } - if (outI) { - /* sample including outside of edges of image */ - row1I = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1; - row2I = (unsigned char *)in->rect + ((size_t)in->x) * y2 * 4 + 4 * x1; - row3I = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x2; - row4I = (unsigned char *)in->rect + ((size_t)in->x) * y2 * 4 + 4 * x2; - - /* need to add 0.5 to avoid rounding down (causes darken with the smear brush) - * tested with white images and this should not wrap back to zero */ - outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f; - outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f; - outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f; - outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f; - } + float *row1, *row2, *row3, *row4, a, b; + unsigned char *row1I, *row2I, *row3I, *row4I; + float a_b, ma_b, a_mb, ma_mb; + int y1, y2, x1, x2; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x1 = (int)floor(u); + x2 = (int)ceil(u); + y1 = (int)floor(v); + y2 = (int)ceil(v); + + /* sample area entirely outside image? */ + if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { + return; + } + + /* wrap interpolation pixels - main difference from bilinear_interpolation_color */ + if (x1 < 0) + x1 = in->x + x1; + if (y1 < 0) + y1 = in->y + y1; + + if (x2 >= in->x) + x2 = x2 - in->x; + if (y2 >= in->y) + y2 = y2 - in->y; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; + ma_b = (1.0f - a) * b; + a_mb = a * (1.0f - b); + ma_mb = (1.0f - a) * (1.0f - b); + + if (outF) { + /* sample including outside of edges of image */ + row1 = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1; + row2 = in->rect_float + ((size_t)in->x) * y2 * 4 + 4 * x1; + row3 = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x2; + row4 = in->rect_float + ((size_t)in->x) * y2 * 4 + 4 * x2; + + outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + + /* clamp here or else we can easily get off-range */ + CLAMP(outF[0], 0.0f, 1.0f); + CLAMP(outF[1], 0.0f, 1.0f); + CLAMP(outF[2], 0.0f, 1.0f); + CLAMP(outF[3], 0.0f, 1.0f); + } + if (outI) { + /* sample including outside of edges of image */ + row1I = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1; + row2I = (unsigned char *)in->rect + ((size_t)in->x) * y2 * 4 + 4 * x1; + row3I = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x2; + row4I = (unsigned char *)in->rect + ((size_t)in->x) * y2 * 4 + 4 * x2; + + /* need to add 0.5 to avoid rounding down (causes darken with the smear brush) + * tested with white images and this should not wrap back to zero */ + outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f; + outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f; + outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f; + outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f; + } } void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) { - unsigned char *outI = NULL; - float *outF = NULL; + unsigned char *outI = NULL; + float *outF = NULL; - if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { - return; - } + if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { + return; + } - pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ + pixel_from_buffer( + out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ - bilinear_interpolation_color(in, outI, outF, u, v); + bilinear_interpolation_color(in, outI, outF, u, v); } /* function assumes out to be zero'ed, only does RGBA */ /* NEAREST INTERPOLATION */ -void nearest_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) +void nearest_interpolation_color( + struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - const float *dataF; - unsigned char *dataI; - int y1, x1; - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)(u); - y1 = (int)(v); - - /* sample area entirely outside image? */ - if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) { - if (outI) - outI[0] = outI[1] = outI[2] = outI[3] = 0; - if (outF) - outF[0] = outF[1] = outF[2] = outF[3] = 0.0f; - return; - } - - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) { - if (outI) { - outI[0] = 0; - outI[1] = 0; - outI[2] = 0; - outI[3] = 0; - } - if (outF) { - outF[0] = 0.0f; - outF[1] = 0.0f; - outF[2] = 0.0f; - outF[3] = 0.0f; - } - } - else { - dataI = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1; - if (outI) { - outI[0] = dataI[0]; - outI[1] = dataI[1]; - outI[2] = dataI[2]; - outI[3] = dataI[3]; - } - dataF = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1; - if (outF) { - outF[0] = dataF[0]; - outF[1] = dataF[1]; - outF[2] = dataF[2]; - outF[3] = dataF[3]; - } - } + const float *dataF; + unsigned char *dataI; + int y1, x1; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x1 = (int)(u); + y1 = (int)(v); + + /* sample area entirely outside image? */ + if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) { + if (outI) + outI[0] = outI[1] = outI[2] = outI[3] = 0; + if (outF) + outF[0] = outF[1] = outF[2] = outF[3] = 0.0f; + return; + } + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) { + if (outI) { + outI[0] = 0; + outI[1] = 0; + outI[2] = 0; + outI[3] = 0; + } + if (outF) { + outF[0] = 0.0f; + outF[1] = 0.0f; + outF[2] = 0.0f; + outF[3] = 0.0f; + } + } + else { + dataI = (unsigned char *)in->rect + ((size_t)in->x) * y1 * 4 + 4 * x1; + if (outI) { + outI[0] = dataI[0]; + outI[1] = dataI[1]; + outI[2] = dataI[2]; + outI[3] = dataI[3]; + } + dataF = in->rect_float + ((size_t)in->x) * y1 * 4 + 4 * x1; + if (outF) { + outF[0] = dataF[0]; + outF[1] = dataF[1]; + outF[2] = dataF[2]; + outF[3] = dataF[3]; + } + } } - -void nearest_interpolation_color_wrap(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) +void nearest_interpolation_color_wrap( + struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - const float *dataF; - unsigned char *dataI; - int y, x; - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x = (int) floor(u); - y = (int) floor(v); - - x = x % in->x; - y = y % in->y; - - /* wrap interpolation pixels - main difference from nearest_interpolation_color */ - if (x < 0) x += in->x; - if (y < 0) y += in->y; - - dataI = (unsigned char *)in->rect + ((size_t)in->x) * y * 4 + 4 * x; - if (outI) { - outI[0] = dataI[0]; - outI[1] = dataI[1]; - outI[2] = dataI[2]; - outI[3] = dataI[3]; - } - dataF = in->rect_float + ((size_t)in->x) * y * 4 + 4 * x; - if (outF) { - outF[0] = dataF[0]; - outF[1] = dataF[1]; - outF[2] = dataF[2]; - outF[3] = dataF[3]; - } + const float *dataF; + unsigned char *dataI; + int y, x; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x = (int)floor(u); + y = (int)floor(v); + + x = x % in->x; + y = y % in->y; + + /* wrap interpolation pixels - main difference from nearest_interpolation_color */ + if (x < 0) + x += in->x; + if (y < 0) + y += in->y; + + dataI = (unsigned char *)in->rect + ((size_t)in->x) * y * 4 + 4 * x; + if (outI) { + outI[0] = dataI[0]; + outI[1] = dataI[1]; + outI[2] = dataI[2]; + outI[3] = dataI[3]; + } + dataF = in->rect_float + ((size_t)in->x) * y * 4 + 4 * x; + if (outF) { + outF[0] = dataF[0]; + outF[1] = dataF[1]; + outF[2] = dataF[2]; + outF[3] = dataF[3]; + } } void nearest_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, int yout) { - unsigned char *outI = NULL; - float *outF = NULL; + unsigned char *outI = NULL; + float *outF = NULL; - if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { - return; - } + if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { + return; + } - pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ + pixel_from_buffer( + out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ - nearest_interpolation_color(in, outI, outF, x, y); + nearest_interpolation_color(in, outI, outF, x, y); } /*********************** Threaded image processing *************************/ -static void processor_apply_func(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid)) +static void processor_apply_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) { - void (*do_thread) (void *) = (void (*) (void *)) BLI_task_pool_userdata(pool); - do_thread(taskdata); + void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_userdata(pool); + do_thread(taskdata); } -void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_customdata, - void (init_handle) (void *handle, int start_line, int tot_line, - void *customdata), - void *(do_thread) (void *)) +void IMB_processor_apply_threaded( + int buffer_lines, + int handle_size, + void *init_customdata, + void(init_handle)(void *handle, int start_line, int tot_line, void *customdata), + void *(do_thread)(void *)) { - const int lines_per_task = 64; + const int lines_per_task = 64; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool; - void *handles; - int total_tasks = (buffer_lines + lines_per_task - 1) / lines_per_task; - int i, start_line; + void *handles; + int total_tasks = (buffer_lines + lines_per_task - 1) / lines_per_task; + int i, start_line; - task_pool = BLI_task_pool_create(task_scheduler, do_thread); + task_pool = BLI_task_pool_create(task_scheduler, do_thread); - handles = MEM_callocN(handle_size * total_tasks, "processor apply threaded handles"); + handles = MEM_callocN(handle_size * total_tasks, "processor apply threaded handles"); - start_line = 0; + start_line = 0; - for (i = 0; i < total_tasks; i++) { - int lines_per_current_task; - void *handle = ((char *) handles) + handle_size * i; + for (i = 0; i < total_tasks; i++) { + int lines_per_current_task; + void *handle = ((char *)handles) + handle_size * i; - if (i < total_tasks - 1) - lines_per_current_task = lines_per_task; - else - lines_per_current_task = buffer_lines - start_line; + if (i < total_tasks - 1) + lines_per_current_task = lines_per_task; + else + lines_per_current_task = buffer_lines - start_line; - init_handle(handle, start_line, lines_per_current_task, init_customdata); + init_handle(handle, start_line, lines_per_current_task, init_customdata); - BLI_task_pool_push(task_pool, processor_apply_func, handle, false, TASK_PRIORITY_LOW); + BLI_task_pool_push(task_pool, processor_apply_func, handle, false, TASK_PRIORITY_LOW); - start_line += lines_per_task; - } + start_line += lines_per_task; + } - /* work and wait until tasks are done */ - BLI_task_pool_work_and_wait(task_pool); + /* work and wait until tasks are done */ + BLI_task_pool_work_and_wait(task_pool); - /* Free memory. */ - MEM_freeN(handles); - BLI_task_pool_free(task_pool); + /* Free memory. */ + MEM_freeN(handles); + BLI_task_pool_free(task_pool); } typedef struct ScanlineGlobalData { - void *custom_data; - ScanlineThreadFunc do_thread; - int scanlines_per_task; - int total_scanlines; + void *custom_data; + ScanlineThreadFunc do_thread; + int scanlines_per_task; + int total_scanlines; } ScanlineGlobalData; typedef struct ScanlineTask { - int start_scanline; - int num_scanlines; + int start_scanline; + int num_scanlines; } ScanlineTask; -static void processor_apply_scanline_func(TaskPool * __restrict pool, +static void processor_apply_scanline_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) { - ScanlineGlobalData *data = BLI_task_pool_userdata(pool); - int start_scanline = POINTER_AS_INT(taskdata); - int num_scanlines = min_ii(data->scanlines_per_task, - data->total_scanlines - start_scanline); - data->do_thread(data->custom_data, - start_scanline, - num_scanlines); + ScanlineGlobalData *data = BLI_task_pool_userdata(pool); + int start_scanline = POINTER_AS_INT(taskdata); + int num_scanlines = min_ii(data->scanlines_per_task, data->total_scanlines - start_scanline); + data->do_thread(data->custom_data, start_scanline, num_scanlines); } void IMB_processor_apply_threaded_scanlines(int total_scanlines, ScanlineThreadFunc do_thread, void *custom_data) { - const int scanlines_per_task = 64; - ScanlineGlobalData data; - data.custom_data = custom_data; - data.do_thread = do_thread; - data.scanlines_per_task = scanlines_per_task; - data.total_scanlines = total_scanlines; - const int total_tasks = (total_scanlines + scanlines_per_task - 1) / scanlines_per_task; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &data); - for (int i = 0, start_line = 0; i < total_tasks; i++) { - BLI_task_pool_push(task_pool, - processor_apply_scanline_func, - POINTER_FROM_INT(start_line), - false, - TASK_PRIORITY_LOW); - start_line += scanlines_per_task; - } - - /* work and wait until tasks are done */ - BLI_task_pool_work_and_wait(task_pool); - - /* Free memory. */ - BLI_task_pool_free(task_pool); + const int scanlines_per_task = 64; + ScanlineGlobalData data; + data.custom_data = custom_data; + data.do_thread = do_thread; + data.scanlines_per_task = scanlines_per_task; + data.total_scanlines = total_scanlines; + const int total_tasks = (total_scanlines + scanlines_per_task - 1) / scanlines_per_task; + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &data); + for (int i = 0, start_line = 0; i < total_tasks; i++) { + BLI_task_pool_push(task_pool, + processor_apply_scanline_func, + POINTER_FROM_INT(start_line), + false, + TASK_PRIORITY_LOW); + start_line += scanlines_per_task; + } + + /* work and wait until tasks are done */ + BLI_task_pool_work_and_wait(task_pool); + + /* Free memory. */ + BLI_task_pool_free(task_pool); } /* Alpha-under */ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]) { - size_t a = ((size_t)x) * y; - float *fp = rect_float; + size_t a = ((size_t)x) * y; + float *fp = rect_float; - while (a--) { - if (fp[3] == 0.0f) { - copy_v3_v3(fp, backcol); - } - else { - float mul = 1.0f - fp[3]; + while (a--) { + if (fp[3] == 0.0f) { + copy_v3_v3(fp, backcol); + } + else { + float mul = 1.0f - fp[3]; - fp[0] += mul * backcol[0]; - fp[1] += mul * backcol[1]; - fp[2] += mul * backcol[2]; - } + fp[0] += mul * backcol[0]; + fp[1] += mul * backcol[1]; + fp[2] += mul * backcol[2]; + } - fp[3] = 1.0f; + fp[3] = 1.0f; - fp += 4; - } + fp += 4; + } } void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]) { - size_t a = ((size_t)x) * y; - unsigned char *cp = rect; - - while (a--) { - if (cp[3] == 255) { - /* pass */ - } - else if (cp[3] == 0) { - cp[0] = backcol[0] * 255; - cp[1] = backcol[1] * 255; - cp[2] = backcol[2] * 255; - } - else { - float alpha = cp[3] / 255.0; - float mul = 1.0f - alpha; - - cp[0] = (cp[0] * alpha) + mul * backcol[0]; - cp[1] = (cp[1] * alpha) + mul * backcol[1]; - cp[2] = (cp[2] * alpha) + mul * backcol[2]; - } - - cp[3] = 255; - - cp += 4; - } + size_t a = ((size_t)x) * y; + unsigned char *cp = rect; + + while (a--) { + if (cp[3] == 255) { + /* pass */ + } + else if (cp[3] == 0) { + cp[0] = backcol[0] * 255; + cp[1] = backcol[1] * 255; + cp[2] = backcol[2] * 255; + } + else { + float alpha = cp[3] / 255.0; + float mul = 1.0f - alpha; + + cp[0] = (cp[0] * alpha) + mul * backcol[0]; + cp[1] = (cp[1] * alpha) + mul * backcol[1]; + cp[2] = (cp[2] * alpha) + mul * backcol[2]; + } + + cp[3] = 255; + + cp += 4; + } } diff --git a/source/blender/imbuf/intern/imbuf.h b/source/blender/imbuf/intern/imbuf.h index 1546c2790d7..514b6a24cf0 100644 --- a/source/blender/imbuf/intern/imbuf.h +++ b/source/blender/imbuf/intern/imbuf.h @@ -43,7 +43,8 @@ #endif #define SWAP_SHORT(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff)) -#define SWAP_LONG(x) (((x) << 24) | (((x) & 0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff)) +#define SWAP_LONG(x) \ + (((x) << 24) | (((x)&0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff)) #define ENDIAN_NOP(x) (x) @@ -61,4 +62,4 @@ #define IMB_DPI_DEFAULT 72.0f -#endif /* __IMBUF_H__ */ +#endif /* __IMBUF_H__ */ diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 6de3cabf5bd..106c04f39f6 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -45,13 +45,11 @@ # include "ffmpeg_compat.h" #endif - static const char magic[] = "BlenMIdx"; static const char temp_ext[] = "_part"; -static const int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75, - IMB_PROXY_100 }; -static const float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 }; +static const int proxy_sizes[] = {IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75, IMB_PROXY_100}; +static const float proxy_fac[] = {0.25, 0.50, 0.75, 1.00}; #ifdef WITH_FFMPEG static int tc_types[] = {IMB_TC_RECORD_RUN, @@ -69,362 +67,358 @@ static int tc_types[] = {IMB_TC_RECORD_RUN, anim_index_builder *IMB_index_builder_create(const char *name) { - anim_index_builder *rv = MEM_callocN(sizeof(struct anim_index_builder), - "index builder"); + anim_index_builder *rv = MEM_callocN(sizeof(struct anim_index_builder), "index builder"); - fprintf(stderr, "Starting work on index: %s\n", name); + fprintf(stderr, "Starting work on index: %s\n", name); - BLI_strncpy(rv->name, name, sizeof(rv->name)); - BLI_strncpy(rv->temp_name, name, sizeof(rv->temp_name)); + BLI_strncpy(rv->name, name, sizeof(rv->name)); + BLI_strncpy(rv->temp_name, name, sizeof(rv->temp_name)); - strcat(rv->temp_name, temp_ext); + strcat(rv->temp_name, temp_ext); - BLI_make_existing_file(rv->temp_name); + BLI_make_existing_file(rv->temp_name); - rv->fp = BLI_fopen(rv->temp_name, "wb"); + rv->fp = BLI_fopen(rv->temp_name, "wb"); - if (!rv->fp) { - fprintf(stderr, "Couldn't open index target: %s! " - "Index build broken!\n", rv->temp_name); - MEM_freeN(rv); - return NULL; - } + if (!rv->fp) { + fprintf(stderr, + "Couldn't open index target: %s! " + "Index build broken!\n", + rv->temp_name); + MEM_freeN(rv); + return NULL; + } - fprintf(rv->fp, "%s%c%.3d", magic, (ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v', - INDEX_FILE_VERSION); + fprintf(rv->fp, "%s%c%.3d", magic, (ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v', INDEX_FILE_VERSION); - return rv; + return rv; } void IMB_index_builder_add_entry(anim_index_builder *fp, - int frameno, unsigned long long seek_pos, + int frameno, + unsigned long long seek_pos, unsigned long long seek_pos_dts, unsigned long long pts) { - fwrite(&frameno, sizeof(int), 1, fp->fp); - fwrite(&seek_pos, sizeof(unsigned long long), 1, fp->fp); - fwrite(&seek_pos_dts, sizeof(unsigned long long), 1, fp->fp); - fwrite(&pts, sizeof(unsigned long long), 1, fp->fp); + fwrite(&frameno, sizeof(int), 1, fp->fp); + fwrite(&seek_pos, sizeof(unsigned long long), 1, fp->fp); + fwrite(&seek_pos_dts, sizeof(unsigned long long), 1, fp->fp); + fwrite(&pts, sizeof(unsigned long long), 1, fp->fp); } void IMB_index_builder_proc_frame(anim_index_builder *fp, unsigned char *buffer, int data_size, - int frameno, unsigned long long seek_pos, + int frameno, + unsigned long long seek_pos, unsigned long long seek_pos_dts, unsigned long long pts) { - if (fp->proc_frame) { - anim_index_entry e; - e.frameno = frameno; - e.seek_pos = seek_pos; - e.seek_pos_dts = seek_pos_dts; - e.pts = pts; - - fp->proc_frame(fp, buffer, data_size, &e); - } - else { - IMB_index_builder_add_entry(fp, frameno, seek_pos, - seek_pos_dts, pts); - } + if (fp->proc_frame) { + anim_index_entry e; + e.frameno = frameno; + e.seek_pos = seek_pos; + e.seek_pos_dts = seek_pos_dts; + e.pts = pts; + + fp->proc_frame(fp, buffer, data_size, &e); + } + else { + IMB_index_builder_add_entry(fp, frameno, seek_pos, seek_pos_dts, pts); + } } void IMB_index_builder_finish(anim_index_builder *fp, int rollback) { - if (fp->delete_priv_data) { - fp->delete_priv_data(fp); - } + if (fp->delete_priv_data) { + fp->delete_priv_data(fp); + } - fclose(fp->fp); + fclose(fp->fp); - if (rollback) { - unlink(fp->temp_name); - } - else { - unlink(fp->name); - BLI_rename(fp->temp_name, fp->name); - } + if (rollback) { + unlink(fp->temp_name); + } + else { + unlink(fp->name); + BLI_rename(fp->temp_name, fp->name); + } - MEM_freeN(fp); + MEM_freeN(fp); } struct anim_index *IMB_indexer_open(const char *name) { - char header[13]; - struct anim_index *idx; - FILE *fp = BLI_fopen(name, "rb"); - int i; - - if (!fp) { - return NULL; - } - - if (fread(header, 12, 1, fp) != 1) { - fclose(fp); - return NULL; - } - - header[12] = 0; - - if (memcmp(header, magic, 8) != 0) { - fclose(fp); - return NULL; - } - - if (atoi(header + 9) != INDEX_FILE_VERSION) { - fclose(fp); - return NULL; - } - - idx = MEM_callocN(sizeof(struct anim_index), "anim_index"); - - BLI_strncpy(idx->name, name, sizeof(idx->name)); - - fseek(fp, 0, SEEK_END); - - idx->num_entries = (ftell(fp) - 12) / - (sizeof(int) + /* framepos */ - sizeof(unsigned long long) + /* seek_pos */ - sizeof(unsigned long long) + /* seek_pos_dts */ - sizeof(unsigned long long) /* pts */ - ); - - fseek(fp, 12, SEEK_SET); - - idx->entries = MEM_callocN(sizeof(struct anim_index_entry) * - idx->num_entries, "anim_index_entries"); - - for (i = 0; i < idx->num_entries; i++) { - fread(&idx->entries[i].frameno, - sizeof(int), 1, fp); - fread(&idx->entries[i].seek_pos, - sizeof(unsigned long long), 1, fp); - fread(&idx->entries[i].seek_pos_dts, - sizeof(unsigned long long), 1, fp); - fread(&idx->entries[i].pts, - sizeof(unsigned long long), 1, fp); - } - - if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) { - for (i = 0; i < idx->num_entries; i++) { - BLI_endian_switch_int32(&idx->entries[i].frameno); - BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos); - BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos_dts); - BLI_endian_switch_int64((int64_t *)&idx->entries[i].pts); - } - } - - fclose(fp); - - return idx; + char header[13]; + struct anim_index *idx; + FILE *fp = BLI_fopen(name, "rb"); + int i; + + if (!fp) { + return NULL; + } + + if (fread(header, 12, 1, fp) != 1) { + fclose(fp); + return NULL; + } + + header[12] = 0; + + if (memcmp(header, magic, 8) != 0) { + fclose(fp); + return NULL; + } + + if (atoi(header + 9) != INDEX_FILE_VERSION) { + fclose(fp); + return NULL; + } + + idx = MEM_callocN(sizeof(struct anim_index), "anim_index"); + + BLI_strncpy(idx->name, name, sizeof(idx->name)); + + fseek(fp, 0, SEEK_END); + + idx->num_entries = (ftell(fp) - 12) / (sizeof(int) + /* framepos */ + sizeof(unsigned long long) + /* seek_pos */ + sizeof(unsigned long long) + /* seek_pos_dts */ + sizeof(unsigned long long) /* pts */ + ); + + fseek(fp, 12, SEEK_SET); + + idx->entries = MEM_callocN(sizeof(struct anim_index_entry) * idx->num_entries, + "anim_index_entries"); + + for (i = 0; i < idx->num_entries; i++) { + fread(&idx->entries[i].frameno, sizeof(int), 1, fp); + fread(&idx->entries[i].seek_pos, sizeof(unsigned long long), 1, fp); + fread(&idx->entries[i].seek_pos_dts, sizeof(unsigned long long), 1, fp); + fread(&idx->entries[i].pts, sizeof(unsigned long long), 1, fp); + } + + if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) { + for (i = 0; i < idx->num_entries; i++) { + BLI_endian_switch_int32(&idx->entries[i].frameno); + BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos); + BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos_dts); + BLI_endian_switch_int64((int64_t *)&idx->entries[i].pts); + } + } + + fclose(fp); + + return idx; } -unsigned long long IMB_indexer_get_seek_pos( - struct anim_index *idx, int frame_index) +unsigned long long IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index) { - if (frame_index < 0) { - frame_index = 0; - } - if (frame_index >= idx->num_entries) { - frame_index = idx->num_entries - 1; - } - return idx->entries[frame_index].seek_pos; + if (frame_index < 0) { + frame_index = 0; + } + if (frame_index >= idx->num_entries) { + frame_index = idx->num_entries - 1; + } + return idx->entries[frame_index].seek_pos; } -unsigned long long IMB_indexer_get_seek_pos_dts( - struct anim_index *idx, int frame_index) +unsigned long long IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index) { - if (frame_index < 0) { - frame_index = 0; - } - if (frame_index >= idx->num_entries) { - frame_index = idx->num_entries - 1; - } - return idx->entries[frame_index].seek_pos_dts; + if (frame_index < 0) { + frame_index = 0; + } + if (frame_index >= idx->num_entries) { + frame_index = idx->num_entries - 1; + } + return idx->entries[frame_index].seek_pos_dts; } int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno) { - int len = idx->num_entries; - int half; - int middle; - int first = 0; - - /* bsearch (lower bound) the right index */ - - while (len > 0) { - half = len >> 1; - middle = first; - - middle += half; - - if (idx->entries[middle].frameno < frameno) { - first = middle; - first++; - len = len - half - 1; - } - else { - len = half; - } - } - - if (first == idx->num_entries) { - return idx->num_entries - 1; - } - else { - return first; - } + int len = idx->num_entries; + int half; + int middle; + int first = 0; + + /* bsearch (lower bound) the right index */ + + while (len > 0) { + half = len >> 1; + middle = first; + + middle += half; + + if (idx->entries[middle].frameno < frameno) { + first = middle; + first++; + len = len - half - 1; + } + else { + len = half; + } + } + + if (first == idx->num_entries) { + return idx->num_entries - 1; + } + else { + return first; + } } -unsigned long long IMB_indexer_get_pts(struct anim_index *idx, - int frame_index) +unsigned long long IMB_indexer_get_pts(struct anim_index *idx, int frame_index) { - if (frame_index < 0) { - frame_index = 0; - } - if (frame_index >= idx->num_entries) { - frame_index = idx->num_entries - 1; - } - return idx->entries[frame_index].pts; + if (frame_index < 0) { + frame_index = 0; + } + if (frame_index >= idx->num_entries) { + frame_index = idx->num_entries - 1; + } + return idx->entries[frame_index].pts; } int IMB_indexer_get_duration(struct anim_index *idx) { - if (idx->num_entries == 0) { - return 0; - } - return idx->entries[idx->num_entries - 1].frameno + 1; + if (idx->num_entries == 0) { + return 0; + } + return idx->entries[idx->num_entries - 1].frameno + 1; } -int IMB_indexer_can_scan(struct anim_index *idx, - int old_frame_index, int new_frame_index) +int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index) { - /* makes only sense, if it is the same I-Frame and we are not - * trying to run backwards in time... */ - return (IMB_indexer_get_seek_pos(idx, old_frame_index) == IMB_indexer_get_seek_pos(idx, new_frame_index) && - old_frame_index < new_frame_index); + /* makes only sense, if it is the same I-Frame and we are not + * trying to run backwards in time... */ + return (IMB_indexer_get_seek_pos(idx, old_frame_index) == + IMB_indexer_get_seek_pos(idx, new_frame_index) && + old_frame_index < new_frame_index); } void IMB_indexer_close(struct anim_index *idx) { - MEM_freeN(idx->entries); - MEM_freeN(idx); + MEM_freeN(idx->entries); + MEM_freeN(idx); } int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size) { - switch (pr_size) { - case IMB_PROXY_NONE: /* if we got here, something is broken anyways, - * so sane defaults... */ - return 0; - case IMB_PROXY_25: - return 0; - case IMB_PROXY_50: - return 1; - case IMB_PROXY_75: - return 2; - case IMB_PROXY_100: - return 3; - default: - return 0; - } + switch (pr_size) { + case IMB_PROXY_NONE: /* if we got here, something is broken anyways, + * so sane defaults... */ + return 0; + case IMB_PROXY_25: + return 0; + case IMB_PROXY_50: + return 1; + case IMB_PROXY_75: + return 2; + case IMB_PROXY_100: + return 3; + default: + return 0; + } } int IMB_timecode_to_array_index(IMB_Timecode_Type tc) { - switch (tc) { - case IMB_TC_NONE: /* if we got here, something is broken anyways, - * so sane defaults... */ - return 0; - case IMB_TC_RECORD_RUN: - return 0; - case IMB_TC_FREE_RUN: - return 1; - case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN: - return 2; - case IMB_TC_RECORD_RUN_NO_GAPS: - return 3; - default: - return 0; - } + switch (tc) { + case IMB_TC_NONE: /* if we got here, something is broken anyways, + * so sane defaults... */ + return 0; + case IMB_TC_RECORD_RUN: + return 0; + case IMB_TC_FREE_RUN: + return 1; + case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN: + return 2; + case IMB_TC_RECORD_RUN_NO_GAPS: + return 3; + default: + return 0; + } } - /* ---------------------------------------------------------------------- * - rebuild helper functions * ---------------------------------------------------------------------- */ static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_len) { - if (!anim->index_dir[0]) { - char fname[FILE_MAXFILE]; - BLI_split_dirfile(anim->name, index_dir, fname, index_dir_len, sizeof(fname)); - BLI_path_append(index_dir, index_dir_len, "BL_proxy"); - BLI_path_append(index_dir, index_dir_len, fname); - } - else { - BLI_strncpy(index_dir, anim->index_dir, index_dir_len); - } + if (!anim->index_dir[0]) { + char fname[FILE_MAXFILE]; + BLI_split_dirfile(anim->name, index_dir, fname, index_dir_len, sizeof(fname)); + BLI_path_append(index_dir, index_dir_len, "BL_proxy"); + BLI_path_append(index_dir, index_dir_len, fname); + } + else { + BLI_strncpy(index_dir, anim->index_dir, index_dir_len); + } } void IMB_anim_get_fname(struct anim *anim, char *file, int size) { - char fname[FILE_MAXFILE]; - BLI_split_dirfile(anim->name, file, fname, size, sizeof(fname)); - BLI_strncpy(file, fname, size); + char fname[FILE_MAXFILE]; + BLI_split_dirfile(anim->name, file, fname, size, sizeof(fname)); + BLI_strncpy(file, fname, size); } -static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size, - char *fname, bool temp) +static void get_proxy_filename(struct anim *anim, + IMB_Proxy_Size preview_size, + char *fname, + bool temp) { - char index_dir[FILE_MAXDIR]; - int i = IMB_proxy_size_to_array_index(preview_size); + char index_dir[FILE_MAXDIR]; + int i = IMB_proxy_size_to_array_index(preview_size); - char proxy_name[256]; - char stream_suffix[20]; - const char *name = (temp) ? "proxy_%d%s_part.avi" : "proxy_%d%s.avi"; + char proxy_name[256]; + char stream_suffix[20]; + const char *name = (temp) ? "proxy_%d%s_part.avi" : "proxy_%d%s.avi"; - stream_suffix[0] = 0; + stream_suffix[0] = 0; - if (anim->streamindex > 0) { - BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex); - } + if (anim->streamindex > 0) { + BLI_snprintf(stream_suffix, sizeof(stream_suffix), "_st%d", anim->streamindex); + } - BLI_snprintf(proxy_name, sizeof(proxy_name), name, - (int) (proxy_fac[i] * 100), stream_suffix, anim->suffix); + BLI_snprintf(proxy_name, + sizeof(proxy_name), + name, + (int)(proxy_fac[i] * 100), + stream_suffix, + anim->suffix); - get_index_dir(anim, index_dir, sizeof(index_dir)); + get_index_dir(anim, index_dir, sizeof(index_dir)); - BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); + BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); } -static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, - char *fname) +static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char *fname) { - char index_dir[FILE_MAXDIR]; - int i = IMB_timecode_to_array_index(tc); - const char *index_names[] = { - "record_run%s%s.blen_tc", - "free_run%s%s.blen_tc", - "interp_free_run%s%s.blen_tc", - "record_run_no_gaps%s%s.blen_tc", - }; + char index_dir[FILE_MAXDIR]; + int i = IMB_timecode_to_array_index(tc); + const char *index_names[] = { + "record_run%s%s.blen_tc", + "free_run%s%s.blen_tc", + "interp_free_run%s%s.blen_tc", + "record_run_no_gaps%s%s.blen_tc", + }; - char stream_suffix[20]; - char index_name[256]; + char stream_suffix[20]; + char index_name[256]; - stream_suffix[0] = 0; + stream_suffix[0] = 0; - if (anim->streamindex > 0) { - BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex); - } + if (anim->streamindex > 0) { + BLI_snprintf(stream_suffix, 20, "_st%d", anim->streamindex); + } - BLI_snprintf(index_name, 256, index_names[i], stream_suffix, anim->suffix); + BLI_snprintf(index_name, 256, index_names[i], stream_suffix, anim->suffix); - get_index_dir(anim, index_dir, sizeof(index_dir)); + get_index_dir(anim, index_dir, sizeof(index_dir)); - BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, - index_dir, index_name); + BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name); } /* ---------------------------------------------------------------------- @@ -432,10 +426,9 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, * ---------------------------------------------------------------------- */ typedef struct IndexBuildContext { - int anim_type; + int anim_type; } IndexBuildContext; - /* ---------------------------------------------------------------------- * - ffmpeg rebuilder * ---------------------------------------------------------------------- */ @@ -443,533 +436,527 @@ typedef struct IndexBuildContext { #ifdef WITH_FFMPEG struct proxy_output_ctx { - AVFormatContext *of; - AVStream *st; - AVCodecContext *c; - AVCodec *codec; - struct SwsContext *sws_ctx; - AVFrame *frame; - int cfra; - int proxy_size; - int orig_height; - struct anim *anim; + AVFormatContext *of; + AVStream *st; + AVCodecContext *c; + AVCodec *codec; + struct SwsContext *sws_ctx; + AVFrame *frame; + int cfra; + int proxy_size; + int orig_height; + struct anim *anim; }; // work around stupid swscaler 16 bytes alignment bug... static int round_up(int x, int mod) { - return x + ((mod - (x % mod)) % mod); + return x + ((mod - (x % mod)) % mod); } static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( - struct anim *anim, - AVStream *st, int proxy_size, int width, int height, - int quality) + struct anim *anim, AVStream *st, int proxy_size, int width, int height, int quality) { - struct proxy_output_ctx *rv = MEM_callocN( - sizeof(struct proxy_output_ctx), "alloc_proxy_output"); - - char fname[FILE_MAX]; - int ffmpeg_quality; - - /* JPEG requires this */ - width = round_up(width, 8); - height = round_up(height, 8); - - rv->proxy_size = proxy_size; - rv->anim = anim; - - get_proxy_filename(rv->anim, rv->proxy_size, fname, true); - BLI_make_existing_file(fname); - - rv->of = avformat_alloc_context(); - rv->of->oformat = av_guess_format("avi", NULL, NULL); - - BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename)); - - fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename); - - rv->st = avformat_new_stream(rv->of, NULL); - rv->st->id = 0; - - rv->c = rv->st->codec; - rv->c->codec_type = AVMEDIA_TYPE_VIDEO; - rv->c->codec_id = AV_CODEC_ID_MJPEG; - rv->c->width = width; - rv->c->height = height; - - rv->of->oformat->video_codec = rv->c->codec_id; - rv->codec = avcodec_find_encoder(rv->c->codec_id); - - if (!rv->codec) { - fprintf(stderr, "No ffmpeg MJPEG encoder available? " - "Proxy not built!\n"); - av_free(rv->of); - return NULL; - } - - if (rv->codec->pix_fmts) { - rv->c->pix_fmt = rv->codec->pix_fmts[0]; - } - else { - rv->c->pix_fmt = AV_PIX_FMT_YUVJ420P; - } - - rv->c->sample_aspect_ratio = - rv->st->sample_aspect_ratio = - st->codec->sample_aspect_ratio; - - rv->c->time_base.den = 25; - rv->c->time_base.num = 1; - rv->st->time_base = rv->c->time_base; - - /* there's no way to set JPEG quality in the same way as in AVI JPEG and image sequence, - * but this seems to be giving expected quality result */ - ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f); - av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0); - av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0); - - if (rv->of->flags & AVFMT_GLOBALHEADER) { - rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER; - } - - if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) { - fprintf(stderr, "Couldn't open outputfile! " - "Proxy not built!\n"); - av_free(rv->of); - return 0; - } - - avcodec_open2(rv->c, rv->codec, NULL); - - rv->orig_height = av_get_cropped_height_from_codec(st->codec); - - if (st->codec->width != width || st->codec->height != height || - st->codec->pix_fmt != rv->c->pix_fmt) - { - rv->frame = av_frame_alloc(); - avpicture_fill((AVPicture *) rv->frame, - MEM_mallocN(avpicture_get_size( - rv->c->pix_fmt, - round_up(width, 16), height), - "alloc proxy output frame"), - rv->c->pix_fmt, round_up(width, 16), height); - - rv->sws_ctx = sws_getContext( - st->codec->width, - rv->orig_height, - st->codec->pix_fmt, - width, height, - rv->c->pix_fmt, - SWS_FAST_BILINEAR | SWS_PRINT_INFO, - NULL, NULL, NULL); - } - - if (avformat_write_header(rv->of, NULL) < 0) { - fprintf(stderr, "Couldn't set output parameters? " - "Proxy not built!\n"); - av_free(rv->of); - return 0; - } - - return rv; + struct proxy_output_ctx *rv = MEM_callocN(sizeof(struct proxy_output_ctx), "alloc_proxy_output"); + + char fname[FILE_MAX]; + int ffmpeg_quality; + + /* JPEG requires this */ + width = round_up(width, 8); + height = round_up(height, 8); + + rv->proxy_size = proxy_size; + rv->anim = anim; + + get_proxy_filename(rv->anim, rv->proxy_size, fname, true); + BLI_make_existing_file(fname); + + rv->of = avformat_alloc_context(); + rv->of->oformat = av_guess_format("avi", NULL, NULL); + + BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename)); + + fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename); + + rv->st = avformat_new_stream(rv->of, NULL); + rv->st->id = 0; + + rv->c = rv->st->codec; + rv->c->codec_type = AVMEDIA_TYPE_VIDEO; + rv->c->codec_id = AV_CODEC_ID_MJPEG; + rv->c->width = width; + rv->c->height = height; + + rv->of->oformat->video_codec = rv->c->codec_id; + rv->codec = avcodec_find_encoder(rv->c->codec_id); + + if (!rv->codec) { + fprintf(stderr, + "No ffmpeg MJPEG encoder available? " + "Proxy not built!\n"); + av_free(rv->of); + return NULL; + } + + if (rv->codec->pix_fmts) { + rv->c->pix_fmt = rv->codec->pix_fmts[0]; + } + else { + rv->c->pix_fmt = AV_PIX_FMT_YUVJ420P; + } + + rv->c->sample_aspect_ratio = rv->st->sample_aspect_ratio = st->codec->sample_aspect_ratio; + + rv->c->time_base.den = 25; + rv->c->time_base.num = 1; + rv->st->time_base = rv->c->time_base; + + /* there's no way to set JPEG quality in the same way as in AVI JPEG and image sequence, + * but this seems to be giving expected quality result */ + ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f); + av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0); + av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0); + + if (rv->of->flags & AVFMT_GLOBALHEADER) { + rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER; + } + + if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) { + fprintf(stderr, + "Couldn't open outputfile! " + "Proxy not built!\n"); + av_free(rv->of); + return 0; + } + + avcodec_open2(rv->c, rv->codec, NULL); + + rv->orig_height = av_get_cropped_height_from_codec(st->codec); + + if (st->codec->width != width || st->codec->height != height || + st->codec->pix_fmt != rv->c->pix_fmt) { + rv->frame = av_frame_alloc(); + avpicture_fill((AVPicture *)rv->frame, + MEM_mallocN(avpicture_get_size(rv->c->pix_fmt, round_up(width, 16), height), + "alloc proxy output frame"), + rv->c->pix_fmt, + round_up(width, 16), + height); + + rv->sws_ctx = sws_getContext(st->codec->width, + rv->orig_height, + st->codec->pix_fmt, + width, + height, + rv->c->pix_fmt, + SWS_FAST_BILINEAR | SWS_PRINT_INFO, + NULL, + NULL, + NULL); + } + + if (avformat_write_header(rv->of, NULL) < 0) { + fprintf(stderr, + "Couldn't set output parameters? " + "Proxy not built!\n"); + av_free(rv->of); + return 0; + } + + return rv; } -static int add_to_proxy_output_ffmpeg( - struct proxy_output_ctx *ctx, AVFrame *frame) +static int add_to_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, AVFrame *frame) { - AVPacket packet = { 0 }; - int ret, got_output; - - av_init_packet(&packet); - - if (!ctx) { - return 0; - } - - if (ctx->sws_ctx && frame && - (frame->data[0] || frame->data[1] || - frame->data[2] || frame->data[3])) - { - sws_scale(ctx->sws_ctx, (const uint8_t *const *) frame->data, - frame->linesize, 0, ctx->orig_height, - ctx->frame->data, ctx->frame->linesize); - } - - frame = ctx->sws_ctx ? (frame ? ctx->frame : 0) : frame; - - if (frame) { - frame->pts = ctx->cfra++; - } - - ret = avcodec_encode_video2(ctx->c, &packet, frame, &got_output); - if (ret < 0) { - fprintf(stderr, "Error encoding proxy frame %d for '%s'\n", - ctx->cfra - 1, ctx->of->filename); - return 0; - } - - if (got_output) { - if (packet.pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(packet.pts, - ctx->c->time_base, - ctx->st->time_base); - } - if (packet.dts != AV_NOPTS_VALUE) { - packet.dts = av_rescale_q(packet.dts, - ctx->c->time_base, - ctx->st->time_base); - } - - packet.stream_index = ctx->st->index; - - if (av_interleaved_write_frame(ctx->of, &packet) != 0) { - fprintf(stderr, "Error writing proxy frame %d " - "into '%s'\n", ctx->cfra - 1, - ctx->of->filename); - return 0; - } - - return 1; - } - else { - return 0; - } + AVPacket packet = {0}; + int ret, got_output; + + av_init_packet(&packet); + + if (!ctx) { + return 0; + } + + if (ctx->sws_ctx && frame && + (frame->data[0] || frame->data[1] || frame->data[2] || frame->data[3])) { + sws_scale(ctx->sws_ctx, + (const uint8_t *const *)frame->data, + frame->linesize, + 0, + ctx->orig_height, + ctx->frame->data, + ctx->frame->linesize); + } + + frame = ctx->sws_ctx ? (frame ? ctx->frame : 0) : frame; + + if (frame) { + frame->pts = ctx->cfra++; + } + + ret = avcodec_encode_video2(ctx->c, &packet, frame, &got_output); + if (ret < 0) { + fprintf(stderr, "Error encoding proxy frame %d for '%s'\n", ctx->cfra - 1, ctx->of->filename); + return 0; + } + + if (got_output) { + if (packet.pts != AV_NOPTS_VALUE) { + packet.pts = av_rescale_q(packet.pts, ctx->c->time_base, ctx->st->time_base); + } + if (packet.dts != AV_NOPTS_VALUE) { + packet.dts = av_rescale_q(packet.dts, ctx->c->time_base, ctx->st->time_base); + } + + packet.stream_index = ctx->st->index; + + if (av_interleaved_write_frame(ctx->of, &packet) != 0) { + fprintf(stderr, + "Error writing proxy frame %d " + "into '%s'\n", + ctx->cfra - 1, + ctx->of->filename); + return 0; + } + + return 1; + } + else { + return 0; + } } -static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, - int rollback) +static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, int rollback) { - char fname[FILE_MAX]; - char fname_tmp[FILE_MAX]; + char fname[FILE_MAX]; + char fname_tmp[FILE_MAX]; - if (!ctx) { - return; - } + if (!ctx) { + return; + } - if (!rollback) { - while (add_to_proxy_output_ffmpeg(ctx, NULL)) {} - } + if (!rollback) { + while (add_to_proxy_output_ffmpeg(ctx, NULL)) { + } + } - avcodec_flush_buffers(ctx->c); + avcodec_flush_buffers(ctx->c); - av_write_trailer(ctx->of); + av_write_trailer(ctx->of); - avcodec_close(ctx->c); + avcodec_close(ctx->c); - if (ctx->of->oformat) { - if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) { - avio_close(ctx->of->pb); - } - } - avformat_free_context(ctx->of); + if (ctx->of->oformat) { + if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) { + avio_close(ctx->of->pb); + } + } + avformat_free_context(ctx->of); - if (ctx->sws_ctx) { - sws_freeContext(ctx->sws_ctx); + if (ctx->sws_ctx) { + sws_freeContext(ctx->sws_ctx); - MEM_freeN(ctx->frame->data[0]); - av_free(ctx->frame); - } + MEM_freeN(ctx->frame->data[0]); + av_free(ctx->frame); + } - get_proxy_filename(ctx->anim, ctx->proxy_size, - fname_tmp, true); + get_proxy_filename(ctx->anim, ctx->proxy_size, fname_tmp, true); - if (rollback) { - unlink(fname_tmp); - } - else { - get_proxy_filename(ctx->anim, ctx->proxy_size, - fname, false); - unlink(fname); - BLI_rename(fname_tmp, fname); - } + if (rollback) { + unlink(fname_tmp); + } + else { + get_proxy_filename(ctx->anim, ctx->proxy_size, fname, false); + unlink(fname); + BLI_rename(fname_tmp, fname); + } - MEM_freeN(ctx); + MEM_freeN(ctx); } typedef struct FFmpegIndexBuilderContext { - int anim_type; - - AVFormatContext *iFormatCtx; - AVCodecContext *iCodecCtx; - AVCodec *iCodec; - AVStream *iStream; - int videoStream; - - int num_proxy_sizes; - int num_indexers; - - struct proxy_output_ctx *proxy_ctx[IMB_PROXY_MAX_SLOT]; - anim_index_builder *indexer[IMB_TC_MAX_SLOT]; - - IMB_Timecode_Type tcs_in_use; - IMB_Proxy_Size proxy_sizes_in_use; - - unsigned long long seek_pos; - unsigned long long last_seek_pos; - unsigned long long seek_pos_dts; - unsigned long long seek_pos_pts; - unsigned long long last_seek_pos_dts; - unsigned long long start_pts; - double frame_rate; - double pts_time_base; - int frameno, frameno_gapless; - int start_pts_set; + int anim_type; + + AVFormatContext *iFormatCtx; + AVCodecContext *iCodecCtx; + AVCodec *iCodec; + AVStream *iStream; + int videoStream; + + int num_proxy_sizes; + int num_indexers; + + struct proxy_output_ctx *proxy_ctx[IMB_PROXY_MAX_SLOT]; + anim_index_builder *indexer[IMB_TC_MAX_SLOT]; + + IMB_Timecode_Type tcs_in_use; + IMB_Proxy_Size proxy_sizes_in_use; + + unsigned long long seek_pos; + unsigned long long last_seek_pos; + unsigned long long seek_pos_dts; + unsigned long long seek_pos_pts; + unsigned long long last_seek_pos_dts; + unsigned long long start_pts; + double frame_rate; + double pts_time_base; + int frameno, frameno_gapless; + int start_pts_set; } FFmpegIndexBuilderContext; -static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Timecode_Type tcs_in_use, - IMB_Proxy_Size proxy_sizes_in_use, int quality) +static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, + IMB_Timecode_Type tcs_in_use, + IMB_Proxy_Size proxy_sizes_in_use, + int quality) { - FFmpegIndexBuilderContext *context = MEM_callocN(sizeof(FFmpegIndexBuilderContext), "FFmpeg index builder context"); - int num_proxy_sizes = IMB_PROXY_MAX_SLOT; - int num_indexers = IMB_TC_MAX_SLOT; - int i, streamcount; - - context->tcs_in_use = tcs_in_use; - context->proxy_sizes_in_use = proxy_sizes_in_use; - context->num_proxy_sizes = IMB_PROXY_MAX_SLOT; - context->num_indexers = IMB_TC_MAX_SLOT; - - memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx)); - memset(context->indexer, 0, sizeof(context->indexer)); - - if (avformat_open_input(&context->iFormatCtx, anim->name, NULL, NULL) != 0) { - MEM_freeN(context); - return NULL; - } - - if (avformat_find_stream_info(context->iFormatCtx, NULL) < 0) { - avformat_close_input(&context->iFormatCtx); - MEM_freeN(context); - return NULL; - } - - streamcount = anim->streamindex; - - /* Find the video stream */ - context->videoStream = -1; - for (i = 0; i < context->iFormatCtx->nb_streams; i++) - if (context->iFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if (streamcount > 0) { - streamcount--; - continue; - } - context->videoStream = i; - break; - } - - if (context->videoStream == -1) { - avformat_close_input(&context->iFormatCtx); - MEM_freeN(context); - return NULL; - } - - context->iStream = context->iFormatCtx->streams[context->videoStream]; - context->iCodecCtx = context->iStream->codec; - - context->iCodec = avcodec_find_decoder(context->iCodecCtx->codec_id); - - if (context->iCodec == NULL) { - avformat_close_input(&context->iFormatCtx); - MEM_freeN(context); - return NULL; - } - - context->iCodecCtx->workaround_bugs = 1; - - if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) { - avformat_close_input(&context->iFormatCtx); - MEM_freeN(context); - return NULL; - } - - for (i = 0; i < num_proxy_sizes; i++) { - if (proxy_sizes_in_use & proxy_sizes[i]) { - context->proxy_ctx[i] = alloc_proxy_output_ffmpeg( - anim, context->iStream, proxy_sizes[i], - context->iCodecCtx->width * proxy_fac[i], - av_get_cropped_height_from_codec( - context->iCodecCtx) * proxy_fac[i], - quality); - if (!context->proxy_ctx[i]) { - proxy_sizes_in_use &= ~proxy_sizes[i]; - } - } - } - - for (i = 0; i < num_indexers; i++) { - if (tcs_in_use & tc_types[i]) { - char fname[FILE_MAX]; - - get_tc_filename(anim, tc_types[i], fname); - - context->indexer[i] = IMB_index_builder_create(fname); - if (!context->indexer[i]) { - tcs_in_use &= ~tc_types[i]; - } - } - } - - return (IndexBuildContext *)context; + FFmpegIndexBuilderContext *context = MEM_callocN(sizeof(FFmpegIndexBuilderContext), + "FFmpeg index builder context"); + int num_proxy_sizes = IMB_PROXY_MAX_SLOT; + int num_indexers = IMB_TC_MAX_SLOT; + int i, streamcount; + + context->tcs_in_use = tcs_in_use; + context->proxy_sizes_in_use = proxy_sizes_in_use; + context->num_proxy_sizes = IMB_PROXY_MAX_SLOT; + context->num_indexers = IMB_TC_MAX_SLOT; + + memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx)); + memset(context->indexer, 0, sizeof(context->indexer)); + + if (avformat_open_input(&context->iFormatCtx, anim->name, NULL, NULL) != 0) { + MEM_freeN(context); + return NULL; + } + + if (avformat_find_stream_info(context->iFormatCtx, NULL) < 0) { + avformat_close_input(&context->iFormatCtx); + MEM_freeN(context); + return NULL; + } + + streamcount = anim->streamindex; + + /* Find the video stream */ + context->videoStream = -1; + for (i = 0; i < context->iFormatCtx->nb_streams; i++) + if (context->iFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (streamcount > 0) { + streamcount--; + continue; + } + context->videoStream = i; + break; + } + + if (context->videoStream == -1) { + avformat_close_input(&context->iFormatCtx); + MEM_freeN(context); + return NULL; + } + + context->iStream = context->iFormatCtx->streams[context->videoStream]; + context->iCodecCtx = context->iStream->codec; + + context->iCodec = avcodec_find_decoder(context->iCodecCtx->codec_id); + + if (context->iCodec == NULL) { + avformat_close_input(&context->iFormatCtx); + MEM_freeN(context); + return NULL; + } + + context->iCodecCtx->workaround_bugs = 1; + + if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) { + avformat_close_input(&context->iFormatCtx); + MEM_freeN(context); + return NULL; + } + + for (i = 0; i < num_proxy_sizes; i++) { + if (proxy_sizes_in_use & proxy_sizes[i]) { + context->proxy_ctx[i] = alloc_proxy_output_ffmpeg( + anim, + context->iStream, + proxy_sizes[i], + context->iCodecCtx->width * proxy_fac[i], + av_get_cropped_height_from_codec(context->iCodecCtx) * proxy_fac[i], + quality); + if (!context->proxy_ctx[i]) { + proxy_sizes_in_use &= ~proxy_sizes[i]; + } + } + } + + for (i = 0; i < num_indexers; i++) { + if (tcs_in_use & tc_types[i]) { + char fname[FILE_MAX]; + + get_tc_filename(anim, tc_types[i], fname); + + context->indexer[i] = IMB_index_builder_create(fname); + if (!context->indexer[i]) { + tcs_in_use &= ~tc_types[i]; + } + } + } + + return (IndexBuildContext *)context; } static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int stop) { - int i; + int i; - for (i = 0; i < context->num_indexers; i++) { - if (context->tcs_in_use & tc_types[i]) { - IMB_index_builder_finish(context->indexer[i], stop); - } - } + for (i = 0; i < context->num_indexers; i++) { + if (context->tcs_in_use & tc_types[i]) { + IMB_index_builder_finish(context->indexer[i], stop); + } + } - for (i = 0; i < context->num_proxy_sizes; i++) { - if (context->proxy_sizes_in_use & proxy_sizes[i]) { - free_proxy_output_ffmpeg(context->proxy_ctx[i], stop); - } - } + for (i = 0; i < context->num_proxy_sizes; i++) { + if (context->proxy_sizes_in_use & proxy_sizes[i]) { + free_proxy_output_ffmpeg(context->proxy_ctx[i], stop); + } + } - avcodec_close(context->iCodecCtx); - avformat_close_input(&context->iFormatCtx); + avcodec_close(context->iCodecCtx); + avformat_close_input(&context->iFormatCtx); - MEM_freeN(context); + MEM_freeN(context); } -static void index_rebuild_ffmpeg_proc_decoded_frame( - FFmpegIndexBuilderContext *context, - AVPacket *curr_packet, - AVFrame *in_frame) +static void index_rebuild_ffmpeg_proc_decoded_frame(FFmpegIndexBuilderContext *context, + AVPacket *curr_packet, + AVFrame *in_frame) { - int i; - unsigned long long s_pos = context->seek_pos; - unsigned long long s_dts = context->seek_pos_dts; - unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame); - - for (i = 0; i < context->num_proxy_sizes; i++) { - add_to_proxy_output_ffmpeg(context->proxy_ctx[i], in_frame); - } - - if (!context->start_pts_set) { - context->start_pts = pts; - context->start_pts_set = true; - } - - 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 - * information is in place, when we seek - * to the I-Frame presented *after* the P-Frame, - * but located before the P-Frame within - * the stream */ - - if (pts < context->seek_pos_pts) { - s_pos = context->last_seek_pos; - s_dts = context->last_seek_pos_dts; - } - - for (i = 0; i < context->num_indexers; i++) { - if (context->tcs_in_use & tc_types[i]) { - int tc_frameno = context->frameno; - - if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS) - tc_frameno = context->frameno_gapless; - - IMB_index_builder_proc_frame( - context->indexer[i], - curr_packet->data, - curr_packet->size, - tc_frameno, - s_pos, s_dts, pts); - } - } - - context->frameno_gapless++; + int i; + unsigned long long s_pos = context->seek_pos; + unsigned long long s_dts = context->seek_pos_dts; + unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame); + + for (i = 0; i < context->num_proxy_sizes; i++) { + add_to_proxy_output_ffmpeg(context->proxy_ctx[i], in_frame); + } + + if (!context->start_pts_set) { + context->start_pts = pts; + context->start_pts_set = true; + } + + 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 + * information is in place, when we seek + * to the I-Frame presented *after* the P-Frame, + * but located before the P-Frame within + * the stream */ + + if (pts < context->seek_pos_pts) { + s_pos = context->last_seek_pos; + s_dts = context->last_seek_pos_dts; + } + + for (i = 0; i < context->num_indexers; i++) { + if (context->tcs_in_use & tc_types[i]) { + int tc_frameno = context->frameno; + + if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS) + tc_frameno = context->frameno_gapless; + + IMB_index_builder_proc_frame(context->indexer[i], + curr_packet->data, + curr_packet->size, + tc_frameno, + s_pos, + s_dts, + pts); + } + } + + context->frameno_gapless++; } static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, - short *stop, short *do_update, float *progress) + short *stop, + short *do_update, + float *progress) { - AVFrame *in_frame = 0; - AVPacket next_packet; - uint64_t stream_size; - - memset(&next_packet, 0, sizeof(AVPacket)); - - in_frame = av_frame_alloc(); - - stream_size = avio_size(context->iFormatCtx->pb); - - context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iFormatCtx, context->iStream)); - context->pts_time_base = av_q2d(context->iStream->time_base); - - while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) { - int frame_finished = 0; - float next_progress = (float)((int)floor(((double) next_packet.pos) * 100 / - ((double) stream_size) + 0.5)) / 100; - - if (*progress != next_progress) { - *progress = next_progress; - *do_update = true; - } - - if (*stop) { - av_free_packet(&next_packet); - break; - } - - if (next_packet.stream_index == context->videoStream) { - if (next_packet.flags & AV_PKT_FLAG_KEY) { - context->last_seek_pos = context->seek_pos; - context->last_seek_pos_dts = context->seek_pos_dts; - context->seek_pos = next_packet.pos; - context->seek_pos_dts = next_packet.dts; - context->seek_pos_pts = next_packet.pts; - } - - avcodec_decode_video2( - context->iCodecCtx, in_frame, &frame_finished, - &next_packet); - } - - if (frame_finished) { - index_rebuild_ffmpeg_proc_decoded_frame( - context, &next_packet, in_frame); - } - av_free_packet(&next_packet); - } - - /* process pictures still stuck in decoder engine after EOF - * according to ffmpeg docs using 0-size packets. - * - * At least, if we haven't already stopped... */ - - /* this creates the 0-size packet and prevents a memory leak. */ - av_free_packet(&next_packet); - - if (!*stop) { - int frame_finished; - - do { - frame_finished = 0; - - avcodec_decode_video2( - context->iCodecCtx, in_frame, &frame_finished, - &next_packet); - - if (frame_finished) { - index_rebuild_ffmpeg_proc_decoded_frame( - context, &next_packet, in_frame); - } - } while (frame_finished); - } - - av_free(in_frame); - - return 1; + AVFrame *in_frame = 0; + AVPacket next_packet; + uint64_t stream_size; + + memset(&next_packet, 0, sizeof(AVPacket)); + + in_frame = av_frame_alloc(); + + stream_size = avio_size(context->iFormatCtx->pb); + + context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iFormatCtx, context->iStream)); + context->pts_time_base = av_q2d(context->iStream->time_base); + + while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) { + int frame_finished = 0; + float next_progress = + (float)((int)floor(((double)next_packet.pos) * 100 / ((double)stream_size) + 0.5)) / 100; + + if (*progress != next_progress) { + *progress = next_progress; + *do_update = true; + } + + if (*stop) { + av_free_packet(&next_packet); + break; + } + + if (next_packet.stream_index == context->videoStream) { + if (next_packet.flags & AV_PKT_FLAG_KEY) { + context->last_seek_pos = context->seek_pos; + context->last_seek_pos_dts = context->seek_pos_dts; + context->seek_pos = next_packet.pos; + context->seek_pos_dts = next_packet.dts; + context->seek_pos_pts = next_packet.pts; + } + + avcodec_decode_video2(context->iCodecCtx, in_frame, &frame_finished, &next_packet); + } + + if (frame_finished) { + index_rebuild_ffmpeg_proc_decoded_frame(context, &next_packet, in_frame); + } + av_free_packet(&next_packet); + } + + /* process pictures still stuck in decoder engine after EOF + * according to ffmpeg docs using 0-size packets. + * + * At least, if we haven't already stopped... */ + + /* this creates the 0-size packet and prevents a memory leak. */ + av_free_packet(&next_packet); + + if (!*stop) { + int frame_finished; + + do { + frame_finished = 0; + + avcodec_decode_video2(context->iCodecCtx, in_frame, &frame_finished, &next_packet); + + if (frame_finished) { + index_rebuild_ffmpeg_proc_decoded_frame(context, &next_packet, in_frame); + } + } while (frame_finished); + } + + av_free(in_frame); + + return 1; } #endif @@ -980,386 +967,386 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, #ifdef WITH_AVI typedef struct FallbackIndexBuilderContext { - int anim_type; + int anim_type; - struct anim *anim; - AviMovie *proxy_ctx[IMB_PROXY_MAX_SLOT]; - IMB_Proxy_Size proxy_sizes_in_use; + struct anim *anim; + AviMovie *proxy_ctx[IMB_PROXY_MAX_SLOT]; + IMB_Proxy_Size proxy_sizes_in_use; } FallbackIndexBuilderContext; static AviMovie *alloc_proxy_output_avi( - struct anim *anim, char *filename, int width, int height, - int quality) + struct anim *anim, char *filename, int width, int height, int quality) { - int x, y; - AviFormat format; - double framerate; - AviMovie *avi; - short frs_sec = 25; /* it doesn't really matter for proxies, - * but sane defaults help anyways...*/ - float frs_sec_base = 1.0; + int x, y; + AviFormat format; + double framerate; + AviMovie *avi; + short frs_sec = 25; /* it doesn't really matter for proxies, + * but sane defaults help anyways...*/ + float frs_sec_base = 1.0; - IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base, false); + IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base, false); - x = width; - y = height; + x = width; + y = height; - framerate = (double) frs_sec / (double) frs_sec_base; + framerate = (double)frs_sec / (double)frs_sec_base; - avi = MEM_mallocN(sizeof(AviMovie), "avimovie"); + avi = MEM_mallocN(sizeof(AviMovie), "avimovie"); - format = AVI_FORMAT_MJPEG; + format = AVI_FORMAT_MJPEG; - if (AVI_open_compress(filename, avi, 1, format) != AVI_ERROR_NONE) { - MEM_freeN(avi); - return NULL; - } + if (AVI_open_compress(filename, avi, 1, format) != AVI_ERROR_NONE) { + MEM_freeN(avi); + return NULL; + } - AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x); - AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y); - AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality); - AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate); + AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x); + AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y); + AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality); + AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate); - avi->interlace = 0; - avi->odd_fields = 0; + avi->interlace = 0; + avi->odd_fields = 0; - return avi; + return avi; } -static IndexBuildContext *index_fallback_create_context(struct anim *anim, IMB_Timecode_Type UNUSED(tcs_in_use), - IMB_Proxy_Size proxy_sizes_in_use, int quality) +static IndexBuildContext *index_fallback_create_context(struct anim *anim, + IMB_Timecode_Type UNUSED(tcs_in_use), + IMB_Proxy_Size proxy_sizes_in_use, + int quality) { - FallbackIndexBuilderContext *context; - int i; + FallbackIndexBuilderContext *context; + int i; - /* since timecode indices only work with ffmpeg right now, - * don't know a sensible fallback here... - * - * so no proxies... - */ - if (proxy_sizes_in_use == IMB_PROXY_NONE) { - return NULL; - } + /* since timecode indices only work with ffmpeg right now, + * don't know a sensible fallback here... + * + * so no proxies... + */ + if (proxy_sizes_in_use == IMB_PROXY_NONE) { + return NULL; + } - context = MEM_callocN(sizeof(FallbackIndexBuilderContext), "fallback index builder context"); + context = MEM_callocN(sizeof(FallbackIndexBuilderContext), "fallback index builder context"); - context->anim = anim; - context->proxy_sizes_in_use = proxy_sizes_in_use; + context->anim = anim; + context->proxy_sizes_in_use = proxy_sizes_in_use; - memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx)); + memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx)); - for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { - if (context->proxy_sizes_in_use & proxy_sizes[i]) { - char fname[FILE_MAX]; + for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { + if (context->proxy_sizes_in_use & proxy_sizes[i]) { + char fname[FILE_MAX]; - get_proxy_filename(anim, proxy_sizes[i], fname, true); - BLI_make_existing_file(fname); + get_proxy_filename(anim, proxy_sizes[i], fname, true); + BLI_make_existing_file(fname); - context->proxy_ctx[i] = alloc_proxy_output_avi(anim, fname, - anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality); - } - } + context->proxy_ctx[i] = alloc_proxy_output_avi( + anim, fname, anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality); + } + } - return (IndexBuildContext *)context; + return (IndexBuildContext *)context; } static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, int stop) { - struct anim *anim = context->anim; - char fname[FILE_MAX]; - char fname_tmp[FILE_MAX]; - int i; - - for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { - if (context->proxy_sizes_in_use & proxy_sizes[i]) { - AVI_close_compress(context->proxy_ctx[i]); - MEM_freeN(context->proxy_ctx[i]); - - get_proxy_filename(anim, proxy_sizes[i], fname_tmp, true); - get_proxy_filename(anim, proxy_sizes[i], fname, false); - - if (stop) { - unlink(fname_tmp); - } - else { - unlink(fname); - rename(fname_tmp, fname); - } - } - } + struct anim *anim = context->anim; + char fname[FILE_MAX]; + char fname_tmp[FILE_MAX]; + int i; + + for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { + if (context->proxy_sizes_in_use & proxy_sizes[i]) { + AVI_close_compress(context->proxy_ctx[i]); + MEM_freeN(context->proxy_ctx[i]); + + get_proxy_filename(anim, proxy_sizes[i], fname_tmp, true); + get_proxy_filename(anim, proxy_sizes[i], fname, false); + + if (stop) { + unlink(fname_tmp); + } + else { + unlink(fname); + rename(fname_tmp, fname); + } + } + } } static void index_rebuild_fallback(FallbackIndexBuilderContext *context, - short *stop, short *do_update, float *progress) + short *stop, + short *do_update, + float *progress) { - int cnt = IMB_anim_get_duration(context->anim, IMB_TC_NONE); - int i, pos; - struct anim *anim = context->anim; + int cnt = IMB_anim_get_duration(context->anim, IMB_TC_NONE); + int i, pos; + struct anim *anim = context->anim; - for (pos = 0; pos < cnt; pos++) { - struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE); - struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf); - float next_progress = (float) pos / (float) cnt; + for (pos = 0; pos < cnt; pos++) { + struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE); + struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf); + float next_progress = (float)pos / (float)cnt; - if (*progress != next_progress) { - *progress = next_progress; - *do_update = true; - } + if (*progress != next_progress) { + *progress = next_progress; + *do_update = true; + } - if (*stop) { - break; - } + if (*stop) { + break; + } - IMB_flipy(tmp_ibuf); + IMB_flipy(tmp_ibuf); - for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { - if (context->proxy_sizes_in_use & proxy_sizes[i]) { - int x = anim->x * proxy_fac[i]; - int y = anim->y * proxy_fac[i]; + for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { + if (context->proxy_sizes_in_use & proxy_sizes[i]) { + int x = anim->x * proxy_fac[i]; + int y = anim->y * proxy_fac[i]; - struct ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf); + struct ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf); - IMB_scalefastImBuf(s_ibuf, x, y); + IMB_scalefastImBuf(s_ibuf, x, y); - IMB_convert_rgba_to_abgr(s_ibuf); + IMB_convert_rgba_to_abgr(s_ibuf); - AVI_write_frame(context->proxy_ctx[i], pos, - AVI_FORMAT_RGB32, - s_ibuf->rect, x * y * 4); + AVI_write_frame(context->proxy_ctx[i], pos, AVI_FORMAT_RGB32, s_ibuf->rect, x * y * 4); - /* note that libavi free's the buffer... */ - s_ibuf->rect = NULL; + /* note that libavi free's the buffer... */ + s_ibuf->rect = NULL; - IMB_freeImBuf(s_ibuf); - } - } + IMB_freeImBuf(s_ibuf); + } + } - IMB_freeImBuf(tmp_ibuf); - IMB_freeImBuf(ibuf); - } + IMB_freeImBuf(tmp_ibuf); + IMB_freeImBuf(ibuf); + } } -#endif /* WITH_AVI */ +#endif /* WITH_AVI */ /* ---------------------------------------------------------------------- * - public API * ---------------------------------------------------------------------- */ -IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use, - IMB_Proxy_Size proxy_sizes_in_use, int quality, - const bool overwrite, GSet *file_list) +IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, + IMB_Timecode_Type tcs_in_use, + IMB_Proxy_Size proxy_sizes_in_use, + int quality, + const bool overwrite, + GSet *file_list) { - IndexBuildContext *context = NULL; - IMB_Proxy_Size proxy_sizes_to_build = proxy_sizes_in_use; - int i; - - /* Don't generate the same file twice! */ - if (file_list) { - for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) { - IMB_Proxy_Size proxy_size = proxy_sizes[i]; - if (proxy_size & proxy_sizes_to_build) { - char filename[FILE_MAX]; - get_proxy_filename(anim, proxy_size, filename, false); - - void **filename_key_p; - if (!BLI_gset_ensure_p_ex(file_list, filename, &filename_key_p)) { - *filename_key_p = BLI_strdup(filename); - } - else { - proxy_sizes_to_build &= ~proxy_size; - printf("Proxy: %s already registered for generation, skipping\n", filename); - } - } - } - } - - if (!overwrite) { - IMB_Proxy_Size built_proxies = IMB_anim_proxy_get_existing(anim); - if (built_proxies != 0) { - - for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) { - IMB_Proxy_Size proxy_size = proxy_sizes[i]; - if (proxy_size & built_proxies) { - char filename[FILE_MAX]; - get_proxy_filename(anim, proxy_size, filename, false); - printf("Skipping proxy: %s\n", filename); - } - } - } - proxy_sizes_to_build &= ~built_proxies; - } - - fflush(stdout); - - if (proxy_sizes_to_build == 0) { - return NULL; - } - - - switch (anim->curtype) { + IndexBuildContext *context = NULL; + IMB_Proxy_Size proxy_sizes_to_build = proxy_sizes_in_use; + int i; + + /* Don't generate the same file twice! */ + if (file_list) { + for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) { + IMB_Proxy_Size proxy_size = proxy_sizes[i]; + if (proxy_size & proxy_sizes_to_build) { + char filename[FILE_MAX]; + get_proxy_filename(anim, proxy_size, filename, false); + + void **filename_key_p; + if (!BLI_gset_ensure_p_ex(file_list, filename, &filename_key_p)) { + *filename_key_p = BLI_strdup(filename); + } + else { + proxy_sizes_to_build &= ~proxy_size; + printf("Proxy: %s already registered for generation, skipping\n", filename); + } + } + } + } + + if (!overwrite) { + IMB_Proxy_Size built_proxies = IMB_anim_proxy_get_existing(anim); + if (built_proxies != 0) { + + for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) { + IMB_Proxy_Size proxy_size = proxy_sizes[i]; + if (proxy_size & built_proxies) { + char filename[FILE_MAX]; + get_proxy_filename(anim, proxy_size, filename, false); + printf("Skipping proxy: %s\n", filename); + } + } + } + proxy_sizes_to_build &= ~built_proxies; + } + + fflush(stdout); + + if (proxy_sizes_to_build == 0) { + return NULL; + } + + switch (anim->curtype) { #ifdef WITH_FFMPEG - case ANIM_FFMPEG: - context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality); - break; + case ANIM_FFMPEG: + context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality); + break; #endif #ifdef WITH_AVI - default: - context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality); - break; + default: + context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality); + break; #endif - } + } - if (context) - context->anim_type = anim->curtype; + if (context) + context->anim_type = anim->curtype; - return context; + return context; - UNUSED_VARS(tcs_in_use, proxy_sizes_in_use, quality); + UNUSED_VARS(tcs_in_use, proxy_sizes_in_use, quality); } void IMB_anim_index_rebuild(struct IndexBuildContext *context, - short *stop, short *do_update, float *progress) + short *stop, + short *do_update, + float *progress) { - switch (context->anim_type) { + switch (context->anim_type) { #ifdef WITH_FFMPEG - case ANIM_FFMPEG: - index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress); - break; + case ANIM_FFMPEG: + 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; + default: + index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress); + break; #endif - } + } - UNUSED_VARS(stop, do_update, progress); + UNUSED_VARS(stop, do_update, progress); } void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop) { - switch (context->anim_type) { + switch (context->anim_type) { #ifdef WITH_FFMPEG - case ANIM_FFMPEG: - index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop); - break; + case ANIM_FFMPEG: + index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop); + break; #endif #ifdef WITH_AVI - default: - index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop); - break; + default: + index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop); + break; #endif - } + } - /* static defined at top of the file */ - UNUSED_VARS(stop, proxy_sizes); + /* static defined at top of the file */ + UNUSED_VARS(stop, proxy_sizes); } - void IMB_free_indices(struct anim *anim) { - int i; - - for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { - if (anim->proxy_anim[i]) { - IMB_close_anim(anim->proxy_anim[i]); - anim->proxy_anim[i] = NULL; - } - } - - for (i = 0; i < IMB_TC_MAX_SLOT; i++) { - if (anim->curr_idx[i]) { - IMB_indexer_close(anim->curr_idx[i]); - anim->curr_idx[i] = NULL; - } - } - - - anim->proxies_tried = 0; - anim->indices_tried = 0; + int i; + + for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { + if (anim->proxy_anim[i]) { + IMB_close_anim(anim->proxy_anim[i]); + anim->proxy_anim[i] = NULL; + } + } + + for (i = 0; i < IMB_TC_MAX_SLOT; i++) { + if (anim->curr_idx[i]) { + IMB_indexer_close(anim->curr_idx[i]); + anim->curr_idx[i] = NULL; + } + } + + anim->proxies_tried = 0; + anim->indices_tried = 0; } void IMB_anim_set_index_dir(struct anim *anim, const char *dir) { - if (STREQ(anim->index_dir, dir)) { - return; - } - BLI_strncpy(anim->index_dir, dir, sizeof(anim->index_dir)); + if (STREQ(anim->index_dir, dir)) { + return; + } + BLI_strncpy(anim->index_dir, dir, sizeof(anim->index_dir)); - IMB_free_indices(anim); + IMB_free_indices(anim); } -struct anim *IMB_anim_open_proxy( - struct anim *anim, IMB_Proxy_Size preview_size) +struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size) { - char fname[FILE_MAX]; - int i = IMB_proxy_size_to_array_index(preview_size); + char fname[FILE_MAX]; + int i = IMB_proxy_size_to_array_index(preview_size); - if (anim->proxy_anim[i]) { - return anim->proxy_anim[i]; - } + if (anim->proxy_anim[i]) { + return anim->proxy_anim[i]; + } - if (anim->proxies_tried & preview_size) { - return NULL; - } + if (anim->proxies_tried & preview_size) { + return NULL; + } - get_proxy_filename(anim, preview_size, fname, false); + get_proxy_filename(anim, preview_size, fname, false); - /* proxies are generated in the same color space as animation itself */ - anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, anim->colorspace); + /* proxies are generated in the same color space as animation itself */ + anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, anim->colorspace); - anim->proxies_tried |= preview_size; + anim->proxies_tried |= preview_size; - return anim->proxy_anim[i]; + return anim->proxy_anim[i]; } -struct anim_index *IMB_anim_open_index( - struct anim *anim, IMB_Timecode_Type tc) +struct anim_index *IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc) { - char fname[FILE_MAX]; - int i = IMB_timecode_to_array_index(tc); + char fname[FILE_MAX]; + int i = IMB_timecode_to_array_index(tc); - if (anim->curr_idx[i]) { - return anim->curr_idx[i]; - } + if (anim->curr_idx[i]) { + return anim->curr_idx[i]; + } - if (anim->indices_tried & tc) { - return NULL; - } + if (anim->indices_tried & tc) { + return NULL; + } - get_tc_filename(anim, tc, fname); + get_tc_filename(anim, tc, fname); - anim->curr_idx[i] = IMB_indexer_open(fname); + anim->curr_idx[i] = IMB_indexer_open(fname); - anim->indices_tried |= tc; + anim->indices_tried |= tc; - return anim->curr_idx[i]; + return anim->curr_idx[i]; } -int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, - int position) +int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position) { - struct anim_index *idx = IMB_anim_open_index(anim, tc); + struct anim_index *idx = IMB_anim_open_index(anim, tc); - if (!idx) { - return position; - } + if (!idx) { + return position; + } - return IMB_indexer_get_frame_index(idx, position); + return IMB_indexer_get_frame_index(idx, position); } IMB_Proxy_Size IMB_anim_proxy_get_existing(struct anim *anim) { - const int num_proxy_sizes = IMB_PROXY_MAX_SLOT; - IMB_Proxy_Size existing = 0; - int i; - for (i = 0; i < num_proxy_sizes; ++i) { - IMB_Proxy_Size proxy_size = proxy_sizes[i]; - char filename[FILE_MAX]; - get_proxy_filename(anim, proxy_size, filename, false); - if (BLI_exists(filename)) { - existing |= proxy_size; - } - } - return existing; + const int num_proxy_sizes = IMB_PROXY_MAX_SLOT; + IMB_Proxy_Size existing = 0; + int i; + for (i = 0; i < num_proxy_sizes; ++i) { + IMB_Proxy_Size proxy_size = proxy_sizes[i]; + char filename[FILE_MAX]; + get_proxy_filename(anim, proxy_size, filename, false); + if (BLI_exists(filename)) { + existing |= proxy_size; + } + } + return existing; } diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 5bed5b28b14..ee1a6b57c26 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -21,7 +21,6 @@ * \ingroup imbuf */ - #include #include "BLI_utildefines.h" @@ -40,18 +39,18 @@ #define IMAGIC 0732 typedef struct { - ushort imagic; /* stuff saved on disk . . */ - ushort type; - ushort dim; - ushort xsize; - ushort ysize; - ushort zsize; - uint min; - uint max; - uchar _pad1[4]; - char name[80]; - uint colormap; - uchar _pad2[404]; + ushort imagic; /* stuff saved on disk . . */ + ushort type; + ushort dim; + ushort xsize; + ushort ysize; + ushort zsize; + uint min; + uint max; + uchar _pad1[4]; + char name[80]; + uint colormap; + uchar _pad2[404]; } IMAGE; #define HEADER_SIZE 512 @@ -62,36 +61,44 @@ BLI_STATIC_ASSERT(sizeof(IMAGE) == HEADER_SIZE, "Invalid header size"); #define GINTLUM (156) #define BINTLUM (21) -#define ILUM(r, g, b) ((int)(RINTLUM * (r) + GINTLUM * (g) + BINTLUM * (b)) >> 8) +#define ILUM(r, g, b) ((int)(RINTLUM * (r) + GINTLUM * (g) + BINTLUM * (b)) >> 8) -#define OFFSET_R 0 /* this is byte order dependent */ -#define OFFSET_G 1 -#define OFFSET_B 2 +#define OFFSET_R 0 /* this is byte order dependent */ +#define OFFSET_G 1 +#define OFFSET_B 2 // #define OFFSET_A 3 -#define CHANOFFSET(z) (3 - (z)) /* this is byte order dependent */ +#define CHANOFFSET(z) (3 - (z)) /* this is byte order dependent */ // #define TYPEMASK 0xff00 -#define BPPMASK 0x00ff +#define BPPMASK 0x00ff // #define ITYPE_VERBATIM 0x0000 // UNUSED -#define ITYPE_RLE 0x0100 -#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE) +#define ITYPE_RLE 0x0100 +#define ISRLE(type) (((type)&0xff00) == ITYPE_RLE) // #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM) -#define BPP(type) ((type) & BPPMASK) -#define RLE(bpp) (ITYPE_RLE | (bpp)) +#define BPP(type) ((type)&BPPMASK) +#define RLE(bpp) (ITYPE_RLE | (bpp)) // #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) // UNUSED // #define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2) // UNUSED // #define RLE_NOP 0x00 /* local struct for mem access */ typedef struct MFileOffset { - const uchar *_file_data; - uint _file_offset; + const uchar *_file_data; + uint _file_offset; } MFileOffset; #define MFILE_DATA(inf) ((void)0, ((inf)->_file_data + (inf)->_file_offset)) -#define MFILE_STEP(inf, step) { (inf)->_file_offset += step; } ((void)0) -#define MFILE_SEEK(inf, pos) { (inf)->_file_offset = pos; } ((void)0) +#define MFILE_STEP(inf, step) \ + { \ + (inf)->_file_offset += step; \ + } \ + ((void)0) +#define MFILE_SEEK(inf, pos) \ + { \ + (inf)->_file_offset = pos; \ + } \ + ((void)0) /* error flags */ #define DIRTY_FLAG_EOF (1 << 0) @@ -108,8 +115,10 @@ static int putlong(FILE *outf, uint val); static int writetab(FILE *outf, uint *tab, int len); static void readtab(MFileOffset *inf, uint *tab, int len); -static int expandrow(uchar *optr, const uchar *optr_end, const uchar *iptr, const uchar *iptr_end, int z); -static int expandrow2(float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z); +static int expandrow( + uchar *optr, const uchar *optr_end, const uchar *iptr, const uchar *iptr_end, int z); +static int expandrow2( + float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z); static void interleaverow(uchar *lptr, const uchar *cptr, int z, int n); static void interleaverow2(float *lptr, const uchar *cptr, int z, int n); static int compressrow(uchar *lbuf, uchar *rlebuf, int z, int cnt); @@ -121,107 +130,109 @@ static void lumrow(uchar *rgbptr, uchar *lumptr, int n); static ushort getshort(MFileOffset *inf) { - const uchar *buf; + const uchar *buf; - buf = MFILE_DATA(inf); - MFILE_STEP(inf, 2); + buf = MFILE_DATA(inf); + MFILE_STEP(inf, 2); - return ((ushort)buf[0] << 8) + ((ushort)buf[1] << 0); + return ((ushort)buf[0] << 8) + ((ushort)buf[1] << 0); } static uint getlong(MFileOffset *mofs) { - const uchar *buf; + const uchar *buf; - buf = MFILE_DATA(mofs); - MFILE_STEP(mofs, 4); + buf = MFILE_DATA(mofs); + MFILE_STEP(mofs, 4); - return ((uint)buf[0] << 24) + ((uint)buf[1] << 16) + ((uint)buf[2] << 8) + ((uint)buf[3] << 0); + return ((uint)buf[0] << 24) + ((uint)buf[1] << 16) + ((uint)buf[2] << 8) + ((uint)buf[3] << 0); } static void putshort(FILE *outf, ushort val) { - uchar buf[2]; + uchar buf[2]; - buf[0] = (val >> 8); - buf[1] = (val >> 0); - fwrite(buf, 2, 1, outf); + buf[0] = (val >> 8); + buf[1] = (val >> 0); + fwrite(buf, 2, 1, outf); } static int putlong(FILE *outf, uint val) { - uchar buf[4]; + uchar buf[4]; - buf[0] = (val >> 24); - buf[1] = (val >> 16); - buf[2] = (val >> 8); - buf[3] = (val >> 0); - return fwrite(buf, 4, 1, outf); + buf[0] = (val >> 24); + buf[1] = (val >> 16); + buf[2] = (val >> 8); + buf[3] = (val >> 0); + return fwrite(buf, 4, 1, outf); } static void readheader(MFileOffset *inf, IMAGE *image) { - memset(image, 0, sizeof(IMAGE)); - image->imagic = getshort(inf); - image->type = getshort(inf); - image->dim = getshort(inf); - image->xsize = getshort(inf); - image->ysize = getshort(inf); - image->zsize = getshort(inf); + memset(image, 0, sizeof(IMAGE)); + image->imagic = getshort(inf); + image->type = getshort(inf); + image->dim = getshort(inf); + image->xsize = getshort(inf); + image->ysize = getshort(inf); + image->zsize = getshort(inf); } static int writeheader(FILE *outf, IMAGE *image) { - IMAGE t = {0}; - - fwrite(&t, sizeof(IMAGE), 1, outf); - fseek(outf, 0, SEEK_SET); - putshort(outf, image->imagic); - putshort(outf, image->type); - putshort(outf, image->dim); - putshort(outf, image->xsize); - putshort(outf, image->ysize); - putshort(outf, image->zsize); - putlong(outf, image->min); - putlong(outf, image->max); - putlong(outf, 0); - return fwrite("no name", 8, 1, outf); + IMAGE t = {0}; + + fwrite(&t, sizeof(IMAGE), 1, outf); + fseek(outf, 0, SEEK_SET); + putshort(outf, image->imagic); + putshort(outf, image->type); + putshort(outf, image->dim); + putshort(outf, image->xsize); + putshort(outf, image->ysize); + putshort(outf, image->zsize); + putlong(outf, image->min); + putlong(outf, image->max); + putlong(outf, 0); + return fwrite("no name", 8, 1, outf); } static int writetab(FILE *outf, uint *tab, int len) { - int r = 0; + int r = 0; - while (len) { - r = putlong(outf, *tab++); - len -= 4; - } - return r; + while (len) { + r = putlong(outf, *tab++); + len -= 4; + } + return r; } static void readtab(MFileOffset *inf, uint *tab, int len) { - while (len) { - *tab++ = getlong(inf); - len -= 4; - } + while (len) { + *tab++ = getlong(inf); + len -= 4; + } } static void test_endian_zbuf(struct ImBuf *ibuf) { - int len; - int *zval; + int len; + int *zval; - if (BIG_LONG(1) == 1) return; - if (ibuf->zbuf == NULL) return; + if (BIG_LONG(1) == 1) + return; + if (ibuf->zbuf == NULL) + return; - len = ibuf->x * ibuf->y; - zval = ibuf->zbuf; + len = ibuf->x * ibuf->y; + zval = ibuf->zbuf; - while (len--) { - zval[0] = BIG_LONG(zval[0]); - zval++; - } + while (len--) { + zval[0] = BIG_LONG(zval[0]); + zval++; + } } /* from misc_util: flip the bytes from x */ @@ -232,7 +243,7 @@ static void test_endian_zbuf(struct ImBuf *ibuf) int imb_is_a_iris(const uchar *mem) { - return ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC)); + return ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC)); } /* @@ -243,516 +254,535 @@ int imb_is_a_iris(const uchar *mem) struct ImBuf *imb_loadiris(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { - uint *base, *lptr = NULL; - float *fbase, *fptr = NULL; - uint *zbase, *zptr; - const uchar *rledat; - const uchar *mem_end = mem + size; - MFileOffset _inf_data = {mem, 0}, *inf = &_inf_data; - IMAGE image; - int bpp, rle, cur, badorder; - ImBuf *ibuf = NULL; - uchar dirty_flag = 0; - - if (size < HEADER_SIZE) { - return NULL; - } - - if (!imb_is_a_iris(mem)) { - return NULL; - } - - /* OCIO_TODO: only tested with 1 byte per pixel, not sure how to test with other settings */ - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - readheader(inf, &image); - if (image.imagic != IMAGIC) { - fprintf(stderr, "longimagedata: bad magic number in image file\n"); - return(NULL); - } - - rle = ISRLE(image.type); - bpp = BPP(image.type); - if (bpp != 1 && bpp != 2) { - fprintf(stderr, "longimagedata: image must have 1 or 2 byte per pix chan\n"); - return(NULL); - } - if ((uint)image.zsize > 8) { - fprintf(stderr, "longimagedata: channels over 8 not supported\n"); - return(NULL); - } - - const int xsize = image.xsize; - const int ysize = image.ysize; - const int zsize = image.zsize; - - if (flags & IB_test) { - ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0); - if (ibuf) ibuf->ftype = IMB_FTYPE_IMAGIC; - return(ibuf); - } - - if (rle) { - size_t tablen = (size_t)ysize * (size_t)zsize * sizeof(int); - MFILE_SEEK(inf, HEADER_SIZE); - - uint *starttab = MEM_mallocN(tablen, "iris starttab"); - uint *lengthtab = MEM_mallocN(tablen, "iris endtab"); + uint *base, *lptr = NULL; + float *fbase, *fptr = NULL; + uint *zbase, *zptr; + const uchar *rledat; + const uchar *mem_end = mem + size; + MFileOffset _inf_data = {mem, 0}, *inf = &_inf_data; + IMAGE image; + int bpp, rle, cur, badorder; + ImBuf *ibuf = NULL; + uchar dirty_flag = 0; + + if (size < HEADER_SIZE) { + return NULL; + } + + if (!imb_is_a_iris(mem)) { + return NULL; + } + + /* OCIO_TODO: only tested with 1 byte per pixel, not sure how to test with other settings */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + readheader(inf, &image); + if (image.imagic != IMAGIC) { + fprintf(stderr, "longimagedata: bad magic number in image file\n"); + return (NULL); + } + + rle = ISRLE(image.type); + bpp = BPP(image.type); + if (bpp != 1 && bpp != 2) { + fprintf(stderr, "longimagedata: image must have 1 or 2 byte per pix chan\n"); + return (NULL); + } + if ((uint)image.zsize > 8) { + fprintf(stderr, "longimagedata: channels over 8 not supported\n"); + return (NULL); + } + + const int xsize = image.xsize; + const int ysize = image.ysize; + const int zsize = image.zsize; + + if (flags & IB_test) { + ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0); + if (ibuf) + ibuf->ftype = IMB_FTYPE_IMAGIC; + return (ibuf); + } + + if (rle) { + size_t tablen = (size_t)ysize * (size_t)zsize * sizeof(int); + MFILE_SEEK(inf, HEADER_SIZE); + + uint *starttab = MEM_mallocN(tablen, "iris starttab"); + uint *lengthtab = MEM_mallocN(tablen, "iris endtab"); #define MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(p) \ - if (UNLIKELY((p) > mem_end)) { dirty_flag |= DIRTY_FLAG_EOF; goto fail_rle; } ((void)0) - - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(MFILE_DATA(inf) + ((4 * 2) * tablen)); - - readtab(inf, starttab, tablen); - readtab(inf, lengthtab, tablen); - - /* check data order */ - cur = 0; - badorder = 0; - for (size_t y = 0; y < ysize; y++) { - for (size_t z = 0; z < zsize; z++) { - if (starttab[y + z * ysize] < cur) { - badorder = 1; - break; - } - cur = starttab[y + z * ysize]; - } - if (badorder) - break; - } - - if (bpp == 1) { - - ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect); - if (!ibuf) { - goto fail_rle; - } - if (ibuf->planes > 32) ibuf->planes = 32; - base = ibuf->rect; - zbase = (uint *)ibuf->zbuf; - - if (badorder) { - for (size_t z = 0; z < zsize; z++) { - lptr = base; - for (size_t y = 0; y < ysize; y++) { - MFILE_SEEK(inf, starttab[y + z * ysize]); - rledat = MFILE_DATA(inf); - MFILE_STEP(inf, lengthtab[y + z * ysize]); - const uchar *rledat_next = MFILE_DATA(inf); - uint *lptr_next = lptr + xsize; - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); - dirty_flag |= expandrow((uchar *)lptr, (uchar *)lptr_next, rledat, rledat_next, 3 - z); - lptr = lptr_next; - } - } - } - else { - lptr = base; - zptr = zbase; - for (size_t y = 0; y < ysize; y++) { - - uint *lptr_next = lptr + xsize; - uint *zptr_next = zptr + xsize; - - for (size_t z = 0; z < zsize; z++) { - MFILE_SEEK(inf, starttab[y + z * ysize]); - rledat = MFILE_DATA(inf); - MFILE_STEP(inf, lengthtab[y + z * ysize]); - const uchar *rledat_next = MFILE_DATA(inf); - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); - if (z < 4) { - dirty_flag |= expandrow((uchar *)lptr, (uchar *)lptr_next, rledat, rledat_next, 3 - z); - } - else if (z < 8) { - dirty_flag |= expandrow((uchar *)zptr, (uchar *)zptr_next, rledat, rledat_next, 7 - z); - } - } - lptr = lptr_next; - zptr = zptr_next; - } - } - - - } - else { /* bpp == 2 */ - - ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect) | IB_rectfloat); - if (!ibuf) { - goto fail_rle; - } - - fbase = ibuf->rect_float; - - if (badorder) { - for (size_t z = 0; z < zsize; z++) { - fptr = fbase; - for (size_t y = 0; y < ysize; y++) { - MFILE_SEEK(inf, starttab[y + z * ysize]); - rledat = MFILE_DATA(inf); - MFILE_STEP(inf, lengthtab[y + z * ysize]); - const uchar *rledat_next = MFILE_DATA(inf); - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); - float *fptr_next = fptr + (xsize * 4); - dirty_flag |= expandrow2(fptr, fptr_next, rledat, rledat_next, 3 - z); - fptr = fptr_next; - } - } - } - else { - fptr = fbase; - float *fptr_next = fptr + (xsize * 4); - - for (size_t y = 0; y < ysize; y++) { - - for (size_t z = 0; z < zsize; z++) { - MFILE_SEEK(inf, starttab[y + z * ysize]); - rledat = MFILE_DATA(inf); - MFILE_STEP(inf, lengthtab[y + z * ysize]); - const uchar *rledat_next = MFILE_DATA(inf); - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); - dirty_flag |= expandrow2(fptr, fptr_next, rledat, rledat_next, 3 - z); - } - fptr = fptr_next; - } - } - } + if (UNLIKELY((p) > mem_end)) { \ + dirty_flag |= DIRTY_FLAG_EOF; \ + goto fail_rle; \ + } \ + ((void)0) + + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(MFILE_DATA(inf) + ((4 * 2) * tablen)); + + readtab(inf, starttab, tablen); + readtab(inf, lengthtab, tablen); + + /* check data order */ + cur = 0; + badorder = 0; + for (size_t y = 0; y < ysize; y++) { + for (size_t z = 0; z < zsize; z++) { + if (starttab[y + z * ysize] < cur) { + badorder = 1; + break; + } + cur = starttab[y + z * ysize]; + } + if (badorder) + break; + } + + if (bpp == 1) { + + ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect); + if (!ibuf) { + goto fail_rle; + } + if (ibuf->planes > 32) + ibuf->planes = 32; + base = ibuf->rect; + zbase = (uint *)ibuf->zbuf; + + if (badorder) { + for (size_t z = 0; z < zsize; z++) { + lptr = base; + for (size_t y = 0; y < ysize; y++) { + MFILE_SEEK(inf, starttab[y + z * ysize]); + rledat = MFILE_DATA(inf); + MFILE_STEP(inf, lengthtab[y + z * ysize]); + const uchar *rledat_next = MFILE_DATA(inf); + uint *lptr_next = lptr + xsize; + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); + dirty_flag |= expandrow((uchar *)lptr, (uchar *)lptr_next, rledat, rledat_next, 3 - z); + lptr = lptr_next; + } + } + } + else { + lptr = base; + zptr = zbase; + for (size_t y = 0; y < ysize; y++) { + + uint *lptr_next = lptr + xsize; + uint *zptr_next = zptr + xsize; + + for (size_t z = 0; z < zsize; z++) { + MFILE_SEEK(inf, starttab[y + z * ysize]); + rledat = MFILE_DATA(inf); + MFILE_STEP(inf, lengthtab[y + z * ysize]); + const uchar *rledat_next = MFILE_DATA(inf); + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); + if (z < 4) { + dirty_flag |= expandrow( + (uchar *)lptr, (uchar *)lptr_next, rledat, rledat_next, 3 - z); + } + else if (z < 8) { + dirty_flag |= expandrow( + (uchar *)zptr, (uchar *)zptr_next, rledat, rledat_next, 7 - z); + } + } + lptr = lptr_next; + zptr = zptr_next; + } + } + } + else { /* bpp == 2 */ + + ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect) | IB_rectfloat); + if (!ibuf) { + goto fail_rle; + } + + fbase = ibuf->rect_float; + + if (badorder) { + for (size_t z = 0; z < zsize; z++) { + fptr = fbase; + for (size_t y = 0; y < ysize; y++) { + MFILE_SEEK(inf, starttab[y + z * ysize]); + rledat = MFILE_DATA(inf); + MFILE_STEP(inf, lengthtab[y + z * ysize]); + const uchar *rledat_next = MFILE_DATA(inf); + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); + float *fptr_next = fptr + (xsize * 4); + dirty_flag |= expandrow2(fptr, fptr_next, rledat, rledat_next, 3 - z); + fptr = fptr_next; + } + } + } + else { + fptr = fbase; + float *fptr_next = fptr + (xsize * 4); + + for (size_t y = 0; y < ysize; y++) { + + for (size_t z = 0; z < zsize; z++) { + MFILE_SEEK(inf, starttab[y + z * ysize]); + rledat = MFILE_DATA(inf); + MFILE_STEP(inf, lengthtab[y + z * ysize]); + const uchar *rledat_next = MFILE_DATA(inf); + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next); + dirty_flag |= expandrow2(fptr, fptr_next, rledat, rledat_next, 3 - z); + } + fptr = fptr_next; + } + } + } #undef MFILE_CAPACITY_AT_PTR_OK_OR_FAIL -fail_rle: - MEM_freeN(starttab); - MEM_freeN(lengthtab); + fail_rle: + MEM_freeN(starttab); + MEM_freeN(lengthtab); - if (!ibuf) { - return NULL; - } - } - else { + if (!ibuf) { + return NULL; + } + } + else { #define MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(p) \ - if (UNLIKELY((p) > mem_end)) { dirty_flag |= DIRTY_FLAG_EOF; goto fail_uncompressed; } ((void)0) - - if (bpp == 1) { - - ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect); - if (!ibuf) { - goto fail_uncompressed; - } - if (ibuf->planes > 32) ibuf->planes = 32; - - base = ibuf->rect; - zbase = (uint *)ibuf->zbuf; - - MFILE_SEEK(inf, HEADER_SIZE); - rledat = MFILE_DATA(inf); - - for (size_t z = 0; z < zsize; z++) { - - if (z < 4) lptr = base; - else if (z < 8) lptr = zbase; - - for (size_t y = 0; y < ysize; y++) { - const uchar *rledat_next = rledat + xsize; - const int z_ofs = 3 - z; - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next + z_ofs); - interleaverow((uchar *)lptr, rledat, z_ofs, xsize); - rledat = rledat_next; - lptr += xsize; - } - } - - } - else { /* bpp == 2 */ - - ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect) | IB_rectfloat); - if (!ibuf) { - goto fail_uncompressed; - } - - fbase = ibuf->rect_float; - - MFILE_SEEK(inf, HEADER_SIZE); - rledat = MFILE_DATA(inf); - - for (size_t z = 0; z < zsize; z++) { - - fptr = fbase; - - for (size_t y = 0; y < ysize; y++) { - const uchar *rledat_next = rledat + xsize * 2; - const int z_ofs = 3 - z; - MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next + z_ofs); - interleaverow2(fptr, rledat, z_ofs, xsize); - rledat = rledat_next; - fptr += xsize * 4; - } - } - - } + if (UNLIKELY((p) > mem_end)) { \ + dirty_flag |= DIRTY_FLAG_EOF; \ + goto fail_uncompressed; \ + } \ + ((void)0) + + if (bpp == 1) { + + ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect); + if (!ibuf) { + goto fail_uncompressed; + } + if (ibuf->planes > 32) + ibuf->planes = 32; + + base = ibuf->rect; + zbase = (uint *)ibuf->zbuf; + + MFILE_SEEK(inf, HEADER_SIZE); + rledat = MFILE_DATA(inf); + + for (size_t z = 0; z < zsize; z++) { + + if (z < 4) + lptr = base; + else if (z < 8) + lptr = zbase; + + for (size_t y = 0; y < ysize; y++) { + const uchar *rledat_next = rledat + xsize; + const int z_ofs = 3 - z; + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next + z_ofs); + interleaverow((uchar *)lptr, rledat, z_ofs, xsize); + rledat = rledat_next; + lptr += xsize; + } + } + } + else { /* bpp == 2 */ + + ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect) | IB_rectfloat); + if (!ibuf) { + goto fail_uncompressed; + } + + fbase = ibuf->rect_float; + + MFILE_SEEK(inf, HEADER_SIZE); + rledat = MFILE_DATA(inf); + + for (size_t z = 0; z < zsize; z++) { + + fptr = fbase; + + for (size_t y = 0; y < ysize; y++) { + const uchar *rledat_next = rledat + xsize * 2; + const int z_ofs = 3 - z; + MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next + z_ofs); + interleaverow2(fptr, rledat, z_ofs, xsize); + rledat = rledat_next; + fptr += xsize * 4; + } + } + } #undef MFILE_CAPACITY_AT_PTR_OK_OR_FAIL -fail_uncompressed: - if (!ibuf) { - return NULL; - } - } - - if (bpp == 1) { - uchar *rect; - - if (image.zsize == 1) { - rect = (uchar *) ibuf->rect; - for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { - rect[0] = 255; - rect[1] = rect[2] = rect[3]; - rect += 4; - } - } - else if (image.zsize == 2) { - /* grayscale with alpha */ - rect = (uchar *) ibuf->rect; - for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { - rect[0] = rect[2]; - rect[1] = rect[2] = rect[3]; - rect += 4; - } - } - else if (image.zsize == 3) { - /* add alpha */ - rect = (uchar *) ibuf->rect; - for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { - rect[0] = 255; - rect += 4; - } - } - - } - else { /* bpp == 2 */ - - if (image.zsize == 1) { - fbase = ibuf->rect_float; - for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { - fbase[0] = 1; - fbase[1] = fbase[2] = fbase[3]; - fbase += 4; - } - } - else if (image.zsize == 2) { - /* grayscale with alpha */ - fbase = ibuf->rect_float; - for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { - fbase[0] = fbase[2]; - fbase[1] = fbase[2] = fbase[3]; - fbase += 4; - } - } - else if (image.zsize == 3) { - /* add alpha */ - fbase = ibuf->rect_float; - for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { - fbase[0] = 1; - fbase += 4; - } - } - - if (flags & IB_rect) { - IMB_rect_from_float(ibuf); - } - - } - - if (dirty_flag) { - fprintf(stderr, "longimagedata: corrupt file content (%d)\n", dirty_flag); - } - ibuf->ftype = IMB_FTYPE_IMAGIC; - - test_endian_zbuf(ibuf); - - if (ibuf->rect) { - IMB_convert_rgba_to_abgr(ibuf); - } - - return(ibuf); + fail_uncompressed: + if (!ibuf) { + return NULL; + } + } + + if (bpp == 1) { + uchar *rect; + + if (image.zsize == 1) { + rect = (uchar *)ibuf->rect; + for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { + rect[0] = 255; + rect[1] = rect[2] = rect[3]; + rect += 4; + } + } + else if (image.zsize == 2) { + /* grayscale with alpha */ + rect = (uchar *)ibuf->rect; + for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { + rect[0] = rect[2]; + rect[1] = rect[2] = rect[3]; + rect += 4; + } + } + else if (image.zsize == 3) { + /* add alpha */ + rect = (uchar *)ibuf->rect; + for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { + rect[0] = 255; + rect += 4; + } + } + } + else { /* bpp == 2 */ + + if (image.zsize == 1) { + fbase = ibuf->rect_float; + for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { + fbase[0] = 1; + fbase[1] = fbase[2] = fbase[3]; + fbase += 4; + } + } + else if (image.zsize == 2) { + /* grayscale with alpha */ + fbase = ibuf->rect_float; + for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { + fbase[0] = fbase[2]; + fbase[1] = fbase[2] = fbase[3]; + fbase += 4; + } + } + else if (image.zsize == 3) { + /* add alpha */ + fbase = ibuf->rect_float; + for (size_t x = (size_t)ibuf->x * (size_t)ibuf->y; x > 0; x--) { + fbase[0] = 1; + fbase += 4; + } + } + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } + } + + if (dirty_flag) { + fprintf(stderr, "longimagedata: corrupt file content (%d)\n", dirty_flag); + } + ibuf->ftype = IMB_FTYPE_IMAGIC; + + test_endian_zbuf(ibuf); + + if (ibuf->rect) { + IMB_convert_rgba_to_abgr(ibuf); + } + + return (ibuf); } /* static utility functions for longimagedata */ static void interleaverow(uchar *lptr, const uchar *cptr, int z, int n) { - lptr += z; - while (n--) { - *lptr = *cptr++; - lptr += 4; - } + lptr += z; + while (n--) { + *lptr = *cptr++; + lptr += 4; + } } static void interleaverow2(float *lptr, const uchar *cptr, int z, int n) { - lptr += z; - while (n--) { - *lptr = ((cptr[0] << 8) | (cptr[1] << 0)) / (float)0xFFFF; - cptr += 2; - lptr += 4; - } + lptr += z; + while (n--) { + *lptr = ((cptr[0] << 8) | (cptr[1] << 0)) / (float)0xFFFF; + cptr += 2; + lptr += 4; + } } static int expandrow2( - float *optr, const float *optr_end, - const uchar *iptr, const uchar *iptr_end, int z) + float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z) { - ushort pixel, count; - float pixel_f; + ushort pixel, count; + float pixel_f; #define EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next) \ - if (UNLIKELY(iptr_next > iptr_end)) { goto fail; } ((void)0) + if (UNLIKELY(iptr_next > iptr_end)) { \ + goto fail; \ + } \ + ((void)0) #define EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next) \ - if (UNLIKELY(optr_next > optr_end)) { goto fail; } ((void)0) - - optr += z; - optr_end += z; - while (1) { - const uchar *iptr_next = iptr + 2; - EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); - pixel = (iptr[0] << 8) | (iptr[1] << 0); - iptr = iptr_next; - - if (!(count = (pixel & 0x7f)) ) - return false; - const float *optr_next = optr + count; - EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next); - if (pixel & 0x80) { - iptr_next = iptr + (count * 2); - EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); - while (count >= 8) { - optr[0 * 4] = ((iptr[0] << 8) | (iptr[1] << 0)) / (float)0xFFFF; - optr[1 * 4] = ((iptr[2] << 8) | (iptr[3] << 0)) / (float)0xFFFF; - optr[2 * 4] = ((iptr[4] << 8) | (iptr[5] << 0)) / (float)0xFFFF; - optr[3 * 4] = ((iptr[6] << 8) | (iptr[7] << 0)) / (float)0xFFFF; - optr[4 * 4] = ((iptr[8] << 8) | (iptr[9] << 0)) / (float)0xFFFF; - optr[5 * 4] = ((iptr[10] << 8) | (iptr[11] << 0)) / (float)0xFFFF; - optr[6 * 4] = ((iptr[12] << 8) | (iptr[13] << 0)) / (float)0xFFFF; - optr[7 * 4] = ((iptr[14] << 8) | (iptr[15] << 0)) / (float)0xFFFF; - optr += 8 * 4; - iptr += 8 * 2; - count -= 8; - } - while (count--) { - *optr = ((iptr[0] << 8) | (iptr[1] << 0)) / (float)0xFFFF; - iptr += 2; - optr += 4; - } - BLI_assert(iptr == iptr_next); - } - else { - iptr_next = iptr + 2; - EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); - pixel_f = ((iptr[0] << 8) | (iptr[1] << 0)) / (float)0xFFFF; - iptr = iptr_next; - - while (count >= 8) { - optr[0 * 4] = pixel_f; - optr[1 * 4] = pixel_f; - optr[2 * 4] = pixel_f; - optr[3 * 4] = pixel_f; - optr[4 * 4] = pixel_f; - optr[5 * 4] = pixel_f; - optr[6 * 4] = pixel_f; - optr[7 * 4] = pixel_f; - optr += 8 * 4; - count -= 8; - } - while (count--) { - *optr = pixel_f; - optr += 4; - } - BLI_assert(iptr == iptr_next); - } - BLI_assert(optr == optr_next); - } - return false; + if (UNLIKELY(optr_next > optr_end)) { \ + goto fail; \ + } \ + ((void)0) + + optr += z; + optr_end += z; + while (1) { + const uchar *iptr_next = iptr + 2; + EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); + pixel = (iptr[0] << 8) | (iptr[1] << 0); + iptr = iptr_next; + + if (!(count = (pixel & 0x7f))) + return false; + const float *optr_next = optr + count; + EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next); + if (pixel & 0x80) { + iptr_next = iptr + (count * 2); + EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); + while (count >= 8) { + optr[0 * 4] = ((iptr[0] << 8) | (iptr[1] << 0)) / (float)0xFFFF; + optr[1 * 4] = ((iptr[2] << 8) | (iptr[3] << 0)) / (float)0xFFFF; + optr[2 * 4] = ((iptr[4] << 8) | (iptr[5] << 0)) / (float)0xFFFF; + optr[3 * 4] = ((iptr[6] << 8) | (iptr[7] << 0)) / (float)0xFFFF; + optr[4 * 4] = ((iptr[8] << 8) | (iptr[9] << 0)) / (float)0xFFFF; + optr[5 * 4] = ((iptr[10] << 8) | (iptr[11] << 0)) / (float)0xFFFF; + optr[6 * 4] = ((iptr[12] << 8) | (iptr[13] << 0)) / (float)0xFFFF; + optr[7 * 4] = ((iptr[14] << 8) | (iptr[15] << 0)) / (float)0xFFFF; + optr += 8 * 4; + iptr += 8 * 2; + count -= 8; + } + while (count--) { + *optr = ((iptr[0] << 8) | (iptr[1] << 0)) / (float)0xFFFF; + iptr += 2; + optr += 4; + } + BLI_assert(iptr == iptr_next); + } + else { + iptr_next = iptr + 2; + EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); + pixel_f = ((iptr[0] << 8) | (iptr[1] << 0)) / (float)0xFFFF; + iptr = iptr_next; + + while (count >= 8) { + optr[0 * 4] = pixel_f; + optr[1 * 4] = pixel_f; + optr[2 * 4] = pixel_f; + optr[3 * 4] = pixel_f; + optr[4 * 4] = pixel_f; + optr[5 * 4] = pixel_f; + optr[6 * 4] = pixel_f; + optr[7 * 4] = pixel_f; + optr += 8 * 4; + count -= 8; + } + while (count--) { + *optr = pixel_f; + optr += 4; + } + BLI_assert(iptr == iptr_next); + } + BLI_assert(optr == optr_next); + } + return false; #undef EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL #undef EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL fail: - return DIRTY_FLAG_ENCODING; + return DIRTY_FLAG_ENCODING; } static int expandrow( - uchar *optr, const uchar *optr_end, - const uchar *iptr, const uchar *iptr_end, int z) + uchar *optr, const uchar *optr_end, const uchar *iptr, const uchar *iptr_end, int z) { - uchar pixel, count; + uchar pixel, count; #define EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next) \ - if (UNLIKELY(iptr_next > iptr_end)) { goto fail; } ((void)0) + if (UNLIKELY(iptr_next > iptr_end)) { \ + goto fail; \ + } \ + ((void)0) #define EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next) \ - if (UNLIKELY(optr_next > optr_end)) { goto fail; } ((void)0) - - optr += z; - optr_end += z; - while (1) { - const uchar *iptr_next = iptr + 1; - EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); - pixel = *iptr; - iptr = iptr_next; - if (!(count = (pixel & 0x7f)) ) - return false; - const uchar *optr_next = optr + ((int)count * 4); - EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next); - - if (pixel & 0x80) { - iptr_next = iptr + count; - EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); - while (count >= 8) { - optr[0 * 4] = iptr[0]; - optr[1 * 4] = iptr[1]; - optr[2 * 4] = iptr[2]; - optr[3 * 4] = iptr[3]; - optr[4 * 4] = iptr[4]; - optr[5 * 4] = iptr[5]; - optr[6 * 4] = iptr[6]; - optr[7 * 4] = iptr[7]; - optr += 8 * 4; - iptr += 8; - count -= 8; - } - while (count--) { - *optr = *iptr++; - optr += 4; - } - BLI_assert(iptr == iptr_next); - } - else { - iptr_next = iptr + 1; - EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); - pixel = *iptr++; - while (count >= 8) { - optr[0 * 4] = pixel; - optr[1 * 4] = pixel; - optr[2 * 4] = pixel; - optr[3 * 4] = pixel; - optr[4 * 4] = pixel; - optr[5 * 4] = pixel; - optr[6 * 4] = pixel; - optr[7 * 4] = pixel; - optr += 8 * 4; - count -= 8; - } - while (count--) { - *optr = pixel; - optr += 4; - } - BLI_assert(iptr == iptr_next); - } - BLI_assert(optr == optr_next); - } - - return false; + if (UNLIKELY(optr_next > optr_end)) { \ + goto fail; \ + } \ + ((void)0) + + optr += z; + optr_end += z; + while (1) { + const uchar *iptr_next = iptr + 1; + EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); + pixel = *iptr; + iptr = iptr_next; + if (!(count = (pixel & 0x7f))) + return false; + const uchar *optr_next = optr + ((int)count * 4); + EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next); + + if (pixel & 0x80) { + iptr_next = iptr + count; + EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); + while (count >= 8) { + optr[0 * 4] = iptr[0]; + optr[1 * 4] = iptr[1]; + optr[2 * 4] = iptr[2]; + optr[3 * 4] = iptr[3]; + optr[4 * 4] = iptr[4]; + optr[5 * 4] = iptr[5]; + optr[6 * 4] = iptr[6]; + optr[7 * 4] = iptr[7]; + optr += 8 * 4; + iptr += 8; + count -= 8; + } + while (count--) { + *optr = *iptr++; + optr += 4; + } + BLI_assert(iptr == iptr_next); + } + else { + iptr_next = iptr + 1; + EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next); + pixel = *iptr++; + while (count >= 8) { + optr[0 * 4] = pixel; + optr[1 * 4] = pixel; + optr[2 * 4] = pixel; + optr[3 * 4] = pixel; + optr[4 * 4] = pixel; + optr[5 * 4] = pixel; + optr[6 * 4] = pixel; + optr[7 * 4] = pixel; + optr += 8 * 4; + count -= 8; + } + while (count--) { + *optr = pixel; + optr += 4; + } + BLI_assert(iptr == iptr_next); + } + BLI_assert(optr == optr_next); + } + + return false; #undef EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL #undef EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL fail: - return DIRTY_FLAG_ENCODING; + return DIRTY_FLAG_ENCODING; } /** @@ -769,174 +799,177 @@ fail: static int output_iris(uint *lptr, int xsize, int ysize, int zsize, const char *name, int *zptr) { - FILE *outf; - IMAGE *image; - int tablen, y, z, pos, len = 0; - uint *starttab, *lengthtab; - uchar *rlebuf; - uint *lumbuf; - int rlebuflen, goodwrite; - - goodwrite = 1; - outf = BLI_fopen(name, "wb"); - if (!outf) return 0; - - tablen = ysize * zsize * sizeof(int); - - image = (IMAGE *)MEM_mallocN(sizeof(IMAGE), "iris image"); - starttab = (uint *)MEM_mallocN(tablen, "iris starttab"); - lengthtab = (uint *)MEM_mallocN(tablen, "iris lengthtab"); - rlebuflen = 1.05 * xsize + 10; - rlebuf = (uchar *)MEM_mallocN(rlebuflen, "iris rlebuf"); - lumbuf = (uint *)MEM_mallocN(xsize * sizeof(int), "iris lumbuf"); - - memset(image, 0, sizeof(IMAGE)); - image->imagic = IMAGIC; - image->type = RLE(1); - if (zsize > 1) - image->dim = 3; - else - image->dim = 2; - image->xsize = xsize; - image->ysize = ysize; - image->zsize = zsize; - image->min = 0; - image->max = 255; - goodwrite *= writeheader(outf, image); - fseek(outf, HEADER_SIZE + (2 * tablen), SEEK_SET); - pos = HEADER_SIZE + (2 * tablen); - - for (y = 0; y < ysize; y++) { - for (z = 0; z < zsize; z++) { - - if (zsize == 1) { - lumrow((uchar *)lptr, (uchar *)lumbuf, xsize); - len = compressrow((uchar *)lumbuf, rlebuf, CHANOFFSET(z), xsize); - } - else { - if (z < 4) { - len = compressrow((uchar *)lptr, rlebuf, CHANOFFSET(z), xsize); - } - else if (z < 8 && zptr) { - len = compressrow((uchar *)zptr, rlebuf, CHANOFFSET(z - 4), xsize); - } - } - if (len > rlebuflen) { - fprintf(stderr, "output_iris: rlebuf is too small - bad poop\n"); - exit(1); - } - goodwrite *= fwrite(rlebuf, len, 1, outf); - starttab[y + z * ysize] = pos; - lengthtab[y + z * ysize] = len; - pos += len; - } - lptr += xsize; - if (zptr) zptr += xsize; - } - - fseek(outf, HEADER_SIZE, SEEK_SET); - goodwrite *= writetab(outf, starttab, tablen); - goodwrite *= writetab(outf, lengthtab, tablen); - MEM_freeN(image); - MEM_freeN(starttab); - MEM_freeN(lengthtab); - MEM_freeN(rlebuf); - MEM_freeN(lumbuf); - fclose(outf); - if (goodwrite) - return 1; - else { - fprintf(stderr, "output_iris: not enough space for image!!\n"); - return 0; - } + FILE *outf; + IMAGE *image; + int tablen, y, z, pos, len = 0; + uint *starttab, *lengthtab; + uchar *rlebuf; + uint *lumbuf; + int rlebuflen, goodwrite; + + goodwrite = 1; + outf = BLI_fopen(name, "wb"); + if (!outf) + return 0; + + tablen = ysize * zsize * sizeof(int); + + image = (IMAGE *)MEM_mallocN(sizeof(IMAGE), "iris image"); + starttab = (uint *)MEM_mallocN(tablen, "iris starttab"); + lengthtab = (uint *)MEM_mallocN(tablen, "iris lengthtab"); + rlebuflen = 1.05 * xsize + 10; + rlebuf = (uchar *)MEM_mallocN(rlebuflen, "iris rlebuf"); + lumbuf = (uint *)MEM_mallocN(xsize * sizeof(int), "iris lumbuf"); + + memset(image, 0, sizeof(IMAGE)); + image->imagic = IMAGIC; + image->type = RLE(1); + if (zsize > 1) + image->dim = 3; + else + image->dim = 2; + image->xsize = xsize; + image->ysize = ysize; + image->zsize = zsize; + image->min = 0; + image->max = 255; + goodwrite *= writeheader(outf, image); + fseek(outf, HEADER_SIZE + (2 * tablen), SEEK_SET); + pos = HEADER_SIZE + (2 * tablen); + + for (y = 0; y < ysize; y++) { + for (z = 0; z < zsize; z++) { + + if (zsize == 1) { + lumrow((uchar *)lptr, (uchar *)lumbuf, xsize); + len = compressrow((uchar *)lumbuf, rlebuf, CHANOFFSET(z), xsize); + } + else { + if (z < 4) { + len = compressrow((uchar *)lptr, rlebuf, CHANOFFSET(z), xsize); + } + else if (z < 8 && zptr) { + len = compressrow((uchar *)zptr, rlebuf, CHANOFFSET(z - 4), xsize); + } + } + if (len > rlebuflen) { + fprintf(stderr, "output_iris: rlebuf is too small - bad poop\n"); + exit(1); + } + goodwrite *= fwrite(rlebuf, len, 1, outf); + starttab[y + z * ysize] = pos; + lengthtab[y + z * ysize] = len; + pos += len; + } + lptr += xsize; + if (zptr) + zptr += xsize; + } + + fseek(outf, HEADER_SIZE, SEEK_SET); + goodwrite *= writetab(outf, starttab, tablen); + goodwrite *= writetab(outf, lengthtab, tablen); + MEM_freeN(image); + MEM_freeN(starttab); + MEM_freeN(lengthtab); + MEM_freeN(rlebuf); + MEM_freeN(lumbuf); + fclose(outf); + if (goodwrite) + return 1; + else { + fprintf(stderr, "output_iris: not enough space for image!!\n"); + return 0; + } } /* static utility functions for output_iris */ static void lumrow(uchar *rgbptr, uchar *lumptr, int n) { - lumptr += CHANOFFSET(0); - while (n--) { - *lumptr = ILUM(rgbptr[OFFSET_R], rgbptr[OFFSET_G], rgbptr[OFFSET_B]); - lumptr += 4; - rgbptr += 4; - } + lumptr += CHANOFFSET(0); + while (n--) { + *lumptr = ILUM(rgbptr[OFFSET_R], rgbptr[OFFSET_G], rgbptr[OFFSET_B]); + lumptr += 4; + rgbptr += 4; + } } static int compressrow(uchar *lbuf, uchar *rlebuf, int z, int cnt) { - uchar *iptr, *ibufend, *sptr, *optr; - short todo, cc; - int count; - - lbuf += z; - iptr = lbuf; - ibufend = iptr + cnt * 4; - optr = rlebuf; - - while (iptr < ibufend) { - sptr = iptr; - iptr += 8; - while ((iptr < ibufend) && ((iptr[-8] != iptr[-4]) || (iptr[-4] != iptr[0]))) - iptr += 4; - iptr -= 8; - count = (iptr - sptr) / 4; - while (count) { - todo = count > 126 ? 126 : count; - count -= todo; - *optr++ = 0x80 | todo; - while (todo > 8) { - optr[0] = sptr[0 * 4]; - optr[1] = sptr[1 * 4]; - optr[2] = sptr[2 * 4]; - optr[3] = sptr[3 * 4]; - optr[4] = sptr[4 * 4]; - optr[5] = sptr[5 * 4]; - optr[6] = sptr[6 * 4]; - optr[7] = sptr[7 * 4]; - - optr += 8; - sptr += 8 * 4; - todo -= 8; - } - while (todo--) { - *optr++ = *sptr; - sptr += 4; - } - } - sptr = iptr; - cc = *iptr; - iptr += 4; - while ( (iptr < ibufend) && (*iptr == cc) ) - iptr += 4; - count = (iptr - sptr) / 4; - while (count) { - todo = count > 126 ? 126 : count; - count -= todo; - *optr++ = todo; - *optr++ = cc; - } - } - *optr++ = 0; - return optr - (uchar *)rlebuf; + uchar *iptr, *ibufend, *sptr, *optr; + short todo, cc; + int count; + + lbuf += z; + iptr = lbuf; + ibufend = iptr + cnt * 4; + optr = rlebuf; + + while (iptr < ibufend) { + sptr = iptr; + iptr += 8; + while ((iptr < ibufend) && ((iptr[-8] != iptr[-4]) || (iptr[-4] != iptr[0]))) + iptr += 4; + iptr -= 8; + count = (iptr - sptr) / 4; + while (count) { + todo = count > 126 ? 126 : count; + count -= todo; + *optr++ = 0x80 | todo; + while (todo > 8) { + optr[0] = sptr[0 * 4]; + optr[1] = sptr[1 * 4]; + optr[2] = sptr[2 * 4]; + optr[3] = sptr[3 * 4]; + optr[4] = sptr[4 * 4]; + optr[5] = sptr[5 * 4]; + optr[6] = sptr[6 * 4]; + optr[7] = sptr[7 * 4]; + + optr += 8; + sptr += 8 * 4; + todo -= 8; + } + while (todo--) { + *optr++ = *sptr; + sptr += 4; + } + } + sptr = iptr; + cc = *iptr; + iptr += 4; + while ((iptr < ibufend) && (*iptr == cc)) + iptr += 4; + count = (iptr - sptr) / 4; + while (count) { + todo = count > 126 ? 126 : count; + count -= todo; + *optr++ = todo; + *optr++ = cc; + } + } + *optr++ = 0; + return optr - (uchar *)rlebuf; } int imb_saveiris(struct ImBuf *ibuf, const char *name, int flags) { - short zsize; - int ret; + short zsize; + int ret; - zsize = (ibuf->planes + 7) >> 3; - if (flags & IB_zbuf && ibuf->zbuf != NULL) zsize = 8; + zsize = (ibuf->planes + 7) >> 3; + if (flags & IB_zbuf && ibuf->zbuf != NULL) + zsize = 8; - IMB_convert_rgba_to_abgr(ibuf); - test_endian_zbuf(ibuf); + IMB_convert_rgba_to_abgr(ibuf); + test_endian_zbuf(ibuf); - ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, name, ibuf->zbuf); + ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, name, ibuf->zbuf); - /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */ - IMB_convert_rgba_to_abgr(ibuf); - test_endian_zbuf(ibuf); + /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */ + IMB_convert_rgba_to_abgr(ibuf); + test_endian_zbuf(ibuf); - return(ret); + return (ret); } diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index aaeb4e4c2ad..4863da8ab18 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -34,55 +34,56 @@ #define JP2_FILEHEADER_SIZE 12 -static const char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; +static const char JP2_HEAD[] = { + 0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; static const char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00}; /* We only need this because of how the presets are set */ /* this typedef is copied from 'openjpeg-1.5.0/applications/codec/image_to_j2k.c' */ typedef struct img_folder { - /** The directory path of the folder containing input images*/ - char *imgdirpath; - /** Output format*/ - char *out_format; - /** Enable option*/ - char set_imgdir; - /** Enable Cod Format for output*/ - char set_out_format; - /** User specified rate stored in case of cinema option*/ - float *rates; + /** The directory path of the folder containing input images*/ + char *imgdirpath; + /** Output format*/ + char *out_format; + /** Enable option*/ + char set_imgdir; + /** Enable Cod Format for output*/ + char set_out_format; + /** User specified rate stored in case of cinema option*/ + float *rates; } img_fol_t; enum { - DCP_CINEMA2K = 3, - DCP_CINEMA4K = 4, + DCP_CINEMA2K = 3, + DCP_CINEMA4K = 4, }; static bool check_jp2(const unsigned char *mem) /* J2K_CFMT */ { - return memcmp(JP2_HEAD, mem, sizeof(JP2_HEAD)) ? 0 : 1; + return memcmp(JP2_HEAD, mem, sizeof(JP2_HEAD)) ? 0 : 1; } static bool check_j2k(const unsigned char *mem) /* J2K_CFMT */ { - return memcmp(J2K_HEAD, mem, sizeof(J2K_HEAD)) ? 0 : 1; + return memcmp(J2K_HEAD, mem, sizeof(J2K_HEAD)) ? 0 : 1; } static OPJ_CODEC_FORMAT format_from_header(const unsigned char mem[JP2_FILEHEADER_SIZE]) { - if (check_jp2(mem)) { - return OPJ_CODEC_JP2; - } - else if (check_j2k(mem)) { - return OPJ_CODEC_J2K; - } - else { - return OPJ_CODEC_UNKNOWN; - } + if (check_jp2(mem)) { + return OPJ_CODEC_JP2; + } + else if (check_j2k(mem)) { + return OPJ_CODEC_J2K; + } + else { + return OPJ_CODEC_UNKNOWN; + } } int imb_is_a_jp2(const unsigned char *buf) { - return check_jp2(buf); + return check_jp2(buf); } /** @@ -90,16 +91,16 @@ int imb_is_a_jp2(const unsigned char *buf) */ static void error_callback(const char *msg, void *client_data) { - FILE *stream = (FILE *)client_data; - fprintf(stream, "[ERROR] %s", msg); + FILE *stream = (FILE *)client_data; + fprintf(stream, "[ERROR] %s", msg); } /** * sample warning callback expecting a FILE* client object */ static void warning_callback(const char *msg, void *client_data) { - FILE *stream = (FILE *)client_data; - fprintf(stream, "[WARNING] %s", msg); + FILE *stream = (FILE *)client_data; + fprintf(stream, "[WARNING] %s", msg); } #ifdef DEBUG @@ -108,92 +109,86 @@ static void warning_callback(const char *msg, void *client_data) */ static void info_callback(const char *msg, void *client_data) { - FILE *stream = (FILE *)client_data; - fprintf(stream, "[INFO] %s", msg); + FILE *stream = (FILE *)client_data; + fprintf(stream, "[INFO] %s", msg); } #endif -#define PIXEL_LOOPER_BEGIN(_rect) \ - for (y = h - 1; y != (unsigned int)(-1); y--) { \ - for (i = y * w, i_next = (y + 1) * w; \ - i < i_next; \ - i++, _rect += 4) \ - { \ +#define PIXEL_LOOPER_BEGIN(_rect) \ + for (y = h - 1; y != (unsigned int)(-1); y--) { \ + for (i = y * w, i_next = (y + 1) * w; i < i_next; i++, _rect += 4) { -#define PIXEL_LOOPER_BEGIN_CHANNELS(_rect, _channels) \ - for (y = h - 1; y != (unsigned int)(-1); y--) { \ - for (i = y * w, i_next = (y + 1) * w; \ - i < i_next; \ - i++, _rect += _channels) \ - { \ +#define PIXEL_LOOPER_BEGIN_CHANNELS(_rect, _channels) \ + for (y = h - 1; y != (unsigned int)(-1); y--) { \ + for (i = y * w, i_next = (y + 1) * w; i < i_next; i++, _rect += _channels) { #define PIXEL_LOOPER_END \ - } \ -} (void)0 \ - + } \ + } \ + (void)0 /** \name Buffer Stream * \{ */ struct BufInfo { - const unsigned char *buf; - const unsigned char *cur; - OPJ_OFF_T len; + const unsigned char *buf; + const unsigned char *cur; + OPJ_OFF_T len; }; static void opj_read_from_buffer_free(void *UNUSED(p_user_data)) { - /* nop */ + /* nop */ } static OPJ_SIZE_T opj_read_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { - struct BufInfo *p_file = p_user_data; - OPJ_UINT32 l_nb_read; - - if (p_file->cur + p_nb_bytes < p_file->buf + p_file->len ) { - l_nb_read = p_nb_bytes; - } - else { - l_nb_read = (OPJ_UINT32)(p_file->buf + p_file->len - p_file->cur); - } - memcpy(p_buffer, p_file->cur, l_nb_read); - p_file->cur += l_nb_read; - - return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1); + struct BufInfo *p_file = p_user_data; + OPJ_UINT32 l_nb_read; + + if (p_file->cur + p_nb_bytes < p_file->buf + p_file->len) { + l_nb_read = p_nb_bytes; + } + else { + l_nb_read = (OPJ_UINT32)(p_file->buf + p_file->len - p_file->cur); + } + memcpy(p_buffer, p_file->cur, l_nb_read); + p_file->cur += l_nb_read; + + return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1); } #if 0 static OPJ_SIZE_T opj_write_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { - struct BufInfo *p_file = p_user_data; - memcpy(p_file->cur, p_buffer, p_nb_bytes); - p_file->cur += p_nb_bytes; - p_file->len += p_nb_bytes; - return p_nb_bytes; + struct BufInfo *p_file = p_user_data; + memcpy(p_file->cur, p_buffer, p_nb_bytes); + p_file->cur += p_nb_bytes; + p_file->len += p_nb_bytes; + return p_nb_bytes; } #endif static OPJ_OFF_T opj_skip_from_buffer(OPJ_OFF_T p_nb_bytes, void *p_user_data) { - struct BufInfo *p_file = p_user_data; - if (p_file->cur + p_nb_bytes < p_file->buf + p_file->len) { - p_file->cur += p_nb_bytes; - return p_nb_bytes; - } - p_file->cur = p_file->buf + p_file->len; - return (OPJ_OFF_T)-1; + struct BufInfo *p_file = p_user_data; + if (p_file->cur + p_nb_bytes < p_file->buf + p_file->len) { + p_file->cur += p_nb_bytes; + return p_nb_bytes; + } + p_file->cur = p_file->buf + p_file->len; + return (OPJ_OFF_T)-1; } static OPJ_BOOL opj_seek_from_buffer(OPJ_OFF_T p_nb_bytes, void *p_user_data) { - struct BufInfo *p_file = p_user_data; - if (p_nb_bytes < p_file->len) { - p_file->cur = p_file->buf + p_nb_bytes; - return OPJ_TRUE; - } - p_file->cur = p_file->buf + p_file->len; - return OPJ_FALSE; + struct BufInfo *p_file = p_user_data; + if (p_nb_bytes < p_file->len) { + p_file->cur = p_file->buf + p_nb_bytes; + return OPJ_TRUE; + } + p_file->cur = p_file->buf + p_file->len; + return OPJ_FALSE; } /** @@ -201,79 +196,78 @@ static OPJ_BOOL opj_seek_from_buffer(OPJ_OFF_T p_nb_bytes, void *p_user_data) * (would be nice if this was supported by the API). */ -static opj_stream_t *opj_stream_create_from_buffer( - struct BufInfo *p_file, OPJ_UINT32 p_size, - OPJ_BOOL p_is_read_stream) +static opj_stream_t *opj_stream_create_from_buffer(struct BufInfo *p_file, + OPJ_UINT32 p_size, + OPJ_BOOL p_is_read_stream) { - opj_stream_t *l_stream = opj_stream_create(p_size, p_is_read_stream); - if (l_stream == NULL) { - return NULL; - } - opj_stream_set_user_data(l_stream, p_file, opj_read_from_buffer_free); - opj_stream_set_user_data_length(l_stream, p_file->len); - opj_stream_set_read_function(l_stream, opj_read_from_buffer); -#if 0 /* UNUSED */ - opj_stream_set_write_function(l_stream, opj_write_from_buffer); + opj_stream_t *l_stream = opj_stream_create(p_size, p_is_read_stream); + if (l_stream == NULL) { + return NULL; + } + opj_stream_set_user_data(l_stream, p_file, opj_read_from_buffer_free); + opj_stream_set_user_data_length(l_stream, p_file->len); + opj_stream_set_read_function(l_stream, opj_read_from_buffer); +#if 0 /* UNUSED */ + opj_stream_set_write_function(l_stream, opj_write_from_buffer); #endif - opj_stream_set_skip_function(l_stream, opj_skip_from_buffer); - opj_stream_set_seek_function(l_stream, opj_seek_from_buffer); + opj_stream_set_skip_function(l_stream, opj_skip_from_buffer); + opj_stream_set_seek_function(l_stream, opj_seek_from_buffer); - return l_stream; + return l_stream; } /** \} */ - /** \name File Stream * \{ */ static void opj_free_from_file(void *p_user_data) { - FILE *f = p_user_data; - fclose(f); + FILE *f = p_user_data; + fclose(f); } -static OPJ_UINT64 opj_get_data_length_from_file (void *p_user_data) +static OPJ_UINT64 opj_get_data_length_from_file(void *p_user_data) { - FILE *p_file = p_user_data; - OPJ_OFF_T file_length = 0; + FILE *p_file = p_user_data; + OPJ_OFF_T file_length = 0; - fseek(p_file, 0, SEEK_END); - file_length = ftell(p_file); - fseek(p_file, 0, SEEK_SET); + fseek(p_file, 0, SEEK_END); + file_length = ftell(p_file); + fseek(p_file, 0, SEEK_SET); - return (OPJ_UINT64)file_length; + return (OPJ_UINT64)file_length; } static OPJ_SIZE_T opj_read_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { - FILE *p_file = p_user_data; - OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, p_file); - return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1; + FILE *p_file = p_user_data; + OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, p_file); + return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1; } static OPJ_SIZE_T opj_write_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { - FILE *p_file = p_user_data; - return fwrite(p_buffer, 1, p_nb_bytes, p_file); + FILE *p_file = p_user_data; + return fwrite(p_buffer, 1, p_nb_bytes, p_file); } static OPJ_OFF_T opj_skip_from_file(OPJ_OFF_T p_nb_bytes, void *p_user_data) { - FILE *p_file = p_user_data; - if (fseek(p_file, p_nb_bytes, SEEK_CUR)) { - return -1; - } - return p_nb_bytes; + FILE *p_file = p_user_data; + if (fseek(p_file, p_nb_bytes, SEEK_CUR)) { + return -1; + } + return p_nb_bytes; } static OPJ_BOOL opj_seek_from_file(OPJ_OFF_T p_nb_bytes, void *p_user_data) { - FILE *p_file = p_user_data; - if (fseek(p_file, p_nb_bytes, SEEK_SET)) { - return OPJ_FALSE; - } - return OPJ_TRUE; + FILE *p_file = p_user_data; + if (fseek(p_file, p_nb_bytes, SEEK_SET)) { + return OPJ_FALSE; + } + return OPJ_TRUE; } /** @@ -281,304 +275,317 @@ static OPJ_BOOL opj_seek_from_file(OPJ_OFF_T p_nb_bytes, void *p_user_data) * (would be nice if this was supported by the API). */ -static opj_stream_t *opj_stream_create_from_file( - const char *filepath, OPJ_UINT32 p_size, OPJ_BOOL p_is_read_stream, - FILE **r_file) +static opj_stream_t *opj_stream_create_from_file(const char *filepath, + OPJ_UINT32 p_size, + OPJ_BOOL p_is_read_stream, + FILE **r_file) { - FILE *p_file = BLI_fopen(filepath, p_is_read_stream ? "rb" : "wb"); - if (p_file == NULL) { - return NULL; - } - - opj_stream_t *l_stream = opj_stream_create(p_size, p_is_read_stream); - if (l_stream == NULL) { - fclose(p_file); - return NULL; - } - - opj_stream_set_user_data(l_stream, p_file, opj_free_from_file); - opj_stream_set_user_data_length(l_stream, opj_get_data_length_from_file(p_file)); - opj_stream_set_write_function(l_stream, opj_write_from_file); - opj_stream_set_read_function(l_stream, opj_read_from_file); - opj_stream_set_skip_function(l_stream, opj_skip_from_file); - opj_stream_set_seek_function(l_stream, opj_seek_from_file); - - if (r_file) { - *r_file = p_file; - } - return l_stream; + FILE *p_file = BLI_fopen(filepath, p_is_read_stream ? "rb" : "wb"); + if (p_file == NULL) { + return NULL; + } + + opj_stream_t *l_stream = opj_stream_create(p_size, p_is_read_stream); + if (l_stream == NULL) { + fclose(p_file); + return NULL; + } + + opj_stream_set_user_data(l_stream, p_file, opj_free_from_file); + opj_stream_set_user_data_length(l_stream, opj_get_data_length_from_file(p_file)); + opj_stream_set_write_function(l_stream, opj_write_from_file); + opj_stream_set_read_function(l_stream, opj_read_from_file); + opj_stream_set_skip_function(l_stream, opj_skip_from_file); + opj_stream_set_seek_function(l_stream, opj_seek_from_file); + + if (r_file) { + *r_file = p_file; + } + return l_stream; } /** \} */ -static ImBuf *imb_load_jp2_stream( - opj_stream_t *stream, OPJ_CODEC_FORMAT p_format, - int flags, char colorspace[IM_MAX_SPACE]); +static ImBuf *imb_load_jp2_stream(opj_stream_t *stream, + OPJ_CODEC_FORMAT p_format, + int flags, + char colorspace[IM_MAX_SPACE]); -ImBuf *imb_load_jp2(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_jp2(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - const OPJ_CODEC_FORMAT format = (size > JP2_FILEHEADER_SIZE) ? format_from_header(mem) : OPJ_CODEC_UNKNOWN; - struct BufInfo buf_wrapper = { .buf = mem, .cur = mem, .len = size, }; - opj_stream_t *stream = opj_stream_create_from_buffer(&buf_wrapper, OPJ_J2K_STREAM_CHUNK_SIZE, true); - ImBuf *ibuf = imb_load_jp2_stream(stream, format, flags, colorspace); - opj_stream_destroy(stream); - return ibuf; + const OPJ_CODEC_FORMAT format = (size > JP2_FILEHEADER_SIZE) ? format_from_header(mem) : + OPJ_CODEC_UNKNOWN; + struct BufInfo buf_wrapper = { + .buf = mem, + .cur = mem, + .len = size, + }; + opj_stream_t *stream = opj_stream_create_from_buffer( + &buf_wrapper, OPJ_J2K_STREAM_CHUNK_SIZE, true); + ImBuf *ibuf = imb_load_jp2_stream(stream, format, flags, colorspace); + opj_stream_destroy(stream); + return ibuf; } ImBuf *imb_load_jp2_filepath(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) { - FILE *p_file = NULL; - unsigned char mem[JP2_FILEHEADER_SIZE]; - opj_stream_t *stream = opj_stream_create_from_file(filepath, OPJ_J2K_STREAM_CHUNK_SIZE, true, &p_file); - if (stream) { - return NULL; - } - else { - if (fread(mem, sizeof(mem), 1, p_file) != sizeof(mem)) { - opj_stream_destroy(stream); - return NULL; - } - else { - fseek(p_file, 0, SEEK_SET); - } - } - - const OPJ_CODEC_FORMAT format = format_from_header(mem); - ImBuf *ibuf = imb_load_jp2_stream(stream, format, flags, colorspace); - opj_stream_destroy(stream); - return ibuf; + FILE *p_file = NULL; + unsigned char mem[JP2_FILEHEADER_SIZE]; + opj_stream_t *stream = opj_stream_create_from_file( + filepath, OPJ_J2K_STREAM_CHUNK_SIZE, true, &p_file); + if (stream) { + return NULL; + } + else { + if (fread(mem, sizeof(mem), 1, p_file) != sizeof(mem)) { + opj_stream_destroy(stream); + return NULL; + } + else { + fseek(p_file, 0, SEEK_SET); + } + } + + const OPJ_CODEC_FORMAT format = format_from_header(mem); + ImBuf *ibuf = imb_load_jp2_stream(stream, format, flags, colorspace); + opj_stream_destroy(stream); + return ibuf; } - -static ImBuf *imb_load_jp2_stream( - opj_stream_t *stream, const OPJ_CODEC_FORMAT format, - int flags, char colorspace[IM_MAX_SPACE]) +static ImBuf *imb_load_jp2_stream(opj_stream_t *stream, + const OPJ_CODEC_FORMAT format, + int flags, + char colorspace[IM_MAX_SPACE]) { - if (format == OPJ_CODEC_UNKNOWN) { - return NULL; - } + if (format == OPJ_CODEC_UNKNOWN) { + return NULL; + } - struct ImBuf *ibuf = NULL; - bool use_float = false; /* for precision higher then 8 use float */ - bool use_alpha = false; + struct ImBuf *ibuf = NULL; + bool use_float = false; /* for precision higher then 8 use float */ + bool use_alpha = false; - long signed_offsets[4] = {0, 0, 0, 0}; - int float_divs[4] = {1, 1, 1, 1}; + long signed_offsets[4] = {0, 0, 0, 0}; + int float_divs[4] = {1, 1, 1, 1}; - unsigned int i, i_next, w, h, planes; - unsigned int y; - int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */ + unsigned int i, i_next, w, h, planes; + unsigned int y; + int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */ - opj_dparameters_t parameters; /* decompression parameters */ + opj_dparameters_t parameters; /* decompression parameters */ - opj_image_t *image = NULL; - opj_codec_t *codec = NULL; /* handle to a decompressor */ + opj_image_t *image = NULL; + opj_codec_t *codec = NULL; /* handle to a decompressor */ - /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */ - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - /* set decoding parameters to default values */ - opj_set_default_decoder_parameters(¶meters); + /* set decoding parameters to default values */ + opj_set_default_decoder_parameters(¶meters); - /* JPEG 2000 compressed image data */ + /* JPEG 2000 compressed image data */ - /* get a decoder handle */ - codec = opj_create_decompress(format); + /* get a decoder handle */ + codec = opj_create_decompress(format); - /* configure the event callbacks (not required) */ - opj_set_error_handler(codec, error_callback, stderr); - opj_set_warning_handler(codec, warning_callback, stderr); -#ifdef DEBUG /* too noisy */ - opj_set_info_handler(codec, info_callback, stderr); + /* configure the event callbacks (not required) */ + opj_set_error_handler(codec, error_callback, stderr); + opj_set_warning_handler(codec, warning_callback, stderr); +#ifdef DEBUG /* too noisy */ + opj_set_info_handler(codec, info_callback, stderr); #endif - /* setup the decoder decoding parameters using the current image and user parameters */ - if (opj_setup_decoder(codec, ¶meters) == false) { - goto finally; - } - - if (opj_read_header(stream, codec, &image) == false) { - printf("OpenJPEG error: failed to read the header\n"); - goto finally; - } - - /* decode the stream and fill the image structure */ - if (opj_decode(codec, stream, image) == false) { - fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); - goto finally; - } - - if ((image->numcomps * image->x1 * image->y1) == 0) { - fprintf(stderr, "\nError: invalid raw image parameters\n"); - goto finally; - } - - w = image->comps[0].w; - h = image->comps[0].h; - - switch (image->numcomps) { - case 1: /* Grayscale */ - case 3: /* Color */ - planes = 24; - use_alpha = false; - break; - default: /* 2 or 4 - Grayscale or Color + alpha */ - planes = 32; /* grayscale + alpha */ - use_alpha = true; - break; - } - - - i = image->numcomps; - if (i > 4) i = 4; - - while (i) { - i--; - - if (image->comps[i].prec > 8) - use_float = true; - - if (image->comps[i].sgnd) - signed_offsets[i] = 1 << (image->comps[i].prec - 1); - - /* only needed for float images but dosnt hurt to calc this */ - float_divs[i] = (1 << image->comps[i].prec) - 1; - } - - ibuf = IMB_allocImBuf(w, h, planes, use_float ? IB_rectfloat : IB_rect); - - if (ibuf == NULL) { - goto finally; - } - - ibuf->ftype = IMB_FTYPE_JP2; - if (1 /* is_jp2 */ ) { - ibuf->foptions.flag |= JP2_JP2; - } - else { - ibuf->foptions.flag |= JP2_J2K; - } - - if (use_float) { - float *rect_float = ibuf->rect_float; - - if (image->numcomps < 3) { - r = image->comps[0].data; - a = (use_alpha) ? image->comps[1].data : NULL; - - /* grayscale 12bits+ */ - if (use_alpha) { - a = image->comps[1].data; - PIXEL_LOOPER_BEGIN(rect_float) { - rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; - rect_float[3] = (a[i] + signed_offsets[1]) / float_divs[1]; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) { - rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; - rect_float[3] = 1.0f; - } - PIXEL_LOOPER_END; - } - } - else { - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - - /* rgb or rgba 12bits+ */ - if (use_alpha) { - a = image->comps[3].data; - PIXEL_LOOPER_BEGIN(rect_float) { - rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; - rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1]; - rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2]; - rect_float[3] = (float)(a[i] + signed_offsets[3]) / float_divs[3]; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) { - rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; - rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1]; - rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2]; - rect_float[3] = 1.0f; - } - PIXEL_LOOPER_END; - } - } - - } - else { - unsigned char *rect_uchar = (unsigned char *)ibuf->rect; - - if (image->numcomps < 3) { - r = image->comps[0].data; - a = (use_alpha) ? image->comps[1].data : NULL; - - /* grayscale */ - if (use_alpha) { - a = image->comps[3].data; - PIXEL_LOOPER_BEGIN(rect_uchar) { - rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]); - rect_uchar[3] = a[i] + signed_offsets[1]; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_uchar) { - rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]); - rect_uchar[3] = 255; - } - PIXEL_LOOPER_END; - } - } - else { - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - - /* 8bit rgb or rgba */ - if (use_alpha) { - a = image->comps[3].data; - PIXEL_LOOPER_BEGIN(rect_uchar) { - rect_uchar[0] = r[i] + signed_offsets[0]; - rect_uchar[1] = g[i] + signed_offsets[1]; - rect_uchar[2] = b[i] + signed_offsets[2]; - rect_uchar[3] = a[i] + signed_offsets[3]; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_uchar) { - rect_uchar[0] = r[i] + signed_offsets[0]; - rect_uchar[1] = g[i] + signed_offsets[1]; - rect_uchar[2] = b[i] + signed_offsets[2]; - rect_uchar[3] = 255; - } - PIXEL_LOOPER_END; - } - } - } - - if (flags & IB_rect) { - IMB_rect_from_float(ibuf); - } + /* setup the decoder decoding parameters using the current image and user parameters */ + if (opj_setup_decoder(codec, ¶meters) == false) { + goto finally; + } + + if (opj_read_header(stream, codec, &image) == false) { + printf("OpenJPEG error: failed to read the header\n"); + goto finally; + } + + /* decode the stream and fill the image structure */ + if (opj_decode(codec, stream, image) == false) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); + goto finally; + } + + if ((image->numcomps * image->x1 * image->y1) == 0) { + fprintf(stderr, "\nError: invalid raw image parameters\n"); + goto finally; + } + + w = image->comps[0].w; + h = image->comps[0].h; + + switch (image->numcomps) { + case 1: /* Grayscale */ + case 3: /* Color */ + planes = 24; + use_alpha = false; + break; + default: /* 2 or 4 - Grayscale or Color + alpha */ + planes = 32; /* grayscale + alpha */ + use_alpha = true; + break; + } + + i = image->numcomps; + if (i > 4) + i = 4; + + while (i) { + i--; + + if (image->comps[i].prec > 8) + use_float = true; + + if (image->comps[i].sgnd) + signed_offsets[i] = 1 << (image->comps[i].prec - 1); + + /* only needed for float images but dosnt hurt to calc this */ + float_divs[i] = (1 << image->comps[i].prec) - 1; + } + + ibuf = IMB_allocImBuf(w, h, planes, use_float ? IB_rectfloat : IB_rect); + + if (ibuf == NULL) { + goto finally; + } + + ibuf->ftype = IMB_FTYPE_JP2; + if (1 /* is_jp2 */) { + ibuf->foptions.flag |= JP2_JP2; + } + else { + ibuf->foptions.flag |= JP2_J2K; + } + + if (use_float) { + float *rect_float = ibuf->rect_float; + + if (image->numcomps < 3) { + r = image->comps[0].data; + a = (use_alpha) ? image->comps[1].data : NULL; + + /* grayscale 12bits+ */ + if (use_alpha) { + a = image->comps[1].data; + PIXEL_LOOPER_BEGIN (rect_float) { + rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / + float_divs[0]; + rect_float[3] = (a[i] + signed_offsets[1]) / float_divs[1]; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_float) { + rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / + float_divs[0]; + rect_float[3] = 1.0f; + } + PIXEL_LOOPER_END; + } + } + else { + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; + + /* rgb or rgba 12bits+ */ + if (use_alpha) { + a = image->comps[3].data; + PIXEL_LOOPER_BEGIN (rect_float) { + rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; + rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1]; + rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2]; + rect_float[3] = (float)(a[i] + signed_offsets[3]) / float_divs[3]; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_float) { + rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0]; + rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1]; + rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2]; + rect_float[3] = 1.0f; + } + PIXEL_LOOPER_END; + } + } + } + else { + unsigned char *rect_uchar = (unsigned char *)ibuf->rect; + + if (image->numcomps < 3) { + r = image->comps[0].data; + a = (use_alpha) ? image->comps[1].data : NULL; + + /* grayscale */ + if (use_alpha) { + a = image->comps[3].data; + PIXEL_LOOPER_BEGIN (rect_uchar) { + rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]); + rect_uchar[3] = a[i] + signed_offsets[1]; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_uchar) { + rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]); + rect_uchar[3] = 255; + } + PIXEL_LOOPER_END; + } + } + else { + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; + + /* 8bit rgb or rgba */ + if (use_alpha) { + a = image->comps[3].data; + PIXEL_LOOPER_BEGIN (rect_uchar) { + rect_uchar[0] = r[i] + signed_offsets[0]; + rect_uchar[1] = g[i] + signed_offsets[1]; + rect_uchar[2] = b[i] + signed_offsets[2]; + rect_uchar[3] = a[i] + signed_offsets[3]; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_uchar) { + rect_uchar[0] = r[i] + signed_offsets[0]; + rect_uchar[1] = g[i] + signed_offsets[1]; + rect_uchar[2] = b[i] + signed_offsets[2]; + rect_uchar[3] = 255; + } + PIXEL_LOOPER_END; + } + } + } + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } finally: - /* free remaining structures */ - if (codec) { - opj_destroy_codec(codec); - } + /* free remaining structures */ + if (codec) { + opj_destroy_codec(codec); + } - if (image) { - opj_image_destroy(image); - } + if (image) { + opj_image_destroy(image); + } - return ibuf; + return ibuf; } //static opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) @@ -586,34 +593,37 @@ finally: /* use inline because the float passed can be a function call that would end up being called many times */ #if 0 -#define UPSAMPLE_8_TO_12(_val) ((_val << 4) | (_val & ((1 << 4) - 1))) -#define UPSAMPLE_8_TO_16(_val) ((_val << 8) + _val) - -#define DOWNSAMPLE_FLOAT_TO_8BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val))) -#define DOWNSAMPLE_FLOAT_TO_12BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val))) -#define DOWNSAMPLE_FLOAT_TO_16BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val))) +# define UPSAMPLE_8_TO_12(_val) ((_val << 4) | (_val & ((1 << 4) - 1))) +# define UPSAMPLE_8_TO_16(_val) ((_val << 8) + _val) + +# define DOWNSAMPLE_FLOAT_TO_8BIT(_val) \ + (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val))) +# define DOWNSAMPLE_FLOAT_TO_12BIT(_val) \ + (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val))) +# define DOWNSAMPLE_FLOAT_TO_16BIT(_val) \ + (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val))) #else BLI_INLINE int UPSAMPLE_8_TO_12(const unsigned char _val) { - return (_val << 4) | (_val & ((1 << 4) - 1)); + return (_val << 4) | (_val & ((1 << 4) - 1)); } BLI_INLINE int UPSAMPLE_8_TO_16(const unsigned char _val) { - return (_val << 8) + _val; + return (_val << 8) + _val; } BLI_INLINE int DOWNSAMPLE_FLOAT_TO_8BIT(const float _val) { - return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val))); + return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val))); } BLI_INLINE int DOWNSAMPLE_FLOAT_TO_12BIT(const float _val) { - return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val))); + return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val))); } BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val) { - return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val))); + return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val))); } #endif @@ -627,645 +637,651 @@ BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val) /* ****************************** COPIED FROM image_to_j2k.c */ /* ----------------------------------------------------------------------- */ -#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/ -#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/ -#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/ -#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/ - +#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/ +#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/ +#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/ +#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/ static int initialise_4K_poc(opj_poc_t *POC, int numres) { - POC[0].tile = 1; - POC[0].resno0 = 0; - POC[0].compno0 = 0; - POC[0].layno1 = 1; - POC[0].resno1 = numres - 1; - POC[0].compno1 = 3; - POC[0].prg1 = OPJ_CPRL; - POC[1].tile = 1; - POC[1].resno0 = numres - 1; - POC[1].compno0 = 0; - POC[1].layno1 = 1; - POC[1].resno1 = numres; - POC[1].compno1 = 3; - POC[1].prg1 = OPJ_CPRL; - return 2; + POC[0].tile = 1; + POC[0].resno0 = 0; + POC[0].compno0 = 0; + POC[0].layno1 = 1; + POC[0].resno1 = numres - 1; + POC[0].compno1 = 3; + POC[0].prg1 = OPJ_CPRL; + POC[1].tile = 1; + POC[1].resno0 = numres - 1; + POC[1].compno0 = 0; + POC[1].layno1 = 1; + POC[1].resno1 = numres; + POC[1].compno1 = 3; + POC[1].prg1 = OPJ_CPRL; + return 2; } static void cinema_parameters(opj_cparameters_t *parameters) { - parameters->tile_size_on = 0; /* false */ - parameters->cp_tdx = 1; - parameters->cp_tdy = 1; + parameters->tile_size_on = 0; /* false */ + parameters->cp_tdx = 1; + parameters->cp_tdy = 1; - /*Tile part*/ - parameters->tp_flag = 'C'; - parameters->tp_on = 1; + /*Tile part*/ + parameters->tp_flag = 'C'; + parameters->tp_on = 1; - /*Tile and Image shall be at (0, 0)*/ - parameters->cp_tx0 = 0; - parameters->cp_ty0 = 0; - parameters->image_offset_x0 = 0; - parameters->image_offset_y0 = 0; + /*Tile and Image shall be at (0, 0)*/ + parameters->cp_tx0 = 0; + parameters->cp_ty0 = 0; + parameters->image_offset_x0 = 0; + parameters->image_offset_y0 = 0; - /*Codeblock size = 32 * 32*/ - parameters->cblockw_init = 32; - parameters->cblockh_init = 32; - parameters->csty |= 0x01; + /*Codeblock size = 32 * 32*/ + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + parameters->csty |= 0x01; - /*The progression order shall be CPRL*/ - parameters->prog_order = OPJ_CPRL; + /*The progression order shall be CPRL*/ + parameters->prog_order = OPJ_CPRL; - /* No ROI */ - parameters->roi_compno = -1; + /* No ROI */ + parameters->roi_compno = -1; - parameters->subsampling_dx = 1; parameters->subsampling_dy = 1; + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; - /* 9-7 transform */ - parameters->irreversible = 1; + /* 9-7 transform */ + parameters->irreversible = 1; } -static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *image, img_fol_t *img_fol) +static void cinema_setup_encoder(opj_cparameters_t *parameters, + opj_image_t *image, + img_fol_t *img_fol) { - int i; - float temp_rate; - - switch (parameters->cp_cinema) { - case OPJ_CINEMA2K_24: - case OPJ_CINEMA2K_48: - if (parameters->numresolution > 6) { - parameters->numresolution = 6; - } - if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))) { - fprintf(stdout, "Image coordinates %u x %u is not 2K compliant.\nJPEG Digital Cinema Profile-3 " - "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n", - image->comps[0].w, image->comps[0].h); - parameters->cp_rsiz = OPJ_STD_RSIZ; - } - else { - parameters->cp_rsiz = DCP_CINEMA2K; - } - break; - - case OPJ_CINEMA4K_24: - if (parameters->numresolution < 1) { - parameters->numresolution = 1; - } - else if (parameters->numresolution > 7) { - parameters->numresolution = 7; - } - if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))) { - fprintf(stdout, "Image coordinates %u x %u is not 4K compliant.\nJPEG Digital Cinema Profile-4" - "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n", - image->comps[0].w, image->comps[0].h); - parameters->cp_rsiz = OPJ_STD_RSIZ; - } - else { - parameters->cp_rsiz = DCP_CINEMA2K; - } - parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution); - break; - case OPJ_OFF: - /* do nothing */ - break; - } - - switch (parameters->cp_cinema) { - case OPJ_CINEMA2K_24: - case OPJ_CINEMA4K_24: - for (i = 0; i < parameters->tcp_numlayers; i++) { - temp_rate = 0; - if (img_fol->rates[i] == 0) { - parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / - (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); - } - else { - temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / - (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); - if (temp_rate > CINEMA_24_CS) { - parameters->tcp_rates[i] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / - (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); - } - else { - parameters->tcp_rates[i] = img_fol->rates[i]; - } - } - } - parameters->max_comp_size = COMP_24_CS; - break; - - case OPJ_CINEMA2K_48: - for (i = 0; i < parameters->tcp_numlayers; i++) { - temp_rate = 0; - if (img_fol->rates[i] == 0) { - parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / - (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); - } - else { - temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / - (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); - if (temp_rate > CINEMA_48_CS) { - parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / - (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); - } - else { - parameters->tcp_rates[i] = img_fol->rates[i]; - } - } - } - parameters->max_comp_size = COMP_48_CS; - break; - case OPJ_OFF: - /* do nothing */ - break; - } - parameters->cp_disto_alloc = 1; + int i; + float temp_rate; + + switch (parameters->cp_cinema) { + case OPJ_CINEMA2K_24: + case OPJ_CINEMA2K_48: + if (parameters->numresolution > 6) { + parameters->numresolution = 6; + } + if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))) { + fprintf(stdout, + "Image coordinates %u x %u is not 2K compliant.\nJPEG Digital Cinema Profile-3 " + "(2K profile) compliance requires that at least one of coordinates match 2048 x " + "1080\n", + image->comps[0].w, + image->comps[0].h); + parameters->cp_rsiz = OPJ_STD_RSIZ; + } + else { + parameters->cp_rsiz = DCP_CINEMA2K; + } + break; + + case OPJ_CINEMA4K_24: + if (parameters->numresolution < 1) { + parameters->numresolution = 1; + } + else if (parameters->numresolution > 7) { + parameters->numresolution = 7; + } + if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))) { + fprintf(stdout, + "Image coordinates %u x %u is not 4K compliant.\nJPEG Digital Cinema Profile-4" + "(4K profile) compliance requires that at least one of coordinates match 4096 x " + "2160\n", + image->comps[0].w, + image->comps[0].h); + parameters->cp_rsiz = OPJ_STD_RSIZ; + } + else { + parameters->cp_rsiz = DCP_CINEMA2K; + } + parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution); + break; + case OPJ_OFF: + /* do nothing */ + break; + } + + switch (parameters->cp_cinema) { + case OPJ_CINEMA2K_24: + case OPJ_CINEMA4K_24: + for (i = 0; i < parameters->tcp_numlayers; i++) { + temp_rate = 0; + if (img_fol->rates[i] == 0) { + parameters->tcp_rates[0] = ((float)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec)) / + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + } + else { + temp_rate = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * + image->comps[0].prec)) / + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_24_CS) { + parameters->tcp_rates[i] = ((float)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec)) / + (CINEMA_24_CS * 8 * image->comps[0].dx * + image->comps[0].dy); + } + else { + parameters->tcp_rates[i] = img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_24_CS; + break; + + case OPJ_CINEMA2K_48: + for (i = 0; i < parameters->tcp_numlayers; i++) { + temp_rate = 0; + if (img_fol->rates[i] == 0) { + parameters->tcp_rates[0] = ((float)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec)) / + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + } + else { + temp_rate = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * + image->comps[0].prec)) / + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_48_CS) { + parameters->tcp_rates[0] = ((float)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec)) / + (CINEMA_48_CS * 8 * image->comps[0].dx * + image->comps[0].dy); + } + else { + parameters->tcp_rates[i] = img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_48_CS; + break; + case OPJ_OFF: + /* do nothing */ + break; + } + parameters->cp_disto_alloc = 1; } static float channel_colormanage_noop(float value) { - return value; + return value; } static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) { - unsigned char *rect_uchar; - float *rect_float, from_straight[4]; - - unsigned int subsampling_dx = parameters->subsampling_dx; - unsigned int subsampling_dy = parameters->subsampling_dy; - - unsigned int i, i_next, numcomps, w, h, prec; - unsigned int y; - int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */ - OPJ_COLOR_SPACE color_space; - opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */ - opj_image_t *image = NULL; - - float (*chanel_colormanage_cb)(float); - - img_fol_t img_fol; /* only needed for cinema presets */ - memset(&img_fol, 0, sizeof(img_fol_t)); - - if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) { - /* float buffer was managed already, no need in color space conversion */ - chanel_colormanage_cb = channel_colormanage_noop; - } - else { - /* standard linear-to-srgb conversion if float buffer wasn't managed */ - chanel_colormanage_cb = linearrgb_to_srgb; - } - - if (ibuf->foptions.flag & JP2_CINE) { - - if (ibuf->x == 4096 || ibuf->y == 2160) - parameters->cp_cinema = OPJ_CINEMA4K_24; - else { - if (ibuf->foptions.flag & JP2_CINE_48FPS) { - parameters->cp_cinema = OPJ_CINEMA2K_48; - } - else { - parameters->cp_cinema = OPJ_CINEMA2K_24; - } - } - if (parameters->cp_cinema) { - img_fol.rates = (float *)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates"); - for (i = 0; i < parameters->tcp_numlayers; i++) { - img_fol.rates[i] = parameters->tcp_rates[i]; - } - cinema_parameters(parameters); - } - - color_space = (ibuf->foptions.flag & JP2_YCC) ? OPJ_CLRSPC_SYCC : OPJ_CLRSPC_SRGB; - prec = 12; - numcomps = 3; - } - else { - /* Get settings from the imbuf */ - color_space = (ibuf->foptions.flag & JP2_YCC) ? OPJ_CLRSPC_SYCC : OPJ_CLRSPC_SRGB; - - if (ibuf->foptions.flag & JP2_16BIT) prec = 16; - else if (ibuf->foptions.flag & JP2_12BIT) prec = 12; - else prec = 8; - - /* 32bit images == alpha channel */ - /* grayscale not supported yet */ - numcomps = (ibuf->planes == 32) ? 4 : 3; - } - - w = ibuf->x; - h = ibuf->y; - - - /* initialize image components */ - memset(&cmptparm, 0, 4 * sizeof(opj_image_cmptparm_t)); - for (i = 0; i < numcomps; i++) { - cmptparm[i].prec = prec; - cmptparm[i].bpp = prec; - cmptparm[i].sgnd = 0; - cmptparm[i].dx = subsampling_dx; - cmptparm[i].dy = subsampling_dy; - cmptparm[i].w = w; - cmptparm[i].h = h; - } - /* create the image */ - image = opj_image_create(numcomps, &cmptparm[0], color_space); - if (!image) { - printf("Error: opj_image_create() failed\n"); - return NULL; - } - - /* set image offset and reference grid */ - image->x0 = parameters->image_offset_x0; - image->y0 = parameters->image_offset_y0; - image->x1 = image->x0 + (w - 1) * subsampling_dx + 1 + image->x0; - image->y1 = image->y0 + (h - 1) * subsampling_dy + 1 + image->y0; - - /* set image data */ - rect_uchar = (unsigned char *) ibuf->rect; - rect_float = ibuf->rect_float; - - /* set the destination channels */ - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - a = (numcomps == 4) ? image->comps[3].data : NULL; - - if (rect_float && rect_uchar && prec == 8) { - /* No need to use the floating point buffer, just write the 8 bits from the char buffer */ - rect_float = NULL; - } - - if (rect_float) { - int channels_in_float = ibuf->channels ? ibuf->channels : 4; - - switch (prec) { - case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */ - if (numcomps == 4) { - if (channels_in_float == 4) { - PIXEL_LOOPER_BEGIN(rect_float) - { - premul_to_straight_v4_v4(from_straight, rect_float); - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]); - } - PIXEL_LOOPER_END; - } - else if (channels_in_float == 3) { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); - a[i] = 255; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = b[i] = r[i]; - a[i] = 255; - } - PIXEL_LOOPER_END; - } - } - else { - if (channels_in_float == 4) { - PIXEL_LOOPER_BEGIN(rect_float) - { - premul_to_straight_v4_v4(from_straight, rect_float); - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2])); - } - PIXEL_LOOPER_END; - } - else if (channels_in_float == 3) { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = b[i] = r[i]; - } - PIXEL_LOOPER_END; - } - } - break; - - case 12: - if (numcomps == 4) { - if (channels_in_float == 4) { - PIXEL_LOOPER_BEGIN(rect_float) - { - premul_to_straight_v4_v4(from_straight, rect_float); - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]); - } - PIXEL_LOOPER_END; - } - else if (channels_in_float == 3) { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); - a[i] = 4095; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = b[i] = r[i]; - a[i] = 4095; - } - PIXEL_LOOPER_END; - } - } - else { - if (channels_in_float == 4) { - PIXEL_LOOPER_BEGIN(rect_float) - { - premul_to_straight_v4_v4(from_straight, rect_float); - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2])); - } - PIXEL_LOOPER_END; - } - else if (channels_in_float == 3) { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = b[i] = r[i]; - } - PIXEL_LOOPER_END; - } - } - break; - - case 16: - if (numcomps == 4) { - if (channels_in_float == 4) { - PIXEL_LOOPER_BEGIN(rect_float) - { - premul_to_straight_v4_v4(from_straight, rect_float); - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]); - } - PIXEL_LOOPER_END; - } - else if (channels_in_float == 3) { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); - a[i] = 65535; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = b[i] = r[i]; - a[i] = 65535; - } - PIXEL_LOOPER_END; - } - } - else { - if (channels_in_float == 4) { - PIXEL_LOOPER_BEGIN(rect_float) - { - premul_to_straight_v4_v4(from_straight, rect_float); - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2])); - } - PIXEL_LOOPER_END; - } - else if (channels_in_float == 3) { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = b[i] = r[i]; - } - PIXEL_LOOPER_END; - } - } - break; - } - } - else { - /* just use rect*/ - switch (prec) { - case 8: - if (numcomps == 4) { - PIXEL_LOOPER_BEGIN(rect_uchar) - { - r[i] = rect_uchar[0]; - g[i] = rect_uchar[1]; - b[i] = rect_uchar[2]; - a[i] = rect_uchar[3]; - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_uchar) - { - r[i] = rect_uchar[0]; - g[i] = rect_uchar[1]; - b[i] = rect_uchar[2]; - } - PIXEL_LOOPER_END; - } - break; - - case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */ - if (numcomps == 4) { - PIXEL_LOOPER_BEGIN(rect_uchar) - { - r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]); - g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]); - b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]); - a[i] = UPSAMPLE_8_TO_12(rect_uchar[3]); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_uchar) - { - r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]); - g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]); - b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]); - } - PIXEL_LOOPER_END; - } - break; - - case 16: - if (numcomps == 4) { - PIXEL_LOOPER_BEGIN(rect_uchar) - { - r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]); - g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]); - b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]); - a[i] = UPSAMPLE_8_TO_16(rect_uchar[3]); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_uchar) - { - r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]); - g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]); - b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]); - } - PIXEL_LOOPER_END; - } - break; - } - } - - /* Decide if MCT should be used */ - parameters->tcp_mct = image->numcomps == 3 ? 1 : 0; - - if (parameters->cp_cinema) { - cinema_setup_encoder(parameters, image, &img_fol); - } - - if (img_fol.rates) - MEM_freeN(img_fol.rates); - - return image; + unsigned char *rect_uchar; + float *rect_float, from_straight[4]; + + unsigned int subsampling_dx = parameters->subsampling_dx; + unsigned int subsampling_dy = parameters->subsampling_dy; + + unsigned int i, i_next, numcomps, w, h, prec; + unsigned int y; + int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */ + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */ + opj_image_t *image = NULL; + + float (*chanel_colormanage_cb)(float); + + img_fol_t img_fol; /* only needed for cinema presets */ + memset(&img_fol, 0, sizeof(img_fol_t)); + + if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) { + /* float buffer was managed already, no need in color space conversion */ + chanel_colormanage_cb = channel_colormanage_noop; + } + else { + /* standard linear-to-srgb conversion if float buffer wasn't managed */ + chanel_colormanage_cb = linearrgb_to_srgb; + } + + if (ibuf->foptions.flag & JP2_CINE) { + + if (ibuf->x == 4096 || ibuf->y == 2160) + parameters->cp_cinema = OPJ_CINEMA4K_24; + else { + if (ibuf->foptions.flag & JP2_CINE_48FPS) { + parameters->cp_cinema = OPJ_CINEMA2K_48; + } + else { + parameters->cp_cinema = OPJ_CINEMA2K_24; + } + } + if (parameters->cp_cinema) { + img_fol.rates = (float *)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates"); + for (i = 0; i < parameters->tcp_numlayers; i++) { + img_fol.rates[i] = parameters->tcp_rates[i]; + } + cinema_parameters(parameters); + } + + color_space = (ibuf->foptions.flag & JP2_YCC) ? OPJ_CLRSPC_SYCC : OPJ_CLRSPC_SRGB; + prec = 12; + numcomps = 3; + } + else { + /* Get settings from the imbuf */ + color_space = (ibuf->foptions.flag & JP2_YCC) ? OPJ_CLRSPC_SYCC : OPJ_CLRSPC_SRGB; + + if (ibuf->foptions.flag & JP2_16BIT) + prec = 16; + else if (ibuf->foptions.flag & JP2_12BIT) + prec = 12; + else + prec = 8; + + /* 32bit images == alpha channel */ + /* grayscale not supported yet */ + numcomps = (ibuf->planes == 32) ? 4 : 3; + } + + w = ibuf->x; + h = ibuf->y; + + /* initialize image components */ + memset(&cmptparm, 0, 4 * sizeof(opj_image_cmptparm_t)); + for (i = 0; i < numcomps; i++) { + cmptparm[i].prec = prec; + cmptparm[i].bpp = prec; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if (!image) { + printf("Error: opj_image_create() failed\n"); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = image->x0 + (w - 1) * subsampling_dx + 1 + image->x0; + image->y1 = image->y0 + (h - 1) * subsampling_dy + 1 + image->y0; + + /* set image data */ + rect_uchar = (unsigned char *)ibuf->rect; + rect_float = ibuf->rect_float; + + /* set the destination channels */ + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; + a = (numcomps == 4) ? image->comps[3].data : NULL; + + if (rect_float && rect_uchar && prec == 8) { + /* No need to use the floating point buffer, just write the 8 bits from the char buffer */ + rect_float = NULL; + } + + if (rect_float) { + int channels_in_float = ibuf->channels ? ibuf->channels : 4; + + switch (prec) { + case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */ + if (numcomps == 4) { + if (channels_in_float == 4) { + PIXEL_LOOPER_BEGIN (rect_float) { + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]); + } + PIXEL_LOOPER_END; + } + else if (channels_in_float == 3) { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) + { + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); + a[i] = 255; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) + { + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = b[i] = r[i]; + a[i] = 255; + } + PIXEL_LOOPER_END; + } + } + else { + if (channels_in_float == 4) { + PIXEL_LOOPER_BEGIN (rect_float) { + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2])); + } + PIXEL_LOOPER_END; + } + else if (channels_in_float == 3) { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) + { + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) + { + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = b[i] = r[i]; + } + PIXEL_LOOPER_END; + } + } + break; + + case 12: + if (numcomps == 4) { + if (channels_in_float == 4) { + PIXEL_LOOPER_BEGIN (rect_float) { + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]); + } + PIXEL_LOOPER_END; + } + else if (channels_in_float == 3) { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) + { + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); + a[i] = 4095; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) + { + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = b[i] = r[i]; + a[i] = 4095; + } + PIXEL_LOOPER_END; + } + } + else { + if (channels_in_float == 4) { + PIXEL_LOOPER_BEGIN (rect_float) { + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2])); + } + PIXEL_LOOPER_END; + } + else if (channels_in_float == 3) { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) + { + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) + { + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = b[i] = r[i]; + } + PIXEL_LOOPER_END; + } + } + break; + + case 16: + if (numcomps == 4) { + if (channels_in_float == 4) { + PIXEL_LOOPER_BEGIN (rect_float) { + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]); + } + PIXEL_LOOPER_END; + } + else if (channels_in_float == 3) { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) + { + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); + a[i] = 65535; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) + { + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = b[i] = r[i]; + a[i] = 65535; + } + PIXEL_LOOPER_END; + } + } + else { + if (channels_in_float == 4) { + PIXEL_LOOPER_BEGIN (rect_float) { + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2])); + } + PIXEL_LOOPER_END; + } + else if (channels_in_float == 3) { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3) + { + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1) + { + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = b[i] = r[i]; + } + PIXEL_LOOPER_END; + } + } + break; + } + } + else { + /* just use rect*/ + switch (prec) { + case 8: + if (numcomps == 4) { + PIXEL_LOOPER_BEGIN (rect_uchar) { + r[i] = rect_uchar[0]; + g[i] = rect_uchar[1]; + b[i] = rect_uchar[2]; + a[i] = rect_uchar[3]; + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_uchar) { + r[i] = rect_uchar[0]; + g[i] = rect_uchar[1]; + b[i] = rect_uchar[2]; + } + PIXEL_LOOPER_END; + } + break; + + case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */ + if (numcomps == 4) { + PIXEL_LOOPER_BEGIN (rect_uchar) { + r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]); + g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]); + b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]); + a[i] = UPSAMPLE_8_TO_12(rect_uchar[3]); + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_uchar) { + r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]); + g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]); + b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]); + } + PIXEL_LOOPER_END; + } + break; + + case 16: + if (numcomps == 4) { + PIXEL_LOOPER_BEGIN (rect_uchar) { + r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]); + g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]); + b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]); + a[i] = UPSAMPLE_8_TO_16(rect_uchar[3]); + } + PIXEL_LOOPER_END; + } + else { + PIXEL_LOOPER_BEGIN (rect_uchar) { + r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]); + g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]); + b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]); + } + PIXEL_LOOPER_END; + } + break; + } + } + + /* Decide if MCT should be used */ + parameters->tcp_mct = image->numcomps == 3 ? 1 : 0; + + if (parameters->cp_cinema) { + cinema_setup_encoder(parameters, image, &img_fol); + } + + if (img_fol.rates) + MEM_freeN(img_fol.rates); + + return image; } int imb_save_jp2_stream(struct ImBuf *ibuf, opj_stream_t *stream, int flags); int imb_save_jp2(struct ImBuf *ibuf, const char *filepath, int flags) { - opj_stream_t *stream = opj_stream_create_from_file(filepath, OPJ_J2K_STREAM_CHUNK_SIZE, false, NULL); - if (stream == NULL) { - return 0; - } - int ret = imb_save_jp2_stream(ibuf, stream, flags); - opj_stream_destroy(stream); - return ret; + opj_stream_t *stream = opj_stream_create_from_file( + filepath, OPJ_J2K_STREAM_CHUNK_SIZE, false, NULL); + if (stream == NULL) { + return 0; + } + int ret = imb_save_jp2_stream(ibuf, stream, flags); + opj_stream_destroy(stream); + return ret; } /* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ int imb_save_jp2_stream(struct ImBuf *ibuf, opj_stream_t *stream, int UNUSED(flags)) { - int quality = ibuf->foptions.quality; - - opj_cparameters_t parameters; /* compression parameters */ - opj_image_t *image = NULL; - - /* set encoding parameters to default values */ - opj_set_default_encoder_parameters(¶meters); - - /* compression ratio */ - /* invert range, from 10-100, 100-1 - * where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/ - parameters.tcp_rates[0] = ((100 - quality) / 90.0f * 99.0f) + 1; - - - parameters.tcp_numlayers = 1; /* only one resolution */ - parameters.cp_disto_alloc = 1; - - image = ibuftoimage(ibuf, ¶meters); - - opj_codec_t *codec = NULL; - int ok = false; - /* JP2 format output */ - { - /* get a JP2 compressor handle */ - OPJ_CODEC_FORMAT format = OPJ_CODEC_JP2; - if (ibuf->foptions.flag & JP2_J2K) { - format = OPJ_CODEC_J2K; - } - else if (ibuf->foptions.flag & JP2_JP2) { - format = OPJ_CODEC_JP2; - } - - codec = opj_create_compress(format); - - /* configure the event callbacks (not required) */ - opj_set_error_handler(codec, error_callback, stderr); - opj_set_warning_handler(codec, warning_callback, stderr); -#ifdef DEBUG /* too noisy */ - opj_set_info_handler(codec, info_callback, stderr); + int quality = ibuf->foptions.quality; + + opj_cparameters_t parameters; /* compression parameters */ + opj_image_t *image = NULL; + + /* set encoding parameters to default values */ + opj_set_default_encoder_parameters(¶meters); + + /* compression ratio */ + /* invert range, from 10-100, 100-1 + * where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/ + parameters.tcp_rates[0] = ((100 - quality) / 90.0f * 99.0f) + 1; + + parameters.tcp_numlayers = 1; /* only one resolution */ + parameters.cp_disto_alloc = 1; + + image = ibuftoimage(ibuf, ¶meters); + + opj_codec_t *codec = NULL; + int ok = false; + /* JP2 format output */ + { + /* get a JP2 compressor handle */ + OPJ_CODEC_FORMAT format = OPJ_CODEC_JP2; + if (ibuf->foptions.flag & JP2_J2K) { + format = OPJ_CODEC_J2K; + } + else if (ibuf->foptions.flag & JP2_JP2) { + format = OPJ_CODEC_JP2; + } + + codec = opj_create_compress(format); + + /* configure the event callbacks (not required) */ + opj_set_error_handler(codec, error_callback, stderr); + opj_set_warning_handler(codec, warning_callback, stderr); +#ifdef DEBUG /* too noisy */ + opj_set_info_handler(codec, info_callback, stderr); #endif - /* setup the encoder parameters using the current image and using user parameters */ - if (opj_setup_encoder(codec, ¶meters, image) == false) { - goto finally; - } + /* setup the encoder parameters using the current image and using user parameters */ + if (opj_setup_encoder(codec, ¶meters, image) == false) { + goto finally; + } - if (opj_start_compress(codec, image, stream) == false) { - goto finally; - } - if (opj_encode(codec, stream) == false) { - goto finally; - } - if (opj_end_compress(codec, stream) == false) { - goto finally; - } - } + if (opj_start_compress(codec, image, stream) == false) { + goto finally; + } + if (opj_encode(codec, stream) == false) { + goto finally; + } + if (opj_end_compress(codec, stream) == false) { + goto finally; + } + } - ok = true; + ok = true; finally: - /* free remaining compression structures */ - if (codec) { - opj_destroy_codec(codec); - } + /* free remaining compression structures */ + if (codec) { + opj_destroy_codec(codec); + } - /* free image data */ - if (image) { - opj_image_destroy(image); - } + /* free image data */ + if (image) { + opj_image_destroy(image); + } - if (ok == false) { - fprintf(stderr, "failed to encode image\n"); - } + if (ok == false) { + fprintf(stderr, "failed to encode image\n"); + } - return ok; + return ok; } diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 25b23d9a19d..6743fe536b1 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -21,8 +21,6 @@ * \ingroup imbuf */ - - /* This little block needed for linking to Blender... */ #include #include @@ -61,8 +59,9 @@ static uchar ibuf_quality; int imb_is_a_jpeg(const unsigned char *mem) { - if ((mem[0] == 0xFF) && (mem[1] == 0xD8)) return 1; - return 0; + if ((mem[0] == 0xFF) && (mem[1] == 0xD8)) + return 1; + return 0; } /*---------------------------------------------------------- @@ -70,25 +69,25 @@ int imb_is_a_jpeg(const unsigned char *mem) *---------------------------------------------------------- */ typedef struct my_error_mgr { - struct jpeg_error_mgr pub; /* "public" fields */ + struct jpeg_error_mgr pub; /* "public" fields */ - jmp_buf setjmp_buffer; /* for return to caller */ + jmp_buf setjmp_buffer; /* for return to caller */ } my_error_mgr; typedef my_error_mgr *my_error_ptr; static void jpeg_error(j_common_ptr cinfo) { - my_error_ptr err = (my_error_ptr)cinfo->err; + my_error_ptr err = (my_error_ptr)cinfo->err; - /* Always display the message */ - (*cinfo->err->output_message)(cinfo); + /* Always display the message */ + (*cinfo->err->output_message)(cinfo); - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); - /* return control to the setjmp point */ - longjmp(err->setjmp_buffer, 1); + /* return control to the setjmp point */ + longjmp(err->setjmp_buffer, 1); } /*---------------------------------------------------------- @@ -97,547 +96,545 @@ static void jpeg_error(j_common_ptr cinfo) #if 0 typedef struct { - unsigned char *buffer; - int filled; + unsigned char *buffer; + int filled; } buffer_struct; #endif typedef struct { - struct jpeg_source_mgr pub; /* public fields */ + struct jpeg_source_mgr pub; /* public fields */ - const unsigned char *buffer; - int size; - JOCTET terminal[2]; + const unsigned char *buffer; + int size; + JOCTET terminal[2]; } my_source_mgr; typedef my_source_mgr *my_src_ptr; static void init_source(j_decompress_ptr cinfo) { - (void)cinfo; /* unused */ + (void)cinfo; /* unused */ } - static boolean fill_input_buffer(j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr)cinfo->src; - /* Since we have given all we have got already - * we simply fake an end of file - */ + /* Since we have given all we have got already + * we simply fake an end of file + */ - src->pub.next_input_byte = src->terminal; - src->pub.bytes_in_buffer = 2; - src->terminal[0] = (JOCTET) 0xFF; - src->terminal[1] = (JOCTET) JPEG_EOI; + src->pub.next_input_byte = src->terminal; + src->pub.bytes_in_buffer = 2; + src->terminal[0] = (JOCTET)0xFF; + src->terminal[1] = (JOCTET)JPEG_EOI; - return true; + return true; } - static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr)cinfo->src; - if (num_bytes > 0) { - /* prevent skipping over file end */ - size_t skip_size = (size_t)num_bytes <= src->pub.bytes_in_buffer ? num_bytes : src->pub.bytes_in_buffer; + if (num_bytes > 0) { + /* prevent skipping over file end */ + size_t skip_size = (size_t)num_bytes <= src->pub.bytes_in_buffer ? num_bytes : + src->pub.bytes_in_buffer; - src->pub.next_input_byte = src->pub.next_input_byte + skip_size; - src->pub.bytes_in_buffer = src->pub.bytes_in_buffer - skip_size; - } + src->pub.next_input_byte = src->pub.next_input_byte + skip_size; + src->pub.bytes_in_buffer = src->pub.bytes_in_buffer - skip_size; + } } - static void term_source(j_decompress_ptr cinfo) { - (void)cinfo; /* unused */ + (void)cinfo; /* unused */ } static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, size_t size) { - my_src_ptr src; + my_src_ptr src; - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr)); - } + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)( + (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr)); + } - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; - src->pub.term_source = term_source; + src = (my_src_ptr)cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = term_source; - src->pub.bytes_in_buffer = size; - src->pub.next_input_byte = buffer; + src->pub.bytes_in_buffer = size; + src->pub.next_input_byte = buffer; - src->buffer = buffer; - src->size = size; + src->buffer = buffer; + src->size = size; } +#define MAKESTMT(stuff) \ + do { \ + stuff \ + } while (0) -#define MAKESTMT(stuff) do { stuff } while (0) - -#define INPUT_VARS(cinfo) \ - struct jpeg_source_mgr *datasrc = (cinfo)->src; \ - const JOCTET * next_input_byte = datasrc->next_input_byte; \ - size_t bytes_in_buffer = datasrc->bytes_in_buffer +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr *datasrc = (cinfo)->src; \ + const JOCTET *next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer /* Unload the local copies --- do this only at a restart boundary */ -#define INPUT_SYNC(cinfo) \ - ( datasrc->next_input_byte = next_input_byte, \ - datasrc->bytes_in_buffer = bytes_in_buffer ) +#define INPUT_SYNC(cinfo) \ + (datasrc->next_input_byte = next_input_byte, datasrc->bytes_in_buffer = bytes_in_buffer) /* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */ -#define INPUT_RELOAD(cinfo) \ - ( next_input_byte = datasrc->next_input_byte, \ - bytes_in_buffer = datasrc->bytes_in_buffer ) +#define INPUT_RELOAD(cinfo) \ + (next_input_byte = datasrc->next_input_byte, bytes_in_buffer = datasrc->bytes_in_buffer) /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, * but we must reload the local copies after a successful fill. */ -#define MAKE_BYTE_AVAIL(cinfo, action) \ - if (bytes_in_buffer == 0) { \ - if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ - INPUT_RELOAD(cinfo); \ - } (void)0 - +#define MAKE_BYTE_AVAIL(cinfo, action) \ + if (bytes_in_buffer == 0) { \ + if (!(*datasrc->fill_input_buffer)(cinfo)) { \ + action; \ + } \ + INPUT_RELOAD(cinfo); \ + } \ + (void)0 /* Read a byte into variable V. * If must suspend, take the specified action (typically "return false"). */ -#define INPUT_BYTE(cinfo, V, action) \ - MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) +#define INPUT_BYTE(cinfo, V, action) \ + MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); 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++); ) +#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++);) struct NeoGeo_Word { - uchar pad1; - uchar pad2; - uchar pad3; - uchar quality; -} ; + uchar pad1; + uchar pad2; + uchar pad3; + uchar quality; +}; BLI_STATIC_ASSERT(sizeof(struct NeoGeo_Word) == 4, "Must be 4 bytes"); static boolean handle_app1(j_decompress_ptr cinfo) { - INT32 length; /* initialized by the macro */ - INT32 i; - char neogeo[128]; - - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return false); - length -= 2; - - if (length < 16) { - for (i = 0; i < length; i++) { - INPUT_BYTE(cinfo, neogeo[i], return false); - } - length = 0; - if (STREQLEN(neogeo, "NeoGeo", 6)) { - struct NeoGeo_Word *neogeo_word = (struct NeoGeo_Word *)(neogeo + 6); - ibuf_quality = neogeo_word->quality; - } - } - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) { - (*cinfo->src->skip_input_data)(cinfo, length); - } - return true; + INT32 length; /* initialized by the macro */ + INT32 i; + char neogeo[128]; + + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return false); + length -= 2; + + if (length < 16) { + for (i = 0; i < length; i++) { + INPUT_BYTE(cinfo, neogeo[i], return false); + } + length = 0; + if (STREQLEN(neogeo, "NeoGeo", 6)) { + struct NeoGeo_Word *neogeo_word = (struct NeoGeo_Word *)(neogeo + 6); + ibuf_quality = neogeo_word->quality; + } + } + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) { + (*cinfo->src->skip_input_data)(cinfo, length); + } + return true; } - static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int flags) { - JSAMPARRAY row_pointer; - JSAMPLE *buffer = NULL; - int row_stride; - int x, y, depth, r, g, b, k; - struct ImBuf *ibuf = NULL; - uchar *rect; - jpeg_saved_marker_ptr marker; - char *str, *key, *value; - - /* install own app1 handler */ - ibuf_quality = jpeg_default_quality; - jpeg_set_marker_processor(cinfo, 0xe1, handle_app1); - cinfo->dct_method = JDCT_FLOAT; - jpeg_save_markers(cinfo, JPEG_COM, 0xffff); - - if (jpeg_read_header(cinfo, false) == JPEG_HEADER_OK) { - x = cinfo->image_width; - y = cinfo->image_height; - depth = cinfo->num_components; - - if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK; - - jpeg_start_decompress(cinfo); - - if (flags & IB_test) { - jpeg_abort_decompress(cinfo); - ibuf = IMB_allocImBuf(x, y, 8 * depth, 0); - } - else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) { - jpeg_abort_decompress(cinfo); - } - else { - row_stride = cinfo->output_width * depth; - - row_pointer = (*cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1); - - for (y = ibuf->y - 1; y >= 0; y--) { - jpeg_read_scanlines(cinfo, row_pointer, 1); - rect = (uchar *) (ibuf->rect + y * ibuf->x); - buffer = row_pointer[0]; - - switch (depth) { - case 1: - for (x = ibuf->x; x > 0; x--) { - rect[3] = 255; - rect[0] = rect[1] = rect[2] = *buffer++; - rect += 4; - } - break; - case 3: - for (x = ibuf->x; x > 0; x--) { - rect[3] = 255; - rect[0] = *buffer++; - rect[1] = *buffer++; - rect[2] = *buffer++; - rect += 4; - } - break; - case 4: - for (x = ibuf->x; x > 0; x--) { - r = *buffer++; - g = *buffer++; - b = *buffer++; - k = *buffer++; - - r = (r * k) / 255; - g = (g * k) / 255; - b = (b * k) / 255; - - rect[3] = 255; - rect[2] = b; - rect[1] = g; - rect[0] = r; - rect += 4; - } - break; - } - } - - marker = cinfo->marker_list; - while (marker) { - if (marker->marker != JPEG_COM) - goto next_stamp_marker; - - /* - * JPEG marker strings are not null-terminated, - * create a null-terminated copy before going further - */ - str = BLI_strdupn((char *)marker->data, marker->data_length); - - /* - * Because JPEG format don't support the - * pair "key/value" like PNG, we store the - * stampinfo in a single "encode" string: - * "Blender:key:value" - * - * That is why we need split it to the - * common key/value here. - */ - if (!STREQLEN(str, "Blender", 7)) { - /* - * Maybe the file have text that - * we don't know "what it's", in that - * case we keep the text (with a - * key "None"). - * This is only for don't "lose" - * the information when we write - * it back to disk. - */ - IMB_metadata_ensure(&ibuf->metadata); - IMB_metadata_set_field(ibuf->metadata, "None", str); - ibuf->flags |= IB_metadata; - MEM_freeN(str); - goto next_stamp_marker; - } - - key = strchr(str, ':'); - /* - * A little paranoid, but the file maybe - * is broken... and a "extra" check is better - * then segfault ;) - */ - if (!key) { - MEM_freeN(str); - goto next_stamp_marker; - } - - key++; - value = strchr(key, ':'); - if (!value) { - MEM_freeN(str); - goto next_stamp_marker; - } - - *value = '\0'; /* need finish the key string */ - value++; - IMB_metadata_ensure(&ibuf->metadata); - IMB_metadata_set_field(ibuf->metadata, key, value); - ibuf->flags |= IB_metadata; - MEM_freeN(str); -next_stamp_marker: - marker = marker->next; - } - - jpeg_finish_decompress(cinfo); - } - - jpeg_destroy((j_common_ptr) cinfo); - if (ibuf) { - ibuf->ftype = IMB_FTYPE_JPG; - ibuf->foptions.quality = MIN2(ibuf_quality, 100); - } - } - - return(ibuf); + JSAMPARRAY row_pointer; + JSAMPLE *buffer = NULL; + int row_stride; + int x, y, depth, r, g, b, k; + struct ImBuf *ibuf = NULL; + uchar *rect; + jpeg_saved_marker_ptr marker; + char *str, *key, *value; + + /* install own app1 handler */ + ibuf_quality = jpeg_default_quality; + jpeg_set_marker_processor(cinfo, 0xe1, handle_app1); + cinfo->dct_method = JDCT_FLOAT; + jpeg_save_markers(cinfo, JPEG_COM, 0xffff); + + if (jpeg_read_header(cinfo, false) == JPEG_HEADER_OK) { + x = cinfo->image_width; + y = cinfo->image_height; + depth = cinfo->num_components; + + if (cinfo->jpeg_color_space == JCS_YCCK) + cinfo->out_color_space = JCS_CMYK; + + jpeg_start_decompress(cinfo); + + if (flags & IB_test) { + jpeg_abort_decompress(cinfo); + ibuf = IMB_allocImBuf(x, y, 8 * depth, 0); + } + else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) { + jpeg_abort_decompress(cinfo); + } + else { + row_stride = cinfo->output_width * depth; + + row_pointer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1); + + for (y = ibuf->y - 1; y >= 0; y--) { + jpeg_read_scanlines(cinfo, row_pointer, 1); + rect = (uchar *)(ibuf->rect + y * ibuf->x); + buffer = row_pointer[0]; + + switch (depth) { + case 1: + for (x = ibuf->x; x > 0; x--) { + rect[3] = 255; + rect[0] = rect[1] = rect[2] = *buffer++; + rect += 4; + } + break; + case 3: + for (x = ibuf->x; x > 0; x--) { + rect[3] = 255; + rect[0] = *buffer++; + rect[1] = *buffer++; + rect[2] = *buffer++; + rect += 4; + } + break; + case 4: + for (x = ibuf->x; x > 0; x--) { + r = *buffer++; + g = *buffer++; + b = *buffer++; + k = *buffer++; + + r = (r * k) / 255; + g = (g * k) / 255; + b = (b * k) / 255; + + rect[3] = 255; + rect[2] = b; + rect[1] = g; + rect[0] = r; + rect += 4; + } + break; + } + } + + marker = cinfo->marker_list; + while (marker) { + if (marker->marker != JPEG_COM) + goto next_stamp_marker; + + /* + * JPEG marker strings are not null-terminated, + * create a null-terminated copy before going further + */ + str = BLI_strdupn((char *)marker->data, marker->data_length); + + /* + * Because JPEG format don't support the + * pair "key/value" like PNG, we store the + * stampinfo in a single "encode" string: + * "Blender:key:value" + * + * That is why we need split it to the + * common key/value here. + */ + if (!STREQLEN(str, "Blender", 7)) { + /* + * Maybe the file have text that + * we don't know "what it's", in that + * case we keep the text (with a + * key "None"). + * This is only for don't "lose" + * the information when we write + * it back to disk. + */ + IMB_metadata_ensure(&ibuf->metadata); + IMB_metadata_set_field(ibuf->metadata, "None", str); + ibuf->flags |= IB_metadata; + MEM_freeN(str); + goto next_stamp_marker; + } + + key = strchr(str, ':'); + /* + * A little paranoid, but the file maybe + * is broken... and a "extra" check is better + * then segfault ;) + */ + if (!key) { + MEM_freeN(str); + goto next_stamp_marker; + } + + key++; + value = strchr(key, ':'); + if (!value) { + MEM_freeN(str); + goto next_stamp_marker; + } + + *value = '\0'; /* need finish the key string */ + value++; + IMB_metadata_ensure(&ibuf->metadata); + IMB_metadata_set_field(ibuf->metadata, key, value); + ibuf->flags |= IB_metadata; + MEM_freeN(str); + next_stamp_marker: + marker = marker->next; + } + + jpeg_finish_decompress(cinfo); + } + + jpeg_destroy((j_common_ptr)cinfo); + if (ibuf) { + ibuf->ftype = IMB_FTYPE_JPG; + ibuf->foptions.quality = MIN2(ibuf_quality, 100); + } + } + + return (ibuf); } -ImBuf *imb_load_jpeg(const unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_jpeg(const unsigned char *buffer, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo; - struct my_error_mgr jerr; - ImBuf *ibuf; + struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo; + struct my_error_mgr jerr; + ImBuf *ibuf; - if (!imb_is_a_jpeg(buffer)) return NULL; + if (!imb_is_a_jpeg(buffer)) + return NULL; - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - cinfo->err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = jpeg_error; + cinfo->err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpeg_error; - /* Establish the setjmp return context for my_error_exit to use. */ - if (setjmp(jerr.setjmp_buffer)) { - /* If we get here, the JPEG code has signaled an error. - * We need to clean up the JPEG object, close the input file, and return. - */ - jpeg_destroy_decompress(cinfo); - return NULL; - } + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(cinfo); + return NULL; + } - jpeg_create_decompress(cinfo); - memory_source(cinfo, buffer, size); + jpeg_create_decompress(cinfo); + memory_source(cinfo, buffer, size); - ibuf = ibJpegImageFromCinfo(cinfo, flags); + ibuf = ibJpegImageFromCinfo(cinfo, flags); - return(ibuf); + return (ibuf); } - static void write_jpeg(struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf) { - JSAMPLE *buffer = NULL; - JSAMPROW row_pointer[1]; - uchar *rect; - int x, y; - char neogeo[128]; - struct NeoGeo_Word *neogeo_word; - - jpeg_start_compress(cinfo, true); - - strcpy(neogeo, "NeoGeo"); - neogeo_word = (struct NeoGeo_Word *)(neogeo + 6); - memset(neogeo_word, 0, sizeof(*neogeo_word)); - neogeo_word->quality = ibuf->foptions.quality; - jpeg_write_marker(cinfo, 0xe1, (JOCTET *) neogeo, 10); - if (ibuf->metadata) { - IDProperty *prop; - /* Static storage array for the short metadata. */ - char static_text[1024]; - const int static_text_size = ARRAY_SIZE(static_text); - for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) { - if (prop->type == IDP_STRING) { - int text_len; - if (!strcmp(prop->name, "None")) { - jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) IDP_String(prop), prop->len + 1); - } - - char *text = static_text; - int text_size = static_text_size; - /* 7 is for Blender, 2 colon separators, length of property - * name and property value, followed by the NULL-terminator. */ - const int text_length_required = 7 + 2 + strlen(prop->name) + strlen(IDP_String(prop)) + 1; - if (text_length_required <= static_text_size) { - text = MEM_mallocN(text_length_required, "jpeg metadata field"); - text_size = text_length_required; - } - - /* - * The JPEG format don't support a pair "key/value" - * like PNG, so we "encode" the stamp in a - * single string: - * "Blender:key:value" - * - * The first "Blender" is a simple identify to help - * in the read process. - */ - text_len = BLI_snprintf(text, text_size, "Blender:%s:%s", prop->name, IDP_String(prop)); - jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) text, text_len + 1); - - /* TODO(sergey): Ideally we will try to re-use allocation as - * much as possible. In practice, such long fields don't happen - * often. */ - if (text != static_text) { - MEM_freeN(text); - } - } - } - } - - row_pointer[0] = - MEM_mallocN(sizeof(JSAMPLE) * - cinfo->input_components * - cinfo->image_width, "jpeg row_pointer"); - - for (y = ibuf->y - 1; y >= 0; y--) { - rect = (uchar *) (ibuf->rect + y * ibuf->x); - buffer = row_pointer[0]; - - switch (cinfo->in_color_space) { - case JCS_RGB: - for (x = 0; x < ibuf->x; x++) { - *buffer++ = rect[0]; - *buffer++ = rect[1]; - *buffer++ = rect[2]; - rect += 4; - } - break; - case JCS_GRAYSCALE: - for (x = 0; x < ibuf->x; x++) { - *buffer++ = rect[0]; - rect += 4; - } - break; - case JCS_UNKNOWN: - memcpy(buffer, rect, 4 * ibuf->x); - break; - /* default was missing... intentional ? */ - default: - /* do nothing */ - break; - } - - jpeg_write_scanlines(cinfo, row_pointer, 1); - } - - jpeg_finish_compress(cinfo); - MEM_freeN(row_pointer[0]); + JSAMPLE *buffer = NULL; + JSAMPROW row_pointer[1]; + uchar *rect; + int x, y; + char neogeo[128]; + struct NeoGeo_Word *neogeo_word; + + jpeg_start_compress(cinfo, true); + + strcpy(neogeo, "NeoGeo"); + neogeo_word = (struct NeoGeo_Word *)(neogeo + 6); + memset(neogeo_word, 0, sizeof(*neogeo_word)); + neogeo_word->quality = ibuf->foptions.quality; + jpeg_write_marker(cinfo, 0xe1, (JOCTET *)neogeo, 10); + if (ibuf->metadata) { + IDProperty *prop; + /* Static storage array for the short metadata. */ + char static_text[1024]; + const int static_text_size = ARRAY_SIZE(static_text); + for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) { + if (prop->type == IDP_STRING) { + int text_len; + if (!strcmp(prop->name, "None")) { + jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *)IDP_String(prop), prop->len + 1); + } + + char *text = static_text; + int text_size = static_text_size; + /* 7 is for Blender, 2 colon separators, length of property + * name and property value, followed by the NULL-terminator. */ + const int text_length_required = 7 + 2 + strlen(prop->name) + strlen(IDP_String(prop)) + 1; + if (text_length_required <= static_text_size) { + text = MEM_mallocN(text_length_required, "jpeg metadata field"); + text_size = text_length_required; + } + + /* + * The JPEG format don't support a pair "key/value" + * like PNG, so we "encode" the stamp in a + * single string: + * "Blender:key:value" + * + * The first "Blender" is a simple identify to help + * in the read process. + */ + text_len = BLI_snprintf(text, text_size, "Blender:%s:%s", prop->name, IDP_String(prop)); + jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *)text, text_len + 1); + + /* TODO(sergey): Ideally we will try to re-use allocation as + * much as possible. In practice, such long fields don't happen + * often. */ + if (text != static_text) { + MEM_freeN(text); + } + } + } + } + + row_pointer[0] = MEM_mallocN(sizeof(JSAMPLE) * cinfo->input_components * cinfo->image_width, + "jpeg row_pointer"); + + for (y = ibuf->y - 1; y >= 0; y--) { + rect = (uchar *)(ibuf->rect + y * ibuf->x); + buffer = row_pointer[0]; + + switch (cinfo->in_color_space) { + case JCS_RGB: + for (x = 0; x < ibuf->x; x++) { + *buffer++ = rect[0]; + *buffer++ = rect[1]; + *buffer++ = rect[2]; + rect += 4; + } + break; + case JCS_GRAYSCALE: + for (x = 0; x < ibuf->x; x++) { + *buffer++ = rect[0]; + rect += 4; + } + break; + case JCS_UNKNOWN: + memcpy(buffer, rect, 4 * ibuf->x); + break; + /* default was missing... intentional ? */ + default: + /* do nothing */ + break; + } + + jpeg_write_scanlines(cinfo, row_pointer, 1); + } + + jpeg_finish_compress(cinfo); + MEM_freeN(row_pointer[0]); } - static int init_jpeg(FILE *outfile, struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf) { - int quality; + int quality; - quality = ibuf->foptions.quality; - if (quality <= 0) quality = jpeg_default_quality; - if (quality > 100) quality = 100; + quality = ibuf->foptions.quality; + if (quality <= 0) + quality = jpeg_default_quality; + if (quality > 100) + quality = 100; - jpeg_create_compress(cinfo); - jpeg_stdio_dest(cinfo, outfile); + jpeg_create_compress(cinfo); + jpeg_stdio_dest(cinfo, outfile); - cinfo->image_width = ibuf->x; - cinfo->image_height = ibuf->y; + cinfo->image_width = ibuf->x; + cinfo->image_height = ibuf->y; - cinfo->in_color_space = JCS_RGB; - if (ibuf->planes == 8) cinfo->in_color_space = JCS_GRAYSCALE; + cinfo->in_color_space = JCS_RGB; + if (ibuf->planes == 8) + cinfo->in_color_space = JCS_GRAYSCALE; #if 0 - /* just write RGBA as RGB, - * unsupported feature only confuses other s/w */ + /* just write RGBA as RGB, + * unsupported feature only confuses other s/w */ - if (ibuf->planes == 32) cinfo->in_color_space = JCS_UNKNOWN; + if (ibuf->planes == 32) cinfo->in_color_space = JCS_UNKNOWN; #endif - switch (cinfo->in_color_space) { - case JCS_RGB: - cinfo->input_components = 3; - break; - case JCS_GRAYSCALE: - cinfo->input_components = 1; - break; - case JCS_UNKNOWN: - cinfo->input_components = 4; - break; - /* default was missing... intentional ? */ - default: - /* do nothing */ - break; - } - jpeg_set_defaults(cinfo); - - /* own settings */ - - cinfo->dct_method = JDCT_FLOAT; - jpeg_set_quality(cinfo, quality, true); - - return(0); + switch (cinfo->in_color_space) { + case JCS_RGB: + cinfo->input_components = 3; + break; + case JCS_GRAYSCALE: + cinfo->input_components = 1; + break; + case JCS_UNKNOWN: + cinfo->input_components = 4; + break; + /* default was missing... intentional ? */ + default: + /* do nothing */ + break; + } + jpeg_set_defaults(cinfo); + + /* own settings */ + + cinfo->dct_method = JDCT_FLOAT; + jpeg_set_quality(cinfo, quality, true); + + return (0); } - static int save_stdjpeg(const char *name, struct ImBuf *ibuf) { - FILE *outfile; - struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo; - struct my_error_mgr jerr; + FILE *outfile; + struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo; + struct my_error_mgr jerr; - if ((outfile = BLI_fopen(name, "wb")) == NULL) - return 0; + if ((outfile = BLI_fopen(name, "wb")) == NULL) + return 0; - cinfo->err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = jpeg_error; + cinfo->err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpeg_error; - /* Establish the setjmp return context for jpeg_error to use. */ - if (setjmp(jerr.setjmp_buffer)) { - /* If we get here, the JPEG code has signaled an error. - * We need to clean up the JPEG object, close the input file, and return. - */ - jpeg_destroy_compress(cinfo); - fclose(outfile); - remove(name); - return 0; - } + /* Establish the setjmp return context for jpeg_error to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_compress(cinfo); + fclose(outfile); + remove(name); + return 0; + } - init_jpeg(outfile, cinfo, ibuf); + init_jpeg(outfile, cinfo, ibuf); - write_jpeg(cinfo, ibuf); + write_jpeg(cinfo, ibuf); - fclose(outfile); - jpeg_destroy_compress(cinfo); + fclose(outfile); + jpeg_destroy_compress(cinfo); - return 1; + return 1; } int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags) { - ibuf->flags = flags; - return save_stdjpeg(name, ibuf); + ibuf->flags = flags; + return save_stdjpeg(name, ibuf); } diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index cc4c2661ef2..ed3b214047a 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -21,7 +21,6 @@ * \ingroup imbuf */ - #include #include @@ -39,77 +38,79 @@ #define METADATA_MAX_VALUE_LENGTH 1024 - void IMB_metadata_ensure(struct IDProperty **metadata) { - if (*metadata != NULL) { - return; - } + if (*metadata != NULL) { + return; + } - IDPropertyTemplate val; - *metadata = IDP_New(IDP_GROUP, &val, "metadata"); + IDPropertyTemplate val; + *metadata = IDP_New(IDP_GROUP, &val, "metadata"); } void IMB_metadata_free(struct IDProperty *metadata) { - if (metadata == NULL) { - return; - } + if (metadata == NULL) { + return; + } - IDP_FreeProperty(metadata); - MEM_freeN(metadata); + IDP_FreeProperty(metadata); + MEM_freeN(metadata); } -bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *field, const size_t len) +bool IMB_metadata_get_field(struct IDProperty *metadata, + const char *key, + char *field, + const size_t len) { - IDProperty *prop; + IDProperty *prop; - if (metadata == NULL) { - return false; - } + if (metadata == NULL) { + return false; + } - prop = IDP_GetPropertyFromGroup(metadata, key); + prop = IDP_GetPropertyFromGroup(metadata, key); - if (prop && prop->type == IDP_STRING) { - BLI_strncpy(field, IDP_String(prop), len); - return true; - } - return false; + if (prop && prop->type == IDP_STRING) { + BLI_strncpy(field, IDP_String(prop), len); + return true; + } + return false; } void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb) { - BLI_assert(dimb != simb); - if (simb->metadata) { - IMB_metadata_free(dimb->metadata); - dimb->metadata = IDP_CopyProperty(simb->metadata); - } + BLI_assert(dimb != simb); + if (simb->metadata) { + IMB_metadata_free(dimb->metadata); + dimb->metadata = IDP_CopyProperty(simb->metadata); + } } void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value) { - BLI_assert(metadata); - IDProperty *prop = IDP_GetPropertyFromGroup(metadata, key); + BLI_assert(metadata); + IDProperty *prop = IDP_GetPropertyFromGroup(metadata, key); - if (prop != NULL && prop->type != IDP_STRING) { - IDP_FreeFromGroup(metadata, prop); - prop = NULL; - } + if (prop != NULL && prop->type != IDP_STRING) { + IDP_FreeFromGroup(metadata, prop); + prop = NULL; + } - if (prop == NULL) { - prop = IDP_NewString(value, key, METADATA_MAX_VALUE_LENGTH); - IDP_AddToGroup(metadata, prop); - } + if (prop == NULL) { + prop = IDP_NewString(value, key, METADATA_MAX_VALUE_LENGTH); + IDP_AddToGroup(metadata, prop); + } - IDP_AssignString(prop, value, METADATA_MAX_VALUE_LENGTH); + IDP_AssignString(prop, value, METADATA_MAX_VALUE_LENGTH); } void IMB_metadata_foreach(struct ImBuf *ibuf, IMBMetadataForeachCb callback, void *userdata) { - if (ibuf->metadata == NULL) { - return; - } - for (IDProperty *prop = ibuf->metadata->data.group.first; prop != NULL; prop = prop->next) { - callback(prop->name, IDP_String(prop), userdata); - } + if (ibuf->metadata == NULL) { + return; + } + for (IDProperty *prop = ibuf->metadata->data.group.first; prop != NULL; prop = prop->next) { + callback(prop->name, IDP_String(prop), userdata); + } } diff --git a/source/blender/imbuf/intern/module.c b/source/blender/imbuf/intern/module.c index c22ac2c9bfc..dc3d4cfbb62 100644 --- a/source/blender/imbuf/intern/module.c +++ b/source/blender/imbuf/intern/module.c @@ -18,7 +18,6 @@ * \ingroup imbuf */ - #include #include "BLI_utildefines.h" @@ -30,18 +29,18 @@ void IMB_init(void) { - imb_refcounter_lock_init(); - imb_mmap_lock_init(); - imb_filetypes_init(); - imb_tile_cache_init(); - colormanagement_init(); + imb_refcounter_lock_init(); + imb_mmap_lock_init(); + imb_filetypes_init(); + imb_tile_cache_init(); + colormanagement_init(); } void IMB_exit(void) { - imb_tile_cache_exit(); - imb_filetypes_exit(); - colormanagement_exit(); - imb_mmap_lock_exit(); - imb_refcounter_lock_exit(); + imb_tile_cache_exit(); + imb_filetypes_exit(); + colormanagement_exit(); + imb_mmap_lock_exit(); + imb_refcounter_lock_exit(); } diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index 78a45d29775..fe6909b0f3f 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -42,7 +42,7 @@ #ifdef DEBUG_MESSAGES # if defined __GNUC__ -# define PRINT(format, args ...) printf(format, ##args) +# define PRINT(format, args...) printf(format, ##args) # else # define PRINT(format, ...) printf(__VA_ARGS__) # endif @@ -54,552 +54,562 @@ static MEM_CacheLimiterC *limitor = NULL; static pthread_mutex_t limitor_lock = BLI_MUTEX_INITIALIZER; typedef struct MovieCache { - char name[64]; + char name[64]; - GHash *hash; - GHashHashFP hashfp; - GHashCmpFP cmpfp; - MovieCacheGetKeyDataFP getdatafp; + GHash *hash; + GHashHashFP hashfp; + GHashCmpFP cmpfp; + MovieCacheGetKeyDataFP getdatafp; - MovieCacheGetPriorityDataFP getprioritydatafp; - MovieCacheGetItemPriorityFP getitempriorityfp; - MovieCachePriorityDeleterFP prioritydeleterfp; + MovieCacheGetPriorityDataFP getprioritydatafp; + MovieCacheGetItemPriorityFP getitempriorityfp; + MovieCachePriorityDeleterFP prioritydeleterfp; - struct BLI_mempool *keys_pool; - struct BLI_mempool *items_pool; - struct BLI_mempool *userkeys_pool; + struct BLI_mempool *keys_pool; + struct BLI_mempool *items_pool; + struct BLI_mempool *userkeys_pool; - int keysize; + int keysize; - void *last_userkey; + void *last_userkey; - int totseg, *points, proxy, render_flags; /* for visual statistics optimization */ - int pad; + int totseg, *points, proxy, render_flags; /* for visual statistics optimization */ + int pad; } MovieCache; typedef struct MovieCacheKey { - MovieCache *cache_owner; - void *userkey; + MovieCache *cache_owner; + void *userkey; } MovieCacheKey; typedef struct MovieCacheItem { - MovieCache *cache_owner; - ImBuf *ibuf; - MEM_CacheLimiterHandleC *c_handle; - void *priority_data; + MovieCache *cache_owner; + ImBuf *ibuf; + MEM_CacheLimiterHandleC *c_handle; + void *priority_data; } MovieCacheItem; static unsigned int moviecache_hashhash(const void *keyv) { - const MovieCacheKey *key = keyv; + const MovieCacheKey *key = keyv; - return key->cache_owner->hashfp(key->userkey); + return key->cache_owner->hashfp(key->userkey); } static bool moviecache_hashcmp(const void *av, const void *bv) { - const MovieCacheKey *a = av; - const MovieCacheKey *b = bv; + const MovieCacheKey *a = av; + const MovieCacheKey *b = bv; - return a->cache_owner->cmpfp(a->userkey, b->userkey); + return a->cache_owner->cmpfp(a->userkey, b->userkey); } static void moviecache_keyfree(void *val) { - MovieCacheKey *key = val; + MovieCacheKey *key = val; - BLI_mempool_free(key->cache_owner->userkeys_pool, key->userkey); + BLI_mempool_free(key->cache_owner->userkeys_pool, key->userkey); - BLI_mempool_free(key->cache_owner->keys_pool, key); + BLI_mempool_free(key->cache_owner->keys_pool, key); } static void moviecache_valfree(void *val) { - MovieCacheItem *item = (MovieCacheItem *)val; - MovieCache *cache = item->cache_owner; + MovieCacheItem *item = (MovieCacheItem *)val; + MovieCache *cache = item->cache_owner; - PRINT("%s: cache '%s' free item %p buffer %p\n", __func__, cache->name, item, item->ibuf); + PRINT("%s: cache '%s' free item %p buffer %p\n", __func__, cache->name, item, item->ibuf); - if (item->ibuf) { - MEM_CacheLimiter_unmanage(item->c_handle); - IMB_freeImBuf(item->ibuf); - } + if (item->ibuf) { + MEM_CacheLimiter_unmanage(item->c_handle); + IMB_freeImBuf(item->ibuf); + } - if (item->priority_data && cache->prioritydeleterfp) { - cache->prioritydeleterfp(item->priority_data); - } + if (item->priority_data && cache->prioritydeleterfp) { + cache->prioritydeleterfp(item->priority_data); + } - BLI_mempool_free(item->cache_owner->items_pool, item); + BLI_mempool_free(item->cache_owner->items_pool, item); } static void check_unused_keys(MovieCache *cache) { - GHashIterator gh_iter; + GHashIterator gh_iter; - BLI_ghashIterator_init(&gh_iter, cache->hash); + BLI_ghashIterator_init(&gh_iter, cache->hash); - while (!BLI_ghashIterator_done(&gh_iter)) { - const MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); - const MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); - bool remove; + while (!BLI_ghashIterator_done(&gh_iter)) { + const MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); + const MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); + bool remove; - BLI_ghashIterator_step(&gh_iter); + BLI_ghashIterator_step(&gh_iter); - remove = !item->ibuf; + remove = !item->ibuf; - if (remove) { - PRINT("%s: cache '%s' remove item %p without buffer\n", __func__, cache->name, item); - } + if (remove) { + PRINT("%s: cache '%s' remove item %p without buffer\n", __func__, cache->name, item); + } - if (remove) - BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree); - } + if (remove) + BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree); + } } static int compare_int(const void *av, const void *bv) { - const int *a = av; - const int *b = bv; - return *a - *b; + const int *a = av; + const int *b = bv; + return *a - *b; } static void IMB_moviecache_destructor(void *p) { - MovieCacheItem *item = (MovieCacheItem *)p; + MovieCacheItem *item = (MovieCacheItem *)p; - if (item && item->ibuf) { - MovieCache *cache = item->cache_owner; + if (item && item->ibuf) { + MovieCache *cache = item->cache_owner; - PRINT("%s: cache '%s' destroy item %p buffer %p\n", __func__, cache->name, item, item->ibuf); + PRINT("%s: cache '%s' destroy item %p buffer %p\n", __func__, cache->name, item, item->ibuf); - IMB_freeImBuf(item->ibuf); + IMB_freeImBuf(item->ibuf); - item->ibuf = NULL; - item->c_handle = NULL; + item->ibuf = NULL; + item->c_handle = NULL; - /* force cached segments to be updated */ - if (cache->points) { - MEM_freeN(cache->points); - cache->points = NULL; - } - } + /* force cached segments to be updated */ + if (cache->points) { + MEM_freeN(cache->points); + cache->points = NULL; + } + } } /* approximate size of ImBuf in memory */ static size_t IMB_get_size_in_memory(ImBuf *ibuf) { - int a; - size_t size = 0, channel_size = 0; - - /* Persistent images should have no affect on how "normal" - * images are cached. - * - * This is a bit arbitrary, but would make it so only movies - * and sequences are memory limited, keeping textures in the - * memory in order to avoid constant file reload on viewport - * update. - */ - if (ibuf->userflags & IB_PERSISTENT) { - return 0; - } - - size += sizeof(ImBuf); - - if (ibuf->rect) - channel_size += sizeof(char); - - if (ibuf->rect_float) - channel_size += sizeof(float); - - size += channel_size * ibuf->x * ibuf->y * ibuf->channels; - - if (ibuf->miptot) { - for (a = 0; a < ibuf->miptot; a++) { - if (ibuf->mipmap[a]) - size += IMB_get_size_in_memory(ibuf->mipmap[a]); - } - } - - if (ibuf->tiles) { - size += sizeof(unsigned int) * ibuf->ytiles * ibuf->xtiles; - } - - return size; + int a; + size_t size = 0, channel_size = 0; + + /* Persistent images should have no affect on how "normal" + * images are cached. + * + * This is a bit arbitrary, but would make it so only movies + * and sequences are memory limited, keeping textures in the + * memory in order to avoid constant file reload on viewport + * update. + */ + if (ibuf->userflags & IB_PERSISTENT) { + return 0; + } + + size += sizeof(ImBuf); + + if (ibuf->rect) + channel_size += sizeof(char); + + if (ibuf->rect_float) + channel_size += sizeof(float); + + size += channel_size * ibuf->x * ibuf->y * ibuf->channels; + + if (ibuf->miptot) { + for (a = 0; a < ibuf->miptot; a++) { + if (ibuf->mipmap[a]) + size += IMB_get_size_in_memory(ibuf->mipmap[a]); + } + } + + if (ibuf->tiles) { + size += sizeof(unsigned int) * ibuf->ytiles * ibuf->xtiles; + } + + return size; } static size_t get_item_size(void *p) { - size_t size = sizeof(MovieCacheItem); - MovieCacheItem *item = (MovieCacheItem *) p; + size_t size = sizeof(MovieCacheItem); + MovieCacheItem *item = (MovieCacheItem *)p; - if (item->ibuf) - size += IMB_get_size_in_memory(item->ibuf); + if (item->ibuf) + size += IMB_get_size_in_memory(item->ibuf); - return size; + return size; } static int get_item_priority(void *item_v, int default_priority) { - MovieCacheItem *item = (MovieCacheItem *) item_v; - MovieCache *cache = item->cache_owner; - int priority; + MovieCacheItem *item = (MovieCacheItem *)item_v; + MovieCache *cache = item->cache_owner; + int priority; - if (!cache->getitempriorityfp) { - PRINT("%s: cache '%s' item %p use default priority %d\n", __func__, cache-> name, item, default_priority); + if (!cache->getitempriorityfp) { + PRINT("%s: cache '%s' item %p use default priority %d\n", + __func__, + cache->name, + item, + default_priority); - return default_priority; - } + return default_priority; + } - priority = cache->getitempriorityfp(cache->last_userkey, item->priority_data); + priority = cache->getitempriorityfp(cache->last_userkey, item->priority_data); - PRINT("%s: cache '%s' item %p priority %d\n", __func__, cache-> name, item, priority); + PRINT("%s: cache '%s' item %p priority %d\n", __func__, cache->name, item, priority); - return priority; + return priority; } static bool get_item_destroyable(void *item_v) { - MovieCacheItem *item = (MovieCacheItem *) item_v; - /* IB_BITMAPDIRTY means image was modified from inside blender and - * changes are not saved to disk. - * - * Such buffers are never to be freed. - */ - if ((item->ibuf->userflags & IB_BITMAPDIRTY) || - (item->ibuf->userflags & IB_PERSISTENT)) - { - return false; - } - return true; + MovieCacheItem *item = (MovieCacheItem *)item_v; + /* IB_BITMAPDIRTY means image was modified from inside blender and + * changes are not saved to disk. + * + * Such buffers are never to be freed. + */ + if ((item->ibuf->userflags & IB_BITMAPDIRTY) || (item->ibuf->userflags & IB_PERSISTENT)) { + return false; + } + return true; } void IMB_moviecache_init(void) { - limitor = new_MEM_CacheLimiter(IMB_moviecache_destructor, get_item_size); + limitor = new_MEM_CacheLimiter(IMB_moviecache_destructor, get_item_size); - MEM_CacheLimiter_ItemPriority_Func_set(limitor, get_item_priority); - MEM_CacheLimiter_ItemDestroyable_Func_set(limitor, get_item_destroyable); + MEM_CacheLimiter_ItemPriority_Func_set(limitor, get_item_priority); + MEM_CacheLimiter_ItemDestroyable_Func_set(limitor, get_item_destroyable); } void IMB_moviecache_destruct(void) { - if (limitor) - delete_MEM_CacheLimiter(limitor); + if (limitor) + delete_MEM_CacheLimiter(limitor); } -MovieCache *IMB_moviecache_create(const char *name, int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp) +MovieCache *IMB_moviecache_create(const char *name, + int keysize, + GHashHashFP hashfp, + GHashCmpFP cmpfp) { - MovieCache *cache; + MovieCache *cache; - PRINT("%s: cache '%s' create\n", __func__, name); + PRINT("%s: cache '%s' create\n", __func__, name); - cache = MEM_callocN(sizeof(MovieCache), "MovieCache"); + cache = MEM_callocN(sizeof(MovieCache), "MovieCache"); - BLI_strncpy(cache->name, name, sizeof(cache->name)); + BLI_strncpy(cache->name, name, sizeof(cache->name)); - cache->keys_pool = BLI_mempool_create(sizeof(MovieCacheKey), 0, 64, BLI_MEMPOOL_NOP); - cache->items_pool = BLI_mempool_create(sizeof(MovieCacheItem), 0, 64, BLI_MEMPOOL_NOP); - cache->userkeys_pool = BLI_mempool_create(keysize, 0, 64, BLI_MEMPOOL_NOP); - cache->hash = BLI_ghash_new(moviecache_hashhash, moviecache_hashcmp, "MovieClip ImBuf cache hash"); + cache->keys_pool = BLI_mempool_create(sizeof(MovieCacheKey), 0, 64, BLI_MEMPOOL_NOP); + cache->items_pool = BLI_mempool_create(sizeof(MovieCacheItem), 0, 64, BLI_MEMPOOL_NOP); + cache->userkeys_pool = BLI_mempool_create(keysize, 0, 64, BLI_MEMPOOL_NOP); + cache->hash = BLI_ghash_new( + moviecache_hashhash, moviecache_hashcmp, "MovieClip ImBuf cache hash"); - cache->keysize = keysize; - cache->hashfp = hashfp; - cache->cmpfp = cmpfp; - cache->proxy = -1; + cache->keysize = keysize; + cache->hashfp = hashfp; + cache->cmpfp = cmpfp; + cache->proxy = -1; - return cache; + return cache; } void IMB_moviecache_set_getdata_callback(MovieCache *cache, MovieCacheGetKeyDataFP getdatafp) { - cache->getdatafp = getdatafp; + cache->getdatafp = getdatafp; } -void IMB_moviecache_set_priority_callback(struct MovieCache *cache, MovieCacheGetPriorityDataFP getprioritydatafp, +void IMB_moviecache_set_priority_callback(struct MovieCache *cache, + MovieCacheGetPriorityDataFP getprioritydatafp, MovieCacheGetItemPriorityFP getitempriorityfp, MovieCachePriorityDeleterFP prioritydeleterfp) { - cache->last_userkey = MEM_mallocN(cache->keysize, "movie cache last user key"); + cache->last_userkey = MEM_mallocN(cache->keysize, "movie cache last user key"); - cache->getprioritydatafp = getprioritydatafp; - cache->getitempriorityfp = getitempriorityfp; - cache->prioritydeleterfp = prioritydeleterfp; + cache->getprioritydatafp = getprioritydatafp; + cache->getitempriorityfp = getitempriorityfp; + cache->prioritydeleterfp = prioritydeleterfp; } static void do_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf, bool need_lock) { - MovieCacheKey *key; - MovieCacheItem *item; + MovieCacheKey *key; + MovieCacheItem *item; - if (!limitor) - IMB_moviecache_init(); + if (!limitor) + IMB_moviecache_init(); - IMB_refImBuf(ibuf); + IMB_refImBuf(ibuf); - key = BLI_mempool_alloc(cache->keys_pool); - key->cache_owner = cache; - key->userkey = BLI_mempool_alloc(cache->userkeys_pool); - memcpy(key->userkey, userkey, cache->keysize); + key = BLI_mempool_alloc(cache->keys_pool); + key->cache_owner = cache; + key->userkey = BLI_mempool_alloc(cache->userkeys_pool); + memcpy(key->userkey, userkey, cache->keysize); - item = BLI_mempool_alloc(cache->items_pool); + item = BLI_mempool_alloc(cache->items_pool); - PRINT("%s: cache '%s' put %p, item %p\n", __func__, cache-> name, ibuf, item); + PRINT("%s: cache '%s' put %p, item %p\n", __func__, cache->name, ibuf, item); - item->ibuf = ibuf; - item->cache_owner = cache; - item->c_handle = NULL; - item->priority_data = NULL; + item->ibuf = ibuf; + item->cache_owner = cache; + item->c_handle = NULL; + item->priority_data = NULL; - if (cache->getprioritydatafp) { - item->priority_data = cache->getprioritydatafp(userkey); - } + if (cache->getprioritydatafp) { + item->priority_data = cache->getprioritydatafp(userkey); + } - BLI_ghash_reinsert(cache->hash, key, item, moviecache_keyfree, moviecache_valfree); + BLI_ghash_reinsert(cache->hash, key, item, moviecache_keyfree, moviecache_valfree); - if (cache->last_userkey) { - memcpy(cache->last_userkey, userkey, cache->keysize); - } + if (cache->last_userkey) { + memcpy(cache->last_userkey, userkey, cache->keysize); + } - if (need_lock) - BLI_mutex_lock(&limitor_lock); + if (need_lock) + BLI_mutex_lock(&limitor_lock); - item->c_handle = MEM_CacheLimiter_insert(limitor, item); + item->c_handle = MEM_CacheLimiter_insert(limitor, item); - MEM_CacheLimiter_ref(item->c_handle); - MEM_CacheLimiter_enforce_limits(limitor); - MEM_CacheLimiter_unref(item->c_handle); + MEM_CacheLimiter_ref(item->c_handle); + MEM_CacheLimiter_enforce_limits(limitor); + MEM_CacheLimiter_unref(item->c_handle); - if (need_lock) - BLI_mutex_unlock(&limitor_lock); + if (need_lock) + BLI_mutex_unlock(&limitor_lock); - /* cache limiter can't remove unused keys which points to destroyed values */ - check_unused_keys(cache); + /* cache limiter can't remove unused keys which points to destroyed values */ + check_unused_keys(cache); - if (cache->points) { - MEM_freeN(cache->points); - cache->points = NULL; - } + if (cache->points) { + MEM_freeN(cache->points); + cache->points = NULL; + } } void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf) { - do_moviecache_put(cache, userkey, ibuf, true); + do_moviecache_put(cache, userkey, ibuf, true); } bool IMB_moviecache_put_if_possible(MovieCache *cache, void *userkey, ImBuf *ibuf) { - size_t mem_in_use, mem_limit, elem_size; - bool result = false; + size_t mem_in_use, mem_limit, elem_size; + bool result = false; - elem_size = IMB_get_size_in_memory(ibuf); - mem_limit = MEM_CacheLimiter_get_maximum(); + elem_size = IMB_get_size_in_memory(ibuf); + mem_limit = MEM_CacheLimiter_get_maximum(); - BLI_mutex_lock(&limitor_lock); - mem_in_use = MEM_CacheLimiter_get_memory_in_use(limitor); + BLI_mutex_lock(&limitor_lock); + mem_in_use = MEM_CacheLimiter_get_memory_in_use(limitor); - if (mem_in_use + elem_size <= mem_limit) { - do_moviecache_put(cache, userkey, ibuf, false); - result = true; - } + if (mem_in_use + elem_size <= mem_limit) { + do_moviecache_put(cache, userkey, ibuf, false); + result = true; + } - BLI_mutex_unlock(&limitor_lock); + BLI_mutex_unlock(&limitor_lock); - return result; + return result; } ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey) { - MovieCacheKey key; - MovieCacheItem *item; + MovieCacheKey key; + MovieCacheItem *item; - key.cache_owner = cache; - key.userkey = userkey; - item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key); + key.cache_owner = cache; + key.userkey = userkey; + item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key); - if (item) { - if (item->ibuf) { - BLI_mutex_lock(&limitor_lock); - MEM_CacheLimiter_touch(item->c_handle); - BLI_mutex_unlock(&limitor_lock); + if (item) { + if (item->ibuf) { + BLI_mutex_lock(&limitor_lock); + MEM_CacheLimiter_touch(item->c_handle); + BLI_mutex_unlock(&limitor_lock); - IMB_refImBuf(item->ibuf); + IMB_refImBuf(item->ibuf); - return item->ibuf; - } - } + return item->ibuf; + } + } - return NULL; + return NULL; } bool IMB_moviecache_has_frame(MovieCache *cache, void *userkey) { - MovieCacheKey key; - MovieCacheItem *item; + MovieCacheKey key; + MovieCacheItem *item; - key.cache_owner = cache; - key.userkey = userkey; - item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key); + key.cache_owner = cache; + key.userkey = userkey; + item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key); - return item != NULL; + return item != NULL; } void IMB_moviecache_free(MovieCache *cache) { - PRINT("%s: cache '%s' free\n", __func__, cache->name); + PRINT("%s: cache '%s' free\n", __func__, cache->name); - BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree); + BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree); - BLI_mempool_destroy(cache->keys_pool); - BLI_mempool_destroy(cache->items_pool); - BLI_mempool_destroy(cache->userkeys_pool); + BLI_mempool_destroy(cache->keys_pool); + BLI_mempool_destroy(cache->items_pool); + BLI_mempool_destroy(cache->userkeys_pool); - if (cache->points) - MEM_freeN(cache->points); + if (cache->points) + MEM_freeN(cache->points); - if (cache->last_userkey) - MEM_freeN(cache->last_userkey); + if (cache->last_userkey) + MEM_freeN(cache->last_userkey); - MEM_freeN(cache); + MEM_freeN(cache); } -void IMB_moviecache_cleanup(MovieCache *cache, bool (cleanup_check_cb) (ImBuf *ibuf, void *userkey, void *userdata), void *userdata) +void IMB_moviecache_cleanup(MovieCache *cache, + bool(cleanup_check_cb)(ImBuf *ibuf, void *userkey, void *userdata), + void *userdata) { - GHashIterator gh_iter; + GHashIterator gh_iter; - check_unused_keys(cache); + check_unused_keys(cache); - BLI_ghashIterator_init(&gh_iter, cache->hash); + BLI_ghashIterator_init(&gh_iter, cache->hash); - while (!BLI_ghashIterator_done(&gh_iter)) { - MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); - MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); + while (!BLI_ghashIterator_done(&gh_iter)) { + MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); + MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); - BLI_ghashIterator_step(&gh_iter); + BLI_ghashIterator_step(&gh_iter); - if (cleanup_check_cb(item->ibuf, key->userkey, userdata)) { - PRINT("%s: cache '%s' remove item %p\n", __func__, cache->name, item); + if (cleanup_check_cb(item->ibuf, key->userkey, userdata)) { + PRINT("%s: cache '%s' remove item %p\n", __func__, cache->name, item); - BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree); - } - } + BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree); + } + } } /* get segments of cached frames. useful for debugging cache policies */ -void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r) +void IMB_moviecache_get_cache_segments( + MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r) { - *totseg_r = 0; - *points_r = NULL; - - if (!cache->getdatafp) - return; - - if (cache->proxy != proxy || cache->render_flags != render_flags) { - if (cache->points) - MEM_freeN(cache->points); - - cache->points = NULL; - } - - if (cache->points) { - *totseg_r = cache->totseg; - *points_r = cache->points; - } - else { - int totframe = BLI_ghash_len(cache->hash); - int *frames = MEM_callocN(totframe * sizeof(int), "movieclip cache frames"); - int a, totseg = 0; - GHashIterator gh_iter; - - a = 0; - GHASH_ITER(gh_iter, cache->hash) { - MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); - MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); - int framenr, curproxy, curflags; - - if (item->ibuf) { - cache->getdatafp(key->userkey, &framenr, &curproxy, &curflags); - - if (curproxy == proxy && curflags == render_flags) - frames[a++] = framenr; - } - } - - qsort(frames, totframe, sizeof(int), compare_int); - - /* count */ - for (a = 0; a < totframe; a++) { - if (a && frames[a] - frames[a - 1] != 1) - totseg++; - - if (a == totframe - 1) - totseg++; - } - - if (totseg) { - int b, *points; - - points = MEM_callocN(2 * sizeof(int) * totseg, "movieclip cache segments"); - - /* fill */ - for (a = 0, b = 0; a < totframe; a++) { - if (a == 0) - points[b++] = frames[a]; - - if (a && frames[a] - frames[a - 1] != 1) { - points[b++] = frames[a - 1]; - points[b++] = frames[a]; - } - - if (a == totframe - 1) - points[b++] = frames[a]; - } - - *totseg_r = totseg; - *points_r = points; - - cache->totseg = totseg; - cache->points = points; - cache->proxy = proxy; - cache->render_flags = render_flags; - } - - MEM_freeN(frames); - } + *totseg_r = 0; + *points_r = NULL; + + if (!cache->getdatafp) + return; + + if (cache->proxy != proxy || cache->render_flags != render_flags) { + if (cache->points) + MEM_freeN(cache->points); + + cache->points = NULL; + } + + if (cache->points) { + *totseg_r = cache->totseg; + *points_r = cache->points; + } + else { + int totframe = BLI_ghash_len(cache->hash); + int *frames = MEM_callocN(totframe * sizeof(int), "movieclip cache frames"); + int a, totseg = 0; + GHashIterator gh_iter; + + a = 0; + GHASH_ITER (gh_iter, cache->hash) { + MovieCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); + MovieCacheItem *item = BLI_ghashIterator_getValue(&gh_iter); + int framenr, curproxy, curflags; + + if (item->ibuf) { + cache->getdatafp(key->userkey, &framenr, &curproxy, &curflags); + + if (curproxy == proxy && curflags == render_flags) + frames[a++] = framenr; + } + } + + qsort(frames, totframe, sizeof(int), compare_int); + + /* count */ + for (a = 0; a < totframe; a++) { + if (a && frames[a] - frames[a - 1] != 1) + totseg++; + + if (a == totframe - 1) + totseg++; + } + + if (totseg) { + int b, *points; + + points = MEM_callocN(2 * sizeof(int) * totseg, "movieclip cache segments"); + + /* fill */ + for (a = 0, b = 0; a < totframe; a++) { + if (a == 0) + points[b++] = frames[a]; + + if (a && frames[a] - frames[a - 1] != 1) { + points[b++] = frames[a - 1]; + points[b++] = frames[a]; + } + + if (a == totframe - 1) + points[b++] = frames[a]; + } + + *totseg_r = totseg; + *points_r = points; + + cache->totseg = totseg; + cache->points = points; + cache->proxy = proxy; + cache->render_flags = render_flags; + } + + MEM_freeN(frames); + } } struct MovieCacheIter *IMB_moviecacheIter_new(MovieCache *cache) { - GHashIterator *iter; + GHashIterator *iter; - check_unused_keys(cache); - iter = BLI_ghashIterator_new(cache->hash); + check_unused_keys(cache); + iter = BLI_ghashIterator_new(cache->hash); - return (struct MovieCacheIter *) iter; + return (struct MovieCacheIter *)iter; } void IMB_moviecacheIter_free(struct MovieCacheIter *iter) { - BLI_ghashIterator_free((GHashIterator *) iter); + BLI_ghashIterator_free((GHashIterator *)iter); } bool IMB_moviecacheIter_done(struct MovieCacheIter *iter) { - return BLI_ghashIterator_done((GHashIterator *) iter); + return BLI_ghashIterator_done((GHashIterator *)iter); } void IMB_moviecacheIter_step(struct MovieCacheIter *iter) { - BLI_ghashIterator_step((GHashIterator *) iter); + BLI_ghashIterator_step((GHashIterator *)iter); } ImBuf *IMB_moviecacheIter_getImBuf(struct MovieCacheIter *iter) { - MovieCacheItem *item = BLI_ghashIterator_getValue((GHashIterator *) iter); - return item->ibuf; + MovieCacheItem *item = BLI_ghashIterator_getValue((GHashIterator *)iter); + return item->ibuf; } void *IMB_moviecacheIter_getUserKey(struct MovieCacheIter *iter) { - MovieCacheKey *key = BLI_ghashIterator_getKey((GHashIterator *) iter); - return key->userkey; + MovieCacheKey *key = BLI_ghashIterator_getKey((GHashIterator *)iter); + return key->userkey; } diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt index 3311d3fd9b4..984e62bc75a 100644 --- a/source/blender/imbuf/intern/oiio/CMakeLists.txt +++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt @@ -19,14 +19,14 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - .. - ../.. - ../../../blenkernel - ../../../blenlib - ../../../makesdna - ../../../../../intern/guardedalloc - ../../../../../intern/utfconv + . + .. + ../.. + ../../../blenkernel + ../../../blenlib + ../../../makesdna + ../../../../../intern/guardedalloc + ../../../../../intern/utfconv ) set(INC_SYS @@ -34,25 +34,25 @@ set(INC_SYS ) set(SRC - openimageio_api.h + openimageio_api.h - openimageio_api.cpp + openimageio_api.cpp ) set(LIB ) if(WITH_OPENIMAGEIO) - list(APPEND INC_SYS - ${OPENIMAGEIO_INCLUDE_DIRS} - ${BOOST_INCLUDE_DIR} - ) - if(WITH_IMAGE_OPENEXR) - list(APPEND INC_SYS - ${OPENEXR_INCLUDE_DIRS} - ) - endif() - add_definitions(-DWITH_OPENIMAGEIO) + list(APPEND INC_SYS + ${OPENIMAGEIO_INCLUDE_DIRS} + ${BOOST_INCLUDE_DIR} + ) + if(WITH_IMAGE_OPENEXR) + list(APPEND INC_SYS + ${OPENEXR_INCLUDE_DIRS} + ) + endif() + add_definitions(-DWITH_OPENIMAGEIO) endif() blender_add_lib(bf_imbuf_openimageio "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 4a21478de13..7b14678ed62 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -24,7 +24,7 @@ #include #if defined(WIN32) -#include "utfconv.h" +# include "utfconv.h" #endif // NOTE: Keep first, BLI_path_util conflicts with OIIO's format. @@ -32,8 +32,7 @@ #include #include -extern "C" -{ +extern "C" { #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -52,232 +51,227 @@ using std::unique_ptr; typedef unsigned char uchar; -template +template static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha) { - if (components == 2) { - for (int i = width * height - 1; i >= 0; i--) { - pixels[i * 4 + 3] = pixels[i * 2 + 1]; - pixels[i * 4 + 2] = pixels[i * 2 + 0]; - pixels[i * 4 + 1] = pixels[i * 2 + 0]; - pixels[i * 4 + 0] = pixels[i * 2 + 0]; - } - } - else if (components == 3) { - for (int i = width * height - 1; i >= 0; i--) { - pixels[i * 4 + 3] = alpha; - pixels[i * 4 + 2] = pixels[i * 3 + 2]; - pixels[i * 4 + 1] = pixels[i * 3 + 1]; - pixels[i * 4 + 0] = pixels[i * 3 + 0]; - - } - } - else if (components == 1) { - for (int i = width * height - 1; i >= 0; i--) { - pixels[i * 4 + 3] = alpha; - pixels[i * 4 + 2] = pixels[i]; - pixels[i * 4 + 1] = pixels[i]; - pixels[i * 4 + 0] = pixels[i]; - } - } - + if (components == 2) { + for (int i = width * height - 1; i >= 0; i--) { + pixels[i * 4 + 3] = pixels[i * 2 + 1]; + pixels[i * 4 + 2] = pixels[i * 2 + 0]; + pixels[i * 4 + 1] = pixels[i * 2 + 0]; + pixels[i * 4 + 0] = pixels[i * 2 + 0]; + } + } + else if (components == 3) { + for (int i = width * height - 1; i >= 0; i--) { + pixels[i * 4 + 3] = alpha; + pixels[i * 4 + 2] = pixels[i * 3 + 2]; + pixels[i * 4 + 1] = pixels[i * 3 + 1]; + pixels[i * 4 + 0] = pixels[i * 3 + 0]; + } + } + else if (components == 1) { + for (int i = width * height - 1; i >= 0; i--) { + pixels[i * 4 + 3] = alpha; + pixels[i * 4 + 2] = pixels[i]; + pixels[i * 4 + 1] = pixels[i]; + pixels[i * 4 + 0] = pixels[i]; + } + } } -static ImBuf *imb_oiio_load_image(ImageInput *in, int width, int height, int components, int flags, bool is_alpha) +static ImBuf *imb_oiio_load_image( + ImageInput *in, int width, int height, int components, int flags, bool is_alpha) { - ImBuf *ibuf; - int scanlinesize = width * components * sizeof(uchar); - - /* allocate the memory for the image */ - ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect); - - try - { - if (!in->read_image(TypeDesc::UINT8, - (uchar *)ibuf->rect + (height - 1) * scanlinesize, - AutoStride, - -scanlinesize, - AutoStride)) - { - std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl - << in->geterror() << std::endl; - - if (ibuf) - IMB_freeImBuf(ibuf); - - return NULL; - } - } - catch (const std::exception &exc) - { - std::cerr << exc.what() << std::endl; - if (ibuf) IMB_freeImBuf(ibuf); - - return NULL; - } - - /* ImBuf always needs 4 channels */ - fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF); - - return ibuf; + ImBuf *ibuf; + int scanlinesize = width * components * sizeof(uchar); + + /* allocate the memory for the image */ + ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect); + + try { + if (!in->read_image(TypeDesc::UINT8, + (uchar *)ibuf->rect + (height - 1) * scanlinesize, + AutoStride, + -scanlinesize, + AutoStride)) { + std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl + << in->geterror() << std::endl; + + if (ibuf) + IMB_freeImBuf(ibuf); + + return NULL; + } + } + catch (const std::exception &exc) { + std::cerr << exc.what() << std::endl; + if (ibuf) + IMB_freeImBuf(ibuf); + + return NULL; + } + + /* ImBuf always needs 4 channels */ + fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF); + + return ibuf; } -static ImBuf *imb_oiio_load_image_float(ImageInput *in, int width, int height, int components, int flags, bool is_alpha) +static ImBuf *imb_oiio_load_image_float( + ImageInput *in, int width, int height, int components, int flags, bool is_alpha) { - ImBuf *ibuf; - int scanlinesize = width * components * sizeof(float); - - /* allocate the memory for the image */ - ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat); - - try - { - if (!in->read_image(TypeDesc::FLOAT, - (uchar *)ibuf->rect_float + (height - 1) * scanlinesize, - AutoStride, - -scanlinesize, - AutoStride)) - { - std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl - << in->geterror() << std::endl; - - if (ibuf) - IMB_freeImBuf(ibuf); - - return NULL; - } - } - catch (const std::exception &exc) - { - std::cerr << exc.what() << std::endl; - if (ibuf) IMB_freeImBuf(ibuf); - - return NULL; - } - - /* ImBuf always needs 4 channels */ - fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f); - - /* note: Photoshop 16 bit files never has alpha with it, so no need to handle associated/unassociated alpha */ - return ibuf; + ImBuf *ibuf; + int scanlinesize = width * components * sizeof(float); + + /* allocate the memory for the image */ + ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat); + + try { + if (!in->read_image(TypeDesc::FLOAT, + (uchar *)ibuf->rect_float + (height - 1) * scanlinesize, + AutoStride, + -scanlinesize, + AutoStride)) { + std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl + << in->geterror() << std::endl; + + if (ibuf) + IMB_freeImBuf(ibuf); + + return NULL; + } + } + catch (const std::exception &exc) { + std::cerr << exc.what() << std::endl; + if (ibuf) + IMB_freeImBuf(ibuf); + + return NULL; + } + + /* ImBuf always needs 4 channels */ + fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f); + + /* note: Photoshop 16 bit files never has alpha with it, so no need to handle associated/unassociated alpha */ + return ibuf; } -extern "C" -{ +extern "C" { int imb_is_a_photoshop(const char *filename) { - const char *photoshop_extension[] = { - ".psd", - ".pdd", - ".psb", - NULL, - }; - - return BLI_path_extension_check_array(filename, photoshop_extension); + const char *photoshop_extension[] = { + ".psd", + ".pdd", + ".psb", + NULL, + }; + + return BLI_path_extension_check_array(filename, photoshop_extension); } int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags) { - if (flags & IB_mem) { - std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory" - << " currently not supported" << std::endl; - imb_addencodedbufferImBuf(ibuf); - ibuf->encodedsize = 0; - return(0); - } - - return(0); + if (flags & IB_mem) { + std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory" + << " currently not supported" << std::endl; + imb_addencodedbufferImBuf(ibuf); + ibuf->encodedsize = 0; + return (0); + } + + return (0); } struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE]) { - struct ImBuf *ibuf = NULL; - int width, height, components; - bool is_float, is_alpha; - int basesize; - char file_colorspace[IM_MAX_SPACE]; - - /* load image from file through OIIO */ - if (imb_is_a_photoshop(filename) == 0) return (NULL); - - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - unique_ptr in(ImageInput::create(filename)); - if (!in) { - std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl - << OIIO_NAMESPACE::geterror() << std::endl; - return NULL; - } - - ImageSpec spec, config; - config.attribute("oiio:UnassociatedAlpha", (int) 1); - - if (!in->open(filename, spec, config)) { - std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl - << in->geterror() << std::endl; - return NULL; - } - - string ics = spec.get_string_attribute("oiio:ColorSpace"); - BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE); - - /* only use colorspaces exis */ - if (colormanage_colorspace_get_named(file_colorspace)) - strcpy(colorspace, file_colorspace); - else - std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace - << "\") not supported in existent OCIO configuration file. Fallback " - << "to system default colorspace (\"" << colorspace << "\")." << std::endl; - - width = spec.width; - height = spec.height; - components = spec.nchannels; - is_alpha = spec.alpha_channel != -1; - basesize = spec.format.basesize(); - is_float = basesize > 1; - - /* we only handle certain number of components */ - if (!(components >= 1 && components <= 4)) { - if (in) { - in->close(); - } - return NULL; - } - - if (is_float) - ibuf = imb_oiio_load_image_float(in.get(), width, height, components, flags, is_alpha); - else - ibuf = imb_oiio_load_image(in.get(), width, height, components, flags, is_alpha); - - if (in) { - in->close(); - } - - if (!ibuf) - return NULL; - - /* ImBuf always needs 4 channels */ - ibuf->ftype = IMB_FTYPE_PSD; - ibuf->channels = 4; - ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize; - - try - { - return ibuf; - } - catch (const std::exception &exc) - { - std::cerr << exc.what() << std::endl; - if (ibuf) IMB_freeImBuf(ibuf); - - return NULL; - } + struct ImBuf *ibuf = NULL; + int width, height, components; + bool is_float, is_alpha; + int basesize; + char file_colorspace[IM_MAX_SPACE]; + + /* load image from file through OIIO */ + if (imb_is_a_photoshop(filename) == 0) + return (NULL); + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + unique_ptr in(ImageInput::create(filename)); + if (!in) { + std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl + << OIIO_NAMESPACE::geterror() << std::endl; + return NULL; + } + + ImageSpec spec, config; + config.attribute("oiio:UnassociatedAlpha", (int)1); + + if (!in->open(filename, spec, config)) { + std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl + << in->geterror() << std::endl; + return NULL; + } + + string ics = spec.get_string_attribute("oiio:ColorSpace"); + BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE); + + /* only use colorspaces exis */ + if (colormanage_colorspace_get_named(file_colorspace)) + strcpy(colorspace, file_colorspace); + else + std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace + << "\") not supported in existent OCIO configuration file. Fallback " + << "to system default colorspace (\"" << colorspace << "\")." << std::endl; + + width = spec.width; + height = spec.height; + components = spec.nchannels; + is_alpha = spec.alpha_channel != -1; + basesize = spec.format.basesize(); + is_float = basesize > 1; + + /* we only handle certain number of components */ + if (!(components >= 1 && components <= 4)) { + if (in) { + in->close(); + } + return NULL; + } + + if (is_float) + ibuf = imb_oiio_load_image_float(in.get(), width, height, components, flags, is_alpha); + else + ibuf = imb_oiio_load_image(in.get(), width, height, components, flags, is_alpha); + + if (in) { + in->close(); + } + + if (!ibuf) + return NULL; + + /* ImBuf always needs 4 channels */ + ibuf->ftype = IMB_FTYPE_PSD; + ibuf->channels = 4; + ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize; + + try { + return ibuf; + } + catch (const std::exception &exc) { + std::cerr << exc.what() << std::endl; + if (ibuf) + IMB_freeImBuf(ibuf); + + return NULL; + } } int OIIO_getVersionHex(void) { - return openimageio_version(); + return openimageio_version(); } -} // export "C" +} // export "C" diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h index d6249af2a0a..520ad0c5da5 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.h +++ b/source/blender/imbuf/intern/oiio/openimageio_api.h @@ -21,7 +21,6 @@ * \ingroup openimageio */ - #ifndef __OPENIMAGEIO_API_H__ #define __OPENIMAGEIO_API_H__ @@ -33,11 +32,11 @@ extern "C" { struct ImBuf; -int imb_is_a_photoshop (const char *name); +int imb_is_a_photoshop(const char *name); -int imb_save_photoshop (struct ImBuf *ibuf, const char *name, int flags); +int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_photoshop (const char *name, int flags, char *colorspace); +struct ImBuf *imb_load_photoshop(const char *name, int flags, char *colorspace); int OIIO_getVersionHex(void); @@ -46,4 +45,4 @@ int OIIO_getVersionHex(void); #endif -#endif /* __OPENIMAGEIO_API_H__ */ +#endif /* __OPENIMAGEIO_API_H__ */ diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index c9ede9ff07f..fc584ace81e 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -19,14 +19,14 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - .. - ../.. - ../../../blenkernel - ../../../blenlib - ../../../makesdna - ../../../../../intern/guardedalloc - ../../../../../intern/utfconv + . + .. + ../.. + ../../../blenkernel + ../../../blenlib + ../../../makesdna + ../../../../../intern/guardedalloc + ../../../../../intern/utfconv ) set(INC_SYS @@ -34,20 +34,20 @@ set(INC_SYS ) set(SRC - openexr_api.h - openexr_multi.h + openexr_api.h + openexr_multi.h - openexr_api.cpp + openexr_api.cpp ) set(LIB ) if(WITH_IMAGE_OPENEXR) - list(APPEND INC_SYS - ${OPENEXR_INCLUDE_DIRS} - ) - add_definitions(-DWITH_OPENEXR) + list(APPEND INC_SYS + ${OPENEXR_INCLUDE_DIRS} + ) + add_definitions(-DWITH_OPENEXR) endif() blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 155f971c5eb..d0f550feb0d 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -61,12 +61,11 @@ #include -#if defined (WIN32) -#include "utfconv.h" +#if defined(WIN32) +# include "utfconv.h" #endif -extern "C" -{ +extern "C" { // The following prevents a linking error in debug mode for MSVC using the libs in CVS #if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && _MSC_VER < 1900 @@ -100,63 +99,62 @@ extern "C" { using namespace Imf; using namespace Imath; -extern "C" -{ +extern "C" { /* prototype */ static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname); -static bool exr_has_multiview(MultiPartInputFile& file); -static bool exr_has_multipart_file(MultiPartInputFile& file); -static bool exr_has_alpha(MultiPartInputFile& file); -static bool exr_has_zbuffer(MultiPartInputFile& file); +static bool exr_has_multiview(MultiPartInputFile &file); +static bool exr_has_multipart_file(MultiPartInputFile &file); +static bool exr_has_alpha(MultiPartInputFile &file); +static bool exr_has_zbuffer(MultiPartInputFile &file); static void exr_printf(const char *__restrict format, ...); -static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, - bool *r_singlelayer, bool *r_multilayer, bool *r_multiview); +static void imb_exr_type_by_channels(ChannelList &channels, + StringVector &views, + bool *r_singlelayer, + bool *r_multilayer, + bool *r_multiview); } /* Memory Input Stream */ -class Mem_IStream : public Imf::IStream -{ -public: - - Mem_IStream(unsigned char *exrbuf, size_t exrsize) : - IStream("dummy"), _exrpos(0), _exrsize(exrsize) - { - _exrbuf = exrbuf; - } - - virtual bool read(char c[], int n); - virtual Int64 tellg(); - virtual void seekg(Int64 pos); - virtual void clear(); - //virtual ~Mem_IStream() {}; // unused - -private: - - Int64 _exrpos; - Int64 _exrsize; - unsigned char *_exrbuf; +class Mem_IStream : public Imf::IStream { + public: + Mem_IStream(unsigned char *exrbuf, size_t exrsize) + : IStream("dummy"), _exrpos(0), _exrsize(exrsize) + { + _exrbuf = exrbuf; + } + + virtual bool read(char c[], int n); + virtual Int64 tellg(); + virtual void seekg(Int64 pos); + virtual void clear(); + //virtual ~Mem_IStream() {}; // unused + + private: + Int64 _exrpos; + Int64 _exrsize; + unsigned char *_exrbuf; }; bool Mem_IStream::read(char c[], int n) { - if (n + _exrpos <= _exrsize) { - memcpy(c, (void *)(&_exrbuf[_exrpos]), n); - _exrpos += n; - return true; - } - else - return false; + if (n + _exrpos <= _exrsize) { + memcpy(c, (void *)(&_exrbuf[_exrpos]), n); + _exrpos += n; + return true; + } + else + return false; } Int64 Mem_IStream::tellg() { - return _exrpos; + return _exrpos; } void Mem_IStream::seekg(Int64 pos) { - _exrpos = pos; + _exrpos = pos; } void Mem_IStream::clear() @@ -165,132 +163,127 @@ void Mem_IStream::clear() /* File Input Stream */ -class IFileStream : public Imf::IStream -{ -public: - IFileStream(const char *filename) - : IStream(filename) - { - /* utf-8 file path support on windows */ -#if defined (WIN32) - wchar_t *wfilename = alloc_utf16_from_8(filename, 0); - ifs.open(wfilename, std::ios_base::binary); - free(wfilename); +class IFileStream : public Imf::IStream { + public: + IFileStream(const char *filename) : IStream(filename) + { + /* utf-8 file path support on windows */ +#if defined(WIN32) + wchar_t *wfilename = alloc_utf16_from_8(filename, 0); + ifs.open(wfilename, std::ios_base::binary); + free(wfilename); #else - ifs.open(filename, std::ios_base::binary); + ifs.open(filename, std::ios_base::binary); #endif - if (!ifs) - Iex::throwErrnoExc(); - } - - virtual bool read(char c[], int n) - { - if (!ifs) - throw Iex::InputExc("Unexpected end of file."); - - errno = 0; - ifs.read(c, n); - return check_error(); - } - - virtual Int64 tellg() - { - return std::streamoff(ifs.tellg()); - } - - virtual void seekg(Int64 pos) - { - ifs.seekg(pos); - check_error(); - } - - virtual void clear() - { - ifs.clear(); - } - -private: - bool check_error() - { - if (!ifs) { - if (errno) - Iex::throwErrnoExc(); - - return false; - } - - return true; - } - - std::ifstream ifs; + if (!ifs) + Iex::throwErrnoExc(); + } + + virtual bool read(char c[], int n) + { + if (!ifs) + throw Iex::InputExc("Unexpected end of file."); + + errno = 0; + ifs.read(c, n); + return check_error(); + } + + virtual Int64 tellg() + { + return std::streamoff(ifs.tellg()); + } + + virtual void seekg(Int64 pos) + { + ifs.seekg(pos); + check_error(); + } + + virtual void clear() + { + ifs.clear(); + } + + private: + bool check_error() + { + if (!ifs) { + if (errno) + Iex::throwErrnoExc(); + + return false; + } + + return true; + } + + std::ifstream ifs; }; /* File Output Stream */ -class OFileStream : public OStream -{ -public: - OFileStream(const char *filename) - : OStream(filename) - { - /* utf-8 file path support on windows */ -#if defined (WIN32) - wchar_t *wfilename = alloc_utf16_from_8(filename, 0); - ofs.open(wfilename, std::ios_base::binary); - free(wfilename); +class OFileStream : public OStream { + public: + OFileStream(const char *filename) : OStream(filename) + { + /* utf-8 file path support on windows */ +#if defined(WIN32) + wchar_t *wfilename = alloc_utf16_from_8(filename, 0); + ofs.open(wfilename, std::ios_base::binary); + free(wfilename); #else - ofs.open(filename, std::ios_base::binary); + ofs.open(filename, std::ios_base::binary); #endif - if (!ofs) - Iex::throwErrnoExc(); - } - - virtual void write(const char c[], int n) - { - errno = 0; - ofs.write(c, n); - check_error(); - } - - virtual Int64 tellp() - { - return std::streamoff(ofs.tellp()); - } - - virtual void seekp(Int64 pos) - { - ofs.seekp(pos); - check_error(); - } - -private: - void check_error() - { - if (!ofs) { - if (errno) - Iex::throwErrnoExc(); - - throw Iex::ErrnoExc("File output failed."); - } - } - - std::ofstream ofs; + if (!ofs) + Iex::throwErrnoExc(); + } + + virtual void write(const char c[], int n) + { + errno = 0; + ofs.write(c, n); + check_error(); + } + + virtual Int64 tellp() + { + return std::streamoff(ofs.tellp()); + } + + virtual void seekp(Int64 pos) + { + ofs.seekp(pos); + check_error(); + } + + private: + void check_error() + { + if (!ofs) { + if (errno) + Iex::throwErrnoExc(); + + throw Iex::ErrnoExc("File output failed."); + } + } + + std::ofstream ofs; }; struct _RGBAZ { - half r; - half g; - half b; - half a; - half z; + half r; + half g; + half b; + half a; + half z; }; typedef struct _RGBAZ RGBAZ; -extern "C" -{ +extern "C" { /** * Test presence of OpenEXR file. @@ -298,249 +291,255 @@ extern "C" */ int imb_is_a_openexr(const unsigned char *mem) { - return Imf::isImfMagic((const char *)mem); + return Imf::isImfMagic((const char *)mem); } static void openexr_header_compression(Header *header, int compression) { - switch (compression) { - case R_IMF_EXR_CODEC_NONE: - header->compression() = NO_COMPRESSION; - break; - case R_IMF_EXR_CODEC_PXR24: - header->compression() = PXR24_COMPRESSION; - break; - case R_IMF_EXR_CODEC_ZIP: - header->compression() = ZIP_COMPRESSION; - break; - case R_IMF_EXR_CODEC_PIZ: - header->compression() = PIZ_COMPRESSION; - break; - case R_IMF_EXR_CODEC_RLE: - header->compression() = RLE_COMPRESSION; - break; - case R_IMF_EXR_CODEC_ZIPS: - header->compression() = ZIPS_COMPRESSION; - break; - case R_IMF_EXR_CODEC_B44: - header->compression() = B44_COMPRESSION; - break; - case R_IMF_EXR_CODEC_B44A: - header->compression() = B44A_COMPRESSION; - break; + switch (compression) { + case R_IMF_EXR_CODEC_NONE: + header->compression() = NO_COMPRESSION; + break; + case R_IMF_EXR_CODEC_PXR24: + header->compression() = PXR24_COMPRESSION; + break; + case R_IMF_EXR_CODEC_ZIP: + header->compression() = ZIP_COMPRESSION; + break; + case R_IMF_EXR_CODEC_PIZ: + header->compression() = PIZ_COMPRESSION; + break; + case R_IMF_EXR_CODEC_RLE: + header->compression() = RLE_COMPRESSION; + break; + case R_IMF_EXR_CODEC_ZIPS: + header->compression() = ZIPS_COMPRESSION; + break; + case R_IMF_EXR_CODEC_B44: + header->compression() = B44_COMPRESSION; + break; + case R_IMF_EXR_CODEC_B44A: + header->compression() = B44A_COMPRESSION; + break; #if OPENEXR_VERSION_MAJOR >= 2 && OPENEXR_VERSION_MINOR >= 2 - case R_IMF_EXR_CODEC_DWAA: - header->compression() = DWAA_COMPRESSION; - break; - case R_IMF_EXR_CODEC_DWAB: - header->compression() = DWAB_COMPRESSION; - break; + case R_IMF_EXR_CODEC_DWAA: + header->compression() = DWAA_COMPRESSION; + break; + case R_IMF_EXR_CODEC_DWAB: + header->compression() = DWAB_COMPRESSION; + break; #endif - default: - header->compression() = ZIP_COMPRESSION; - break; - } + default: + header->compression() = ZIP_COMPRESSION; + break; + } } static void openexr_header_metadata(Header *header, struct ImBuf *ibuf) { - if (ibuf->metadata) { - IDProperty *prop; - - for (prop = (IDProperty *)ibuf->metadata->data.group.first; prop; prop = prop->next) { - if (prop->type == IDP_STRING) { - header->insert(prop->name, StringAttribute(IDP_String(prop))); - } - } - } - - if (ibuf->ppm[0] > 0.0) - addXDensity(*header, ibuf->ppm[0] / 39.3700787); /* 1 meter = 39.3700787 inches */ + if (ibuf->metadata) { + IDProperty *prop; + + for (prop = (IDProperty *)ibuf->metadata->data.group.first; prop; prop = prop->next) { + if (prop->type == IDP_STRING) { + header->insert(prop->name, StringAttribute(IDP_String(prop))); + } + } + } + + if (ibuf->ppm[0] > 0.0) + addXDensity(*header, ibuf->ppm[0] / 39.3700787); /* 1 meter = 39.3700787 inches */ } -static void openexr_header_metadata_callback(void *data, const char *propname, char *prop, int UNUSED(len)) +static void openexr_header_metadata_callback(void *data, + const char *propname, + char *prop, + int UNUSED(len)) { - Header *header = (Header *)data; - header->insert(propname, StringAttribute(prop)); + Header *header = (Header *)data; + header->insert(propname, StringAttribute(prop)); } - -static bool imb_save_openexr_half( - ImBuf *ibuf, const char *name, const int flags) +static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags) { - const int channels = ibuf->channels; - const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); - const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ - const int width = ibuf->x; - const int height = ibuf->y; - - try - { - Header header(width, height); - - openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); - openexr_header_metadata(&header, ibuf); - - /* create channels */ - header.channels().insert("R", Channel(HALF)); - header.channels().insert("G", Channel(HALF)); - header.channels().insert("B", Channel(HALF)); - if (is_alpha) - header.channels().insert("A", Channel(HALF)); - if (is_zbuf) // z we do as float always - header.channels().insert("Z", Channel(Imf::FLOAT)); - - FrameBuffer frameBuffer; - - /* manually create ofstream, so we can handle utf-8 filepaths on windows */ - OFileStream file_stream(name); - OutputFile file(file_stream, header); - - /* we store first everything in half array */ - std::vector pixels(height * width); - RGBAZ *to = &pixels[0]; - int xstride = sizeof(RGBAZ); - int ystride = xstride * width; - - /* indicate used buffers */ - frameBuffer.insert("R", Slice(HALF, (char *) &to->r, xstride, ystride)); - frameBuffer.insert("G", Slice(HALF, (char *) &to->g, xstride, ystride)); - frameBuffer.insert("B", Slice(HALF, (char *) &to->b, xstride, ystride)); - if (is_alpha) { - frameBuffer.insert("A", Slice(HALF, (char *) &to->a, xstride, ystride)); - } - if (is_zbuf) { - frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); - } - if (ibuf->rect_float) { - float *from; - - for (int i = ibuf->y - 1; i >= 0; i--) { - from = ibuf->rect_float + channels * i * width; - - for (int j = ibuf->x; j > 0; j--) { - to->r = from[0]; - to->g = (channels >= 2) ? from[1] : from[0]; - to->b = (channels >= 3) ? from[2] : from[0]; - to->a = (channels >= 4) ? from[3] : 1.0f; - to++; from += channels; - } - } - } - else { - unsigned char *from; - - for (int i = ibuf->y - 1; i >= 0; i--) { - from = (unsigned char *)ibuf->rect + 4 * i * width; - - for (int j = ibuf->x; j > 0; j--) { - to->r = srgb_to_linearrgb((float)from[0] / 255.0f); - to->g = srgb_to_linearrgb((float)from[1] / 255.0f); - to->b = srgb_to_linearrgb((float)from[2] / 255.0f); - to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; - to++; from += 4; - } - } - } - - exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); - - file.setFrameBuffer(frameBuffer); - file.writePixels(height); - } - catch (const std::exception& exc) - { - printf("OpenEXR-save: ERROR: %s\n", exc.what()); - - return false; - } - - return true; + const int channels = ibuf->channels; + const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); + const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ + const int width = ibuf->x; + const int height = ibuf->y; + + try { + Header header(width, height); + + openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); + openexr_header_metadata(&header, ibuf); + + /* create channels */ + header.channels().insert("R", Channel(HALF)); + header.channels().insert("G", Channel(HALF)); + header.channels().insert("B", Channel(HALF)); + if (is_alpha) + header.channels().insert("A", Channel(HALF)); + if (is_zbuf) // z we do as float always + header.channels().insert("Z", Channel(Imf::FLOAT)); + + FrameBuffer frameBuffer; + + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + OFileStream file_stream(name); + OutputFile file(file_stream, header); + + /* we store first everything in half array */ + std::vector pixels(height * width); + RGBAZ *to = &pixels[0]; + int xstride = sizeof(RGBAZ); + int ystride = xstride * width; + + /* indicate used buffers */ + frameBuffer.insert("R", Slice(HALF, (char *)&to->r, xstride, ystride)); + frameBuffer.insert("G", Slice(HALF, (char *)&to->g, xstride, ystride)); + frameBuffer.insert("B", Slice(HALF, (char *)&to->b, xstride, ystride)); + if (is_alpha) { + frameBuffer.insert("A", Slice(HALF, (char *)&to->a, xstride, ystride)); + } + if (is_zbuf) { + frameBuffer.insert("Z", + Slice(Imf::FLOAT, + (char *)(ibuf->zbuf_float + (height - 1) * width), + sizeof(float), + sizeof(float) * -width)); + } + if (ibuf->rect_float) { + float *from; + + for (int i = ibuf->y - 1; i >= 0; i--) { + from = ibuf->rect_float + channels * i * width; + + for (int j = ibuf->x; j > 0; j--) { + to->r = from[0]; + to->g = (channels >= 2) ? from[1] : from[0]; + to->b = (channels >= 3) ? from[2] : from[0]; + to->a = (channels >= 4) ? from[3] : 1.0f; + to++; + from += channels; + } + } + } + else { + unsigned char *from; + + for (int i = ibuf->y - 1; i >= 0; i--) { + from = (unsigned char *)ibuf->rect + 4 * i * width; + + for (int j = ibuf->x; j > 0; j--) { + to->r = srgb_to_linearrgb((float)from[0] / 255.0f); + to->g = srgb_to_linearrgb((float)from[1] / 255.0f); + to->b = srgb_to_linearrgb((float)from[2] / 255.0f); + to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; + to++; + from += 4; + } + } + } + + exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); + + file.setFrameBuffer(frameBuffer); + file.writePixels(height); + } + catch (const std::exception &exc) { + printf("OpenEXR-save: ERROR: %s\n", exc.what()); + + return false; + } + + return true; } -static bool imb_save_openexr_float( - ImBuf *ibuf, const char *name, const int flags) +static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flags) { - const int channels = ibuf->channels; - const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); - const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ - const int width = ibuf->x; - const int height = ibuf->y; - - try - { - Header header(width, height); - - openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); - openexr_header_metadata(&header, ibuf); - - /* create channels */ - header.channels().insert("R", Channel(Imf::FLOAT)); - header.channels().insert("G", Channel(Imf::FLOAT)); - header.channels().insert("B", Channel(Imf::FLOAT)); - if (is_alpha) - header.channels().insert("A", Channel(Imf::FLOAT)); - if (is_zbuf) - header.channels().insert("Z", Channel(Imf::FLOAT)); - - FrameBuffer frameBuffer; - - /* manually create ofstream, so we can handle utf-8 filepaths on windows */ - OFileStream file_stream(name); - OutputFile file(file_stream, header); - - int xstride = sizeof(float) * channels; - int ystride = -xstride * width; - - /* last scanline, stride negative */ - float *rect[4] = {NULL, NULL, NULL, NULL}; - rect[0] = ibuf->rect_float + channels * (height - 1) * width; - rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; - rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; - rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ - - frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); - frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); - frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); - if (is_alpha) { - frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); - } - if (is_zbuf) { - frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); - } - - file.setFrameBuffer(frameBuffer); - file.writePixels(height); - } - catch (const std::exception& exc) - { - printf("OpenEXR-save: ERROR: %s\n", exc.what()); - return false; - } - - return true; + const int channels = ibuf->channels; + const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); + const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ + const int width = ibuf->x; + const int height = ibuf->y; + + try { + Header header(width, height); + + openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); + openexr_header_metadata(&header, ibuf); + + /* create channels */ + header.channels().insert("R", Channel(Imf::FLOAT)); + header.channels().insert("G", Channel(Imf::FLOAT)); + header.channels().insert("B", Channel(Imf::FLOAT)); + if (is_alpha) + header.channels().insert("A", Channel(Imf::FLOAT)); + if (is_zbuf) + header.channels().insert("Z", Channel(Imf::FLOAT)); + + FrameBuffer frameBuffer; + + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + OFileStream file_stream(name); + OutputFile file(file_stream, header); + + int xstride = sizeof(float) * channels; + int ystride = -xstride * width; + + /* last scanline, stride negative */ + float *rect[4] = {NULL, NULL, NULL, NULL}; + rect[0] = ibuf->rect_float + channels * (height - 1) * width; + rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; + rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; + rect[3] = (channels >= 4) ? + rect[0] + 3 : + rect[0]; /* red as alpha, is this needed since alpha isn't written? */ + + frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); + frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); + frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); + if (is_alpha) { + frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); + } + if (is_zbuf) { + frameBuffer.insert("Z", + Slice(Imf::FLOAT, + (char *)(ibuf->zbuf_float + (height - 1) * width), + sizeof(float), + sizeof(float) * -width)); + } + + file.setFrameBuffer(frameBuffer); + file.writePixels(height); + } + catch (const std::exception &exc) { + printf("OpenEXR-save: ERROR: %s\n", exc.what()); + return false; + } + + return true; } int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) { - if (flags & IB_mem) { - printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n"); - imb_addencodedbufferImBuf(ibuf); - ibuf->encodedsize = 0; - return(0); - } - - if (ibuf->foptions.flag & OPENEXR_HALF) - return (int) imb_save_openexr_half(ibuf, name, flags); - else { - /* when no float rect, we save as half (16 bits is sufficient) */ - if (ibuf->rect_float == NULL) - return (int) imb_save_openexr_half(ibuf, name, flags); - else - return (int) imb_save_openexr_float(ibuf, name, flags); - } + if (flags & IB_mem) { + printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n"); + imb_addencodedbufferImBuf(ibuf); + ibuf->encodedsize = 0; + return (0); + } + + if (ibuf->foptions.flag & OPENEXR_HALF) + return (int)imb_save_openexr_half(ibuf, name, flags); + else { + /* when no float rect, we save as half (16 bits is sufficient) */ + if (ibuf->rect_float == NULL) + return (int)imb_save_openexr_half(ibuf, name, flags); + else + return (int)imb_save_openexr_float(ibuf, name, flags); + } } /* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */ @@ -555,691 +554,740 @@ int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) static ListBase exrhandles = {NULL, NULL}; typedef struct ExrHandle { - struct ExrHandle *next, *prev; - char name[FILE_MAX]; + struct ExrHandle *next, *prev; + char name[FILE_MAX]; - IStream *ifile_stream; - MultiPartInputFile *ifile; + IStream *ifile_stream; + MultiPartInputFile *ifile; - OFileStream *ofile_stream; - MultiPartOutputFile *mpofile; - OutputFile *ofile; + OFileStream *ofile_stream; + MultiPartOutputFile *mpofile; + OutputFile *ofile; - int tilex, tiley; - int width, height; - int mipmap; + int tilex, tiley; + int width, height; + int mipmap; - StringVector *multiView; /* it needs to be a pointer due to Windows release builds of EXR2.0 segfault when opening EXR bug */ - int parts; + StringVector * + multiView; /* it needs to be a pointer due to Windows release builds of EXR2.0 segfault when opening EXR bug */ + int parts; - ListBase channels; /* flattened out, ExrChannel */ - ListBase layers; /* hierarchical, pointing in end to ExrChannel */ + ListBase channels; /* flattened out, ExrChannel */ + ListBase layers; /* hierarchical, pointing in end to ExrChannel */ - int num_half_channels; /* used during filr save, allows faster temporary buffers allocation */ + int num_half_channels; /* used during filr save, allows faster temporary buffers allocation */ } ExrHandle; /* flattened out channel */ typedef struct ExrChannel { - struct ExrChannel *next, *prev; - - char name[EXR_TOT_MAXNAME + 1]; /* full name with everything */ - struct MultiViewChannelName *m; /* struct to store all multipart channel info */ - int xstride, ystride; /* step to next pixel, to next scanline */ - float *rect; /* first pointer to write in */ - char chan_id; /* quick lookup of channel char */ - int view_id; /* quick lookup of channel view */ - bool use_half_float; /* when saving use half float for file storage */ + struct ExrChannel *next, *prev; + + char name[EXR_TOT_MAXNAME + 1]; /* full name with everything */ + struct MultiViewChannelName *m; /* struct to store all multipart channel info */ + int xstride, ystride; /* step to next pixel, to next scanline */ + float *rect; /* first pointer to write in */ + char chan_id; /* quick lookup of channel char */ + int view_id; /* quick lookup of channel view */ + bool use_half_float; /* when saving use half float for file storage */ } ExrChannel; - /* hierarchical; layers -> passes -> channels[] */ typedef struct ExrPass { - struct ExrPass *next, *prev; - char name[EXR_PASS_MAXNAME]; - int totchan; - float *rect; - struct ExrChannel *chan[EXR_PASS_MAXCHAN]; - char chan_id[EXR_PASS_MAXCHAN]; - - char internal_name[EXR_PASS_MAXNAME]; /* name with no view */ - char view[EXR_VIEW_MAXNAME]; - int view_id; + struct ExrPass *next, *prev; + char name[EXR_PASS_MAXNAME]; + int totchan; + float *rect; + struct ExrChannel *chan[EXR_PASS_MAXCHAN]; + char chan_id[EXR_PASS_MAXCHAN]; + + char internal_name[EXR_PASS_MAXNAME]; /* name with no view */ + char view[EXR_VIEW_MAXNAME]; + int view_id; } ExrPass; typedef struct ExrLayer { - struct ExrLayer *next, *prev; - char name[EXR_LAY_MAXNAME + 1]; - ListBase passes; + struct ExrLayer *next, *prev; + char name[EXR_LAY_MAXNAME + 1]; + ListBase passes; } ExrLayer; /* ********************** */ void *IMB_exr_get_handle(void) { - ExrHandle *data = (ExrHandle *)MEM_callocN(sizeof(ExrHandle), "exr handle"); - data->multiView = new StringVector(); + ExrHandle *data = (ExrHandle *)MEM_callocN(sizeof(ExrHandle), "exr handle"); + data->multiView = new StringVector(); - BLI_addtail(&exrhandles, data); - return data; + BLI_addtail(&exrhandles, data); + return data; } void *IMB_exr_get_handle_name(const char *name) { - ExrHandle *data = (ExrHandle *) BLI_rfindstring(&exrhandles, name, offsetof(ExrHandle, name)); + ExrHandle *data = (ExrHandle *)BLI_rfindstring(&exrhandles, name, offsetof(ExrHandle, name)); - if (data == NULL) { - data = (ExrHandle *)IMB_exr_get_handle(); - BLI_strncpy(data->name, name, strlen(name) + 1); - } - return data; + if (data == NULL) { + data = (ExrHandle *)IMB_exr_get_handle(); + BLI_strncpy(data->name, name, strlen(name) + 1); + } + return data; } /* multiview functions */ -} // extern "C" +} // extern "C" -extern "C" -{ +extern "C" { void IMB_exr_add_view(void *handle, const char *name) { - ExrHandle *data = (ExrHandle *)handle; - data->multiView->push_back(name); + ExrHandle *data = (ExrHandle *)handle; + data->multiView->push_back(name); } -static int imb_exr_get_multiView_id(StringVector& views, const std::string& name) +static int imb_exr_get_multiView_id(StringVector &views, const std::string &name) { - int count = 0; - for (StringVector::const_iterator i = views.begin(); count < views.size(); ++i) { - if (name == *i) - return count; - else - count ++; - } - - /* no views or wrong name */ - return -1; + int count = 0; + for (StringVector::const_iterator i = views.begin(); count < views.size(); ++i) { + if (name == *i) + return count; + else + count++; + } + + /* no views or wrong name */ + return -1; } -static void imb_exr_get_views(MultiPartInputFile& file, StringVector& views) +static void imb_exr_get_views(MultiPartInputFile &file, StringVector &views) { - if (exr_has_multipart_file(file) == false) { - if (exr_has_multiview(file)) { - StringVector sv = multiView(file.header(0)); - for (StringVector::const_iterator i = sv.begin(); i != sv.end(); ++i) - views.push_back(*i); - } - } - - else { - for (int p = 0; p < file.parts(); p++) { - std::string view = ""; - if (file.header(p).hasView()) - view = file.header(p).view(); - - if (imb_exr_get_multiView_id(views, view) == -1) - views.push_back(view); - } - } + if (exr_has_multipart_file(file) == false) { + if (exr_has_multiview(file)) { + StringVector sv = multiView(file.header(0)); + for (StringVector::const_iterator i = sv.begin(); i != sv.end(); ++i) + views.push_back(*i); + } + } + + else { + for (int p = 0; p < file.parts(); p++) { + std::string view = ""; + if (file.header(p).hasView()) + view = file.header(p).view(); + + if (imb_exr_get_multiView_id(views, view) == -1) + views.push_back(view); + } + } } /* Multilayer Blender files have the view name in all the passes (even the default view one) */ static void imb_exr_insert_view_name(char *name_full, const char *passname, const char *viewname) { - BLI_assert(!ELEM(name_full, passname, viewname)); - - if (viewname == NULL || viewname[0] == '\0') { - BLI_strncpy(name_full, passname, sizeof(((ExrChannel *)NULL)->name)); - return; - } - - const char delims[] = {'.', '\0'}; - const char *sep; - const char *token; - size_t len; - - len = BLI_str_rpartition(passname, delims, &sep, &token); - - if (sep) { - BLI_snprintf(name_full, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passname, viewname, token); - } - else { - BLI_snprintf(name_full, EXR_PASS_MAXNAME, "%s.%s", passname, viewname); - } + BLI_assert(!ELEM(name_full, passname, viewname)); + + if (viewname == NULL || viewname[0] == '\0') { + BLI_strncpy(name_full, passname, sizeof(((ExrChannel *)NULL)->name)); + return; + } + + const char delims[] = {'.', '\0'}; + const char *sep; + const char *token; + size_t len; + + len = BLI_str_rpartition(passname, delims, &sep, &token); + + if (sep) { + BLI_snprintf(name_full, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passname, viewname, token); + } + else { + BLI_snprintf(name_full, EXR_PASS_MAXNAME, "%s.%s", passname, viewname); + } } /* adds flattened ExrChannels */ /* xstride, ystride and rect can be done in set_channel too, for tile writing */ /* passname does not include view */ void IMB_exr_add_channel(void *handle, - const char *layname, const char *passname, const char *viewname, - int xstride, int ystride, float *rect, + const char *layname, + const char *passname, + const char *viewname, + int xstride, + int ystride, + float *rect, bool use_half_float) { - ExrHandle *data = (ExrHandle *)handle; - ExrChannel *echan; - - echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr channel"); - echan->m = new MultiViewChannelName (); - - if (layname && layname[0] != '\0') { - echan->m->name = layname; - echan->m->name.append("."); - echan->m->name.append(passname); - } - else { - echan->m->name.assign(passname); - } - - echan->m->internal_name = echan->m->name; - - echan->m->view.assign(viewname ? viewname : ""); - - /* quick look up */ - echan->view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, echan->m->view)); - - /* name has to be unique, thus it's a combination of layer, pass, view, and channel */ - if (layname && layname[0] != '\0') { - imb_exr_insert_view_name(echan->name, echan->m->name.c_str(), echan->m->view.c_str()); - } - else if (data->multiView->size() >= 1) { - std::string raw_name = insertViewName(echan->m->name, *data->multiView, echan->view_id); - BLI_strncpy(echan->name, raw_name.c_str(), sizeof(echan->name)); - } - else { - BLI_strncpy(echan->name, echan->m->name.c_str(), sizeof(echan->name)); - } - - echan->xstride = xstride; - echan->ystride = ystride; - echan->rect = rect; - echan->use_half_float = use_half_float; - - if (echan->use_half_float) { - data->num_half_channels++; - } - - exr_printf("added channel %s\n", echan->name); - BLI_addtail(&data->channels, echan); + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *echan; + + echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr channel"); + echan->m = new MultiViewChannelName(); + + if (layname && layname[0] != '\0') { + echan->m->name = layname; + echan->m->name.append("."); + echan->m->name.append(passname); + } + else { + echan->m->name.assign(passname); + } + + echan->m->internal_name = echan->m->name; + + echan->m->view.assign(viewname ? viewname : ""); + + /* quick look up */ + echan->view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, echan->m->view)); + + /* name has to be unique, thus it's a combination of layer, pass, view, and channel */ + if (layname && layname[0] != '\0') { + imb_exr_insert_view_name(echan->name, echan->m->name.c_str(), echan->m->view.c_str()); + } + else if (data->multiView->size() >= 1) { + std::string raw_name = insertViewName(echan->m->name, *data->multiView, echan->view_id); + BLI_strncpy(echan->name, raw_name.c_str(), sizeof(echan->name)); + } + else { + BLI_strncpy(echan->name, echan->m->name.c_str(), sizeof(echan->name)); + } + + echan->xstride = xstride; + echan->ystride = ystride; + echan->rect = rect; + echan->use_half_float = use_half_float; + + if (echan->use_half_float) { + data->num_half_channels++; + } + + exr_printf("added channel %s\n", echan->name); + BLI_addtail(&data->channels, echan); } /* used for output files (from RenderResult) (single and multilayer, single and multiview) */ -int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress, const StampData *stamp) +int IMB_exr_begin_write(void *handle, + const char *filename, + int width, + int height, + int compress, + const StampData *stamp) { - ExrHandle *data = (ExrHandle *)handle; - Header header(width, height); - ExrChannel *echan; + ExrHandle *data = (ExrHandle *)handle; + Header header(width, height); + ExrChannel *echan; - data->width = width; - data->height = height; + data->width = width; + data->height = height; - bool is_singlelayer, is_multilayer, is_multiview; + bool is_singlelayer, is_multilayer, is_multiview; - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - header.channels().insert(echan->name, - Channel(echan->use_half_float ? Imf::HALF : Imf::FLOAT)); - } + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + header.channels().insert(echan->name, Channel(echan->use_half_float ? Imf::HALF : Imf::FLOAT)); + } - openexr_header_compression(&header, compress); - BKE_stamp_info_callback(&header, const_cast(stamp), openexr_header_metadata_callback, false); - /* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */ + openexr_header_compression(&header, compress); + BKE_stamp_info_callback( + &header, const_cast(stamp), openexr_header_metadata_callback, false); + /* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */ - imb_exr_type_by_channels(header.channels(), *data->multiView, &is_singlelayer, &is_multilayer, &is_multiview); + imb_exr_type_by_channels( + header.channels(), *data->multiView, &is_singlelayer, &is_multilayer, &is_multiview); - if (is_multilayer) - header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer")); + if (is_multilayer) + header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer")); - if (is_multiview) - addMultiView(header, *data->multiView); + if (is_multiview) + addMultiView(header, *data->multiView); - /* avoid crash/abort when we don't have permission to write here */ - /* manually create ofstream, so we can handle utf-8 filepaths on windows */ - try { - data->ofile_stream = new OFileStream(filename); - data->ofile = new OutputFile(*(data->ofile_stream), header); - } - catch (const std::exception& exc) { - std::cerr << "IMB_exr_begin_write: ERROR: " << exc.what() << std::endl; + /* avoid crash/abort when we don't have permission to write here */ + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + try { + data->ofile_stream = new OFileStream(filename); + data->ofile = new OutputFile(*(data->ofile_stream), header); + } + catch (const std::exception &exc) { + std::cerr << "IMB_exr_begin_write: ERROR: " << exc.what() << std::endl; - delete data->ofile; - delete data->ofile_stream; + delete data->ofile; + delete data->ofile_stream; - data->ofile = NULL; - data->ofile_stream = NULL; - } + data->ofile = NULL; + data->ofile_stream = NULL; + } - return (data->ofile != NULL); + return (data->ofile != NULL); } /* only used for writing temp. render results (not image files) * (FSA and Save Buffers) */ -void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) +void IMB_exrtile_begin_write( + void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { - ExrHandle *data = (ExrHandle *)handle; - Header header(width, height); - std::vector
headers; - ExrChannel *echan; - - data->tilex = tilex; - data->tiley = tiley; - data->width = width; - data->height = height; - data->mipmap = mipmap; - - header.setTileDescription(TileDescription(tilex, tiley, (mipmap) ? MIPMAP_LEVELS : ONE_LEVEL)); - header.compression() = RLE_COMPRESSION; - header.setType(TILEDIMAGE); - - header.insert("BlenderMultiChannel", StringAttribute("Blender V2.43")); - - int numparts = data->multiView->size(); - - /* copy header from all parts of input to our header array - * those temporary files have one part per view */ - for (int i = 0; i < numparts; i++) { - headers.push_back (header); - headers[headers.size() - 1].setView((*(data->multiView))[i]); - headers[headers.size() - 1].setName((*(data->multiView))[i]); - } - - exr_printf("\nIMB_exrtile_begin_write\n"); - exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); - exr_printf("---------------------------------------------------------------\n"); - - /* assign channels */ - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - /* Tiles are expected to be saved with full float currently. */ - BLI_assert(echan->use_half_float == 0); - - echan->m->internal_name = echan->m->name; - echan->m->part_number = echan->view_id; - - headers[echan->view_id].channels().insert(echan->m->internal_name, Channel(Imf::FLOAT)); - exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); - } - - /* avoid crash/abort when we don't have permission to write here */ - /* manually create ofstream, so we can handle utf-8 filepaths on windows */ - try { - data->ofile_stream = new OFileStream(filename); - data->mpofile = new MultiPartOutputFile(*(data->ofile_stream), &headers[0], headers.size()); - } - catch (const std::exception &) { - delete data->mpofile; - delete data->ofile_stream; - - data->mpofile = NULL; - data->ofile_stream = NULL; - } + ExrHandle *data = (ExrHandle *)handle; + Header header(width, height); + std::vector
headers; + ExrChannel *echan; + + data->tilex = tilex; + data->tiley = tiley; + data->width = width; + data->height = height; + data->mipmap = mipmap; + + header.setTileDescription(TileDescription(tilex, tiley, (mipmap) ? MIPMAP_LEVELS : ONE_LEVEL)); + header.compression() = RLE_COMPRESSION; + header.setType(TILEDIMAGE); + + header.insert("BlenderMultiChannel", StringAttribute("Blender V2.43")); + + int numparts = data->multiView->size(); + + /* copy header from all parts of input to our header array + * those temporary files have one part per view */ + for (int i = 0; i < numparts; i++) { + headers.push_back(header); + headers[headers.size() - 1].setView((*(data->multiView))[i]); + headers[headers.size() - 1].setName((*(data->multiView))[i]); + } + + exr_printf("\nIMB_exrtile_begin_write\n"); + exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); + exr_printf("---------------------------------------------------------------\n"); + + /* assign channels */ + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + /* Tiles are expected to be saved with full float currently. */ + BLI_assert(echan->use_half_float == 0); + + echan->m->internal_name = echan->m->name; + echan->m->part_number = echan->view_id; + + headers[echan->view_id].channels().insert(echan->m->internal_name, Channel(Imf::FLOAT)); + exr_printf("%d %-6s %-22s \"%s\"\n", + echan->m->part_number, + echan->m->view.c_str(), + echan->m->name.c_str(), + echan->m->internal_name.c_str()); + } + + /* avoid crash/abort when we don't have permission to write here */ + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + try { + data->ofile_stream = new OFileStream(filename); + data->mpofile = new MultiPartOutputFile(*(data->ofile_stream), &headers[0], headers.size()); + } + catch (const std::exception &) { + delete data->mpofile; + delete data->ofile_stream; + + data->mpofile = NULL; + data->ofile_stream = NULL; + } } /* read from file */ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height) { - ExrHandle *data = (ExrHandle *)handle; - ExrChannel *echan; - - if (BLI_exists(filename) && BLI_file_size(filename) > 32) { /* 32 is arbitrary, but zero length files crashes exr */ - /* avoid crash/abort when we don't have permission to write here */ - try { - data->ifile_stream = new IFileStream(filename); - data->ifile = new MultiPartInputFile(*(data->ifile_stream)); - } - catch (const std::exception &) { - delete data->ifile; - delete data->ifile_stream; - - data->ifile = NULL; - data->ifile_stream = NULL; - } - - if (data->ifile) { - Box2i dw = data->ifile->header(0).dataWindow(); - data->width = *width = dw.max.x - dw.min.x + 1; - data->height = *height = dw.max.y - dw.min.y + 1; - - imb_exr_get_views(*data->ifile, *data->multiView); - - std::vector channels; - GetChannelsInMultiPartFile(*data->ifile, channels); - - for (size_t i = 0; i < channels.size(); i++) { - IMB_exr_add_channel(data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL, false); - - echan = (ExrChannel *)data->channels.last; - echan->m->name = channels[i].name; - echan->m->view = channels[i].view; - echan->m->part_number = channels[i].part_number; - echan->m->internal_name = channels[i].internal_name; - } - - return 1; - } - } - return 0; + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *echan; + + if (BLI_exists(filename) && + BLI_file_size(filename) > 32) { /* 32 is arbitrary, but zero length files crashes exr */ + /* avoid crash/abort when we don't have permission to write here */ + try { + data->ifile_stream = new IFileStream(filename); + data->ifile = new MultiPartInputFile(*(data->ifile_stream)); + } + catch (const std::exception &) { + delete data->ifile; + delete data->ifile_stream; + + data->ifile = NULL; + data->ifile_stream = NULL; + } + + if (data->ifile) { + Box2i dw = data->ifile->header(0).dataWindow(); + data->width = *width = dw.max.x - dw.min.x + 1; + data->height = *height = dw.max.y - dw.min.y + 1; + + imb_exr_get_views(*data->ifile, *data->multiView); + + std::vector channels; + GetChannelsInMultiPartFile(*data->ifile, channels); + + for (size_t i = 0; i < channels.size(); i++) { + IMB_exr_add_channel( + data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL, false); + + echan = (ExrChannel *)data->channels.last; + echan->m->name = channels[i].name; + echan->m->view = channels[i].view; + echan->m->part_number = channels[i].part_number; + echan->m->internal_name = channels[i].internal_name; + } + + return 1; + } + } + return 0; } /* still clumsy name handling, layers/channels can be ordered as list in list later */ /* passname here is the raw channel name without the layer */ -void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect) +void IMB_exr_set_channel( + void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect) { - ExrHandle *data = (ExrHandle *)handle; - ExrChannel *echan; - char name[EXR_TOT_MAXNAME + 1]; - - if (layname && layname[0] != '\0') { - char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1]; - BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); - BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); - - BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass); - } - else { - BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1); - } - - echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name)); - - if (echan) { - echan->xstride = xstride; - echan->ystride = ystride; - echan->rect = rect; - } - else { - printf("IMB_exr_set_channel error %s\n", name); - } + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *echan; + char name[EXR_TOT_MAXNAME + 1]; + + if (layname && layname[0] != '\0') { + char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1]; + BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); + BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); + + BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass); + } + else { + BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1); + } + + echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name)); + + if (echan) { + echan->xstride = xstride; + echan->ystride = ystride; + echan->rect = rect; + } + else { + printf("IMB_exr_set_channel error %s\n", name); + } } -float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname) +float *IMB_exr_channel_rect(void *handle, + const char *layname, + const char *passname, + const char *viewname) { - ExrHandle *data = (ExrHandle *)handle; - ExrChannel *echan; - char name[EXR_TOT_MAXNAME + 1]; - - if (layname) { - char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1]; - BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); - BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); - - BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass); - } - else - BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1); - - /* name has to be unique, thus it's a combination of layer, pass, view, and channel */ - if (layname && layname[0] != '\0') { - char temp_buf[EXR_PASS_MAXNAME]; - imb_exr_insert_view_name(temp_buf, name, viewname); - BLI_strncpy(name, temp_buf, sizeof(name)); - } - else if (data->multiView->size() >= 1) { - const int view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, viewname)); - std::string raw_name = insertViewName(name, *data->multiView, view_id); - BLI_strncpy(name, raw_name.c_str(), sizeof(name)); - } - - echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name)); - - if (echan) - return echan->rect; - - return NULL; + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *echan; + char name[EXR_TOT_MAXNAME + 1]; + + if (layname) { + char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1]; + BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); + BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); + + BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass); + } + else + BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1); + + /* name has to be unique, thus it's a combination of layer, pass, view, and channel */ + if (layname && layname[0] != '\0') { + char temp_buf[EXR_PASS_MAXNAME]; + imb_exr_insert_view_name(temp_buf, name, viewname); + BLI_strncpy(name, temp_buf, sizeof(name)); + } + else if (data->multiView->size() >= 1) { + const int view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, viewname)); + std::string raw_name = insertViewName(name, *data->multiView, view_id); + BLI_strncpy(name, raw_name.c_str(), sizeof(name)); + } + + echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name)); + + if (echan) + return echan->rect; + + return NULL; } void IMB_exr_clear_channels(void *handle) { - ExrHandle *data = (ExrHandle *)handle; - ExrChannel *chan; + ExrHandle *data = (ExrHandle *)handle; + ExrChannel *chan; - for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) - delete chan->m; + for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) + delete chan->m; - BLI_freelistN(&data->channels); + BLI_freelistN(&data->channels); } void IMB_exr_write_channels(void *handle) { - ExrHandle *data = (ExrHandle *)handle; - FrameBuffer frameBuffer; - ExrChannel *echan; - - if (data->channels.first) { - const size_t num_pixels = ((size_t)data->width) * data->height; - half *rect_half = NULL, *current_rect_half = NULL; - - /* We allocate teporary storage for half pixels for all the channels at once. */ - if (data->num_half_channels != 0) { - rect_half = (half *)MEM_mallocN(sizeof(half) * data->num_half_channels * num_pixels, __func__); - current_rect_half = rect_half; - } - - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - /* Writing starts from last scanline, stride negative. */ - if (echan->use_half_float) { - float *rect = echan->rect; - half *cur = current_rect_half; - for (size_t i = 0; i < num_pixels; ++i, ++cur) { - *cur = rect[i * echan->xstride]; - } - half *rect_to_write = current_rect_half + (data->height - 1L) * data->width; - frameBuffer.insert(echan->name, Slice(Imf::HALF, (char *)rect_to_write, - sizeof(half), -data->width * sizeof(half))); - current_rect_half += num_pixels; - } - else { - float *rect = echan->rect + echan->xstride * (data->height - 1L) * data->width; - frameBuffer.insert(echan->name, Slice(Imf::FLOAT, (char *)rect, - echan->xstride * sizeof(float), -echan->ystride * sizeof(float))); - } - } - - data->ofile->setFrameBuffer(frameBuffer); - try { - data->ofile->writePixels(data->height); - } - catch (const std::exception& exc) { - std::cerr << "OpenEXR-writePixels: ERROR: " << exc.what() << std::endl; - } - /* Free temporary buffers. */ - if (rect_half != NULL) { - MEM_freeN(rect_half); - } - } - else { - printf("Error: attempt to save MultiLayer without layers.\n"); - } + ExrHandle *data = (ExrHandle *)handle; + FrameBuffer frameBuffer; + ExrChannel *echan; + + if (data->channels.first) { + const size_t num_pixels = ((size_t)data->width) * data->height; + half *rect_half = NULL, *current_rect_half = NULL; + + /* We allocate teporary storage for half pixels for all the channels at once. */ + if (data->num_half_channels != 0) { + rect_half = (half *)MEM_mallocN(sizeof(half) * data->num_half_channels * num_pixels, + __func__); + current_rect_half = rect_half; + } + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + /* Writing starts from last scanline, stride negative. */ + if (echan->use_half_float) { + float *rect = echan->rect; + half *cur = current_rect_half; + for (size_t i = 0; i < num_pixels; ++i, ++cur) { + *cur = rect[i * echan->xstride]; + } + half *rect_to_write = current_rect_half + (data->height - 1L) * data->width; + frameBuffer.insert( + echan->name, + Slice(Imf::HALF, (char *)rect_to_write, sizeof(half), -data->width * sizeof(half))); + current_rect_half += num_pixels; + } + else { + float *rect = echan->rect + echan->xstride * (data->height - 1L) * data->width; + frameBuffer.insert(echan->name, + Slice(Imf::FLOAT, + (char *)rect, + echan->xstride * sizeof(float), + -echan->ystride * sizeof(float))); + } + } + + data->ofile->setFrameBuffer(frameBuffer); + try { + data->ofile->writePixels(data->height); + } + catch (const std::exception &exc) { + std::cerr << "OpenEXR-writePixels: ERROR: " << exc.what() << std::endl; + } + /* Free temporary buffers. */ + if (rect_half != NULL) { + MEM_freeN(rect_half); + } + } + else { + printf("Error: attempt to save MultiLayer without layers.\n"); + } } /* temporary function, used for FSA and Save Buffers */ /* called once per tile * view */ -void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname, bool empty) +void IMB_exrtile_write_channels( + void *handle, int partx, int party, int level, const char *viewname, bool empty) { - /* Can write empty channels for incomplete renders. */ - ExrHandle *data = (ExrHandle *)handle; - FrameBuffer frameBuffer; - std::string view(viewname); - const int view_id = imb_exr_get_multiView_id(*data->multiView, view); - - exr_printf("\nIMB_exrtile_write_channels(view: %s)\n", viewname); - exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); - exr_printf("---------------------------------------------------------------------\n"); - - if (!empty) { - ExrChannel *echan; - - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - - /* eventually we can make the parts' channels to include - only the current view TODO */ - if (strcmp(viewname, echan->m->view.c_str()) != 0) - continue; - - exr_printf("%d %-6s %-22s \"%s\"\n", - echan->m->part_number, - echan->m->view.c_str(), - echan->m->name.c_str(), - echan->m->internal_name.c_str() - ); - - float *rect = echan->rect - echan->xstride * partx - echan->ystride * party; - frameBuffer.insert(echan->m->internal_name, - Slice(Imf::FLOAT, - (char *)rect, - echan->xstride * sizeof(float), - echan->ystride * sizeof(float) - ) - ); - } - } - - TiledOutputPart out (*data->mpofile, view_id); - out.setFrameBuffer(frameBuffer); - - try { - // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); - out.writeTile(partx / data->tilex, party / data->tiley, level); - } - catch (const std::exception& exc) { - std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; - } + /* Can write empty channels for incomplete renders. */ + ExrHandle *data = (ExrHandle *)handle; + FrameBuffer frameBuffer; + std::string view(viewname); + const int view_id = imb_exr_get_multiView_id(*data->multiView, view); + + exr_printf("\nIMB_exrtile_write_channels(view: %s)\n", viewname); + exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); + exr_printf("---------------------------------------------------------------------\n"); + + if (!empty) { + ExrChannel *echan; + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + + /* eventually we can make the parts' channels to include + only the current view TODO */ + if (strcmp(viewname, echan->m->view.c_str()) != 0) + continue; + + exr_printf("%d %-6s %-22s \"%s\"\n", + echan->m->part_number, + echan->m->view.c_str(), + echan->m->name.c_str(), + echan->m->internal_name.c_str()); + + float *rect = echan->rect - echan->xstride * partx - echan->ystride * party; + frameBuffer.insert(echan->m->internal_name, + Slice(Imf::FLOAT, + (char *)rect, + echan->xstride * sizeof(float), + echan->ystride * sizeof(float))); + } + } + + TiledOutputPart out(*data->mpofile, view_id); + out.setFrameBuffer(frameBuffer); + + try { + // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); + out.writeTile(partx / data->tilex, party / data->tiley, level); + } + catch (const std::exception &exc) { + std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; + } } void IMB_exr_read_channels(void *handle) { - ExrHandle *data = (ExrHandle *)handle; - int numparts = data->ifile->parts(); - - /* check if exr was saved with previous versions of blender which flipped images */ - const StringAttribute *ta = data->ifile->header(0).findTypedAttribute ("BlenderMultiChannel"); - short flip = (ta && STREQLEN(ta->value().c_str(), "Blender V2.43", 13)); /* 'previous multilayer attribute, flipped */ - - exr_printf("\nIMB_exr_read_channels\n%s %-6s %-22s \"%s\"\n---------------------------------------------------------------------\n", "p", "view", "name", "internal_name"); - - for (int i = 0; i < numparts; i++) { - /* Read part header. */ - InputPart in(*data->ifile, i); - Header header = in.header(); - Box2i dw = header.dataWindow(); - - /* Insert all matching channel into framebuffer. */ - FrameBuffer frameBuffer; - ExrChannel *echan; - - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - if (echan->m->part_number != i) { - continue; - } - - exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); - - if (echan->rect) { - float *rect = echan->rect; - size_t xstride = echan->xstride * sizeof(float); - size_t ystride = echan->ystride * sizeof(float); - - if (!flip) { - /* inverse correct first pixel for datawindow coordinates */ - rect -= echan->xstride * (dw.min.x - dw.min.y * data->width); - /* move to last scanline to flip to Blender convention */ - rect += echan->xstride * (data->height - 1) * data->width; - ystride = -ystride; - } - else { - /* inverse correct first pixel for datawindow coordinates */ - rect -= echan->xstride * (dw.min.x + dw.min.y * data->width); - } - - frameBuffer.insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)rect, xstride, ystride)); - } - else - printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); - } - - /* Read pixels. */ - try { - in.setFrameBuffer(frameBuffer); - exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, dw.min.y, dw.max.y); - in.readPixels(dw.min.y, dw.max.y); - } - catch (const std::exception& exc) { - std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; - break; - } - } + ExrHandle *data = (ExrHandle *)handle; + int numparts = data->ifile->parts(); + + /* check if exr was saved with previous versions of blender which flipped images */ + const StringAttribute *ta = data->ifile->header(0).findTypedAttribute( + "BlenderMultiChannel"); + short flip = (ta && STREQLEN(ta->value().c_str(), + "Blender V2.43", + 13)); /* 'previous multilayer attribute, flipped */ + + exr_printf( + "\nIMB_exr_read_channels\n%s %-6s %-22s " + "\"%s\"\n---------------------------------------------------------------------\n", + "p", + "view", + "name", + "internal_name"); + + for (int i = 0; i < numparts; i++) { + /* Read part header. */ + InputPart in(*data->ifile, i); + Header header = in.header(); + Box2i dw = header.dataWindow(); + + /* Insert all matching channel into framebuffer. */ + FrameBuffer frameBuffer; + ExrChannel *echan; + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + if (echan->m->part_number != i) { + continue; + } + + exr_printf("%d %-6s %-22s \"%s\"\n", + echan->m->part_number, + echan->m->view.c_str(), + echan->m->name.c_str(), + echan->m->internal_name.c_str()); + + if (echan->rect) { + float *rect = echan->rect; + size_t xstride = echan->xstride * sizeof(float); + size_t ystride = echan->ystride * sizeof(float); + + if (!flip) { + /* inverse correct first pixel for datawindow coordinates */ + rect -= echan->xstride * (dw.min.x - dw.min.y * data->width); + /* move to last scanline to flip to Blender convention */ + rect += echan->xstride * (data->height - 1) * data->width; + ystride = -ystride; + } + else { + /* inverse correct first pixel for datawindow coordinates */ + rect -= echan->xstride * (dw.min.x + dw.min.y * data->width); + } + + frameBuffer.insert(echan->m->internal_name, + Slice(Imf::FLOAT, (char *)rect, xstride, ystride)); + } + else + printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); + } + + /* Read pixels. */ + try { + in.setFrameBuffer(frameBuffer); + exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, dw.min.y, dw.max.y); + in.readPixels(dw.min.y, dw.max.y); + } + catch (const std::exception &exc) { + std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; + break; + } + } } -void IMB_exr_multilayer_convert(void *handle, void *base, - void * (*addview)(void *base, const char *str), - 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 IMB_exr_multilayer_convert(void *handle, + void *base, + void *(*addview)(void *base, const char *str), + void *(*addlayer)(void *base, const char *str), + void (*addpass)(void *base, + void *lay, + const char *str, + float *rect, + int totchan, + const char *chan_id, const char *view)) { - ExrHandle *data = (ExrHandle *)handle; - ExrLayer *lay; - ExrPass *pass; - - /* RenderResult needs at least one RenderView */ - if (data->multiView->size() == 0) { - addview(base, ""); - } - else { - /* add views to RenderResult */ - for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { - addview(base, (*i).c_str()); - } - } - - if (BLI_listbase_is_empty(&data->layers)) { - printf("cannot convert multilayer, no layers in handle\n"); - return; - } - - for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { - void *laybase = addlayer(base, lay->name); - if (laybase) { - for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { - addpass(base, laybase, pass->internal_name, pass->rect, pass->totchan, pass->chan_id, pass->view); - pass->rect = NULL; - } - } - } + ExrHandle *data = (ExrHandle *)handle; + ExrLayer *lay; + ExrPass *pass; + + /* RenderResult needs at least one RenderView */ + if (data->multiView->size() == 0) { + addview(base, ""); + } + else { + /* add views to RenderResult */ + for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); + ++i) { + addview(base, (*i).c_str()); + } + } + + if (BLI_listbase_is_empty(&data->layers)) { + printf("cannot convert multilayer, no layers in handle\n"); + return; + } + + for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { + void *laybase = addlayer(base, lay->name); + if (laybase) { + for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { + addpass(base, + laybase, + pass->internal_name, + pass->rect, + pass->totchan, + pass->chan_id, + pass->view); + pass->rect = NULL; + } + } + } } void IMB_exr_close(void *handle) { - ExrHandle *data = (ExrHandle *)handle; - ExrLayer *lay; - ExrPass *pass; - ExrChannel *chan; - - delete data->ifile; - delete data->ifile_stream; - delete data->ofile; - delete data->mpofile; - delete data->ofile_stream; - delete data->multiView; - - data->ifile = NULL; - data->ifile_stream = NULL; - data->ofile = NULL; - data->mpofile = NULL; - data->ofile_stream = NULL; - - for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) { - delete chan->m; - } - BLI_freelistN(&data->channels); - - for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { - for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) - if (pass->rect) - MEM_freeN(pass->rect); - BLI_freelistN(&lay->passes); - } - BLI_freelistN(&data->layers); - - BLI_remlink(&exrhandles, data); - MEM_freeN(data); + ExrHandle *data = (ExrHandle *)handle; + ExrLayer *lay; + ExrPass *pass; + ExrChannel *chan; + + delete data->ifile; + delete data->ifile_stream; + delete data->ofile; + delete data->mpofile; + delete data->ofile_stream; + delete data->multiView; + + data->ifile = NULL; + data->ifile_stream = NULL; + data->ofile = NULL; + data->mpofile = NULL; + data->ofile_stream = NULL; + + for (chan = (ExrChannel *)data->channels.first; chan; chan = chan->next) { + delete chan->m; + } + BLI_freelistN(&data->channels); + + for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { + for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) + if (pass->rect) + MEM_freeN(pass->rect); + BLI_freelistN(&lay->passes); + } + BLI_freelistN(&data->layers); + + BLI_remlink(&exrhandles, data); + MEM_freeN(data); } /* ********* */ @@ -1247,678 +1295,696 @@ void IMB_exr_close(void *handle) /* get a substring from the end of the name, separated by '.' */ static int imb_exr_split_token(const char *str, const char *end, const char **token) { - const char delims[] = {'.', '\0'}; - const char *sep; + const char delims[] = {'.', '\0'}; + const char *sep; - BLI_str_partition_ex(str, end, delims, &sep, token, true); + BLI_str_partition_ex(str, end, delims, &sep, token, true); - if (!sep) { - *token = str; - } + if (!sep) { + *token = str; + } - return (int)(end - *token); + return (int)(end - *token); } static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *passname) { - const char *name = echan->m->name.c_str(); - const char *end = name + strlen(name); - const char *token; - char tokenbuf[EXR_TOT_MAXNAME]; - int len; - - /* some multilayers have the combined buffer with names A B G R saved */ - if (name[1] == 0) { - echan->chan_id = name[0]; - layname[0] = '\0'; - - if (ELEM(name[0], 'R', 'G', 'B', 'A')) - strcpy(passname, "Combined"); - else if (name[0] == 'Z') - strcpy(passname, "Depth"); - else - strcpy(passname, name); - - return 1; - } - - /* last token is channel identifier */ - len = imb_exr_split_token(name, end, &token); - if (len == 0) { - printf("multilayer read: bad channel name: %s\n", name); - return 0; - } - else if (len == 1) { - echan->chan_id = token[0]; - } - else if (len > 1) { - bool ok = false; - - if (len == 2) { - /* some multilayers are using two-letter channels name, - * like, MX or NZ, which is basically has structure of - * - * - * This is a bit silly, but see file from [#35658]. - * - * Here we do some magic to distinguish such cases. - */ - if (ELEM(token[1], 'X', 'Y', 'Z') || - ELEM(token[1], 'R', 'G', 'B') || - ELEM(token[1], 'U', 'V', 'A')) - { - echan->chan_id = token[1]; - ok = true; - } - } - else if (BLI_strcaseeq(token, "red")) { - echan->chan_id = 'R'; - ok = true; - } - else if (BLI_strcaseeq(token, "green")) { - echan->chan_id = 'G'; - ok = true; - } - else if (BLI_strcaseeq(token, "blue")) { - echan->chan_id = 'B'; - ok = true; - } - else if (BLI_strcaseeq(token, "alpha")) { - echan->chan_id = 'A'; - ok = true; - } - else if (BLI_strcaseeq(token, "depth")) { - echan->chan_id = 'Z'; - ok = true; - } - - if (ok == false) { - BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME)); - printf("multilayer read: unknown channel token: %s\n", tokenbuf); - return 0; - } - } - end -= len + 1; /* +1 to skip '.' separator */ - - /* second token is pass name */ - len = imb_exr_split_token(name, end, &token); - if (len == 0) { - printf("multilayer read: bad channel name: %s\n", name); - return 0; - } - BLI_strncpy(passname, token, len + 1); - end -= len + 1; /* +1 to skip '.' separator */ - - /* all preceding tokens combined as layer name */ - if (end > name) - BLI_strncpy(layname, name, (int)(end - name) + 1); - else - layname[0] = '\0'; - - return 1; + const char *name = echan->m->name.c_str(); + const char *end = name + strlen(name); + const char *token; + char tokenbuf[EXR_TOT_MAXNAME]; + int len; + + /* some multilayers have the combined buffer with names A B G R saved */ + if (name[1] == 0) { + echan->chan_id = name[0]; + layname[0] = '\0'; + + if (ELEM(name[0], 'R', 'G', 'B', 'A')) + strcpy(passname, "Combined"); + else if (name[0] == 'Z') + strcpy(passname, "Depth"); + else + strcpy(passname, name); + + return 1; + } + + /* last token is channel identifier */ + len = imb_exr_split_token(name, end, &token); + if (len == 0) { + printf("multilayer read: bad channel name: %s\n", name); + return 0; + } + else if (len == 1) { + echan->chan_id = token[0]; + } + else if (len > 1) { + bool ok = false; + + if (len == 2) { + /* some multilayers are using two-letter channels name, + * like, MX or NZ, which is basically has structure of + * + * + * This is a bit silly, but see file from [#35658]. + * + * Here we do some magic to distinguish such cases. + */ + if (ELEM(token[1], 'X', 'Y', 'Z') || ELEM(token[1], 'R', 'G', 'B') || + ELEM(token[1], 'U', 'V', 'A')) { + echan->chan_id = token[1]; + ok = true; + } + } + else if (BLI_strcaseeq(token, "red")) { + echan->chan_id = 'R'; + ok = true; + } + else if (BLI_strcaseeq(token, "green")) { + echan->chan_id = 'G'; + ok = true; + } + else if (BLI_strcaseeq(token, "blue")) { + echan->chan_id = 'B'; + ok = true; + } + else if (BLI_strcaseeq(token, "alpha")) { + echan->chan_id = 'A'; + ok = true; + } + else if (BLI_strcaseeq(token, "depth")) { + echan->chan_id = 'Z'; + ok = true; + } + + if (ok == false) { + BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME)); + printf("multilayer read: unknown channel token: %s\n", tokenbuf); + return 0; + } + } + end -= len + 1; /* +1 to skip '.' separator */ + + /* second token is pass name */ + len = imb_exr_split_token(name, end, &token); + if (len == 0) { + printf("multilayer read: bad channel name: %s\n", name); + return 0; + } + BLI_strncpy(passname, token, len + 1); + end -= len + 1; /* +1 to skip '.' separator */ + + /* all preceding tokens combined as layer name */ + if (end > name) + BLI_strncpy(layname, name, (int)(end - name) + 1); + else + layname[0] = '\0'; + + return 1; } static ExrLayer *imb_exr_get_layer(ListBase *lb, char *layname) { - ExrLayer *lay = (ExrLayer *)BLI_findstring(lb, layname, offsetof(ExrLayer, name)); + ExrLayer *lay = (ExrLayer *)BLI_findstring(lb, layname, offsetof(ExrLayer, name)); - if (lay == NULL) { - lay = (ExrLayer *)MEM_callocN(sizeof(ExrLayer), "exr layer"); - BLI_addtail(lb, lay); - BLI_strncpy(lay->name, layname, EXR_LAY_MAXNAME); - } + if (lay == NULL) { + lay = (ExrLayer *)MEM_callocN(sizeof(ExrLayer), "exr layer"); + BLI_addtail(lb, lay); + BLI_strncpy(lay->name, layname, EXR_LAY_MAXNAME); + } - return lay; + return lay; } static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname) { - ExrPass *pass = (ExrPass *)BLI_findstring(lb, passname, offsetof(ExrPass, name)); + ExrPass *pass = (ExrPass *)BLI_findstring(lb, passname, offsetof(ExrPass, name)); - if (pass == NULL) { - pass = (ExrPass *)MEM_callocN(sizeof(ExrPass), "exr pass"); + if (pass == NULL) { + pass = (ExrPass *)MEM_callocN(sizeof(ExrPass), "exr pass"); - if (STREQ(passname, "Combined")) - BLI_addhead(lb, pass); - else - BLI_addtail(lb, pass); - } + if (STREQ(passname, "Combined")) + BLI_addhead(lb, pass); + else + BLI_addtail(lb, pass); + } - BLI_strncpy(pass->name, passname, EXR_LAY_MAXNAME); + BLI_strncpy(pass->name, passname, EXR_LAY_MAXNAME); - return pass; + return pass; } /* creates channels, makes a hierarchy and assigns memory to channels */ -static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream, MultiPartInputFile &file, int width, int height) +static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream, + MultiPartInputFile &file, + int width, + int height) { - ExrLayer *lay; - ExrPass *pass; - ExrChannel *echan; - ExrHandle *data = (ExrHandle *)IMB_exr_get_handle(); - int a; - char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME]; - - data->ifile_stream = &file_stream; - data->ifile = &file; - - data->width = width; - data->height = height; - - std::vector channels; - GetChannelsInMultiPartFile(*data->ifile, channels); - - imb_exr_get_views(*data->ifile, *data->multiView); - - for (size_t i = 0; i < channels.size(); i++) { - IMB_exr_add_channel(data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL, false); - - echan = (ExrChannel *)data->channels.last; - echan->m->name = channels[i].name; - echan->m->view = channels[i].view; - echan->m->part_number = channels[i].part_number; - echan->m->internal_name = channels[i].internal_name; - } - - /* now try to sort out how to assign memory to the channels */ - /* first build hierarchical layer list */ - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - if (imb_exr_split_channel_name(echan, layname, passname)) { - - const char *view = echan->m->view.c_str(); - char internal_name[EXR_PASS_MAXNAME]; - - BLI_strncpy(internal_name, passname, EXR_PASS_MAXNAME); - - if (view[0] != '\0') { - char tmp_pass[EXR_PASS_MAXNAME]; - BLI_snprintf(tmp_pass, sizeof(tmp_pass), "%s.%s", passname, view); - BLI_strncpy(passname, tmp_pass, sizeof(passname)); - } - - ExrLayer *lay = imb_exr_get_layer(&data->layers, layname); - ExrPass *pass = imb_exr_get_pass(&lay->passes, passname); - - pass->chan[pass->totchan] = echan; - pass->totchan++; - pass->view_id = echan->view_id; - BLI_strncpy(pass->view, view, sizeof(pass->view)); - BLI_strncpy(pass->internal_name, internal_name, EXR_PASS_MAXNAME); - - if (pass->totchan >= EXR_PASS_MAXCHAN) - break; - } - } - if (echan) { - printf("error, too many channels in one pass: %s\n", echan->m->name.c_str()); - IMB_exr_close(data); - return NULL; - } - - /* with some heuristics, try to merge the channels in buffers */ - for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { - for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { - if (pass->totchan) { - pass->rect = (float *)MEM_mapallocN(width * height * pass->totchan * sizeof(float), "pass rect"); - if (pass->totchan == 1) { - echan = pass->chan[0]; - echan->rect = pass->rect; - echan->xstride = 1; - echan->ystride = width; - pass->chan_id[0] = echan->chan_id; - } - else { - char lookup[256]; - - memset(lookup, 0, sizeof(lookup)); - - /* we can have RGB(A), XYZ(W), UVA */ - if (pass->totchan == 3 || pass->totchan == 4) { - if (pass->chan[0]->chan_id == 'B' || pass->chan[1]->chan_id == 'B' || pass->chan[2]->chan_id == 'B') { - lookup[(unsigned int)'R'] = 0; - lookup[(unsigned int)'G'] = 1; - lookup[(unsigned int)'B'] = 2; - lookup[(unsigned int)'A'] = 3; - } - else if (pass->chan[0]->chan_id == 'Y' || pass->chan[1]->chan_id == 'Y' || pass->chan[2]->chan_id == 'Y') { - lookup[(unsigned int)'X'] = 0; - lookup[(unsigned int)'Y'] = 1; - lookup[(unsigned int)'Z'] = 2; - lookup[(unsigned int)'W'] = 3; - } - else { - lookup[(unsigned int)'U'] = 0; - lookup[(unsigned int)'V'] = 1; - lookup[(unsigned int)'A'] = 2; - } - for (a = 0; a < pass->totchan; a++) { - echan = pass->chan[a]; - echan->rect = pass->rect + lookup[(unsigned int)echan->chan_id]; - echan->xstride = pass->totchan; - echan->ystride = width * pass->totchan; - pass->chan_id[(unsigned int)lookup[(unsigned int)echan->chan_id]] = echan->chan_id; - } - } - else { /* unknown */ - for (a = 0; a < pass->totchan; a++) { - echan = pass->chan[a]; - echan->rect = pass->rect + a; - echan->xstride = pass->totchan; - echan->ystride = width * pass->totchan; - pass->chan_id[a] = echan->chan_id; - } - } - } - } - } - } - - return data; + ExrLayer *lay; + ExrPass *pass; + ExrChannel *echan; + ExrHandle *data = (ExrHandle *)IMB_exr_get_handle(); + int a; + char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME]; + + data->ifile_stream = &file_stream; + data->ifile = &file; + + data->width = width; + data->height = height; + + std::vector channels; + GetChannelsInMultiPartFile(*data->ifile, channels); + + imb_exr_get_views(*data->ifile, *data->multiView); + + for (size_t i = 0; i < channels.size(); i++) { + IMB_exr_add_channel( + data, NULL, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, NULL, false); + + echan = (ExrChannel *)data->channels.last; + echan->m->name = channels[i].name; + echan->m->view = channels[i].view; + echan->m->part_number = channels[i].part_number; + echan->m->internal_name = channels[i].internal_name; + } + + /* now try to sort out how to assign memory to the channels */ + /* first build hierarchical layer list */ + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + if (imb_exr_split_channel_name(echan, layname, passname)) { + + const char *view = echan->m->view.c_str(); + char internal_name[EXR_PASS_MAXNAME]; + + BLI_strncpy(internal_name, passname, EXR_PASS_MAXNAME); + + if (view[0] != '\0') { + char tmp_pass[EXR_PASS_MAXNAME]; + BLI_snprintf(tmp_pass, sizeof(tmp_pass), "%s.%s", passname, view); + BLI_strncpy(passname, tmp_pass, sizeof(passname)); + } + + ExrLayer *lay = imb_exr_get_layer(&data->layers, layname); + ExrPass *pass = imb_exr_get_pass(&lay->passes, passname); + + pass->chan[pass->totchan] = echan; + pass->totchan++; + pass->view_id = echan->view_id; + BLI_strncpy(pass->view, view, sizeof(pass->view)); + BLI_strncpy(pass->internal_name, internal_name, EXR_PASS_MAXNAME); + + if (pass->totchan >= EXR_PASS_MAXCHAN) + break; + } + } + if (echan) { + printf("error, too many channels in one pass: %s\n", echan->m->name.c_str()); + IMB_exr_close(data); + return NULL; + } + + /* with some heuristics, try to merge the channels in buffers */ + for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { + for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { + if (pass->totchan) { + pass->rect = (float *)MEM_mapallocN(width * height * pass->totchan * sizeof(float), + "pass rect"); + if (pass->totchan == 1) { + echan = pass->chan[0]; + echan->rect = pass->rect; + echan->xstride = 1; + echan->ystride = width; + pass->chan_id[0] = echan->chan_id; + } + else { + char lookup[256]; + + memset(lookup, 0, sizeof(lookup)); + + /* we can have RGB(A), XYZ(W), UVA */ + if (pass->totchan == 3 || pass->totchan == 4) { + if (pass->chan[0]->chan_id == 'B' || pass->chan[1]->chan_id == 'B' || + pass->chan[2]->chan_id == 'B') { + lookup[(unsigned int)'R'] = 0; + lookup[(unsigned int)'G'] = 1; + lookup[(unsigned int)'B'] = 2; + lookup[(unsigned int)'A'] = 3; + } + else if (pass->chan[0]->chan_id == 'Y' || pass->chan[1]->chan_id == 'Y' || + pass->chan[2]->chan_id == 'Y') { + lookup[(unsigned int)'X'] = 0; + lookup[(unsigned int)'Y'] = 1; + lookup[(unsigned int)'Z'] = 2; + lookup[(unsigned int)'W'] = 3; + } + else { + lookup[(unsigned int)'U'] = 0; + lookup[(unsigned int)'V'] = 1; + lookup[(unsigned int)'A'] = 2; + } + for (a = 0; a < pass->totchan; a++) { + echan = pass->chan[a]; + echan->rect = pass->rect + lookup[(unsigned int)echan->chan_id]; + echan->xstride = pass->totchan; + echan->ystride = width * pass->totchan; + pass->chan_id[(unsigned int)lookup[(unsigned int)echan->chan_id]] = echan->chan_id; + } + } + else { /* unknown */ + for (a = 0; a < pass->totchan; a++) { + echan = pass->chan[a]; + echan->rect = pass->rect + a; + echan->xstride = pass->totchan; + echan->ystride = width * pass->totchan; + pass->chan_id[a] = echan->chan_id; + } + } + } + } + } + } + + return data; } - /* ********************************************************* */ /* debug only */ static void exr_printf(const char *fmt, ...) { #if 0 - char output[1024]; - va_list args; - va_start(args, fmt); - std::vsprintf(output, fmt, args); - va_end(args); - printf("%s", output); + char output[1024]; + va_list args; + va_start(args, fmt); + std::vsprintf(output, fmt, args); + va_end(args); + printf("%s", output); #else - (void)fmt; + (void)fmt; #endif } -static void exr_print_filecontents(MultiPartInputFile& file) +static void exr_print_filecontents(MultiPartInputFile &file) { - int numparts = file.parts(); - if (numparts == 1 && hasMultiView(file.header(0))) { - const StringVector views = multiView(file.header(0)); - printf("OpenEXR-load: MultiView file\n"); - printf("OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str()); - for (StringVector::const_iterator i = views.begin(); i != views.end(); ++i) { - printf("OpenEXR-load: Found view %s\n", (*i).c_str()); - } - } - else if (numparts > 1) { - printf("OpenEXR-load: MultiPart file\n"); - for (int i = 0; i < numparts; i++) { - if (file.header(i).hasView()) - printf("OpenEXR-load: Part %d: view = \"%s\"\n", i, file.header(i).view().c_str()); - } - } - - for (int j = 0; j < numparts; j++) { - const ChannelList& channels = file.header(j).channels(); - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { - const Channel& channel = i.channel(); - printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type); - } - } + int numparts = file.parts(); + if (numparts == 1 && hasMultiView(file.header(0))) { + const StringVector views = multiView(file.header(0)); + printf("OpenEXR-load: MultiView file\n"); + printf("OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str()); + for (StringVector::const_iterator i = views.begin(); i != views.end(); ++i) { + printf("OpenEXR-load: Found view %s\n", (*i).c_str()); + } + } + else if (numparts > 1) { + printf("OpenEXR-load: MultiPart file\n"); + for (int i = 0; i < numparts; i++) { + if (file.header(i).hasView()) + printf("OpenEXR-load: Part %d: view = \"%s\"\n", i, file.header(i).view().c_str()); + } + } + + for (int j = 0; j < numparts; j++) { + const ChannelList &channels = file.header(j).channels(); + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { + const Channel &channel = i.channel(); + printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type); + } + } } /* for non-multilayer, map R G B A channel names to something that's in this file */ -static const char *exr_rgba_channelname(MultiPartInputFile& file, const char *chan) +static const char *exr_rgba_channelname(MultiPartInputFile &file, const char *chan) { - const ChannelList& channels = file.header(0).channels(); - - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { - /* const Channel &channel = i.channel(); */ /* Not used yet */ - const char *str = i.name(); - int len = strlen(str); - if (len) { - if (BLI_strcasecmp(chan, str + len - 1) == 0) { - return str; - } - } - } - return chan; + const ChannelList &channels = file.header(0).channels(); + + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { + /* const Channel &channel = i.channel(); */ /* Not used yet */ + const char *str = i.name(); + int len = strlen(str); + if (len) { + if (BLI_strcasecmp(chan, str + len - 1) == 0) { + return str; + } + } + } + return chan; } -static bool exr_has_rgb(MultiPartInputFile& file) +static bool exr_has_rgb(MultiPartInputFile &file) { - return file.header(0).channels().findChannel("R") != NULL && - file.header(0).channels().findChannel("G") != NULL && - file.header(0).channels().findChannel("B") != NULL; + return file.header(0).channels().findChannel("R") != NULL && + file.header(0).channels().findChannel("G") != NULL && + file.header(0).channels().findChannel("B") != NULL; } -static bool exr_has_luma(MultiPartInputFile& file) +static bool exr_has_luma(MultiPartInputFile &file) { - /* Y channel is the luma and should always present fir luma space images, - * optionally it could be also channels for chromas called BY and RY. - */ - return file.header(0).channels().findChannel("Y") != NULL; + /* Y channel is the luma and should always present fir luma space images, + * optionally it could be also channels for chromas called BY and RY. + */ + return file.header(0).channels().findChannel("Y") != NULL; } -static bool exr_has_chroma(MultiPartInputFile& file) +static bool exr_has_chroma(MultiPartInputFile &file) { - return file.header(0).channels().findChannel("BY") != NULL && - file.header(0).channels().findChannel("RY") != NULL; + return file.header(0).channels().findChannel("BY") != NULL && + file.header(0).channels().findChannel("RY") != NULL; } -static bool exr_has_zbuffer(MultiPartInputFile& file) +static bool exr_has_zbuffer(MultiPartInputFile &file) { - return !(file.header(0).channels().findChannel("Z") == NULL); + return !(file.header(0).channels().findChannel("Z") == NULL); } -static bool exr_has_alpha(MultiPartInputFile& file) +static bool exr_has_alpha(MultiPartInputFile &file) { - return !(file.header(0).channels().findChannel("A") == NULL); + return !(file.header(0).channels().findChannel("A") == NULL); } -static bool imb_exr_is_multilayer_file(MultiPartInputFile& file) +static bool imb_exr_is_multilayer_file(MultiPartInputFile &file) { - const ChannelList& channels = file.header(0).channels(); - std::set layerNames; - - /* will not include empty layer names */ - channels.layers(layerNames); - - if (layerNames.size() > 1) - return true; - - if (layerNames.size()) { - /* if layerNames is not empty, it means at least one layer is non-empty, - * but it also could be layers without names in the file and such case - * shall be considered a multilayer exr - * - * that's what we do here: test whether there're empty layer names together - * with non-empty ones in the file - */ - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) { - std::string layerName = i.name(); - size_t pos = layerName.rfind ('.'); - - if (pos == std::string::npos) - return true; - } - } - - return false; + const ChannelList &channels = file.header(0).channels(); + std::set layerNames; + + /* will not include empty layer names */ + channels.layers(layerNames); + + if (layerNames.size() > 1) + return true; + + if (layerNames.size()) { + /* if layerNames is not empty, it means at least one layer is non-empty, + * but it also could be layers without names in the file and such case + * shall be considered a multilayer exr + * + * that's what we do here: test whether there're empty layer names together + * with non-empty ones in the file + */ + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) { + std::string layerName = i.name(); + size_t pos = layerName.rfind('.'); + + if (pos == std::string::npos) + return true; + } + } + + return false; } -static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, - bool *r_singlelayer, bool *r_multilayer, bool *r_multiview) +static void imb_exr_type_by_channels(ChannelList &channels, + StringVector &views, + bool *r_singlelayer, + bool *r_multilayer, + bool *r_multiview) { - std::set layerNames; - - *r_singlelayer = true; - *r_multilayer = *r_multiview = false; - - /* will not include empty layer names */ - channels.layers(layerNames); - - if (views.size() && views[0] != "") { - *r_multiview = true; - } - else { - *r_singlelayer = false; - *r_multilayer = (layerNames.size() > 1); - *r_multiview = false; - return; - } - - if (layerNames.size()) { - /* if layerNames is not empty, it means at least one layer is non-empty, - * but it also could be layers without names in the file and such case - * shall be considered a multilayer exr - * - * that's what we do here: test whether there're empty layer names together - * with non-empty ones in the file - */ - for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) - for (std::set::iterator i = layerNames.begin(); i != layerNames.end(); i++) - /* see if any layername differs from a viewname */ - if (imb_exr_get_multiView_id(views, *i) == -1) { - std::string layerName = *i; - size_t pos = layerName.rfind ('.'); - - if (pos == std::string::npos) { - *r_multilayer = true; - *r_singlelayer = false; - return; - } - } - } - else { - *r_singlelayer = true; - *r_multilayer = false; - } - - BLI_assert(r_singlelayer != r_multilayer); + std::set layerNames; + + *r_singlelayer = true; + *r_multilayer = *r_multiview = false; + + /* will not include empty layer names */ + channels.layers(layerNames); + + if (views.size() && views[0] != "") { + *r_multiview = true; + } + else { + *r_singlelayer = false; + *r_multilayer = (layerNames.size() > 1); + *r_multiview = false; + return; + } + + if (layerNames.size()) { + /* if layerNames is not empty, it means at least one layer is non-empty, + * but it also could be layers without names in the file and such case + * shall be considered a multilayer exr + * + * that's what we do here: test whether there're empty layer names together + * with non-empty ones in the file + */ + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) + for (std::set::iterator i = layerNames.begin(); i != layerNames.end(); i++) + /* see if any layername differs from a viewname */ + if (imb_exr_get_multiView_id(views, *i) == -1) { + std::string layerName = *i; + size_t pos = layerName.rfind('.'); + + if (pos == std::string::npos) { + *r_multilayer = true; + *r_singlelayer = false; + return; + } + } + } + else { + *r_singlelayer = true; + *r_multilayer = false; + } + + BLI_assert(r_singlelayer != r_multilayer); } -static bool exr_has_multiview(MultiPartInputFile& file) +static bool exr_has_multiview(MultiPartInputFile &file) { - for (int p = 0; p < file.parts(); p++) { - if (hasMultiView(file.header(p))) { - return true; - } - } + for (int p = 0; p < file.parts(); p++) { + if (hasMultiView(file.header(p))) { + return true; + } + } - return false; + return false; } -static bool exr_has_multipart_file(MultiPartInputFile& file) +static bool exr_has_multipart_file(MultiPartInputFile &file) { - return file.parts() > 1; + return file.parts() > 1; } /* it returns true if the file is multilayer or multiview */ -static bool imb_exr_is_multi(MultiPartInputFile& file) +static bool imb_exr_is_multi(MultiPartInputFile &file) { - /* multipart files are treated as multilayer in blender - even if they are single layer openexr with multiview */ - if (exr_has_multipart_file(file)) - return true; + /* multipart files are treated as multilayer in blender - even if they are single layer openexr with multiview */ + if (exr_has_multipart_file(file)) + return true; - if (exr_has_multiview(file)) - return true; + if (exr_has_multiview(file)) + return true; - if (imb_exr_is_multilayer_file(file)) - return true; + if (imb_exr_is_multilayer_file(file)) + return true; - return false; + return false; } bool IMB_exr_has_multilayer(void *handle) { - ExrHandle *data = (ExrHandle *)handle; - return imb_exr_is_multi(*data->ifile); + ExrHandle *data = (ExrHandle *)handle; + return imb_exr_is_multi(*data->ifile); } -struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +struct ImBuf *imb_load_openexr(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - struct ImBuf *ibuf = NULL; - Mem_IStream *membuf = NULL; - MultiPartInputFile *file = NULL; - - if (imb_is_a_openexr(mem) == 0) return(NULL); - - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); - - try - { - bool is_multi; - - membuf = new Mem_IStream((unsigned char *)mem, size); - file = new MultiPartInputFile(*membuf); - - Box2i dw = file->header(0).dataWindow(); - const int width = dw.max.x - dw.min.x + 1; - const int height = dw.max.y - dw.min.y + 1; - - //printf("OpenEXR-load: image data window %d %d %d %d\n", - // dw.min.x, dw.min.y, dw.max.x, dw.max.y); - - if (0) // debug - exr_print_filecontents(*file); - - is_multi = imb_exr_is_multi(*file); - - /* do not make an ibuf when */ - if (is_multi && !(flags & IB_test) && !(flags & IB_multilayer)) { - printf("Error: can't process EXR multilayer file\n"); - } - else { - const int is_alpha = exr_has_alpha(*file); - - ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0); - - if (hasXDensity(file->header(0))) { - ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; - ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio(); - } - - ibuf->ftype = IMB_FTYPE_OPENEXR; - - if (!(flags & IB_test)) { - - if (flags & IB_metadata) { - const Header & header = file->header(0); - Header::ConstIterator iter; - - IMB_metadata_ensure(&ibuf->metadata); - for (iter = header.begin(); iter != header.end(); iter++) { - const StringAttribute *attrib = file->header(0).findTypedAttribute (iter.name()); - - /* not all attributes are string attributes so we might get some NULLs here */ - if (attrib) { - IMB_metadata_set_field(ibuf->metadata, iter.name(), attrib->value().c_str()); - ibuf->flags |= IB_metadata; - } - } - } - - if (is_multi && ((flags & IB_thumbnail) == 0)) { /* only enters with IB_multilayer flag set */ - /* constructs channels for reading, allocates memory in channels */ - ExrHandle *handle = imb_exr_begin_read_mem(*membuf, *file, width, height); - if (handle) { - IMB_exr_read_channels(handle); - ibuf->userdata = handle; /* potential danger, the caller has to check for this! */ - } - } - else { - const bool has_rgb = exr_has_rgb(*file); - const bool has_luma = exr_has_luma(*file); - FrameBuffer frameBuffer; - float *first; - int xstride = sizeof(float) * 4; - int ystride = -xstride * width; - - imb_addrectfloatImBuf(ibuf); - - /* inverse correct first pixel for datawindow coordinates (- dw.min.y because of y flip) */ - first = ibuf->rect_float - 4 * (dw.min.x - dw.min.y * width); - /* but, since we read y-flipped (negative y stride) we move to last scanline */ - first += 4 * (height - 1) * width; - - if (has_rgb) { - frameBuffer.insert(exr_rgba_channelname(*file, "R"), - Slice(Imf::FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(*file, "G"), - Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(*file, "B"), - Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); - } - else if (has_luma) { - frameBuffer.insert(exr_rgba_channelname(*file, "Y"), - Slice(Imf::FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(*file, "BY"), - Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride, 1, 1, 0.5f)); - frameBuffer.insert(exr_rgba_channelname(*file, "RY"), - Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride, 1, 1, 0.5f)); - } - - /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ - frameBuffer.insert(exr_rgba_channelname(*file, "A"), - Slice(Imf::FLOAT, (char *) (first + 3), xstride, ystride, 1, 1, 1.0f)); - - if (exr_has_zbuffer(*file)) { - float *firstz; - - addzbuffloatImBuf(ibuf); - firstz = ibuf->zbuf_float - (dw.min.x - dw.min.y * width); - firstz += (height - 1) * width; - frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)firstz, sizeof(float), -width * sizeof(float))); - } - - InputPart in (*file, 0); - in.setFrameBuffer(frameBuffer); - in.readPixels(dw.min.y, dw.max.y); - - // XXX, ImBuf has no nice way to deal with this. - // ideally IM_rect would be used when the caller wants a rect BUT - // at the moment all functions use IM_rect. - // Disabling this is ok because all functions should check if a rect exists and create one on demand. - // - // Disabling this because the sequencer frees immediate. - // - // if (flag & IM_rect) - // IMB_rect_from_float(ibuf); - - if (!has_rgb && has_luma) { - size_t a; - if (exr_has_chroma(*file)) { - for (a = 0; a < (size_t) ibuf->x * ibuf->y; ++a) { - float *color = ibuf->rect_float + a * 4; - ycc_to_rgb(color[0] * 255.0f, color[1] * 255.0f, color[2] * 255.0f, - &color[0], &color[1], &color[2], - BLI_YCC_ITU_BT709); - } - } - else { - for (a = 0; a < (size_t) ibuf->x * ibuf->y; ++a) { - float *color = ibuf->rect_float + a * 4; - color[1] = color[2] = color[0]; - } - } - } - - /* file is no longer needed */ - delete membuf; - delete file; - } - } - else { - delete membuf; - delete file; - } - - if (flags & IB_alphamode_detect) - ibuf->flags |= IB_alphamode_premul; - } - return(ibuf); - } - catch (const std::exception& exc) - { - std::cerr << exc.what() << std::endl; - if (ibuf) IMB_freeImBuf(ibuf); - delete file; - delete membuf; - - return (0); - } - + struct ImBuf *ibuf = NULL; + Mem_IStream *membuf = NULL; + MultiPartInputFile *file = NULL; + + if (imb_is_a_openexr(mem) == 0) + return (NULL); + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + + try { + bool is_multi; + + membuf = new Mem_IStream((unsigned char *)mem, size); + file = new MultiPartInputFile(*membuf); + + Box2i dw = file->header(0).dataWindow(); + const int width = dw.max.x - dw.min.x + 1; + const int height = dw.max.y - dw.min.y + 1; + + //printf("OpenEXR-load: image data window %d %d %d %d\n", + // dw.min.x, dw.min.y, dw.max.x, dw.max.y); + + if (0) // debug + exr_print_filecontents(*file); + + is_multi = imb_exr_is_multi(*file); + + /* do not make an ibuf when */ + if (is_multi && !(flags & IB_test) && !(flags & IB_multilayer)) { + printf("Error: can't process EXR multilayer file\n"); + } + else { + const int is_alpha = exr_has_alpha(*file); + + ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0); + + if (hasXDensity(file->header(0))) { + ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; + ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio(); + } + + ibuf->ftype = IMB_FTYPE_OPENEXR; + + if (!(flags & IB_test)) { + + if (flags & IB_metadata) { + const Header &header = file->header(0); + Header::ConstIterator iter; + + IMB_metadata_ensure(&ibuf->metadata); + for (iter = header.begin(); iter != header.end(); iter++) { + const StringAttribute *attrib = file->header(0).findTypedAttribute( + iter.name()); + + /* not all attributes are string attributes so we might get some NULLs here */ + if (attrib) { + IMB_metadata_set_field(ibuf->metadata, iter.name(), attrib->value().c_str()); + ibuf->flags |= IB_metadata; + } + } + } + + if (is_multi && + ((flags & IB_thumbnail) == 0)) { /* only enters with IB_multilayer flag set */ + /* constructs channels for reading, allocates memory in channels */ + ExrHandle *handle = imb_exr_begin_read_mem(*membuf, *file, width, height); + if (handle) { + IMB_exr_read_channels(handle); + ibuf->userdata = handle; /* potential danger, the caller has to check for this! */ + } + } + else { + const bool has_rgb = exr_has_rgb(*file); + const bool has_luma = exr_has_luma(*file); + FrameBuffer frameBuffer; + float *first; + int xstride = sizeof(float) * 4; + int ystride = -xstride * width; + + imb_addrectfloatImBuf(ibuf); + + /* inverse correct first pixel for datawindow coordinates (- dw.min.y because of y flip) */ + first = ibuf->rect_float - 4 * (dw.min.x - dw.min.y * width); + /* but, since we read y-flipped (negative y stride) we move to last scanline */ + first += 4 * (height - 1) * width; + + if (has_rgb) { + frameBuffer.insert(exr_rgba_channelname(*file, "R"), + Slice(Imf::FLOAT, (char *)first, xstride, ystride)); + frameBuffer.insert(exr_rgba_channelname(*file, "G"), + Slice(Imf::FLOAT, (char *)(first + 1), xstride, ystride)); + frameBuffer.insert(exr_rgba_channelname(*file, "B"), + Slice(Imf::FLOAT, (char *)(first + 2), xstride, ystride)); + } + else if (has_luma) { + frameBuffer.insert(exr_rgba_channelname(*file, "Y"), + Slice(Imf::FLOAT, (char *)first, xstride, ystride)); + frameBuffer.insert( + exr_rgba_channelname(*file, "BY"), + Slice(Imf::FLOAT, (char *)(first + 1), xstride, ystride, 1, 1, 0.5f)); + frameBuffer.insert( + exr_rgba_channelname(*file, "RY"), + Slice(Imf::FLOAT, (char *)(first + 2), xstride, ystride, 1, 1, 0.5f)); + } + + /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ + frameBuffer.insert(exr_rgba_channelname(*file, "A"), + Slice(Imf::FLOAT, (char *)(first + 3), xstride, ystride, 1, 1, 1.0f)); + + if (exr_has_zbuffer(*file)) { + float *firstz; + + addzbuffloatImBuf(ibuf); + firstz = ibuf->zbuf_float - (dw.min.x - dw.min.y * width); + firstz += (height - 1) * width; + frameBuffer.insert( + "Z", Slice(Imf::FLOAT, (char *)firstz, sizeof(float), -width * sizeof(float))); + } + + InputPart in(*file, 0); + in.setFrameBuffer(frameBuffer); + in.readPixels(dw.min.y, dw.max.y); + + // XXX, ImBuf has no nice way to deal with this. + // ideally IM_rect would be used when the caller wants a rect BUT + // at the moment all functions use IM_rect. + // Disabling this is ok because all functions should check if a rect exists and create one on demand. + // + // Disabling this because the sequencer frees immediate. + // + // if (flag & IM_rect) + // IMB_rect_from_float(ibuf); + + if (!has_rgb && has_luma) { + size_t a; + if (exr_has_chroma(*file)) { + for (a = 0; a < (size_t)ibuf->x * ibuf->y; ++a) { + float *color = ibuf->rect_float + a * 4; + ycc_to_rgb(color[0] * 255.0f, + color[1] * 255.0f, + color[2] * 255.0f, + &color[0], + &color[1], + &color[2], + BLI_YCC_ITU_BT709); + } + } + else { + for (a = 0; a < (size_t)ibuf->x * ibuf->y; ++a) { + float *color = ibuf->rect_float + a * 4; + color[1] = color[2] = color[0]; + } + } + } + + /* file is no longer needed */ + delete membuf; + delete file; + } + } + else { + delete membuf; + delete file; + } + + if (flags & IB_alphamode_detect) + ibuf->flags |= IB_alphamode_premul; + } + return (ibuf); + } + catch (const std::exception &exc) { + std::cerr << exc.what() << std::endl; + if (ibuf) + IMB_freeImBuf(ibuf); + delete file; + delete membuf; + + return (0); + } } void imb_initopenexr(void) { - int num_threads = BLI_system_thread_count(); + int num_threads = BLI_system_thread_count(); - setGlobalThreadCount(num_threads); + setGlobalThreadCount(num_threads); } void imb_exitopenexr(void) { - /* Tells OpenEXR to free thread pool, also ensures there is no running - * tasks. - */ - setGlobalThreadCount(0); + /* Tells OpenEXR to free thread pool, also ensures there is no running + * tasks. + */ + setGlobalThreadCount(0); } -} // export "C" +} // export "C" diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index 7b9094e7eb6..df03d0d205f 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -21,7 +21,6 @@ * \ingroup openexr */ - #ifndef __OPENEXR_API_H__ #define __OPENEXR_API_H__ @@ -31,19 +30,17 @@ extern "C" { #include -void imb_initopenexr (void); -void imb_exitopenexr (void); +void imb_initopenexr(void); +void imb_exitopenexr(void); -int imb_is_a_openexr (const unsigned char *mem); +int imb_is_a_openexr(const unsigned char *mem); -int imb_save_openexr (struct ImBuf *ibuf, const char *name, int flags); +int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_openexr (const unsigned char *mem, size_t size, int flags, char *colorspace); +struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char *colorspace); #ifdef __cplusplus } #endif - - #endif /* __OPENEXR_API_H */ diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index 974b3fe3ca0..58f103aeba0 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -21,7 +21,6 @@ * \ingroup openexr */ - #ifndef __OPENEXR_MULTI_H__ #define __OPENEXR_MULTI_H__ @@ -29,12 +28,11 @@ /* XXX layer+pass name max 64? */ /* This api also supports max 8 channels per pass now. easy to fix! */ -#define EXR_LAY_MAXNAME 64 -#define EXR_PASS_MAXNAME 64 -#define EXR_VIEW_MAXNAME 64 -#define EXR_TOT_MAXNAME 64 -#define EXR_PASS_MAXCHAN 24 - +#define EXR_LAY_MAXNAME 64 +#define EXR_PASS_MAXNAME 64 +#define EXR_VIEW_MAXNAME 64 +#define EXR_TOT_MAXNAME 64 +#define EXR_PASS_MAXCHAN 24 #ifdef __cplusplus extern "C" { @@ -44,39 +42,62 @@ struct StampData; void *IMB_exr_get_handle(void); void *IMB_exr_get_handle_name(const char *name); -void IMB_exr_add_channel(void *handle, - const char *layname, const char *passname, const char *view, - int xstride, int ystride, - float *rect, - bool use_half_float); - -int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height); -int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress, const struct StampData *stamp); -void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley); - -void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect); -float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *view); - -void IMB_exr_read_channels(void *handle); -void IMB_exr_write_channels(void *handle); -void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname, bool empty); -void IMB_exr_clear_channels(void *handle); - -void IMB_exr_multilayer_convert( - void *handle, void *base, - void * (*addview)(void *base, const char *str), - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, - const char *chan_id, const char *view)); - -void IMB_exr_close(void *handle); - -void IMB_exr_add_view(void *handle, const char *name); +void IMB_exr_add_channel(void *handle, + const char *layname, + const char *passname, + const char *view, + int xstride, + int ystride, + float *rect, + bool use_half_float); + +int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height); +int IMB_exr_begin_write(void *handle, + const char *filename, + int width, + int height, + int compress, + const struct StampData *stamp); +void IMB_exrtile_begin_write( + void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley); + +void IMB_exr_set_channel(void *handle, + const char *layname, + const char *passname, + int xstride, + int ystride, + float *rect); +float *IMB_exr_channel_rect(void *handle, + const char *layname, + const char *passname, + const char *view); + +void IMB_exr_read_channels(void *handle); +void IMB_exr_write_channels(void *handle); +void IMB_exrtile_write_channels( + void *handle, int partx, int party, int level, const char *viewname, bool empty); +void IMB_exr_clear_channels(void *handle); + +void IMB_exr_multilayer_convert(void *handle, + void *base, + void *(*addview)(void *base, const char *str), + void *(*addlayer)(void *base, const char *str), + void (*addpass)(void *base, + void *lay, + const char *str, + float *rect, + int totchan, + const char *chan_id, + const char *view)); + +void IMB_exr_close(void *handle); + +void IMB_exr_add_view(void *handle, const char *name); bool IMB_exr_has_multilayer(void *handle); #ifdef __cplusplus -} // extern "C" +} // extern "C" #endif #endif /* __OPENEXR_MULTI_H */ diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 23f4bae1bf8..bfc4291c7b1 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -24,34 +24,107 @@ #include "openexr_api.h" #include "openexr_multi.h" -void *IMB_exr_get_handle (void) {return NULL;} -void *IMB_exr_get_handle_name (const char * /*name*/) { return NULL;} -void IMB_exr_add_channel (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, const char * /*view*/, - int /*xstride*/, int /*ystride*/, float * /*rect*/, - bool /*use_half_float*/) { } +void *IMB_exr_get_handle(void) +{ + return NULL; +} +void *IMB_exr_get_handle_name(const char * /*name*/) +{ + return NULL; +} +void IMB_exr_add_channel(void * /*handle*/, + const char * /*layname*/, + const char * /*passname*/, + const char * /*view*/, + int /*xstride*/, + int /*ystride*/, + float * /*rect*/, + bool /*use_half_float*/) +{ +} -int IMB_exr_begin_read (void * /*handle*/, const char * /*filename*/, int * /*width*/, int * /*height*/) { return 0;} -int IMB_exr_begin_write (void * /*handle*/, const char * /*filename*/, int /*width*/, int /*height*/, int /*compress*/, const struct StampData * /*stamp*/) { return 0;} -void IMB_exrtile_begin_write (void * /*handle*/, const char * /*filename*/, int /*mipmap*/, int /*width*/, int /*height*/, int /*tilex*/, int /*tiley*/) { } +int IMB_exr_begin_read(void * /*handle*/, + const char * /*filename*/, + int * /*width*/, + int * /*height*/) +{ + return 0; +} +int IMB_exr_begin_write(void * /*handle*/, + const char * /*filename*/, + int /*width*/, + int /*height*/, + int /*compress*/, + const struct StampData * /*stamp*/) +{ + return 0; +} +void IMB_exrtile_begin_write(void * /*handle*/, + const char * /*filename*/, + int /*mipmap*/, + int /*width*/, + int /*height*/, + int /*tilex*/, + int /*tiley*/) +{ +} -void IMB_exr_set_channel (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, int /*xstride*/, int /*ystride*/, float * /*rect*/) { } -float *IMB_exr_channel_rect (void * /*handle*/, const char * /*layname*/, const char * /*passname*/, const char * /*view*/) { return NULL; } +void IMB_exr_set_channel(void * /*handle*/, + const char * /*layname*/, + const char * /*passname*/, + int /*xstride*/, + int /*ystride*/, + float * /*rect*/) +{ +} +float *IMB_exr_channel_rect(void * /*handle*/, + const char * /*layname*/, + const char * /*passname*/, + const char * /*view*/) +{ + return NULL; +} -void IMB_exr_read_channels (void * /*handle*/) { } -void IMB_exr_write_channels (void * /*handle*/) { } -void IMB_exrtile_write_channels (void * /*handle*/, int /*partx*/, int /*party*/, int /*level*/, const char * /*viewname*/, bool /*empty*/) { } -void IMB_exr_clear_channels (void * /*handle*/) { } +void IMB_exr_read_channels(void * /*handle*/) +{ +} +void IMB_exr_write_channels(void * /*handle*/) +{ +} +void IMB_exrtile_write_channels(void * /*handle*/, + int /*partx*/, + int /*party*/, + int /*level*/, + const char * /*viewname*/, + bool /*empty*/) +{ +} +void IMB_exr_clear_channels(void * /*handle*/) +{ +} -void IMB_exr_multilayer_convert( - void * /*handle*/, void * /*base*/, - void * (* /*addview*/)(void *base, const char *str), - void * (* /*addlayer*/)(void *base, const char *str), - void (* /*addpass*/)(void *base, void *lay, const char *str, float *rect, int totchan, - const char *chan_id, const char *view)) +void IMB_exr_multilayer_convert(void * /*handle*/, + void * /*base*/, + void *(*/*addview*/)(void *base, const char *str), + void *(*/*addlayer*/)(void *base, const char *str), + void (*/*addpass*/)(void *base, + void *lay, + const char *str, + float *rect, + int totchan, + const char *chan_id, + const char *view)) { } -void IMB_exr_close (void * /*handle*/) { } +void IMB_exr_close(void * /*handle*/) +{ +} -void IMB_exr_add_view(void * /*handle*/, const char * /*name*/) { } -bool IMB_exr_has_multilayer(void * /*handle*/) { return false; } +void IMB_exr_add_view(void * /*handle*/, const char * /*name*/) +{ +} +bool IMB_exr_has_multilayer(void * /*handle*/) +{ + return false; +} diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index e51f24f67d8..27cf30c71ba 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -45,9 +45,9 @@ #include "IMB_colormanagement_intern.h" typedef struct PNGReadStruct { - const unsigned char *data; - unsigned int size; - unsigned int seek; + const unsigned char *data; + unsigned int size; + unsigned int seek; } PNGReadStruct; static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length); @@ -56,719 +56,750 @@ static void Flush(png_structp png_ptr); BLI_INLINE unsigned short UPSAMPLE_8_TO_16(const unsigned char _val) { - return (_val << 8) + _val; + return (_val << 8) + _val; } int imb_is_a_png(const unsigned char *mem) { - int ret_val = 0; + int ret_val = 0; - if (mem) { + if (mem) { #if (PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR == 2) - /* Older version of libpng doesn't use const pointer to memory. */ - ret_val = !png_sig_cmp((png_bytep)mem, 0, 8); + /* Older version of libpng doesn't use const pointer to memory. */ + ret_val = !png_sig_cmp((png_bytep)mem, 0, 8); #else - ret_val = !png_sig_cmp(mem, 0, 8); + ret_val = !png_sig_cmp(mem, 0, 8); #endif - } - return(ret_val); + } + return (ret_val); } static void Flush(png_structp png_ptr) { - (void)png_ptr; + (void)png_ptr; } static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length) { - ImBuf *ibuf = (ImBuf *) png_get_io_ptr(png_ptr); + ImBuf *ibuf = (ImBuf *)png_get_io_ptr(png_ptr); - /* if buffer is to small increase it. */ - while (ibuf->encodedsize + length > ibuf->encodedbuffersize) { - imb_enlargeencodedbufferImBuf(ibuf); - } + /* if buffer is to small increase it. */ + while (ibuf->encodedsize + length > ibuf->encodedbuffersize) { + imb_enlargeencodedbufferImBuf(ibuf); + } - memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length); - ibuf->encodedsize += length; + memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length); + ibuf->encodedsize += length; } static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length) { - PNGReadStruct *rs = (PNGReadStruct *) png_get_io_ptr(png_ptr); - - if (rs) { - if (length <= rs->size - rs->seek) { - memcpy(data, rs->data + rs->seek, length); - rs->seek += length; - return; - } - } - - printf("Reached EOF while decoding PNG\n"); - longjmp(png_jmpbuf(png_ptr), 1); + PNGReadStruct *rs = (PNGReadStruct *)png_get_io_ptr(png_ptr); + + if (rs) { + if (length <= rs->size - rs->seek) { + memcpy(data, rs->data + rs->seek, length); + rs->seek += length; + return; + } + } + + printf("Reached EOF while decoding PNG\n"); + longjmp(png_jmpbuf(png_ptr), 1); } static float channel_colormanage_noop(float value) { - return value; + return value; } /* wrap to avoid macro calling functions multiple times */ BLI_INLINE unsigned short ftoshort(float val) { - return unit_float_to_ushort_clamp(val); + return unit_float_to_ushort_clamp(val); } int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) { - png_structp png_ptr; - png_infop info_ptr; - - unsigned char *pixels = NULL; - unsigned char *from, *to; - unsigned short *pixels16 = NULL, *to16; - float *from_float, from_straight[4]; - png_bytepp row_pointers = NULL; - int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY; - FILE *fp = NULL; - - bool is_16bit = (ibuf->foptions.flag & PNG_16BIT) != 0; - bool has_float = (ibuf->rect_float != NULL); - int channels_in_float = ibuf->channels ? ibuf->channels : 4; - - float (*chanel_colormanage_cb)(float); - size_t num_bytes; - - /* use the jpeg quality setting for compression */ - int compression; - compression = (int)(((float)(ibuf->foptions.quality) / 11.1111f)); - compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression); - - if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) { - /* float buffer was managed already, no need in color space conversion */ - chanel_colormanage_cb = channel_colormanage_noop; - } - else { - /* standard linear-to-srgb conversion if float buffer wasn't managed */ - chanel_colormanage_cb = linearrgb_to_srgb; - } - - /* for prints */ - if (flags & IB_mem) - name = ""; - - bytesperpixel = (ibuf->planes + 7) >> 3; - if ((bytesperpixel > 4) || (bytesperpixel == 2)) { - printf("imb_savepng: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name); - return (0); - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); - if (png_ptr == NULL) { - printf("imb_savepng: Cannot png_create_write_struct for file: '%s'\n", name); - return 0; - } - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - printf("imb_savepng: Cannot png_create_info_struct for file: '%s'\n", name); - return 0; - } - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, &info_ptr); - printf("imb_savepng: Cannot setjmp for file: '%s'\n", name); - return 0; - } - - /* copy image data */ - num_bytes = ((size_t)ibuf->x) * ibuf->y * bytesperpixel; - if (is_16bit) - pixels16 = MEM_mallocN(num_bytes * sizeof(unsigned short), "png 16bit pixels"); - else - pixels = MEM_mallocN(num_bytes * sizeof(unsigned char), "png 8bit pixels"); - - if (pixels == NULL && pixels16 == NULL) { - png_destroy_write_struct(&png_ptr, &info_ptr); - printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name); - return 0; - } - - from = (unsigned char *) ibuf->rect; - to = pixels; - from_float = ibuf->rect_float; - to16 = pixels16; - - switch (bytesperpixel) { - case 4: - color_type = PNG_COLOR_TYPE_RGBA; - if (is_16bit) { - if (has_float) { - if (channels_in_float == 4) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4_v4(from_straight, from_float); - to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); - to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1])); - to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2])); - to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3])); - to16 += 4; from_float += 4; - } - } - else if (channels_in_float == 3) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); - to16[1] = ftoshort(chanel_colormanage_cb(from_float[1])); - to16[2] = ftoshort(chanel_colormanage_cb(from_float[2])); - to16[3] = 65535; - to16 += 4; from_float += 3; - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); - to16[2] = to16[1] = to16[0]; - to16[3] = 65535; - to16 += 4; from_float++; - } - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = UPSAMPLE_8_TO_16(from[0]); - to16[1] = UPSAMPLE_8_TO_16(from[1]); - to16[2] = UPSAMPLE_8_TO_16(from[2]); - to16[3] = UPSAMPLE_8_TO_16(from[3]); - to16 += 4; from += 4; - } - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to[3] = from[3]; - to += 4; from += 4; - } - } - break; - case 3: - color_type = PNG_COLOR_TYPE_RGB; - if (is_16bit) { - if (has_float) { - if (channels_in_float == 4) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4_v4(from_straight, from_float); - to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); - to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1])); - to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2])); - to16 += 3; from_float += 4; - } - } - else if (channels_in_float == 3) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); - to16[1] = ftoshort(chanel_colormanage_cb(from_float[1])); - to16[2] = ftoshort(chanel_colormanage_cb(from_float[2])); - to16 += 3; from_float += 3; - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); - to16[2] = to16[1] = to16[0]; - to16 += 3; from_float++; - } - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = UPSAMPLE_8_TO_16(from[0]); - to16[1] = UPSAMPLE_8_TO_16(from[1]); - to16[2] = UPSAMPLE_8_TO_16(from[2]); - to16 += 3; from += 4; - } - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to += 3; from += 4; - } - } - break; - case 1: - color_type = PNG_COLOR_TYPE_GRAY; - if (is_16bit) { - if (has_float) { - float rgb[3]; - if (channels_in_float == 4) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4_v4(from_straight, from_float); - rgb[0] = chanel_colormanage_cb(from_straight[0]); - rgb[1] = chanel_colormanage_cb(from_straight[1]); - rgb[2] = chanel_colormanage_cb(from_straight[2]); - to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb)); - to16++; from_float += 4; - } - } - else if (channels_in_float == 3) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - rgb[0] = chanel_colormanage_cb(from_float[0]); - rgb[1] = chanel_colormanage_cb(from_float[1]); - rgb[2] = chanel_colormanage_cb(from_float[2]); - to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb)); - to16++; from_float += 3; - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); - to16++; from_float++; - } - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to16[0] = UPSAMPLE_8_TO_16(from[0]); - to16++; from += 4; - } - } - } - else { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - to[0] = from[0]; - to++; from += 4; - } - } - break; - } - - if (flags & IB_mem) { - /* create image in memory */ - imb_addencodedbufferImBuf(ibuf); - ibuf->encodedsize = 0; - - png_set_write_fn(png_ptr, - (png_voidp) ibuf, - WriteData, - Flush); - } - else { - fp = BLI_fopen(name, "wb"); - if (!fp) { - png_destroy_write_struct(&png_ptr, &info_ptr); - if (pixels) - MEM_freeN(pixels); - if (pixels16) - MEM_freeN(pixels16); - printf("imb_savepng: Cannot open file for writing: '%s'\n", name); - return 0; - } - png_init_io(png_ptr, fp); - } + png_structp png_ptr; + png_infop info_ptr; + + unsigned char *pixels = NULL; + unsigned char *from, *to; + unsigned short *pixels16 = NULL, *to16; + float *from_float, from_straight[4]; + png_bytepp row_pointers = NULL; + int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY; + FILE *fp = NULL; + + bool is_16bit = (ibuf->foptions.flag & PNG_16BIT) != 0; + bool has_float = (ibuf->rect_float != NULL); + int channels_in_float = ibuf->channels ? ibuf->channels : 4; + + float (*chanel_colormanage_cb)(float); + size_t num_bytes; + + /* use the jpeg quality setting for compression */ + int compression; + compression = (int)(((float)(ibuf->foptions.quality) / 11.1111f)); + compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression); + + if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) { + /* float buffer was managed already, no need in color space conversion */ + chanel_colormanage_cb = channel_colormanage_noop; + } + else { + /* standard linear-to-srgb conversion if float buffer wasn't managed */ + chanel_colormanage_cb = linearrgb_to_srgb; + } + + /* for prints */ + if (flags & IB_mem) + name = ""; + + bytesperpixel = (ibuf->planes + 7) >> 3; + if ((bytesperpixel > 4) || (bytesperpixel == 2)) { + printf("imb_savepng: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name); + return (0); + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + printf("imb_savepng: Cannot png_create_write_struct for file: '%s'\n", name); + return 0; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + printf("imb_savepng: Cannot png_create_info_struct for file: '%s'\n", name); + return 0; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + printf("imb_savepng: Cannot setjmp for file: '%s'\n", name); + return 0; + } + + /* copy image data */ + num_bytes = ((size_t)ibuf->x) * ibuf->y * bytesperpixel; + if (is_16bit) + pixels16 = MEM_mallocN(num_bytes * sizeof(unsigned short), "png 16bit pixels"); + else + pixels = MEM_mallocN(num_bytes * sizeof(unsigned char), "png 8bit pixels"); + + if (pixels == NULL && pixels16 == NULL) { + png_destroy_write_struct(&png_ptr, &info_ptr); + printf( + "imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", + ibuf->x, + ibuf->y, + bytesperpixel, + name); + return 0; + } + + from = (unsigned char *)ibuf->rect; + to = pixels; + from_float = ibuf->rect_float; + to16 = pixels16; + + switch (bytesperpixel) { + case 4: + color_type = PNG_COLOR_TYPE_RGBA; + if (is_16bit) { + if (has_float) { + if (channels_in_float == 4) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + premul_to_straight_v4_v4(from_straight, from_float); + to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); + to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1])); + to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2])); + to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3])); + to16 += 4; + from_float += 4; + } + } + else if (channels_in_float == 3) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); + to16[1] = ftoshort(chanel_colormanage_cb(from_float[1])); + to16[2] = ftoshort(chanel_colormanage_cb(from_float[2])); + to16[3] = 65535; + to16 += 4; + from_float += 3; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); + to16[2] = to16[1] = to16[0]; + to16[3] = 65535; + to16 += 4; + from_float++; + } + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16[1] = UPSAMPLE_8_TO_16(from[1]); + to16[2] = UPSAMPLE_8_TO_16(from[2]); + to16[3] = UPSAMPLE_8_TO_16(from[3]); + to16 += 4; + from += 4; + } + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to += 4; + from += 4; + } + } + break; + case 3: + color_type = PNG_COLOR_TYPE_RGB; + if (is_16bit) { + if (has_float) { + if (channels_in_float == 4) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + premul_to_straight_v4_v4(from_straight, from_float); + to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); + to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1])); + to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2])); + to16 += 3; + from_float += 4; + } + } + else if (channels_in_float == 3) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); + to16[1] = ftoshort(chanel_colormanage_cb(from_float[1])); + to16[2] = ftoshort(chanel_colormanage_cb(from_float[2])); + to16 += 3; + from_float += 3; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); + to16[2] = to16[1] = to16[0]; + to16 += 3; + from_float++; + } + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16[1] = UPSAMPLE_8_TO_16(from[1]); + to16[2] = UPSAMPLE_8_TO_16(from[2]); + to16 += 3; + from += 4; + } + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to += 3; + from += 4; + } + } + break; + case 1: + color_type = PNG_COLOR_TYPE_GRAY; + if (is_16bit) { + if (has_float) { + float rgb[3]; + if (channels_in_float == 4) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + premul_to_straight_v4_v4(from_straight, from_float); + rgb[0] = chanel_colormanage_cb(from_straight[0]); + rgb[1] = chanel_colormanage_cb(from_straight[1]); + rgb[2] = chanel_colormanage_cb(from_straight[2]); + to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb)); + to16++; + from_float += 4; + } + } + else if (channels_in_float == 3) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + rgb[0] = chanel_colormanage_cb(from_float[0]); + rgb[1] = chanel_colormanage_cb(from_float[1]); + rgb[2] = chanel_colormanage_cb(from_float[2]); + to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb)); + to16++; + from_float += 3; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = ftoshort(chanel_colormanage_cb(from_float[0])); + to16++; + from_float++; + } + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16++; + from += 4; + } + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to[0] = from[0]; + to++; + from += 4; + } + } + break; + } + + if (flags & IB_mem) { + /* create image in memory */ + imb_addencodedbufferImBuf(ibuf); + ibuf->encodedsize = 0; + + png_set_write_fn(png_ptr, (png_voidp)ibuf, WriteData, Flush); + } + else { + fp = BLI_fopen(name, "wb"); + if (!fp) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); + printf("imb_savepng: Cannot open file for writing: '%s'\n", name); + return 0; + } + png_init_io(png_ptr, fp); + } #if 0 - png_set_filter(png_ptr, 0, - PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | - PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | - PNG_FILTER_UP | PNG_FILTER_VALUE_UP | - PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | - PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH | - PNG_ALL_FILTERS); + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH | + PNG_ALL_FILTERS); #endif - png_set_compression_level(png_ptr, compression); - - /* png image settings */ - png_set_IHDR(png_ptr, - info_ptr, - ibuf->x, - ibuf->y, - is_16bit ? 16 : 8, - color_type, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - /* image text info */ - if (ibuf->metadata) { - png_text *metadata; - IDProperty *prop; - - int num_text = 0; - - for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) { - if (prop->type == IDP_STRING) { - num_text++; - } - } - - metadata = MEM_callocN(num_text * sizeof(png_text), "png_metadata"); - num_text = 0; - for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) { - if (prop->type == IDP_STRING) { - metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE; - metadata[num_text].key = prop->name; - metadata[num_text].text = IDP_String(prop); - num_text++; - } - } - - png_set_text(png_ptr, info_ptr, metadata, num_text); - MEM_freeN(metadata); - - } - - if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) { - png_set_pHYs(png_ptr, info_ptr, (unsigned int)(ibuf->ppm[0] + 0.5), (unsigned int)(ibuf->ppm[1] + 0.5), PNG_RESOLUTION_METER); - } - - /* write the file header information */ - png_write_info(png_ptr, info_ptr); + png_set_compression_level(png_ptr, compression); + + /* png image settings */ + png_set_IHDR(png_ptr, + info_ptr, + ibuf->x, + ibuf->y, + is_16bit ? 16 : 8, + color_type, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + /* image text info */ + if (ibuf->metadata) { + png_text *metadata; + IDProperty *prop; + + int num_text = 0; + + for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) { + if (prop->type == IDP_STRING) { + num_text++; + } + } + + metadata = MEM_callocN(num_text * sizeof(png_text), "png_metadata"); + num_text = 0; + for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) { + if (prop->type == IDP_STRING) { + metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE; + metadata[num_text].key = prop->name; + metadata[num_text].text = IDP_String(prop); + num_text++; + } + } + + png_set_text(png_ptr, info_ptr, metadata, num_text); + MEM_freeN(metadata); + } + + if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) { + png_set_pHYs(png_ptr, + info_ptr, + (unsigned int)(ibuf->ppm[0] + 0.5), + (unsigned int)(ibuf->ppm[1] + 0.5), + PNG_RESOLUTION_METER); + } + + /* write the file header information */ + png_write_info(png_ptr, info_ptr); #ifdef __LITTLE_ENDIAN__ - png_set_swap(png_ptr); + png_set_swap(png_ptr); #endif - /* allocate memory for an array of row-pointers */ - row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); - if (row_pointers == NULL) { - printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name); - png_destroy_write_struct(&png_ptr, &info_ptr); - if (pixels) - MEM_freeN(pixels); - if (pixels16) - MEM_freeN(pixels16); - if (fp) { - fclose(fp); - } - return 0; - } - - /* set the individual row-pointers to point at the correct offsets */ - if (is_16bit) { - for (i = 0; i < ibuf->y; i++) { - row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned short *)pixels16 + (((size_t)i) * ibuf->x) * bytesperpixel); - } - } - else { - for (i = 0; i < ibuf->y; i++) { - row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * bytesperpixel * sizeof(unsigned char)); - } - } - - /* write out the entire image data in one call */ - png_write_image(png_ptr, row_pointers); - - /* write the additional chunks to the PNG file (not really needed) */ - png_write_end(png_ptr, info_ptr); - - /* clean up */ - if (pixels) - MEM_freeN(pixels); - if (pixels16) - MEM_freeN(pixels16); - MEM_freeN(row_pointers); - png_destroy_write_struct(&png_ptr, &info_ptr); - - if (fp) { - fflush(fp); - fclose(fp); - } - - return(1); + /* allocate memory for an array of row-pointers */ + row_pointers = (png_bytepp)MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); + if (row_pointers == NULL) { + printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name); + png_destroy_write_struct(&png_ptr, &info_ptr); + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); + if (fp) { + fclose(fp); + } + return 0; + } + + /* set the individual row-pointers to point at the correct offsets */ + if (is_16bit) { + for (i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y - 1 - i] = (png_bytep)((unsigned short *)pixels16 + + (((size_t)i) * ibuf->x) * bytesperpixel); + } + } + else { + for (i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y - 1 - i] = (png_bytep)((unsigned char *)pixels + + (((size_t)i) * ibuf->x) * bytesperpixel * + sizeof(unsigned char)); + } + } + + /* write out the entire image data in one call */ + png_write_image(png_ptr, row_pointers); + + /* write the additional chunks to the PNG file (not really needed) */ + png_write_end(png_ptr, info_ptr); + + /* clean up */ + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); + MEM_freeN(row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + + if (fp) { + fflush(fp); + fclose(fp); + } + + return (1); } static void imb_png_warning(png_structp UNUSED(png_ptr), png_const_charp message) { - /* We suppress iCCP warnings. That's how Blender always used to behave, - * and with new libpng it became too much picky, giving a warning on - * the splash screen even. - */ - if ((G.debug & G_DEBUG) == 0 && STREQLEN(message, "iCCP", 4)) { - return; - } - fprintf(stderr, "libpng warning: %s\n", message); + /* We suppress iCCP warnings. That's how Blender always used to behave, + * and with new libpng it became too much picky, giving a warning on + * the splash screen even. + */ + if ((G.debug & G_DEBUG) == 0 && STREQLEN(message, "iCCP", 4)) { + return; + } + fprintf(stderr, "libpng warning: %s\n", message); } static void imb_png_error(png_structp UNUSED(png_ptr), png_const_charp message) { - fprintf(stderr, "libpng error: %s\n", message); + fprintf(stderr, "libpng error: %s\n", message); } ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { - struct ImBuf *ibuf = NULL; - png_structp png_ptr; - png_infop info_ptr; - unsigned char *pixels = NULL; - unsigned short *pixels16 = NULL; - png_bytepp row_pointers = NULL; - png_uint_32 width, height; - int bit_depth, color_type; - PNGReadStruct ps; - - unsigned char *from, *to; - unsigned short *from16; - float *to_float; - unsigned int channels; - - if (imb_is_a_png(mem) == 0) return(NULL); - - /* both 8 and 16 bit PNGs are default to standard byte colorspace */ - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); - if (png_ptr == NULL) { - printf("Cannot png_create_read_struct\n"); - return NULL; - } - - png_set_error_fn(png_ptr, NULL, imb_png_error, imb_png_warning); - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, - (png_infopp)NULL); - printf("Cannot png_create_info_struct\n"); - return NULL; - } - - ps.size = size; /* XXX, 4gig limit! */ - ps.data = mem; - ps.seek = 0; - - png_set_read_fn(png_ptr, (void *) &ps, ReadData); - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - if (pixels) MEM_freeN(pixels); - if (pixels16) MEM_freeN(pixels16); - if (row_pointers) MEM_freeN(row_pointers); - if (ibuf) IMB_freeImBuf(ibuf); - return NULL; - } - - // png_set_sig_bytes(png_ptr, 8); - - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, - &color_type, NULL, NULL, NULL); - - channels = png_get_channels(png_ptr, info_ptr); - - switch (color_type) { - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - break; - case PNG_COLOR_TYPE_PALETTE: - png_set_palette_to_rgb(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - channels = 4; - } - else { - channels = 3; - } - break; - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth < 8) { - png_set_expand(png_ptr); - bit_depth = 8; - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - /* PNG_COLOR_TYPE_GRAY may also have alpha 'values', like with palette. */ - channels = 2; - } - } - break; - default: - printf("PNG format not supported\n"); - longjmp(png_jmpbuf(png_ptr), 1); - } - - ibuf = IMB_allocImBuf(width, height, 8 * channels, 0); - - if (ibuf) { - ibuf->ftype = IMB_FTYPE_PNG; - if (bit_depth == 16) - ibuf->foptions.flag |= PNG_16BIT; - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { - int unit_type; - png_uint_32 xres, yres; - - if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) { - if (unit_type == PNG_RESOLUTION_METER) { - ibuf->ppm[0] = xres; - ibuf->ppm[1] = yres; - } - } - } - } - else { - printf("Couldn't allocate memory for PNG image\n"); - } - - if (ibuf && ((flags & IB_test) == 0)) { - if (bit_depth == 16) { - imb_addrectfloatImBuf(ibuf); - png_set_swap(png_ptr); - - pixels16 = imb_alloc_pixels(ibuf->x, ibuf->y, channels, sizeof(png_uint_16), "pixels"); - if (pixels16 == NULL || ibuf->rect_float == NULL) { - printf("Cannot allocate pixels array\n"); - longjmp(png_jmpbuf(png_ptr), 1); - } - - /* allocate memory for an array of row-pointers */ - row_pointers = (png_bytepp) MEM_mallocN((size_t)ibuf->y * sizeof(png_uint_16p), "row_pointers"); - if (row_pointers == NULL) { - printf("Cannot allocate row-pointers array\n"); - longjmp(png_jmpbuf(png_ptr), 1); - } - - /* set the individual row-pointers to point at the correct offsets */ - for (size_t i = 0; i < ibuf->y; i++) { - row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((png_uint_16 *)pixels16 + (i * ibuf->x) * channels); - } - - png_read_image(png_ptr, row_pointers); - - /* copy image data */ - - to_float = ibuf->rect_float; - from16 = pixels16; - - switch (channels) { - case 4: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to_float[0] = from16[0] / 65535.0; - to_float[1] = from16[1] / 65535.0; - to_float[2] = from16[2] / 65535.0; - to_float[3] = from16[3] / 65535.0; - to_float += 4; from16 += 4; - } - break; - case 3: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to_float[0] = from16[0] / 65535.0; - to_float[1] = from16[1] / 65535.0; - to_float[2] = from16[2] / 65535.0; - to_float[3] = 1.0; - to_float += 4; from16 += 3; - } - break; - case 2: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; - to_float[3] = from16[1] / 65535.0; - to_float += 4; from16 += 2; - } - break; - case 1: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; - to_float[3] = 1.0; - to_float += 4; from16++; - } - break; - } - } - else { - imb_addrectImBuf(ibuf); - - pixels = imb_alloc_pixels(ibuf->x, ibuf->y, channels, sizeof(unsigned char), "pixels"); - if (pixels == NULL || ibuf->rect == NULL) { - printf("Cannot allocate pixels array\n"); - longjmp(png_jmpbuf(png_ptr), 1); - } - - /* allocate memory for an array of row-pointers */ - row_pointers = (png_bytepp) MEM_mallocN((size_t)ibuf->y * sizeof(png_bytep), "row_pointers"); - if (row_pointers == NULL) { - printf("Cannot allocate row-pointers array\n"); - longjmp(png_jmpbuf(png_ptr), 1); - } - - /* set the individual row-pointers to point at the correct offsets */ - for (int i = 0; i < ibuf->y; i++) { - row_pointers[ibuf->y - 1 - i] = (png_bytep) - ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * channels * sizeof(unsigned char)); - } - - png_read_image(png_ptr, row_pointers); - - /* copy image data */ - - to = (unsigned char *) ibuf->rect; - from = pixels; - - switch (channels) { - case 4: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to[3] = from[3]; - to += 4; from += 4; - } - break; - case 3: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to[3] = 0xff; - to += 4; from += 3; - } - break; - case 2: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to[0] = to[1] = to[2] = from[0]; - to[3] = from[1]; - to += 4; from += 2; - } - break; - case 1: - for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { - to[0] = to[1] = to[2] = from[0]; - to[3] = 0xff; - to += 4; from++; - } - break; - } - } - - if (flags & IB_metadata) { - png_text *text_chunks; - int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); - IMB_metadata_ensure(&ibuf->metadata); - for (int i = 0; i < count; i++) { - IMB_metadata_set_field(ibuf->metadata, text_chunks[i].key, text_chunks[i].text); - ibuf->flags |= IB_metadata; - } - } - - png_read_end(png_ptr, info_ptr); - } - - /* clean up */ - if (pixels) - MEM_freeN(pixels); - if (pixels16) - MEM_freeN(pixels16); - if (row_pointers) - MEM_freeN(row_pointers); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - - return(ibuf); + struct ImBuf *ibuf = NULL; + png_structp png_ptr; + png_infop info_ptr; + unsigned char *pixels = NULL; + unsigned short *pixels16 = NULL; + png_bytepp row_pointers = NULL; + png_uint_32 width, height; + int bit_depth, color_type; + PNGReadStruct ps; + + unsigned char *from, *to; + unsigned short *from16; + float *to_float; + unsigned int channels; + + if (imb_is_a_png(mem) == 0) + return (NULL); + + /* both 8 and 16 bit PNGs are default to standard byte colorspace */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + printf("Cannot png_create_read_struct\n"); + return NULL; + } + + png_set_error_fn(png_ptr, NULL, imb_png_error, imb_png_warning); + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + printf("Cannot png_create_info_struct\n"); + return NULL; + } + + ps.size = size; /* XXX, 4gig limit! */ + ps.data = mem; + ps.seek = 0; + + png_set_read_fn(png_ptr, (void *)&ps, ReadData); + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); + if (row_pointers) + MEM_freeN(row_pointers); + if (ibuf) + IMB_freeImBuf(ibuf); + return NULL; + } + + // png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + channels = png_get_channels(png_ptr, info_ptr); + + switch (color_type) { + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + break; + case PNG_COLOR_TYPE_PALETTE: + png_set_palette_to_rgb(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + channels = 4; + } + else { + channels = 3; + } + break; + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth < 8) { + png_set_expand(png_ptr); + bit_depth = 8; + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + /* PNG_COLOR_TYPE_GRAY may also have alpha 'values', like with palette. */ + channels = 2; + } + } + break; + default: + printf("PNG format not supported\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + ibuf = IMB_allocImBuf(width, height, 8 * channels, 0); + + if (ibuf) { + ibuf->ftype = IMB_FTYPE_PNG; + if (bit_depth == 16) + ibuf->foptions.flag |= PNG_16BIT; + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { + int unit_type; + png_uint_32 xres, yres; + + if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) { + if (unit_type == PNG_RESOLUTION_METER) { + ibuf->ppm[0] = xres; + ibuf->ppm[1] = yres; + } + } + } + } + else { + printf("Couldn't allocate memory for PNG image\n"); + } + + if (ibuf && ((flags & IB_test) == 0)) { + if (bit_depth == 16) { + imb_addrectfloatImBuf(ibuf); + png_set_swap(png_ptr); + + pixels16 = imb_alloc_pixels(ibuf->x, ibuf->y, channels, sizeof(png_uint_16), "pixels"); + if (pixels16 == NULL || ibuf->rect_float == NULL) { + printf("Cannot allocate pixels array\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + /* allocate memory for an array of row-pointers */ + row_pointers = (png_bytepp)MEM_mallocN((size_t)ibuf->y * sizeof(png_uint_16p), + "row_pointers"); + if (row_pointers == NULL) { + printf("Cannot allocate row-pointers array\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + /* set the individual row-pointers to point at the correct offsets */ + for (size_t i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y - 1 - i] = (png_bytep)((png_uint_16 *)pixels16 + + (i * ibuf->x) * channels); + } + + png_read_image(png_ptr, row_pointers); + + /* copy image data */ + + to_float = ibuf->rect_float; + from16 = pixels16; + + switch (channels) { + case 4: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to_float[0] = from16[0] / 65535.0; + to_float[1] = from16[1] / 65535.0; + to_float[2] = from16[2] / 65535.0; + to_float[3] = from16[3] / 65535.0; + to_float += 4; + from16 += 4; + } + break; + case 3: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to_float[0] = from16[0] / 65535.0; + to_float[1] = from16[1] / 65535.0; + to_float[2] = from16[2] / 65535.0; + to_float[3] = 1.0; + to_float += 4; + from16 += 3; + } + break; + case 2: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; + to_float[3] = from16[1] / 65535.0; + to_float += 4; + from16 += 2; + } + break; + case 1: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; + to_float[3] = 1.0; + to_float += 4; + from16++; + } + break; + } + } + else { + imb_addrectImBuf(ibuf); + + pixels = imb_alloc_pixels(ibuf->x, ibuf->y, channels, sizeof(unsigned char), "pixels"); + if (pixels == NULL || ibuf->rect == NULL) { + printf("Cannot allocate pixels array\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + /* allocate memory for an array of row-pointers */ + row_pointers = (png_bytepp)MEM_mallocN((size_t)ibuf->y * sizeof(png_bytep), "row_pointers"); + if (row_pointers == NULL) { + printf("Cannot allocate row-pointers array\n"); + longjmp(png_jmpbuf(png_ptr), 1); + } + + /* set the individual row-pointers to point at the correct offsets */ + for (int i = 0; i < ibuf->y; i++) { + row_pointers[ibuf->y - 1 - i] = (png_bytep)( + (unsigned char *)pixels + (((size_t)i) * ibuf->x) * channels * sizeof(unsigned char)); + } + + png_read_image(png_ptr, row_pointers); + + /* copy image data */ + + to = (unsigned char *)ibuf->rect; + from = pixels; + + switch (channels) { + case 4: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to += 4; + from += 4; + } + break; + case 3: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = 0xff; + to += 4; + from += 3; + } + break; + case 2: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to[0] = to[1] = to[2] = from[0]; + to[3] = from[1]; + to += 4; + from += 2; + } + break; + case 1: + for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) { + to[0] = to[1] = to[2] = from[0]; + to[3] = 0xff; + to += 4; + from++; + } + break; + } + } + + if (flags & IB_metadata) { + png_text *text_chunks; + int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); + IMB_metadata_ensure(&ibuf->metadata); + for (int i = 0; i < count; i++) { + IMB_metadata_set_field(ibuf->metadata, text_chunks[i].key, text_chunks[i].text); + ibuf->flags |= IB_metadata; + } + } + + png_read_end(png_ptr, info_ptr); + } + + /* clean up */ + if (pixels) + MEM_freeN(pixels); + if (pixels16) + MEM_freeN(pixels16); + 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 dce61953432..e3ab460cce4 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -48,7 +48,7 @@ /* needed constants */ #define MINELEN 8 #define MAXELEN 0x7fff -#define MINRUN 4 /* minimum run length */ +#define MINRUN 4 /* minimum run length */ #define RED 0 #define GRN 1 #define BLU 2 @@ -58,98 +58,105 @@ typedef unsigned char RGBE[4]; typedef float fCOLOR[3]; /* copy source -> dest */ -#define COPY_RGBE(c1, c2) (c2[RED] = c1[RED], c2[GRN] = c1[GRN], c2[BLU] = c1[BLU], c2[EXP] = c1[EXP]) +#define COPY_RGBE(c1, c2) \ + (c2[RED] = c1[RED], c2[GRN] = c1[GRN], c2[BLU] = c1[BLU], c2[EXP] = c1[EXP]) /* read routines */ -static const unsigned char *oldreadcolrs(RGBE *scan, const unsigned char *mem, int xmax, const unsigned char *mem_eof) +static const unsigned char *oldreadcolrs(RGBE *scan, + const unsigned char *mem, + int xmax, + const unsigned char *mem_eof) { - size_t i, rshift = 0, len = xmax; - while (len > 0) { - if (UNLIKELY(mem_eof - mem < 4)) { - return NULL; - } - scan[0][RED] = *mem++; - scan[0][GRN] = *mem++; - scan[0][BLU] = *mem++; - scan[0][EXP] = *mem++; - if (scan[0][RED] == 1 && scan[0][GRN] == 1 && scan[0][BLU] == 1) { - for (i = scan[0][EXP] << rshift; i > 0; i--) { - COPY_RGBE(scan[-1], scan[0]); - scan++; - len--; - } - rshift += 8; - } - else { - scan++; - len--; - rshift = 0; - } - } - return mem; + size_t i, rshift = 0, len = xmax; + while (len > 0) { + if (UNLIKELY(mem_eof - mem < 4)) { + return NULL; + } + scan[0][RED] = *mem++; + scan[0][GRN] = *mem++; + scan[0][BLU] = *mem++; + scan[0][EXP] = *mem++; + if (scan[0][RED] == 1 && scan[0][GRN] == 1 && scan[0][BLU] == 1) { + for (i = scan[0][EXP] << rshift; i > 0; i--) { + COPY_RGBE(scan[-1], scan[0]); + scan++; + len--; + } + rshift += 8; + } + else { + scan++; + len--; + rshift = 0; + } + } + return mem; } -static const unsigned char *freadcolrs(RGBE *scan, const unsigned char *mem, int xmax, const unsigned char *mem_eof) +static const unsigned char *freadcolrs(RGBE *scan, + const unsigned char *mem, + int xmax, + const unsigned char *mem_eof) { - if (UNLIKELY(mem_eof - mem < 4)) { - return NULL; - } - - if (UNLIKELY((xmax < MINELEN) | (xmax > MAXELEN))) { - return oldreadcolrs(scan, mem, xmax, mem_eof); - } - - int val = *mem++; - if (val != 2) { - return oldreadcolrs(scan, mem - 1, xmax, mem_eof); - } - - scan[0][GRN] = *mem++; - scan[0][BLU] = *mem++; - - val = *mem++; - - if (scan[0][GRN] != 2 || scan[0][BLU] & 128) { - scan[0][RED] = 2; - scan[0][EXP] = val; - return oldreadcolrs(scan + 1, mem, xmax - 1, mem_eof); - } - - if (UNLIKELY(((scan[0][BLU] << 8) | val) != xmax)) { - return NULL; - } - - for (size_t i = 0; i < 4; i++) { - if (UNLIKELY(mem_eof - mem < 2)) { - return NULL; - } - for (size_t j = 0; j < xmax; ) { - int code = *mem++; - if (code > 128) { - code &= 127; - if (UNLIKELY(code + j > xmax)) { - return NULL; - } - val = *mem++; - while (code--) { - scan[j++][i] = (unsigned char)val; - } - } - else { - if (UNLIKELY(mem_eof - mem < code)) { - return NULL; - } - if (UNLIKELY(code + j > xmax)) { - return NULL; - } - while (code--) { - scan[j++][i] = *mem++; - } - } - } - } - - return mem; + if (UNLIKELY(mem_eof - mem < 4)) { + return NULL; + } + + if (UNLIKELY((xmax < MINELEN) | (xmax > MAXELEN))) { + return oldreadcolrs(scan, mem, xmax, mem_eof); + } + + int val = *mem++; + if (val != 2) { + return oldreadcolrs(scan, mem - 1, xmax, mem_eof); + } + + scan[0][GRN] = *mem++; + scan[0][BLU] = *mem++; + + val = *mem++; + + if (scan[0][GRN] != 2 || scan[0][BLU] & 128) { + scan[0][RED] = 2; + scan[0][EXP] = val; + return oldreadcolrs(scan + 1, mem, xmax - 1, mem_eof); + } + + if (UNLIKELY(((scan[0][BLU] << 8) | val) != xmax)) { + return NULL; + } + + for (size_t i = 0; i < 4; i++) { + if (UNLIKELY(mem_eof - mem < 2)) { + return NULL; + } + for (size_t j = 0; j < xmax;) { + int code = *mem++; + if (code > 128) { + code &= 127; + if (UNLIKELY(code + j > xmax)) { + return NULL; + } + val = *mem++; + while (code--) { + scan[j++][i] = (unsigned char)val; + } + } + else { + if (UNLIKELY(mem_eof - mem < code)) { + return NULL; + } + if (UNLIKELY(code + j > xmax)) { + return NULL; + } + while (code--) { + scan[j++][i] = *mem++; + } + } + } + } + + return mem; } /* helper functions */ @@ -157,250 +164,270 @@ static const unsigned char *freadcolrs(RGBE *scan, const unsigned char *mem, int /* rgbe -> float color */ static void RGBE2FLOAT(RGBE rgbe, fCOLOR fcol) { - if (rgbe[EXP] == 0) { - fcol[RED] = fcol[GRN] = fcol[BLU] = 0; - } - else { - float f = ldexp(1.0, rgbe[EXP] - (COLXS + 8)); - fcol[RED] = f * (rgbe[RED] + 0.5f); - fcol[GRN] = f * (rgbe[GRN] + 0.5f); - fcol[BLU] = f * (rgbe[BLU] + 0.5f); - } + if (rgbe[EXP] == 0) { + fcol[RED] = fcol[GRN] = fcol[BLU] = 0; + } + else { + float f = ldexp(1.0, rgbe[EXP] - (COLXS + 8)); + fcol[RED] = f * (rgbe[RED] + 0.5f); + fcol[GRN] = f * (rgbe[GRN] + 0.5f); + fcol[BLU] = f * (rgbe[BLU] + 0.5f); + } } /* float color -> rgbe */ static void FLOAT2RGBE(fCOLOR fcol, RGBE rgbe) { - int e; - float d = (fcol[RED] > fcol[GRN]) ? fcol[RED] : fcol[GRN]; - if (fcol[BLU] > d) d = fcol[BLU]; - if (d <= 1e-32f) - rgbe[RED] = rgbe[GRN] = rgbe[BLU] = rgbe[EXP] = 0; - else { - 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); - rgbe[EXP] = (unsigned char)(e + COLXS); - } + int e; + float d = (fcol[RED] > fcol[GRN]) ? fcol[RED] : fcol[GRN]; + if (fcol[BLU] > d) + d = fcol[BLU]; + if (d <= 1e-32f) + rgbe[RED] = rgbe[GRN] = rgbe[BLU] = rgbe[EXP] = 0; + else { + 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); + rgbe[EXP] = (unsigned char)(e + COLXS); + } } /* ImBuf read */ int imb_is_a_hdr(const unsigned char *buf) { - /* For recognition, Blender only loads first 32 bytes, so use #?RADIANCE id instead */ - /* update: actually, the 'RADIANCE' part is just an optional program name, the magic word is really only the '#?' part */ - //if (strstr((char *)buf, "#?RADIANCE")) return 1; - if (strstr((char *)buf, "#?")) return 1; - // if (strstr((char *)buf, "32-bit_rle_rgbe")) return 1; - return 0; + /* For recognition, Blender only loads first 32 bytes, so use #?RADIANCE id instead */ + /* update: actually, the 'RADIANCE' part is just an optional program name, the magic word is really only the '#?' part */ + //if (strstr((char *)buf, "#?RADIANCE")) return 1; + if (strstr((char *)buf, "#?")) + return 1; + // if (strstr((char *)buf, "32-bit_rle_rgbe")) return 1; + return 0; } -struct ImBuf *imb_loadhdr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +struct ImBuf *imb_loadhdr(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - struct ImBuf *ibuf; - RGBE *sline; - fCOLOR fcol; - float *rect_float; - int found = 0; - int width = 0, height = 0; - const unsigned char *ptr, *mem_eof = mem + size; - char oriY[80], oriX[80]; - - if (imb_is_a_hdr((void *)mem)) { - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); - - /* find empty line, next line is resolution info */ - size_t x; - for (x = 1; x < size; x++) { - if ((mem[x - 1] == '\n') && (mem[x] == '\n')) { - found = 1; - break; - } - } - if (found && (x < (size + 2))) { - if (sscanf((char *)&mem[x + 1], "%79s %d %79s %d", (char *)&oriY, &height, - (char *)&oriX, &width) != 4) - { - return NULL; - } - - /* find end of this line, data right behind it */ - ptr = (unsigned char *)strchr((char *)&mem[x + 1], '\n'); - ptr++; - - if (flags & IB_test) ibuf = IMB_allocImBuf(width, height, 32, 0); - else ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect) | IB_rectfloat); - - if (UNLIKELY(ibuf == NULL)) { - return NULL; - } - ibuf->ftype = IMB_FTYPE_RADHDR; - - if (flags & IB_alphamode_detect) - ibuf->flags |= IB_alphamode_premul; - - if (flags & IB_test) { - return ibuf; - } - - /* read in and decode the actual data */ - sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__); - rect_float = ibuf->rect_float; - - for (size_t y = 0; y < height; y++) { - ptr = freadcolrs(sline, ptr, width, mem_eof); - if (ptr == NULL) { - printf("WARNING! HDR decode error, image may be just truncated, or completely wrong...\n"); - break; - } - for (x = 0; x < width; x++) { - /* convert to ldr */ - RGBE2FLOAT(sline[x], fcol); - *rect_float++ = fcol[RED]; - *rect_float++ = fcol[GRN]; - *rect_float++ = fcol[BLU]; - *rect_float++ = 1.0f; - } - } - MEM_freeN(sline); - if (oriY[0] == '-') IMB_flipy(ibuf); - - if (flags & IB_rect) { - IMB_rect_from_float(ibuf); - } - - return ibuf; - } - //else printf("Data not found!\n"); - } - //else printf("Not a valid radiance HDR file!\n"); - - return NULL; + struct ImBuf *ibuf; + RGBE *sline; + fCOLOR fcol; + float *rect_float; + int found = 0; + int width = 0, height = 0; + const unsigned char *ptr, *mem_eof = mem + size; + char oriY[80], oriX[80]; + + if (imb_is_a_hdr((void *)mem)) { + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + + /* find empty line, next line is resolution info */ + size_t x; + for (x = 1; x < size; x++) { + if ((mem[x - 1] == '\n') && (mem[x] == '\n')) { + found = 1; + break; + } + } + if (found && (x < (size + 2))) { + if (sscanf((char *)&mem[x + 1], + "%79s %d %79s %d", + (char *)&oriY, + &height, + (char *)&oriX, + &width) != 4) { + return NULL; + } + + /* find end of this line, data right behind it */ + ptr = (unsigned char *)strchr((char *)&mem[x + 1], '\n'); + ptr++; + + if (flags & IB_test) + ibuf = IMB_allocImBuf(width, height, 32, 0); + else + ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect) | IB_rectfloat); + + if (UNLIKELY(ibuf == NULL)) { + return NULL; + } + ibuf->ftype = IMB_FTYPE_RADHDR; + + if (flags & IB_alphamode_detect) + ibuf->flags |= IB_alphamode_premul; + + if (flags & IB_test) { + return ibuf; + } + + /* read in and decode the actual data */ + sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__); + rect_float = ibuf->rect_float; + + for (size_t y = 0; y < height; y++) { + ptr = freadcolrs(sline, ptr, width, mem_eof); + if (ptr == NULL) { + printf( + "WARNING! HDR decode error, image may be just truncated, or completely wrong...\n"); + break; + } + for (x = 0; x < width; x++) { + /* convert to ldr */ + RGBE2FLOAT(sline[x], fcol); + *rect_float++ = fcol[RED]; + *rect_float++ = fcol[GRN]; + *rect_float++ = fcol[BLU]; + *rect_float++ = 1.0f; + } + } + MEM_freeN(sline); + if (oriY[0] == '-') + IMB_flipy(ibuf); + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } + + return ibuf; + } + //else printf("Data not found!\n"); + } + //else printf("Not a valid radiance HDR file!\n"); + + return NULL; } /* ImBuf write */ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufscan, float *fpscan) { - int beg, c2, cnt = 0; - fCOLOR fcol; - RGBE rgbe, *rgbe_scan; - - if (UNLIKELY((ibufscan == NULL) && (fpscan == NULL))) { - return 0; - } - - rgbe_scan = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_write_tmpscan"); - - /* convert scanline */ - for (size_t i = 0, j = 0; i < width; i++) { - if (fpscan) { - fcol[RED] = fpscan[j]; - fcol[GRN] = (channels >= 2) ? fpscan[j + 1] : fpscan[j]; - fcol[BLU] = (channels >= 3) ? fpscan[j + 2] : fpscan[j]; - } - else { - fcol[RED] = (float)ibufscan[j] / 255.f; - fcol[GRN] = (float)((channels >= 2) ? ibufscan[j + 1] : ibufscan[j]) / 255.f; - fcol[BLU] = (float)((channels >= 3) ? ibufscan[j + 2] : ibufscan[j]) / 255.f; - } - FLOAT2RGBE(fcol, rgbe); - COPY_RGBE(rgbe, rgbe_scan[i]); - j += channels; - } - - if ((width < MINELEN) | (width > MAXELEN)) { /* OOBs, write out flat */ - int x = fwrite((char *)rgbe_scan, sizeof(RGBE), width, file) - width; - MEM_freeN(rgbe_scan); - return x; - } - /* put magic header */ - putc(2, file); - putc(2, file); - putc((unsigned char)(width >> 8), file); - putc((unsigned char)(width & 255), file); - /* put components separately */ - for (size_t i = 0; i < 4; i++) { - for (size_t j = 0; j < width; j += cnt) { /* find next run */ - for (beg = j; beg < width; beg += cnt) { - for (cnt = 1; (cnt < 127) && ((beg + cnt) < width) && (rgbe_scan[beg + cnt][i] == rgbe_scan[beg][i]); cnt++) ; - if (cnt >= MINRUN) break; /* long enough */ - } - if (((beg - j) > 1) && ((beg - j) < MINRUN)) { - c2 = j + 1; - while (rgbe_scan[c2++][i] == rgbe_scan[j][i]) { - if (c2 == beg) { /* short run */ - putc((unsigned char)(128 + beg - j), file); - putc((unsigned char)(rgbe_scan[j][i]), file); - j = beg; - break; - } - } - } - while (j < beg) { /* write out non-run */ - if ((c2 = beg - j) > 128) c2 = 128; - putc((unsigned char)(c2), file); - while (c2--) putc(rgbe_scan[j++][i], file); - } - if (cnt >= MINRUN) { /* write out run */ - putc((unsigned char)(128 + cnt), file); - putc(rgbe_scan[beg][i], file); - } - else { - cnt = 0; - } - } - } - MEM_freeN(rgbe_scan); - return(ferror(file) ? -1 : 0); + int beg, c2, cnt = 0; + fCOLOR fcol; + RGBE rgbe, *rgbe_scan; + + if (UNLIKELY((ibufscan == NULL) && (fpscan == NULL))) { + return 0; + } + + rgbe_scan = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_write_tmpscan"); + + /* convert scanline */ + for (size_t i = 0, j = 0; i < width; i++) { + if (fpscan) { + fcol[RED] = fpscan[j]; + fcol[GRN] = (channels >= 2) ? fpscan[j + 1] : fpscan[j]; + fcol[BLU] = (channels >= 3) ? fpscan[j + 2] : fpscan[j]; + } + else { + fcol[RED] = (float)ibufscan[j] / 255.f; + fcol[GRN] = (float)((channels >= 2) ? ibufscan[j + 1] : ibufscan[j]) / 255.f; + fcol[BLU] = (float)((channels >= 3) ? ibufscan[j + 2] : ibufscan[j]) / 255.f; + } + FLOAT2RGBE(fcol, rgbe); + COPY_RGBE(rgbe, rgbe_scan[i]); + j += channels; + } + + if ((width < MINELEN) | (width > MAXELEN)) { /* OOBs, write out flat */ + int x = fwrite((char *)rgbe_scan, sizeof(RGBE), width, file) - width; + MEM_freeN(rgbe_scan); + return x; + } + /* put magic header */ + putc(2, file); + putc(2, file); + putc((unsigned char)(width >> 8), file); + putc((unsigned char)(width & 255), file); + /* put components separately */ + for (size_t i = 0; i < 4; i++) { + for (size_t j = 0; j < width; j += cnt) { /* find next run */ + for (beg = j; beg < width; beg += cnt) { + for (cnt = 1; (cnt < 127) && ((beg + cnt) < width) && + (rgbe_scan[beg + cnt][i] == rgbe_scan[beg][i]); + cnt++) + ; + if (cnt >= MINRUN) + break; /* long enough */ + } + if (((beg - j) > 1) && ((beg - j) < MINRUN)) { + c2 = j + 1; + while (rgbe_scan[c2++][i] == rgbe_scan[j][i]) { + if (c2 == beg) { /* short run */ + putc((unsigned char)(128 + beg - j), file); + putc((unsigned char)(rgbe_scan[j][i]), file); + j = beg; + break; + } + } + } + while (j < beg) { /* write out non-run */ + if ((c2 = beg - j) > 128) + c2 = 128; + putc((unsigned char)(c2), file); + while (c2--) + putc(rgbe_scan[j++][i], file); + } + if (cnt >= MINRUN) { /* write out run */ + putc((unsigned char)(128 + cnt), file); + putc(rgbe_scan[beg][i], file); + } + else { + cnt = 0; + } + } + } + MEM_freeN(rgbe_scan); + return (ferror(file) ? -1 : 0); } static void writeHeader(FILE *file, int width, int height) { - fprintf(file, "#?RADIANCE"); - fputc(10, file); - fprintf(file, "# %s", "Created with Blender"); - fputc(10, file); - fprintf(file, "EXPOSURE=%25.13f", 1.0); - fputc(10, file); - fprintf(file, "FORMAT=32-bit_rle_rgbe"); - fputc(10, file); - fputc(10, file); - fprintf(file, "-Y %d +X %d", height, width); - fputc(10, file); + fprintf(file, "#?RADIANCE"); + fputc(10, file); + fprintf(file, "# %s", "Created with Blender"); + fputc(10, file); + fprintf(file, "EXPOSURE=%25.13f", 1.0); + fputc(10, file); + fprintf(file, "FORMAT=32-bit_rle_rgbe"); + fputc(10, file); + fputc(10, file); + fprintf(file, "-Y %d +X %d", height, width); + fputc(10, file); } int imb_savehdr(struct ImBuf *ibuf, const char *name, int flags) { - FILE *file = BLI_fopen(name, "wb"); - float *fp = NULL; - size_t width = ibuf->x, height = ibuf->y; - unsigned char *cp = NULL; - - (void)flags; /* unused */ - - if (file == NULL) { - return 0; - } - - writeHeader(file, width, height); - - if (ibuf->rect) - cp = (unsigned char *)ibuf->rect + ibuf->channels * (height - 1) * width; - if (ibuf->rect_float) - fp = ibuf->rect_float + ibuf->channels * (height - 1) * width; - - for (size_t y = 0; y < height; y++) { - if (fwritecolrs(file, width, ibuf->channels, cp, fp) < 0) { - fclose(file); - printf("HDR write error\n"); - return 0; - } - if (cp) cp -= ibuf->channels * width; - if (fp) fp -= ibuf->channels * width; - } - - fclose(file); - return 1; + FILE *file = BLI_fopen(name, "wb"); + float *fp = NULL; + size_t width = ibuf->x, height = ibuf->y; + unsigned char *cp = NULL; + + (void)flags; /* unused */ + + if (file == NULL) { + return 0; + } + + writeHeader(file, width, height); + + if (ibuf->rect) + cp = (unsigned char *)ibuf->rect + ibuf->channels * (height - 1) * width; + if (ibuf->rect_float) + fp = ibuf->rect_float + ibuf->channels * (height - 1) * width; + + for (size_t y = 0; y < height; y++) { + if (fwritecolrs(file, width, ibuf->channels, cp, fp) < 0) { + fclose(file); + printf("HDR write error\n"); + return 0; + } + if (cp) + cp -= ibuf->channels * width; + if (fp) + fp -= ibuf->channels * width; + } + + fclose(file); + return 1; } diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index ad4e07030d1..34bae007979 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -22,7 +22,6 @@ * \ingroup imbuf */ - #ifdef _WIN32 # include # include @@ -45,256 +44,267 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" -static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPACE], char effective_colorspace[IM_MAX_SPACE]) +static void imb_handle_alpha(ImBuf *ibuf, + int flags, + char colorspace[IM_MAX_SPACE], + char effective_colorspace[IM_MAX_SPACE]) { - int alpha_flags; - - if (colorspace) { - if (ibuf->rect != NULL && ibuf->rect_float == NULL) { - /* byte buffer is never internally converted to some standard space, - * store pointer to it's color space descriptor instead - */ - ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace); - } - - BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); - } - - if (flags & IB_alphamode_detect) - alpha_flags = ibuf->flags & IB_alphamode_premul; - else - alpha_flags = flags & IB_alphamode_premul; - - if (flags & IB_ignore_alpha) { - IMB_rectfill_alpha(ibuf, 1.0f); - } - else { - if (alpha_flags & IB_alphamode_premul) { - if (ibuf->rect) { - IMB_unpremultiply_alpha(ibuf); - } - else { - /* pass, floats are expected to be premul */ - } - } - else { - if (ibuf->rect_float) { - IMB_premultiply_alpha(ibuf); - } - else { - /* pass, bytes are expected to be straight */ - } - } - } - - /* OCIO_TODO: in some cases it's faster to do threaded conversion, - * but how to distinguish such cases */ - colormanage_imbuf_make_linear(ibuf, effective_colorspace); + int alpha_flags; + + if (colorspace) { + if (ibuf->rect != NULL && ibuf->rect_float == NULL) { + /* byte buffer is never internally converted to some standard space, + * store pointer to it's color space descriptor instead + */ + ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace); + } + + BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); + } + + if (flags & IB_alphamode_detect) + alpha_flags = ibuf->flags & IB_alphamode_premul; + else + alpha_flags = flags & IB_alphamode_premul; + + if (flags & IB_ignore_alpha) { + IMB_rectfill_alpha(ibuf, 1.0f); + } + else { + if (alpha_flags & IB_alphamode_premul) { + if (ibuf->rect) { + IMB_unpremultiply_alpha(ibuf); + } + else { + /* pass, floats are expected to be premul */ + } + } + else { + if (ibuf->rect_float) { + IMB_premultiply_alpha(ibuf); + } + else { + /* pass, bytes are expected to be straight */ + } + } + } + + /* OCIO_TODO: in some cases it's faster to do threaded conversion, + * but how to distinguish such cases */ + colormanage_imbuf_make_linear(ibuf, effective_colorspace); } -ImBuf *IMB_ibImageFromMemory( - const unsigned char *mem, size_t size, int flags, - char colorspace[IM_MAX_SPACE], const char *descr) +ImBuf *IMB_ibImageFromMemory(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE], + const char *descr) { - ImBuf *ibuf; - const ImFileType *type; - char effective_colorspace[IM_MAX_SPACE] = ""; - - if (mem == NULL) { - fprintf(stderr, "%s: NULL pointer\n", __func__); - return NULL; - } - - if (colorspace) - BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); - - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->load) { - ibuf = type->load(mem, size, flags, effective_colorspace); - if (ibuf) { - imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace); - return ibuf; - } - } - } - - if ((flags & IB_test) == 0) - fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); - - return NULL; + ImBuf *ibuf; + const ImFileType *type; + char effective_colorspace[IM_MAX_SPACE] = ""; + + if (mem == NULL) { + fprintf(stderr, "%s: NULL pointer\n", __func__); + return NULL; + } + + if (colorspace) + BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); + + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->load) { + ibuf = type->load(mem, size, flags, effective_colorspace); + if (ibuf) { + imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace); + return ibuf; + } + } + } + + if ((flags & IB_test) == 0) + fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); + + return NULL; } -static ImBuf *IMB_ibImageFromFile(const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr) +static ImBuf *IMB_ibImageFromFile(const char *filepath, + int flags, + char colorspace[IM_MAX_SPACE], + const char *descr) { - ImBuf *ibuf; - const ImFileType *type; - char effective_colorspace[IM_MAX_SPACE] = ""; - - if (colorspace) - BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); - - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->load_filepath) { - ibuf = type->load_filepath(filepath, flags, effective_colorspace); - if (ibuf) { - imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace); - return ibuf; - } - } - } - - if ((flags & IB_test) == 0) - fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); - - return NULL; + ImBuf *ibuf; + const ImFileType *type; + char effective_colorspace[IM_MAX_SPACE] = ""; + + if (colorspace) + BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); + + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->load_filepath) { + ibuf = type->load_filepath(filepath, flags, effective_colorspace); + if (ibuf) { + imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace); + return ibuf; + } + } + } + + if ((flags & IB_test) == 0) + fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); + + return NULL; } static bool imb_is_filepath_format(const char *filepath) { - /* return true if this is one of the formats that can't be loaded from memory */ - return BLI_path_extension_check_array(filepath, imb_ext_image_filepath_only); + /* return true if this is one of the formats that can't be loaded from memory */ + return BLI_path_extension_check_array(filepath, imb_ext_image_filepath_only); } -ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr) +ImBuf *IMB_loadifffile( + int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { - ImBuf *ibuf; - unsigned char *mem; - size_t size; + ImBuf *ibuf; + unsigned char *mem; + size_t size; - if (file == -1) return NULL; + if (file == -1) + return NULL; - if (imb_is_filepath_format(filepath)) - return IMB_ibImageFromFile(filepath, flags, colorspace, descr); + if (imb_is_filepath_format(filepath)) + return IMB_ibImageFromFile(filepath, flags, colorspace, descr); - size = BLI_file_descriptor_size(file); + size = BLI_file_descriptor_size(file); - imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); - imb_mmap_unlock(); + imb_mmap_lock(); + mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + imb_mmap_unlock(); - if (mem == (unsigned char *) -1) { - fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr); - return NULL; - } + if (mem == (unsigned char *)-1) { + fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr); + return NULL; + } - ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr); + ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr); - imb_mmap_lock(); - if (munmap(mem, size)) - fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr); - imb_mmap_unlock(); + imb_mmap_lock(); + if (munmap(mem, size)) + fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr); + imb_mmap_unlock(); - return ibuf; + return ibuf; } static void imb_cache_filename(char *filename, const char *name, int flags) { - /* read .tx instead if it exists and is not older */ - if (flags & IB_tilecache) { - BLI_strncpy(filename, name, IMB_FILENAME_SIZE); - if (!BLI_path_extension_replace(filename, IMB_FILENAME_SIZE, ".tx")) - return; + /* read .tx instead if it exists and is not older */ + if (flags & IB_tilecache) { + BLI_strncpy(filename, name, IMB_FILENAME_SIZE); + if (!BLI_path_extension_replace(filename, IMB_FILENAME_SIZE, ".tx")) + return; - if (BLI_file_older(name, filename)) - return; - } + if (BLI_file_older(name, filename)) + return; + } - BLI_strncpy(filename, name, IMB_FILENAME_SIZE); + BLI_strncpy(filename, name, IMB_FILENAME_SIZE); } ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) { - ImBuf *ibuf; - int file, a; - char filepath_tx[IMB_FILENAME_SIZE]; + ImBuf *ibuf; + int file, a; + char filepath_tx[IMB_FILENAME_SIZE]; - BLI_assert(!BLI_path_is_rel(filepath)); + BLI_assert(!BLI_path_is_rel(filepath)); - imb_cache_filename(filepath_tx, filepath, flags); + imb_cache_filename(filepath_tx, filepath, flags); - file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); - if (file == -1) - return NULL; + file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); + if (file == -1) + return NULL; - ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath_tx); + ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath_tx); - if (ibuf) { - BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); - BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename)); - for (a = 1; a < ibuf->miptot; a++) - BLI_strncpy(ibuf->mipmap[a - 1]->cachename, filepath_tx, sizeof(ibuf->cachename)); - } + if (ibuf) { + BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); + BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename)); + for (a = 1; a < ibuf->miptot; a++) + BLI_strncpy(ibuf->mipmap[a - 1]->cachename, filepath_tx, sizeof(ibuf->cachename)); + } - close(file); + close(file); - return ibuf; + return ibuf; } ImBuf *IMB_testiffname(const char *filepath, int flags) { - ImBuf *ibuf; - int file; - char filepath_tx[IMB_FILENAME_SIZE]; - char colorspace[IM_MAX_SPACE] = "\0"; + ImBuf *ibuf; + int file; + char filepath_tx[IMB_FILENAME_SIZE]; + char colorspace[IM_MAX_SPACE] = "\0"; - BLI_assert(!BLI_path_is_rel(filepath)); + BLI_assert(!BLI_path_is_rel(filepath)); - imb_cache_filename(filepath_tx, filepath, flags); + imb_cache_filename(filepath_tx, filepath, flags); - file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); - if (file == -1) - return NULL; + file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); + if (file == -1) + return NULL; - ibuf = IMB_loadifffile(file, filepath, flags | IB_test | IB_multilayer, colorspace, filepath_tx); + ibuf = IMB_loadifffile(file, filepath, flags | IB_test | IB_multilayer, colorspace, filepath_tx); - if (ibuf) { - BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); - BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename)); - } + if (ibuf) { + BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); + BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename)); + } - close(file); + close(file); - return ibuf; + return ibuf; } static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int *rect) { - const ImFileType *type; - unsigned char *mem; - size_t size; + const ImFileType *type; + unsigned char *mem; + size_t size; - if (file == -1) return; + if (file == -1) + return; - size = BLI_file_descriptor_size(file); + size = BLI_file_descriptor_size(file); - imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); - imb_mmap_unlock(); + imb_mmap_lock(); + mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + imb_mmap_unlock(); - if (mem == (unsigned char *) -1) { - fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename); - return; - } + if (mem == (unsigned char *)-1) { + fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename); + return; + } - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) - if (type->load_tile && type->ftype(type, ibuf)) - type->load_tile(ibuf, mem, size, tx, ty, rect); + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) + if (type->load_tile && type->ftype(type, ibuf)) + type->load_tile(ibuf, mem, size, tx, ty, rect); - imb_mmap_lock(); - if (munmap(mem, size)) - fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename); - imb_mmap_unlock(); + imb_mmap_lock(); + if (munmap(mem, size)) + fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename); + imb_mmap_unlock(); } void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect) { - int file; + int file; - file = BLI_open(ibuf->cachename, O_BINARY | O_RDONLY, 0); - if (file == -1) - return; + file = BLI_open(ibuf->cachename, O_BINARY | O_RDONLY, 0); + if (file == -1) + return; - imb_loadtilefile(ibuf, file, tx, ty, rect); + imb_loadtilefile(ibuf, file, tx, ty, rect); - close(file); + close(file); } diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index ef869e35a36..a069e79b337 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -35,890 +35,1059 @@ #include "IMB_colormanagement.h" -void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned char src2[4], IMB_BlendMode mode) +void IMB_blend_color_byte(unsigned char dst[4], + unsigned char src1[4], + unsigned char src2[4], + IMB_BlendMode mode) { - switch (mode) { - case IMB_BLEND_MIX: - blend_color_mix_byte(dst, src1, src2); break; - case IMB_BLEND_ADD: - blend_color_add_byte(dst, src1, src2); break; - case IMB_BLEND_SUB: - blend_color_sub_byte(dst, src1, src2); break; - case IMB_BLEND_MUL: - blend_color_mul_byte(dst, src1, src2); break; - case IMB_BLEND_LIGHTEN: - blend_color_lighten_byte(dst, src1, src2); break; - case IMB_BLEND_DARKEN: - blend_color_darken_byte(dst, src1, src2); break; - case IMB_BLEND_ERASE_ALPHA: - blend_color_erase_alpha_byte(dst, src1, src2); break; - case IMB_BLEND_ADD_ALPHA: - blend_color_add_alpha_byte(dst, src1, src2); break; - case IMB_BLEND_OVERLAY: - blend_color_overlay_byte(dst, src1, src2); break; - case IMB_BLEND_HARDLIGHT: - blend_color_hardlight_byte(dst, src1, src2); break; - case IMB_BLEND_COLORBURN: - blend_color_burn_byte(dst, src1, src2); break; - case IMB_BLEND_LINEARBURN: - blend_color_linearburn_byte(dst, src1, src2); break; - case IMB_BLEND_COLORDODGE: - blend_color_dodge_byte(dst, src1, src2); break; - case IMB_BLEND_SCREEN: - blend_color_screen_byte(dst, src1, src2); break; - case IMB_BLEND_SOFTLIGHT: - blend_color_softlight_byte(dst, src1, src2); break; - case IMB_BLEND_PINLIGHT: - blend_color_pinlight_byte(dst, src1, src2); break; - case IMB_BLEND_LINEARLIGHT: - blend_color_linearlight_byte(dst, src1, src2); break; - case IMB_BLEND_VIVIDLIGHT: - blend_color_vividlight_byte(dst, src1, src2); break; - case IMB_BLEND_DIFFERENCE: - blend_color_difference_byte(dst, src1, src2); break; - case IMB_BLEND_EXCLUSION: - blend_color_exclusion_byte(dst, src1, src2); break; - case IMB_BLEND_COLOR: - blend_color_color_byte(dst, src1, src2); break; - case IMB_BLEND_HUE: - blend_color_hue_byte(dst, src1, src2); break; - case IMB_BLEND_SATURATION: - blend_color_saturation_byte(dst, src1, src2); break; - case IMB_BLEND_LUMINOSITY: - blend_color_luminosity_byte(dst, src1, src2); break; - - default: - dst[0] = src1[0]; - dst[1] = src1[1]; - dst[2] = src1[2]; - dst[3] = src1[3]; - break; - } + switch (mode) { + case IMB_BLEND_MIX: + blend_color_mix_byte(dst, src1, src2); + break; + case IMB_BLEND_ADD: + blend_color_add_byte(dst, src1, src2); + break; + case IMB_BLEND_SUB: + blend_color_sub_byte(dst, src1, src2); + break; + case IMB_BLEND_MUL: + blend_color_mul_byte(dst, src1, src2); + break; + case IMB_BLEND_LIGHTEN: + blend_color_lighten_byte(dst, src1, src2); + break; + case IMB_BLEND_DARKEN: + blend_color_darken_byte(dst, src1, src2); + break; + case IMB_BLEND_ERASE_ALPHA: + blend_color_erase_alpha_byte(dst, src1, src2); + break; + case IMB_BLEND_ADD_ALPHA: + blend_color_add_alpha_byte(dst, src1, src2); + break; + case IMB_BLEND_OVERLAY: + blend_color_overlay_byte(dst, src1, src2); + break; + case IMB_BLEND_HARDLIGHT: + blend_color_hardlight_byte(dst, src1, src2); + break; + case IMB_BLEND_COLORBURN: + blend_color_burn_byte(dst, src1, src2); + break; + case IMB_BLEND_LINEARBURN: + blend_color_linearburn_byte(dst, src1, src2); + break; + case IMB_BLEND_COLORDODGE: + blend_color_dodge_byte(dst, src1, src2); + break; + case IMB_BLEND_SCREEN: + blend_color_screen_byte(dst, src1, src2); + break; + case IMB_BLEND_SOFTLIGHT: + blend_color_softlight_byte(dst, src1, src2); + break; + case IMB_BLEND_PINLIGHT: + blend_color_pinlight_byte(dst, src1, src2); + break; + case IMB_BLEND_LINEARLIGHT: + blend_color_linearlight_byte(dst, src1, src2); + break; + case IMB_BLEND_VIVIDLIGHT: + blend_color_vividlight_byte(dst, src1, src2); + break; + case IMB_BLEND_DIFFERENCE: + blend_color_difference_byte(dst, src1, src2); + break; + case IMB_BLEND_EXCLUSION: + blend_color_exclusion_byte(dst, src1, src2); + break; + case IMB_BLEND_COLOR: + blend_color_color_byte(dst, src1, src2); + break; + case IMB_BLEND_HUE: + blend_color_hue_byte(dst, src1, src2); + break; + case IMB_BLEND_SATURATION: + blend_color_saturation_byte(dst, src1, src2); + break; + case IMB_BLEND_LUMINOSITY: + blend_color_luminosity_byte(dst, src1, src2); + break; + + default: + dst[0] = src1[0]; + dst[1] = src1[1]; + dst[2] = src1[2]; + dst[3] = src1[3]; + break; + } } void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_BlendMode mode) { - switch (mode) { - case IMB_BLEND_MIX: - blend_color_mix_float(dst, src1, src2); break; - case IMB_BLEND_ADD: - blend_color_add_float(dst, src1, src2); break; - case IMB_BLEND_SUB: - blend_color_sub_float(dst, src1, src2); break; - case IMB_BLEND_MUL: - blend_color_mul_float(dst, src1, src2); break; - case IMB_BLEND_LIGHTEN: - blend_color_lighten_float(dst, src1, src2); break; - case IMB_BLEND_DARKEN: - blend_color_darken_float(dst, src1, src2); break; - case IMB_BLEND_ERASE_ALPHA: - blend_color_erase_alpha_float(dst, src1, src2); break; - case IMB_BLEND_ADD_ALPHA: - blend_color_add_alpha_float(dst, src1, src2); break; - case IMB_BLEND_OVERLAY: - blend_color_overlay_float(dst, src1, src2); break; - case IMB_BLEND_HARDLIGHT: - blend_color_hardlight_float(dst, src1, src2); break; - case IMB_BLEND_COLORBURN: - blend_color_burn_float(dst, src1, src2); break; - case IMB_BLEND_LINEARBURN: - blend_color_linearburn_float(dst, src1, src2); break; - case IMB_BLEND_COLORDODGE: - blend_color_dodge_float(dst, src1, src2); break; - case IMB_BLEND_SCREEN: - blend_color_screen_float(dst, src1, src2); break; - case IMB_BLEND_SOFTLIGHT: - blend_color_softlight_float(dst, src1, src2); break; - case IMB_BLEND_PINLIGHT: - blend_color_pinlight_float(dst, src1, src2); break; - case IMB_BLEND_LINEARLIGHT: - blend_color_linearlight_float(dst, src1, src2); break; - case IMB_BLEND_VIVIDLIGHT: - blend_color_vividlight_float(dst, src1, src2); break; - case IMB_BLEND_DIFFERENCE: - blend_color_difference_float(dst, src1, src2); break; - case IMB_BLEND_EXCLUSION: - blend_color_exclusion_float(dst, src1, src2); break; - case IMB_BLEND_COLOR: - blend_color_color_float(dst, src1, src2); break; - case IMB_BLEND_HUE: - blend_color_hue_float(dst, src1, src2); break; - case IMB_BLEND_SATURATION: - blend_color_saturation_float(dst, src1, src2); break; - case IMB_BLEND_LUMINOSITY: - blend_color_luminosity_float(dst, src1, src2); break; - default: - dst[0] = src1[0]; - dst[1] = src1[1]; - dst[2] = src1[2]; - dst[3] = src1[3]; - break; - } + switch (mode) { + case IMB_BLEND_MIX: + blend_color_mix_float(dst, src1, src2); + break; + case IMB_BLEND_ADD: + blend_color_add_float(dst, src1, src2); + break; + case IMB_BLEND_SUB: + blend_color_sub_float(dst, src1, src2); + break; + case IMB_BLEND_MUL: + blend_color_mul_float(dst, src1, src2); + break; + case IMB_BLEND_LIGHTEN: + blend_color_lighten_float(dst, src1, src2); + break; + case IMB_BLEND_DARKEN: + blend_color_darken_float(dst, src1, src2); + break; + case IMB_BLEND_ERASE_ALPHA: + blend_color_erase_alpha_float(dst, src1, src2); + break; + case IMB_BLEND_ADD_ALPHA: + blend_color_add_alpha_float(dst, src1, src2); + break; + case IMB_BLEND_OVERLAY: + blend_color_overlay_float(dst, src1, src2); + break; + case IMB_BLEND_HARDLIGHT: + blend_color_hardlight_float(dst, src1, src2); + break; + case IMB_BLEND_COLORBURN: + blend_color_burn_float(dst, src1, src2); + break; + case IMB_BLEND_LINEARBURN: + blend_color_linearburn_float(dst, src1, src2); + break; + case IMB_BLEND_COLORDODGE: + blend_color_dodge_float(dst, src1, src2); + break; + case IMB_BLEND_SCREEN: + blend_color_screen_float(dst, src1, src2); + break; + case IMB_BLEND_SOFTLIGHT: + blend_color_softlight_float(dst, src1, src2); + break; + case IMB_BLEND_PINLIGHT: + blend_color_pinlight_float(dst, src1, src2); + break; + case IMB_BLEND_LINEARLIGHT: + blend_color_linearlight_float(dst, src1, src2); + break; + case IMB_BLEND_VIVIDLIGHT: + blend_color_vividlight_float(dst, src1, src2); + break; + case IMB_BLEND_DIFFERENCE: + blend_color_difference_float(dst, src1, src2); + break; + case IMB_BLEND_EXCLUSION: + blend_color_exclusion_float(dst, src1, src2); + break; + case IMB_BLEND_COLOR: + blend_color_color_float(dst, src1, src2); + break; + case IMB_BLEND_HUE: + blend_color_hue_float(dst, src1, src2); + break; + case IMB_BLEND_SATURATION: + blend_color_saturation_float(dst, src1, src2); + break; + case IMB_BLEND_LUMINOSITY: + blend_color_luminosity_float(dst, src1, src2); + break; + default: + dst[0] = src1[0]; + dst[1] = src1[1]; + dst[2] = src1[2]; + dst[3] = src1[3]; + break; + } } /* clipping */ -void IMB_rectclip(ImBuf *dbuf, ImBuf *sbuf, int *destx, - int *desty, int *srcx, int *srcy, int *width, int *height) +void IMB_rectclip(ImBuf *dbuf, + ImBuf *sbuf, + int *destx, + int *desty, + int *srcx, + int *srcy, + int *width, + int *height) { - int tmp; - - if (dbuf == NULL) return; - - if (*destx < 0) { - *srcx -= *destx; - *width += *destx; - *destx = 0; - } - if (*srcx < 0) { - *destx -= *srcx; - *width += *srcx; - *srcx = 0; - } - if (*desty < 0) { - *srcy -= *desty; - *height += *desty; - *desty = 0; - } - if (*srcy < 0) { - *desty -= *srcy; - *height += *srcy; - *srcy = 0; - } - - tmp = dbuf->x - *destx; - if (*width > tmp) *width = tmp; - tmp = dbuf->y - *desty; - if (*height > tmp) *height = tmp; - - if (sbuf) { - tmp = sbuf->x - *srcx; - if (*width > tmp) *width = tmp; - tmp = sbuf->y - *srcy; - if (*height > tmp) *height = tmp; - } - - if ((*height <= 0) || (*width <= 0)) { - *width = 0; - *height = 0; - } + int tmp; + + if (dbuf == NULL) + return; + + if (*destx < 0) { + *srcx -= *destx; + *width += *destx; + *destx = 0; + } + if (*srcx < 0) { + *destx -= *srcx; + *width += *srcx; + *srcx = 0; + } + if (*desty < 0) { + *srcy -= *desty; + *height += *desty; + *desty = 0; + } + if (*srcy < 0) { + *desty -= *srcy; + *height += *srcy; + *srcy = 0; + } + + tmp = dbuf->x - *destx; + if (*width > tmp) + *width = tmp; + tmp = dbuf->y - *desty; + if (*height > tmp) + *height = tmp; + + if (sbuf) { + tmp = sbuf->x - *srcx; + if (*width > tmp) + *width = tmp; + tmp = sbuf->y - *srcy; + if (*height > tmp) + *height = tmp; + } + + if ((*height <= 0) || (*width <= 0)) { + *width = 0; + *height = 0; + } } -static void imb_rectclip3(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, int *destx, - int *desty, int *origx, int *origy, int *srcx, int *srcy, - int *width, int *height) +static void imb_rectclip3(ImBuf *dbuf, + ImBuf *obuf, + ImBuf *sbuf, + int *destx, + int *desty, + int *origx, + int *origy, + int *srcx, + int *srcy, + int *width, + int *height) { - int tmp; - - if (dbuf == NULL) return; - - if (*destx < 0) { - *srcx -= *destx; - *origx -= *destx; - *width += *destx; - *destx = 0; - } - if (*origx < 0) { - *destx -= *origx; - *srcx -= *origx; - *width += *origx; - *origx = 0; - } - if (*srcx < 0) { - *destx -= *srcx; - *origx -= *srcx; - *width += *srcx; - *srcx = 0; - } - - if (*desty < 0) { - *srcy -= *desty; - *origy -= *desty; - *height += *desty; - *desty = 0; - } - if (*origy < 0) { - *desty -= *origy; - *srcy -= *origy; - *height += *origy; - *origy = 0; - } - if (*srcy < 0) { - *desty -= *srcy; - *origy -= *srcy; - *height += *srcy; - *srcy = 0; - } - - tmp = dbuf->x - *destx; - if (*width > tmp) *width = tmp; - tmp = dbuf->y - *desty; - if (*height > tmp) *height = tmp; - - if (obuf) { - tmp = obuf->x - *origx; - if (*width > tmp) *width = tmp; - tmp = obuf->y - *origy; - if (*height > tmp) *height = tmp; - } - - if (sbuf) { - tmp = sbuf->x - *srcx; - if (*width > tmp) *width = tmp; - tmp = sbuf->y - *srcy; - if (*height > tmp) *height = tmp; - } - - if ((*height <= 0) || (*width <= 0)) { - *width = 0; - *height = 0; - } + int tmp; + + if (dbuf == NULL) + return; + + if (*destx < 0) { + *srcx -= *destx; + *origx -= *destx; + *width += *destx; + *destx = 0; + } + if (*origx < 0) { + *destx -= *origx; + *srcx -= *origx; + *width += *origx; + *origx = 0; + } + if (*srcx < 0) { + *destx -= *srcx; + *origx -= *srcx; + *width += *srcx; + *srcx = 0; + } + + if (*desty < 0) { + *srcy -= *desty; + *origy -= *desty; + *height += *desty; + *desty = 0; + } + if (*origy < 0) { + *desty -= *origy; + *srcy -= *origy; + *height += *origy; + *origy = 0; + } + if (*srcy < 0) { + *desty -= *srcy; + *origy -= *srcy; + *height += *srcy; + *srcy = 0; + } + + tmp = dbuf->x - *destx; + if (*width > tmp) + *width = tmp; + tmp = dbuf->y - *desty; + if (*height > tmp) + *height = tmp; + + if (obuf) { + tmp = obuf->x - *origx; + if (*width > tmp) + *width = tmp; + tmp = obuf->y - *origy; + if (*height > tmp) + *height = tmp; + } + + if (sbuf) { + tmp = sbuf->x - *srcx; + if (*width > tmp) + *width = tmp; + tmp = sbuf->y - *srcy; + if (*height > tmp) + *height = tmp; + } + + if ((*height <= 0) || (*width <= 0)) { + *width = 0; + *height = 0; + } } /* copy and blend */ -void IMB_rectcpy(ImBuf *dbuf, ImBuf *sbuf, int destx, - int desty, int srcx, int srcy, int width, int height) +void IMB_rectcpy( + ImBuf *dbuf, ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height) { - IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY, false); + IMB_rectblend(dbuf, + dbuf, + sbuf, + NULL, + NULL, + NULL, + 0, + destx, + desty, + destx, + desty, + srcx, + srcy, + width, + height, + IMB_BLEND_COPY, + false); } -typedef void (*IMB_blend_func)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2); +typedef void (*IMB_blend_func)(unsigned char *dst, + const unsigned char *src1, + const unsigned char *src2); typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2); - -void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, unsigned short *curvemask, - unsigned short *texmask, float mask_max, - int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height, - IMB_BlendMode mode, bool accumulate) +void IMB_rectblend(ImBuf *dbuf, + ImBuf *obuf, + ImBuf *sbuf, + unsigned short *dmask, + unsigned short *curvemask, + unsigned short *texmask, + float mask_max, + int destx, + int desty, + int origx, + int origy, + int srcx, + int srcy, + int width, + int height, + IMB_BlendMode mode, + bool accumulate) { - unsigned int *drect = NULL, *orect = NULL, *srect = NULL, *dr, *or, *sr; - float *drectf = NULL, *orectf = NULL, *srectf = NULL, *drf, *orf, *srf; - unsigned short *cmaskrect = curvemask, *cmr; - unsigned short *dmaskrect = dmask, *dmr; - unsigned short *texmaskrect = texmask, *tmr; - int do_float, do_char, srcskip, destskip, origskip, x; - IMB_blend_func func = NULL; - IMB_blend_func_float func_float = NULL; - - if (dbuf == NULL || obuf == NULL) return; - - imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height); - - if (width == 0 || height == 0) return; - if (sbuf && sbuf->channels != 4) return; - if (dbuf->channels != 4) return; - - do_char = (sbuf && sbuf->rect && dbuf->rect && obuf->rect); - do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float); - - if (do_char) { - drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx; - orect = obuf->rect + ((size_t)origy) * obuf->x + origx; - } - if (do_float) { - drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4; - orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4; - } - - if (dmaskrect) - dmaskrect += ((size_t)origy) * obuf->x + origx; - - destskip = dbuf->x; - origskip = obuf->x; - - if (sbuf) { - if (do_char) srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx; - if (do_float) srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4; - srcskip = sbuf->x; - - if (cmaskrect) - cmaskrect += ((size_t)srcy) * sbuf->x + srcx; - - if (texmaskrect) - texmaskrect += ((size_t)srcy) * sbuf->x + srcx; - } - else { - srect = drect; - srectf = drectf; - srcskip = destskip; - } - - if (mode == IMB_BLEND_COPY) { - /* copy */ - for (; height > 0; height--) { - if (do_char) { - memcpy(drect, srect, width * sizeof(int)); - drect += destskip; - srect += srcskip; - } - - if (do_float) { - memcpy(drectf, srectf, width * sizeof(float) * 4); - drectf += destskip * 4; - srectf += srcskip * 4; - } - } - } - else if (mode == IMB_BLEND_COPY_RGB) { - /* copy rgb only */ - for (; height > 0; height--) { - if (do_char) { - dr = drect; - sr = srect; - for (x = width; x > 0; x--, dr++, sr++) { - ((char *)dr)[0] = ((char *)sr)[0]; - ((char *)dr)[1] = ((char *)sr)[1]; - ((char *)dr)[2] = ((char *)sr)[2]; - } - drect += destskip; - srect += srcskip; - } - - if (do_float) { - drf = drectf; - srf = srectf; - for (x = width; x > 0; x--, drf += 4, srf += 4) { - float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3]; - - drf[0] = srf[0] * map_alpha; - drf[1] = srf[1] * map_alpha; - drf[2] = srf[2] * map_alpha; - } - drectf += destskip * 4; - srectf += srcskip * 4; - } - } - } - else if (mode == IMB_BLEND_COPY_ALPHA) { - /* copy alpha only */ - for (; height > 0; height--) { - if (do_char) { - dr = drect; - sr = srect; - for (x = width; x > 0; x--, dr++, sr++) - ((char *)dr)[3] = ((char *)sr)[3]; - drect += destskip; - srect += srcskip; - } - - if (do_float) { - drf = drectf; - srf = srectf; - for (x = width; x > 0; x--, drf += 4, srf += 4) - drf[3] = srf[3]; - drectf += destskip * 4; - srectf += srcskip * 4; - } - } - } - else { - switch (mode) { - case IMB_BLEND_MIX: - case IMB_BLEND_INTERPOLATE: - func = blend_color_mix_byte; - func_float = blend_color_mix_float; - break; - case IMB_BLEND_ADD: - func = blend_color_add_byte; - func_float = blend_color_add_float; - break; - case IMB_BLEND_SUB: - func = blend_color_sub_byte; - func_float = blend_color_sub_float; - break; - case IMB_BLEND_MUL: - func = blend_color_mul_byte; - func_float = blend_color_mul_float; - break; - case IMB_BLEND_LIGHTEN: - func = blend_color_lighten_byte; - func_float = blend_color_lighten_float; - break; - case IMB_BLEND_DARKEN: - func = blend_color_darken_byte; - func_float = blend_color_darken_float; - break; - case IMB_BLEND_ERASE_ALPHA: - func = blend_color_erase_alpha_byte; - func_float = blend_color_erase_alpha_float; - break; - case IMB_BLEND_ADD_ALPHA: - func = blend_color_add_alpha_byte; - func_float = blend_color_add_alpha_float; - break; - case IMB_BLEND_OVERLAY: - func = blend_color_overlay_byte; - func_float = blend_color_overlay_float; - break; - case IMB_BLEND_HARDLIGHT: - func = blend_color_hardlight_byte; - func_float = blend_color_hardlight_float; - break; - case IMB_BLEND_COLORBURN: - func = blend_color_burn_byte; - func_float = blend_color_burn_float; - break; - case IMB_BLEND_LINEARBURN: - func = blend_color_linearburn_byte; - func_float = blend_color_linearburn_float; - break; - case IMB_BLEND_COLORDODGE: - func = blend_color_dodge_byte; - func_float = blend_color_dodge_float; - break; - case IMB_BLEND_SCREEN: - func = blend_color_screen_byte; - func_float = blend_color_screen_float; - break; - case IMB_BLEND_SOFTLIGHT: - func = blend_color_softlight_byte; - func_float = blend_color_softlight_float; - break; - case IMB_BLEND_PINLIGHT: - func = blend_color_pinlight_byte; - func_float = blend_color_pinlight_float; - break; - case IMB_BLEND_LINEARLIGHT: - func = blend_color_linearlight_byte; - func_float = blend_color_linearlight_float; - break; - case IMB_BLEND_VIVIDLIGHT: - func = blend_color_vividlight_byte; - func_float = blend_color_vividlight_float; - break; - case IMB_BLEND_DIFFERENCE: - func = blend_color_difference_byte; - func_float = blend_color_difference_float; - break; - case IMB_BLEND_EXCLUSION: - func = blend_color_exclusion_byte; - func_float = blend_color_exclusion_float; - break; - case IMB_BLEND_COLOR: - func = blend_color_color_byte; - func_float = blend_color_color_float; - break; - case IMB_BLEND_HUE: - func = blend_color_hue_byte; - func_float = blend_color_hue_float; - break; - case IMB_BLEND_SATURATION: - func = blend_color_saturation_byte; - func_float = blend_color_saturation_float; - break; - case IMB_BLEND_LUMINOSITY: - func = blend_color_luminosity_byte; - func_float = blend_color_luminosity_float; - break; - default: - break; - } - - /* blend */ - for (; height > 0; height--) { - if (do_char) { - dr = drect; - or = orect; - sr = srect; - - if (cmaskrect) { - /* mask accumulation for painting */ - cmr = cmaskrect; - tmr = texmaskrect; - - /* destination mask present, do max alpha masking */ - if (dmaskrect) { - dmr = dmaskrect; - for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, cmr++) { - unsigned char *src = (unsigned char *)sr; - float mask_lim = mask_max * (*cmr); - - if (texmaskrect) - mask_lim *= ((*tmr++) / 65535.0f); - - if (src[3] && mask_lim) { - float mask; - - if (accumulate) - mask = *dmr + mask_lim; - else - mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f)); - - mask = min_ff(mask, 65535.0); - - if (mask > *dmr) { - unsigned char mask_src[4]; - - *dmr = mask; - - mask_src[0] = src[0]; - mask_src[1] = src[1]; - mask_src[2] = src[2]; - - if (mode == IMB_BLEND_INTERPOLATE) { - mask_src[3] = src[3]; - blend_color_interpolate_byte((unsigned char *)dr, (unsigned char *)or, mask_src, mask / 65535.0f); - } - else { - mask_src[3] = divide_round_i(src[3] * mask, 65535); - func((unsigned char *)dr, (unsigned char *)or, mask_src); - } - } - } - } - dmaskrect += origskip; - } - /* no destination mask buffer, do regular blend with masktexture if present */ - else { - for (x = width; x > 0; x--, dr++, or++, sr++, cmr++) { - unsigned char *src = (unsigned char *)sr; - float mask = (float)mask_max * ((float)(*cmr)); - - if (texmaskrect) - mask *= ((float)(*tmr++) / 65535.0f); - - mask = min_ff(mask, 65535.0); - - if (src[3] && (mask > 0.0f)) { - unsigned char mask_src[4]; - - mask_src[0] = src[0]; - mask_src[1] = src[1]; - mask_src[2] = src[2]; - - if (mode == IMB_BLEND_INTERPOLATE) { - mask_src[3] = src[3]; - blend_color_interpolate_byte((unsigned char *)dr, (unsigned char *)or, mask_src, mask / 65535.0f); - } - else { - mask_src[3] = divide_round_i(src[3] * mask, 65535); - func((unsigned char *)dr, (unsigned char *)or, mask_src); - } - } - } - } - - cmaskrect += srcskip; - if (texmaskrect) - texmaskrect += srcskip; - } - else { - /* regular blending */ - for (x = width; x > 0; x--, dr++, or++, sr++) { - if (((unsigned char *)sr)[3]) - func((unsigned char *)dr, (unsigned char *)or, (unsigned char *)sr); - } - } - - drect += destskip; - orect += origskip; - srect += srcskip; - } - - if (do_float) { - drf = drectf; - orf = orectf; - srf = srectf; - - if (cmaskrect) { - /* mask accumulation for painting */ - cmr = cmaskrect; - tmr = texmaskrect; - - /* destination mask present, do max alpha masking */ - if (dmaskrect) { - dmr = dmaskrect; - for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) { - float mask_lim = mask_max * (*cmr); - - if (texmaskrect) - mask_lim *= ((*tmr++) / 65535.0f); - - if (srf[3] && mask_lim) { - float mask; - - if (accumulate) - mask = min_ff(*dmr + mask_lim, 65535.0); - else - mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f)); - - mask = min_ff(mask, 65535.0); - - if (mask > *dmr) { - *dmr = mask; - - if (mode == IMB_BLEND_INTERPOLATE) { - blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f); - } - else { - float mask_srf[4]; - mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); - func_float(drf, orf, mask_srf); - } - } - } - } - dmaskrect += origskip; - } - /* no destination mask buffer, do regular blend with masktexture if present */ - else { - for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) { - float mask = (float)mask_max * ((float)(*cmr)); - - if (texmaskrect) - mask *= ((float)(*tmr++) / 65535.0f); - - mask = min_ff(mask, 65535.0); - - if (srf[3] && (mask > 0.0f)) { - if (mode == IMB_BLEND_INTERPOLATE) { - blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f); - } - else { - float mask_srf[4]; - mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); - func_float(drf, orf, mask_srf); - } - - } - } - } - - cmaskrect += srcskip; - if (texmaskrect) - texmaskrect += srcskip; - } - else { - /* regular blending */ - for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) { - if (srf[3] != 0) - func_float(drf, orf, srf); - } - } - - drectf += destskip * 4; - orectf += origskip * 4; - srectf += srcskip * 4; - } - } - } + unsigned int *drect = NULL, *orect = NULL, *srect = NULL, *dr, * or, *sr; + float *drectf = NULL, *orectf = NULL, *srectf = NULL, *drf, *orf, *srf; + unsigned short *cmaskrect = curvemask, *cmr; + unsigned short *dmaskrect = dmask, *dmr; + unsigned short *texmaskrect = texmask, *tmr; + int do_float, do_char, srcskip, destskip, origskip, x; + IMB_blend_func func = NULL; + IMB_blend_func_float func_float = NULL; + + if (dbuf == NULL || obuf == NULL) + return; + + imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height); + + if (width == 0 || height == 0) + return; + if (sbuf && sbuf->channels != 4) + return; + if (dbuf->channels != 4) + return; + + do_char = (sbuf && sbuf->rect && dbuf->rect && obuf->rect); + do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float); + + if (do_char) { + drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx; + orect = obuf->rect + ((size_t)origy) * obuf->x + origx; + } + if (do_float) { + drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4; + orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4; + } + + if (dmaskrect) + dmaskrect += ((size_t)origy) * obuf->x + origx; + + destskip = dbuf->x; + origskip = obuf->x; + + if (sbuf) { + if (do_char) + srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx; + if (do_float) + srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4; + srcskip = sbuf->x; + + if (cmaskrect) + cmaskrect += ((size_t)srcy) * sbuf->x + srcx; + + if (texmaskrect) + texmaskrect += ((size_t)srcy) * sbuf->x + srcx; + } + else { + srect = drect; + srectf = drectf; + srcskip = destskip; + } + + if (mode == IMB_BLEND_COPY) { + /* copy */ + for (; height > 0; height--) { + if (do_char) { + memcpy(drect, srect, width * sizeof(int)); + drect += destskip; + srect += srcskip; + } + + if (do_float) { + memcpy(drectf, srectf, width * sizeof(float) * 4); + drectf += destskip * 4; + srectf += srcskip * 4; + } + } + } + else if (mode == IMB_BLEND_COPY_RGB) { + /* copy rgb only */ + for (; height > 0; height--) { + if (do_char) { + dr = drect; + sr = srect; + for (x = width; x > 0; x--, dr++, sr++) { + ((char *)dr)[0] = ((char *)sr)[0]; + ((char *)dr)[1] = ((char *)sr)[1]; + ((char *)dr)[2] = ((char *)sr)[2]; + } + drect += destskip; + srect += srcskip; + } + + if (do_float) { + drf = drectf; + srf = srectf; + for (x = width; x > 0; x--, drf += 4, srf += 4) { + float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3]; + + drf[0] = srf[0] * map_alpha; + drf[1] = srf[1] * map_alpha; + drf[2] = srf[2] * map_alpha; + } + drectf += destskip * 4; + srectf += srcskip * 4; + } + } + } + else if (mode == IMB_BLEND_COPY_ALPHA) { + /* copy alpha only */ + for (; height > 0; height--) { + if (do_char) { + dr = drect; + sr = srect; + for (x = width; x > 0; x--, dr++, sr++) + ((char *)dr)[3] = ((char *)sr)[3]; + drect += destskip; + srect += srcskip; + } + + if (do_float) { + drf = drectf; + srf = srectf; + for (x = width; x > 0; x--, drf += 4, srf += 4) + drf[3] = srf[3]; + drectf += destskip * 4; + srectf += srcskip * 4; + } + } + } + else { + switch (mode) { + case IMB_BLEND_MIX: + case IMB_BLEND_INTERPOLATE: + func = blend_color_mix_byte; + func_float = blend_color_mix_float; + break; + case IMB_BLEND_ADD: + func = blend_color_add_byte; + func_float = blend_color_add_float; + break; + case IMB_BLEND_SUB: + func = blend_color_sub_byte; + func_float = blend_color_sub_float; + break; + case IMB_BLEND_MUL: + func = blend_color_mul_byte; + func_float = blend_color_mul_float; + break; + case IMB_BLEND_LIGHTEN: + func = blend_color_lighten_byte; + func_float = blend_color_lighten_float; + break; + case IMB_BLEND_DARKEN: + func = blend_color_darken_byte; + func_float = blend_color_darken_float; + break; + case IMB_BLEND_ERASE_ALPHA: + func = blend_color_erase_alpha_byte; + func_float = blend_color_erase_alpha_float; + break; + case IMB_BLEND_ADD_ALPHA: + func = blend_color_add_alpha_byte; + func_float = blend_color_add_alpha_float; + break; + case IMB_BLEND_OVERLAY: + func = blend_color_overlay_byte; + func_float = blend_color_overlay_float; + break; + case IMB_BLEND_HARDLIGHT: + func = blend_color_hardlight_byte; + func_float = blend_color_hardlight_float; + break; + case IMB_BLEND_COLORBURN: + func = blend_color_burn_byte; + func_float = blend_color_burn_float; + break; + case IMB_BLEND_LINEARBURN: + func = blend_color_linearburn_byte; + func_float = blend_color_linearburn_float; + break; + case IMB_BLEND_COLORDODGE: + func = blend_color_dodge_byte; + func_float = blend_color_dodge_float; + break; + case IMB_BLEND_SCREEN: + func = blend_color_screen_byte; + func_float = blend_color_screen_float; + break; + case IMB_BLEND_SOFTLIGHT: + func = blend_color_softlight_byte; + func_float = blend_color_softlight_float; + break; + case IMB_BLEND_PINLIGHT: + func = blend_color_pinlight_byte; + func_float = blend_color_pinlight_float; + break; + case IMB_BLEND_LINEARLIGHT: + func = blend_color_linearlight_byte; + func_float = blend_color_linearlight_float; + break; + case IMB_BLEND_VIVIDLIGHT: + func = blend_color_vividlight_byte; + func_float = blend_color_vividlight_float; + break; + case IMB_BLEND_DIFFERENCE: + func = blend_color_difference_byte; + func_float = blend_color_difference_float; + break; + case IMB_BLEND_EXCLUSION: + func = blend_color_exclusion_byte; + func_float = blend_color_exclusion_float; + break; + case IMB_BLEND_COLOR: + func = blend_color_color_byte; + func_float = blend_color_color_float; + break; + case IMB_BLEND_HUE: + func = blend_color_hue_byte; + func_float = blend_color_hue_float; + break; + case IMB_BLEND_SATURATION: + func = blend_color_saturation_byte; + func_float = blend_color_saturation_float; + break; + case IMB_BLEND_LUMINOSITY: + func = blend_color_luminosity_byte; + func_float = blend_color_luminosity_float; + break; + default: + break; + } + + /* blend */ + for (; height > 0; height--) { + if (do_char) { + dr = drect; + or = orect; + sr = srect; + + if (cmaskrect) { + /* mask accumulation for painting */ + cmr = cmaskrect; + tmr = texmaskrect; + + /* destination mask present, do max alpha masking */ + if (dmaskrect) { + dmr = dmaskrect; + for (x = width; x > 0; x--, dr++, or ++, sr++, dmr++, cmr++) { + unsigned char *src = (unsigned char *)sr; + float mask_lim = mask_max * (*cmr); + + if (texmaskrect) + mask_lim *= ((*tmr++) / 65535.0f); + + if (src[3] && mask_lim) { + float mask; + + if (accumulate) + mask = *dmr + mask_lim; + else + mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f)); + + mask = min_ff(mask, 65535.0); + + if (mask > *dmr) { + unsigned char mask_src[4]; + + *dmr = mask; + + mask_src[0] = src[0]; + mask_src[1] = src[1]; + mask_src[2] = src[2]; + + if (mode == IMB_BLEND_INTERPOLATE) { + mask_src[3] = src[3]; + blend_color_interpolate_byte( + (unsigned char *)dr, (unsigned char *) or, mask_src, mask / 65535.0f); + } + else { + mask_src[3] = divide_round_i(src[3] * mask, 65535); + func((unsigned char *)dr, (unsigned char *) or, mask_src); + } + } + } + } + dmaskrect += origskip; + } + /* no destination mask buffer, do regular blend with masktexture if present */ + else { + for (x = width; x > 0; x--, dr++, or ++, sr++, cmr++) { + unsigned char *src = (unsigned char *)sr; + float mask = (float)mask_max * ((float)(*cmr)); + + if (texmaskrect) + mask *= ((float)(*tmr++) / 65535.0f); + + mask = min_ff(mask, 65535.0); + + if (src[3] && (mask > 0.0f)) { + unsigned char mask_src[4]; + + mask_src[0] = src[0]; + mask_src[1] = src[1]; + mask_src[2] = src[2]; + + if (mode == IMB_BLEND_INTERPOLATE) { + mask_src[3] = src[3]; + blend_color_interpolate_byte( + (unsigned char *)dr, (unsigned char *) or, mask_src, mask / 65535.0f); + } + else { + mask_src[3] = divide_round_i(src[3] * mask, 65535); + func((unsigned char *)dr, (unsigned char *) or, mask_src); + } + } + } + } + + cmaskrect += srcskip; + if (texmaskrect) + texmaskrect += srcskip; + } + else { + /* regular blending */ + for (x = width; x > 0; x--, dr++, or ++, sr++) { + if (((unsigned char *)sr)[3]) + func((unsigned char *)dr, (unsigned char *) or, (unsigned char *)sr); + } + } + + drect += destskip; + orect += origskip; + srect += srcskip; + } + + if (do_float) { + drf = drectf; + orf = orectf; + srf = srectf; + + if (cmaskrect) { + /* mask accumulation for painting */ + cmr = cmaskrect; + tmr = texmaskrect; + + /* destination mask present, do max alpha masking */ + if (dmaskrect) { + dmr = dmaskrect; + for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) { + float mask_lim = mask_max * (*cmr); + + if (texmaskrect) + mask_lim *= ((*tmr++) / 65535.0f); + + if (srf[3] && mask_lim) { + float mask; + + if (accumulate) + mask = min_ff(*dmr + mask_lim, 65535.0); + else + mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f)); + + mask = min_ff(mask, 65535.0); + + if (mask > *dmr) { + *dmr = mask; + + if (mode == IMB_BLEND_INTERPOLATE) { + blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f); + } + else { + float mask_srf[4]; + mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); + func_float(drf, orf, mask_srf); + } + } + } + } + dmaskrect += origskip; + } + /* no destination mask buffer, do regular blend with masktexture if present */ + else { + for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) { + float mask = (float)mask_max * ((float)(*cmr)); + + if (texmaskrect) + mask *= ((float)(*tmr++) / 65535.0f); + + mask = min_ff(mask, 65535.0); + + if (srf[3] && (mask > 0.0f)) { + if (mode == IMB_BLEND_INTERPOLATE) { + blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f); + } + else { + float mask_srf[4]; + mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); + func_float(drf, orf, mask_srf); + } + } + } + } + + cmaskrect += srcskip; + if (texmaskrect) + texmaskrect += srcskip; + } + else { + /* regular blending */ + for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) { + if (srf[3] != 0) + func_float(drf, orf, srf); + } + } + + drectf += destskip * 4; + orectf += origskip * 4; + srectf += srcskip * 4; + } + } + } } typedef struct RectBlendThreadData { - ImBuf *dbuf, *obuf, *sbuf; - unsigned short *dmask, *curvemask, *texmask; - float mask_max; - int destx, desty, origx, origy; - int srcx, srcy, width; - IMB_BlendMode mode; - bool accumulate; + ImBuf *dbuf, *obuf, *sbuf; + unsigned short *dmask, *curvemask, *texmask; + float mask_max; + int destx, desty, origx, origy; + int srcx, srcy, width; + IMB_BlendMode mode; + bool accumulate; } RectBlendThreadData; -static void rectblend_thread_do(void *data_v, - int start_scanline, - int num_scanlines) +static void rectblend_thread_do(void *data_v, int start_scanline, int num_scanlines) { - RectBlendThreadData *data = (RectBlendThreadData *)data_v; - IMB_rectblend(data->dbuf, data->obuf, data->sbuf, - data->dmask, data->curvemask, data->texmask, - data->mask_max, - data->destx, - data->desty + start_scanline, - data->origx, - data->origy + start_scanline, - data->srcx, - data->srcy + start_scanline, - data->width, num_scanlines, - data->mode, data->accumulate); + RectBlendThreadData *data = (RectBlendThreadData *)data_v; + IMB_rectblend(data->dbuf, + data->obuf, + data->sbuf, + data->dmask, + data->curvemask, + data->texmask, + data->mask_max, + data->destx, + data->desty + start_scanline, + data->origx, + data->origy + start_scanline, + data->srcx, + data->srcy + start_scanline, + data->width, + num_scanlines, + data->mode, + data->accumulate); } -void IMB_rectblend_threaded(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, - unsigned short *dmask, unsigned short *curvemask, - unsigned short *texmask, float mask_max, - int destx, int desty, int origx, int origy, - int srcx, int srcy, int width, int height, - IMB_BlendMode mode, bool accumulate) +void IMB_rectblend_threaded(ImBuf *dbuf, + ImBuf *obuf, + ImBuf *sbuf, + unsigned short *dmask, + unsigned short *curvemask, + unsigned short *texmask, + float mask_max, + int destx, + int desty, + int origx, + int origy, + int srcx, + int srcy, + int width, + int height, + IMB_BlendMode mode, + bool accumulate) { - if (((size_t)width) * height < 64 * 64) { - IMB_rectblend(dbuf, obuf, sbuf, dmask, curvemask, texmask, - mask_max, destx, desty, origx, origy, - srcx, srcy, width, height, mode, accumulate); - } - else { - RectBlendThreadData data; - data.dbuf = dbuf; - data.obuf = obuf; - data.sbuf = sbuf; - data.dmask = dmask; - data.curvemask = curvemask; - data.texmask = texmask; - data.mask_max = mask_max; - data.destx = destx; - data.desty = desty; - data.origx = origx; - data.origy = origy; - data.srcx = srcx; - data.srcy = srcy; - data.width = width; - data.mode = mode; - data.accumulate = accumulate; - IMB_processor_apply_threaded_scanlines( - height, rectblend_thread_do, &data); - } + if (((size_t)width) * height < 64 * 64) { + IMB_rectblend(dbuf, + obuf, + sbuf, + dmask, + curvemask, + texmask, + mask_max, + destx, + desty, + origx, + origy, + srcx, + srcy, + width, + height, + mode, + accumulate); + } + else { + RectBlendThreadData data; + data.dbuf = dbuf; + data.obuf = obuf; + data.sbuf = sbuf; + data.dmask = dmask; + data.curvemask = curvemask; + data.texmask = texmask; + data.mask_max = mask_max; + data.destx = destx; + data.desty = desty; + data.origx = origx; + data.origy = origy; + data.srcx = srcx; + data.srcy = srcy; + data.width = width; + data.mode = mode; + data.accumulate = accumulate; + IMB_processor_apply_threaded_scanlines(height, rectblend_thread_do, &data); + } } /* fill */ void IMB_rectfill(ImBuf *drect, const float col[4]) { - int num; - - if (drect->rect) { - unsigned int *rrect = drect->rect; - char ccol[4]; - - ccol[0] = (int)(col[0] * 255); - ccol[1] = (int)(col[1] * 255); - ccol[2] = (int)(col[2] * 255); - ccol[3] = (int)(col[3] * 255); - - num = drect->x * drect->y; - for (; num > 0; num--) - *rrect++ = *((unsigned int *)ccol); - } - - if (drect->rect_float) { - float *rrectf = drect->rect_float; - - num = drect->x * drect->y; - for (; num > 0; num--) { - *rrectf++ = col[0]; - *rrectf++ = col[1]; - *rrectf++ = col[2]; - *rrectf++ = col[3]; - } - } + int num; + + if (drect->rect) { + unsigned int *rrect = drect->rect; + char ccol[4]; + + ccol[0] = (int)(col[0] * 255); + ccol[1] = (int)(col[1] * 255); + ccol[2] = (int)(col[2] * 255); + ccol[3] = (int)(col[3] * 255); + + num = drect->x * drect->y; + for (; num > 0; num--) + *rrect++ = *((unsigned int *)ccol); + } + + if (drect->rect_float) { + float *rrectf = drect->rect_float; + + num = drect->x * drect->y; + for (; num > 0; num--) { + *rrectf++ = col[0]; + *rrectf++ = col[1]; + *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) +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) { - int i, j; - float a; /* alpha */ - float ai; /* alpha inverted */ - float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */ - if ((!rect && !rectf) || (!col) || col[3] == 0.0f) - return; - - /* sanity checks for coords */ - CLAMP(x1, 0, width); - CLAMP(x2, 0, width); - CLAMP(y1, 0, height); - CLAMP(y2, 0, height); - - if (x1 > x2) SWAP(int, x1, x2); - if (y1 > y2) SWAP(int, y1, y2); - if (x1 == x2 || y1 == y2) return; - - a = col[3]; - ai = 1 - a; - aich = ai / 255.0f; - - if (rect) { - unsigned char *pixel; - unsigned char chr = 0, chg = 0, chb = 0; - float fr = 0, fg = 0, fb = 0; - - const int alphaint = unit_float_to_uchar_clamp(a); - - if (a == 1.0f) { - chr = unit_float_to_uchar_clamp(col[0]); - chg = unit_float_to_uchar_clamp(col[1]); - chb = unit_float_to_uchar_clamp(col[2]); - } - else { - fr = col[0] * a; - fg = col[1] * a; - fb = col[2] * a; - } - for (j = 0; j < y2 - y1; j++) { - for (i = 0; i < x2 - x1; i++) { - pixel = rect + 4 * (((y1 + j) * width) + (x1 + i)); - if (pixel >= rect && pixel < rect + (4 * (width * height))) { - if (a == 1.0f) { - pixel[0] = chr; - pixel[1] = chg; - pixel[2] = chb; - pixel[3] = 255; - } - else { - int alphatest; - pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f); - pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f); - pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f); - pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255); - } - } - } - } - } - - if (rectf) { - float col_conv[4]; - float *pixel; - - if (display) { - copy_v4_v4(col_conv, col); - IMB_colormanagement_display_to_scene_linear_v3(col_conv, display); - } - else { - srgb_to_linearrgb_v4(col_conv, col); - } - - for (j = 0; j < y2 - y1; j++) { - for (i = 0; i < x2 - x1; i++) { - pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i)); - if (a == 1.0f) { - pixel[0] = col_conv[0]; - pixel[1] = col_conv[1]; - pixel[2] = col_conv[2]; - pixel[3] = 1.0f; - } - else { - float alphatest; - pixel[0] = (col_conv[0] * a) + (pixel[0] * ai); - pixel[1] = (col_conv[1] * a) + (pixel[1] * ai); - pixel[2] = (col_conv[2] * a) + (pixel[2] * ai); - pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f; - } - } - } - } + int i, j; + float a; /* alpha */ + float ai; /* alpha inverted */ + float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */ + if ((!rect && !rectf) || (!col) || col[3] == 0.0f) + return; + + /* sanity checks for coords */ + CLAMP(x1, 0, width); + CLAMP(x2, 0, width); + CLAMP(y1, 0, height); + CLAMP(y2, 0, height); + + if (x1 > x2) + SWAP(int, x1, x2); + if (y1 > y2) + SWAP(int, y1, y2); + if (x1 == x2 || y1 == y2) + return; + + a = col[3]; + ai = 1 - a; + aich = ai / 255.0f; + + if (rect) { + unsigned char *pixel; + unsigned char chr = 0, chg = 0, chb = 0; + float fr = 0, fg = 0, fb = 0; + + const int alphaint = unit_float_to_uchar_clamp(a); + + if (a == 1.0f) { + chr = unit_float_to_uchar_clamp(col[0]); + chg = unit_float_to_uchar_clamp(col[1]); + chb = unit_float_to_uchar_clamp(col[2]); + } + else { + fr = col[0] * a; + fg = col[1] * a; + fb = col[2] * a; + } + for (j = 0; j < y2 - y1; j++) { + for (i = 0; i < x2 - x1; i++) { + pixel = rect + 4 * (((y1 + j) * width) + (x1 + i)); + if (pixel >= rect && pixel < rect + (4 * (width * height))) { + if (a == 1.0f) { + pixel[0] = chr; + pixel[1] = chg; + pixel[2] = chb; + pixel[3] = 255; + } + else { + int alphatest; + pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f); + pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f); + pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f); + pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255); + } + } + } + } + } + + if (rectf) { + float col_conv[4]; + float *pixel; + + if (display) { + copy_v4_v4(col_conv, col); + IMB_colormanagement_display_to_scene_linear_v3(col_conv, display); + } + else { + srgb_to_linearrgb_v4(col_conv, col); + } + + for (j = 0; j < y2 - y1; j++) { + for (i = 0; i < x2 - x1; i++) { + pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i)); + if (a == 1.0f) { + pixel[0] = col_conv[0]; + pixel[1] = col_conv[1]; + pixel[2] = col_conv[2]; + pixel[3] = 1.0f; + } + else { + float alphatest; + pixel[0] = (col_conv[0] * a) + (pixel[0] * ai); + pixel[1] = (col_conv[1] * a) + (pixel[1] * ai); + pixel[2] = (col_conv[2] * a) + (pixel[2] * ai); + pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f; + } + } + } + } } -void IMB_rectfill_area(ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display) +void IMB_rectfill_area(ImBuf *ibuf, + const float col[4], + int x1, + int y1, + int x2, + int y2, + struct ColorManagedDisplay *display) { - if (!ibuf) return; - buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display, - x1, y1, x2, y2); + if (!ibuf) + return; + buf_rectfill_area((unsigned char *)ibuf->rect, + ibuf->rect_float, + ibuf->x, + ibuf->y, + col, + display, + x1, + y1, + x2, + y2); } - void IMB_rectfill_alpha(ImBuf *ibuf, const float value) { - int i; - - if (ibuf->rect_float && (ibuf->channels == 4)) { - float *fbuf = ibuf->rect_float + 3; - for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) { *fbuf = value; } - } - - if (ibuf->rect) { - const unsigned char cvalue = value * 255; - unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3; - for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) { *cbuf = cvalue; } - } + int i; + + if (ibuf->rect_float && (ibuf->channels == 4)) { + float *fbuf = ibuf->rect_float + 3; + for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) { + *fbuf = value; + } + } + + if (ibuf->rect) { + const unsigned char cvalue = value * 255; + unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3; + for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) { + *cbuf = cvalue; + } + } } diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c index 277a2d0c491..2b200abc852 100644 --- a/source/blender/imbuf/intern/rotate.c +++ b/source/blender/imbuf/intern/rotate.c @@ -32,82 +32,86 @@ void IMB_flipy(struct ImBuf *ibuf) { - int x, y; + int x, y; - if (ibuf == NULL) return; + if (ibuf == NULL) + return; - if (ibuf->rect) { - unsigned int *top, *bottom, *line; + if (ibuf->rect) { + unsigned int *top, *bottom, *line; - x = ibuf->x; - y = ibuf->y; + x = ibuf->x; + y = ibuf->y; - top = ibuf->rect; - bottom = top + ((y - 1) * x); - line = MEM_mallocN(x * sizeof(int), "linebuf"); + top = ibuf->rect; + bottom = top + ((y - 1) * x); + line = MEM_mallocN(x * sizeof(int), "linebuf"); - y >>= 1; + y >>= 1; - for (; y > 0; y--) { - memcpy(line, top, x * sizeof(int)); - memcpy(top, bottom, x * sizeof(int)); - memcpy(bottom, line, x * sizeof(int)); - bottom -= x; - top += x; - } + for (; y > 0; y--) { + memcpy(line, top, x * sizeof(int)); + memcpy(top, bottom, x * sizeof(int)); + memcpy(bottom, line, x * sizeof(int)); + bottom -= x; + top += x; + } - MEM_freeN(line); - } + MEM_freeN(line); + } - if (ibuf->rect_float) { - float *topf = NULL, *bottomf = NULL, *linef = NULL; + if (ibuf->rect_float) { + float *topf = NULL, *bottomf = NULL, *linef = NULL; - x = ibuf->x; - y = ibuf->y; + x = ibuf->x; + y = ibuf->y; - topf = ibuf->rect_float; - bottomf = topf + 4 * ((y - 1) * x); - linef = MEM_mallocN(4 * x * sizeof(float), "linebuff"); + topf = ibuf->rect_float; + bottomf = topf + 4 * ((y - 1) * x); + linef = MEM_mallocN(4 * x * sizeof(float), "linebuff"); - y >>= 1; + y >>= 1; - for (; y > 0; y--) { - memcpy(linef, topf, 4 * x * sizeof(float)); - memcpy(topf, bottomf, 4 * x * sizeof(float)); - memcpy(bottomf, linef, 4 * x * sizeof(float)); - bottomf -= 4 * x; - topf += 4 * x; - } + for (; y > 0; y--) { + memcpy(linef, topf, 4 * x * sizeof(float)); + memcpy(topf, bottomf, 4 * x * sizeof(float)); + memcpy(bottomf, linef, 4 * x * sizeof(float)); + bottomf -= 4 * x; + topf += 4 * x; + } - MEM_freeN(linef); - } + MEM_freeN(linef); + } } void IMB_flipx(struct ImBuf *ibuf) { - int x, y, xr, xl, yi; - float px_f[4]; - - if (ibuf == NULL) return; - - x = ibuf->x; - y = ibuf->y; - - if (ibuf->rect) { - for (yi = y - 1; yi >= 0; yi--) { - for (xr = x - 1, xl = 0; xr >= xl; xr--, xl++) { - SWAP(unsigned int, ibuf->rect[(x * yi) + xr], ibuf->rect[(x * yi) + xl]); - } - } - } - - if (ibuf->rect_float) { - for (yi = y - 1; yi >= 0; yi--) { - for (xr = x - 1, xl = 0; xr >= xl; xr--, xl++) { - memcpy(&px_f, &ibuf->rect_float[((x * yi) + xr) * 4], 4 * sizeof(float)); - memcpy(&ibuf->rect_float[((x * yi) + xr) * 4], &ibuf->rect_float[((x * yi) + xl) * 4], 4 * sizeof(float)); - memcpy(&ibuf->rect_float[((x * yi) + xl) * 4], &px_f, 4 * sizeof(float)); - } - } - } + int x, y, xr, xl, yi; + float px_f[4]; + + if (ibuf == NULL) + return; + + x = ibuf->x; + y = ibuf->y; + + if (ibuf->rect) { + for (yi = y - 1; yi >= 0; yi--) { + for (xr = x - 1, xl = 0; xr >= xl; xr--, xl++) { + SWAP(unsigned int, ibuf->rect[(x * yi) + xr], ibuf->rect[(x * yi) + xl]); + } + } + } + + if (ibuf->rect_float) { + for (yi = y - 1; yi >= 0; yi--) { + for (xr = x - 1, xl = 0; xr >= xl; xr--, xl++) { + memcpy(&px_f, &ibuf->rect_float[((x * yi) + xr) * 4], 4 * sizeof(float)); + memcpy(&ibuf->rect_float[((x * yi) + xr) * 4], + &ibuf->rect_float[((x * yi) + xl) * 4], + 4 * sizeof(float)); + memcpy(&ibuf->rect_float[((x * yi) + xl) * 4], &px_f, 4 * sizeof(float)); + } + } + } } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index c722f91670e..e57f3bb08f4 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -22,7 +22,6 @@ * \ingroup imbuf */ - #include "BLI_utildefines.h" #include "BLI_math_color.h" #include "BLI_math_interp.h" @@ -34,781 +33,797 @@ #include "IMB_filter.h" -#include "BLI_sys_types.h" // for intptr_t support +#include "BLI_sys_types.h" // for intptr_t support static void imb_half_x_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) { - uchar *p1, *_p1, *dest; - short a, r, g, b; - int x, y; - float af, rf, gf, bf, *p1f, *_p1f, *destf; - bool do_rect, do_float; - - do_rect = (ibuf1->rect != NULL); - do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL); - - _p1 = (uchar *) ibuf1->rect; - dest = (uchar *) ibuf2->rect; - - _p1f = ibuf1->rect_float; - destf = ibuf2->rect_float; - - for (y = ibuf2->y; y > 0; y--) { - p1 = _p1; - p1f = _p1f; - for (x = ibuf2->x; x > 0; x--) { - if (do_rect) { - a = *(p1++); - b = *(p1++); - g = *(p1++); - r = *(p1++); - a += *(p1++); - b += *(p1++); - g += *(p1++); - r += *(p1++); - *(dest++) = a >> 1; - *(dest++) = b >> 1; - *(dest++) = g >> 1; - *(dest++) = r >> 1; - } - if (do_float) { - af = *(p1f++); - bf = *(p1f++); - gf = *(p1f++); - rf = *(p1f++); - af += *(p1f++); - bf += *(p1f++); - gf += *(p1f++); - rf += *(p1f++); - *(destf++) = 0.5f * af; - *(destf++) = 0.5f * bf; - *(destf++) = 0.5f * gf; - *(destf++) = 0.5f * rf; - } - } - if (do_rect) _p1 += (ibuf1->x << 2); - if (do_float) _p1f += (ibuf1->x << 2); - } + uchar *p1, *_p1, *dest; + short a, r, g, b; + int x, y; + float af, rf, gf, bf, *p1f, *_p1f, *destf; + bool do_rect, do_float; + + do_rect = (ibuf1->rect != NULL); + do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL); + + _p1 = (uchar *)ibuf1->rect; + dest = (uchar *)ibuf2->rect; + + _p1f = ibuf1->rect_float; + destf = ibuf2->rect_float; + + for (y = ibuf2->y; y > 0; y--) { + p1 = _p1; + p1f = _p1f; + for (x = ibuf2->x; x > 0; x--) { + if (do_rect) { + a = *(p1++); + b = *(p1++); + g = *(p1++); + r = *(p1++); + a += *(p1++); + b += *(p1++); + g += *(p1++); + r += *(p1++); + *(dest++) = a >> 1; + *(dest++) = b >> 1; + *(dest++) = g >> 1; + *(dest++) = r >> 1; + } + if (do_float) { + af = *(p1f++); + bf = *(p1f++); + gf = *(p1f++); + rf = *(p1f++); + af += *(p1f++); + bf += *(p1f++); + gf += *(p1f++); + rf += *(p1f++); + *(destf++) = 0.5f * af; + *(destf++) = 0.5f * bf; + *(destf++) = 0.5f * gf; + *(destf++) = 0.5f * rf; + } + } + if (do_rect) + _p1 += (ibuf1->x << 2); + if (do_float) + _p1f += (ibuf1->x << 2); + } } struct ImBuf *IMB_half_x(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; + struct ImBuf *ibuf2; - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL); + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) + return (NULL); - if (ibuf1->x <= 1) return(IMB_dupImBuf(ibuf1)); + if (ibuf1->x <= 1) + return (IMB_dupImBuf(ibuf1)); - ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags); - if (ibuf2 == NULL) return (NULL); + ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags); + if (ibuf2 == NULL) + return (NULL); - imb_half_x_no_alloc(ibuf2, ibuf1); + imb_half_x_no_alloc(ibuf2, ibuf1); - return (ibuf2); + return (ibuf2); } struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; - int *p1, *dest, i, col, do_rect, do_float; - float *p1f, *destf; - - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL); - - do_rect = (ibuf1->rect != NULL); - do_float = (ibuf1->rect_float != NULL); - - ibuf2 = IMB_allocImBuf(2 * ibuf1->x, ibuf1->y, ibuf1->planes, ibuf1->flags); - if (ibuf2 == NULL) return (NULL); - - p1 = (int *) ibuf1->rect; - dest = (int *) ibuf2->rect; - p1f = (float *)ibuf1->rect_float; - destf = (float *)ibuf2->rect_float; - - for (i = ibuf1->y * ibuf1->x; i > 0; i--) { - if (do_rect) { - col = *p1++; - *dest++ = col; - *dest++ = col; - } - if (do_float) { - destf[0] = destf[4] = p1f[0]; - destf[1] = destf[5] = p1f[1]; - destf[2] = destf[6] = p1f[2]; - destf[3] = destf[7] = p1f[3]; - destf += 8; - p1f += 4; - } - } - - return (ibuf2); + struct ImBuf *ibuf2; + int *p1, *dest, i, col, do_rect, do_float; + float *p1f, *destf; + + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) + return (NULL); + + do_rect = (ibuf1->rect != NULL); + do_float = (ibuf1->rect_float != NULL); + + ibuf2 = IMB_allocImBuf(2 * ibuf1->x, ibuf1->y, ibuf1->planes, ibuf1->flags); + if (ibuf2 == NULL) + return (NULL); + + p1 = (int *)ibuf1->rect; + dest = (int *)ibuf2->rect; + p1f = (float *)ibuf1->rect_float; + destf = (float *)ibuf2->rect_float; + + for (i = ibuf1->y * ibuf1->x; i > 0; i--) { + if (do_rect) { + col = *p1++; + *dest++ = col; + *dest++ = col; + } + if (do_float) { + destf[0] = destf[4] = p1f[0]; + destf[1] = destf[5] = p1f[1]; + destf[2] = destf[6] = p1f[2]; + destf[3] = destf[7] = p1f[3]; + destf += 8; + p1f += 4; + } + } + + return (ibuf2); } struct ImBuf *IMB_double_x(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; + struct ImBuf *ibuf2; - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL); + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) + return (NULL); - ibuf2 = IMB_double_fast_x(ibuf1); + ibuf2 = IMB_double_fast_x(ibuf1); - imb_filterx(ibuf2); - return (ibuf2); + imb_filterx(ibuf2); + return (ibuf2); } - static void imb_half_y_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) { - uchar *p1, *p2, *_p1, *dest; - short a, r, g, b; - int x, y; - int do_rect, do_float; - float af, rf, gf, bf, *p1f, *p2f, *_p1f, *destf; - - p1 = p2 = NULL; - p1f = p2f = NULL; - - do_rect = (ibuf1->rect != NULL); - do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL); - - _p1 = (uchar *) ibuf1->rect; - dest = (uchar *) ibuf2->rect; - _p1f = (float *) ibuf1->rect_float; - destf = (float *) ibuf2->rect_float; - - for (y = ibuf2->y; y > 0; y--) { - if (do_rect) { - p1 = _p1; - p2 = _p1 + (ibuf1->x << 2); - } - if (do_float) { - p1f = _p1f; - p2f = _p1f + (ibuf1->x << 2); - } - for (x = ibuf2->x; x > 0; x--) { - if (do_rect) { - a = *(p1++); - b = *(p1++); - g = *(p1++); - r = *(p1++); - a += *(p2++); - b += *(p2++); - g += *(p2++); - r += *(p2++); - *(dest++) = a >> 1; - *(dest++) = b >> 1; - *(dest++) = g >> 1; - *(dest++) = r >> 1; - } - if (do_float) { - af = *(p1f++); - bf = *(p1f++); - gf = *(p1f++); - rf = *(p1f++); - af += *(p2f++); - bf += *(p2f++); - gf += *(p2f++); - rf += *(p2f++); - *(destf++) = 0.5f * af; - *(destf++) = 0.5f * bf; - *(destf++) = 0.5f * gf; - *(destf++) = 0.5f * rf; - } - } - if (do_rect) _p1 += (ibuf1->x << 3); - if (do_float) _p1f += (ibuf1->x << 3); - } + uchar *p1, *p2, *_p1, *dest; + short a, r, g, b; + int x, y; + int do_rect, do_float; + float af, rf, gf, bf, *p1f, *p2f, *_p1f, *destf; + + p1 = p2 = NULL; + p1f = p2f = NULL; + + do_rect = (ibuf1->rect != NULL); + do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL); + + _p1 = (uchar *)ibuf1->rect; + dest = (uchar *)ibuf2->rect; + _p1f = (float *)ibuf1->rect_float; + destf = (float *)ibuf2->rect_float; + + for (y = ibuf2->y; y > 0; y--) { + if (do_rect) { + p1 = _p1; + p2 = _p1 + (ibuf1->x << 2); + } + if (do_float) { + p1f = _p1f; + p2f = _p1f + (ibuf1->x << 2); + } + for (x = ibuf2->x; x > 0; x--) { + if (do_rect) { + a = *(p1++); + b = *(p1++); + g = *(p1++); + r = *(p1++); + a += *(p2++); + b += *(p2++); + g += *(p2++); + r += *(p2++); + *(dest++) = a >> 1; + *(dest++) = b >> 1; + *(dest++) = g >> 1; + *(dest++) = r >> 1; + } + if (do_float) { + af = *(p1f++); + bf = *(p1f++); + gf = *(p1f++); + rf = *(p1f++); + af += *(p2f++); + bf += *(p2f++); + gf += *(p2f++); + rf += *(p2f++); + *(destf++) = 0.5f * af; + *(destf++) = 0.5f * bf; + *(destf++) = 0.5f * gf; + *(destf++) = 0.5f * rf; + } + } + if (do_rect) + _p1 += (ibuf1->x << 3); + if (do_float) + _p1f += (ibuf1->x << 3); + } } - struct ImBuf *IMB_half_y(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; + struct ImBuf *ibuf2; - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL); + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) + return (NULL); - if (ibuf1->y <= 1) return(IMB_dupImBuf(ibuf1)); + if (ibuf1->y <= 1) + return (IMB_dupImBuf(ibuf1)); - ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags); - if (ibuf2 == NULL) return (NULL); + ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags); + if (ibuf2 == NULL) + return (NULL); - imb_half_y_no_alloc(ibuf2, ibuf1); + imb_half_y_no_alloc(ibuf2, ibuf1); - return (ibuf2); + return (ibuf2); } - struct ImBuf *IMB_double_fast_y(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; - int *p1, *dest1, *dest2; - float *p1f, *dest1f, *dest2f; - int x, y; - int do_rect, do_float; - - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL); - - do_rect = (ibuf1->rect != NULL); - do_float = (ibuf1->rect_float != NULL); - - ibuf2 = IMB_allocImBuf(ibuf1->x, 2 * ibuf1->y, ibuf1->planes, ibuf1->flags); - if (ibuf2 == NULL) return (NULL); - - p1 = (int *) ibuf1->rect; - dest1 = (int *) ibuf2->rect; - p1f = (float *) ibuf1->rect_float; - dest1f = (float *) ibuf2->rect_float; - - for (y = ibuf1->y; y > 0; y--) { - if (do_rect) { - dest2 = dest1 + ibuf2->x; - for (x = ibuf2->x; x > 0; x--) *dest1++ = *dest2++ = *p1++; - dest1 = dest2; - } - if (do_float) { - dest2f = dest1f + (4 * ibuf2->x); - for (x = ibuf2->x * 4; x > 0; x--) *dest1f++ = *dest2f++ = *p1f++; - dest1f = dest2f; - } - } - - return (ibuf2); + struct ImBuf *ibuf2; + int *p1, *dest1, *dest2; + float *p1f, *dest1f, *dest2f; + int x, y; + int do_rect, do_float; + + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) + return (NULL); + + do_rect = (ibuf1->rect != NULL); + do_float = (ibuf1->rect_float != NULL); + + ibuf2 = IMB_allocImBuf(ibuf1->x, 2 * ibuf1->y, ibuf1->planes, ibuf1->flags); + if (ibuf2 == NULL) + return (NULL); + + p1 = (int *)ibuf1->rect; + dest1 = (int *)ibuf2->rect; + p1f = (float *)ibuf1->rect_float; + dest1f = (float *)ibuf2->rect_float; + + for (y = ibuf1->y; y > 0; y--) { + if (do_rect) { + dest2 = dest1 + ibuf2->x; + for (x = ibuf2->x; x > 0; x--) + *dest1++ = *dest2++ = *p1++; + dest1 = dest2; + } + if (do_float) { + dest2f = dest1f + (4 * ibuf2->x); + for (x = ibuf2->x * 4; x > 0; x--) + *dest1f++ = *dest2f++ = *p1f++; + dest1f = dest2f; + } + } + + return (ibuf2); } struct ImBuf *IMB_double_y(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; + struct ImBuf *ibuf2; - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL) return (NULL); + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL) + return (NULL); - ibuf2 = IMB_double_fast_y(ibuf1); + ibuf2 = IMB_double_fast_y(ibuf1); - IMB_filtery(ibuf2); - return (ibuf2); + IMB_filtery(ibuf2); + return (ibuf2); } /* pretty much specific functions which converts uchar <-> ushort but assumes * ushort range of 255*255 which is more convenient here */ -MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4], const unsigned char color[4]) +MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4], + const unsigned char color[4]) { - unsigned short alpha = color[3]; + unsigned short alpha = color[3]; - result[0] = color[0] * alpha; - result[1] = color[1] * alpha; - result[2] = color[2] * alpha; - result[3] = alpha * 256; + result[0] = color[0] * alpha; + result[1] = color[1] * alpha; + result[2] = color[2] * alpha; + result[3] = alpha * 256; } MINLINE void premul_ushort_to_straight_uchar(unsigned char *result, const unsigned short color[4]) { - if (color[3] <= 255) { - result[0] = unit_ushort_to_uchar(color[0]); - result[1] = unit_ushort_to_uchar(color[1]); - result[2] = unit_ushort_to_uchar(color[2]); - result[3] = unit_ushort_to_uchar(color[3]); - } - else { - unsigned short alpha = color[3] / 256; - - result[0] = unit_ushort_to_uchar((ushort)(color[0] / alpha * 256)); - result[1] = unit_ushort_to_uchar((ushort)(color[1] / alpha * 256)); - result[2] = unit_ushort_to_uchar((ushort)(color[2] / alpha * 256)); - result[3] = unit_ushort_to_uchar(color[3]); - } + if (color[3] <= 255) { + result[0] = unit_ushort_to_uchar(color[0]); + result[1] = unit_ushort_to_uchar(color[1]); + result[2] = unit_ushort_to_uchar(color[2]); + result[3] = unit_ushort_to_uchar(color[3]); + } + else { + unsigned short alpha = color[3] / 256; + + result[0] = unit_ushort_to_uchar((ushort)(color[0] / alpha * 256)); + result[1] = unit_ushort_to_uchar((ushort)(color[1] / alpha * 256)); + result[2] = unit_ushort_to_uchar((ushort)(color[2] / alpha * 256)); + result[3] = unit_ushort_to_uchar(color[3]); + } } /* result in ibuf2, scaling should be done correctly */ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) { - int x, y; - const short do_rect = (ibuf1->rect != NULL); - const short do_float = (ibuf1->rect_float != NULL) && (ibuf2->rect_float != NULL); - - if (do_rect && (ibuf2->rect == NULL)) { - imb_addrectImBuf(ibuf2); - } - - if (ibuf1->x <= 1) { - imb_half_y_no_alloc(ibuf2, ibuf1); - return; - } - if (ibuf1->y <= 1) { - imb_half_x_no_alloc(ibuf2, ibuf1); - return; - } - - if (do_rect) { - unsigned char *cp1, *cp2, *dest; - - cp1 = (unsigned char *) ibuf1->rect; - dest = (unsigned char *) ibuf2->rect; - - for (y = ibuf2->y; y > 0; y--) { - cp2 = cp1 + (ibuf1->x << 2); - for (x = ibuf2->x; x > 0; x--) { - unsigned short p1i[8], p2i[8], desti[4]; - - straight_uchar_to_premul_ushort(p1i, cp1); - straight_uchar_to_premul_ushort(p2i, cp2); - straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4); - straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4); - - desti[0] = ((unsigned int) p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2; - desti[1] = ((unsigned int) p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2; - desti[2] = ((unsigned int) p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2; - desti[3] = ((unsigned int) p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2; - - premul_ushort_to_straight_uchar(dest, desti); - - cp1 += 8; - cp2 += 8; - dest += 4; - } - cp1 = cp2; - if (ibuf1->x & 1) cp1 += 4; - } - } - - if (do_float) { - float *p1f, *p2f, *destf; - - p1f = ibuf1->rect_float; - destf = ibuf2->rect_float; - 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; - } - p1f = p2f; - if (ibuf1->x & 1) p1f += 4; - } - } + int x, y; + const short do_rect = (ibuf1->rect != NULL); + const short do_float = (ibuf1->rect_float != NULL) && (ibuf2->rect_float != NULL); + + if (do_rect && (ibuf2->rect == NULL)) { + imb_addrectImBuf(ibuf2); + } + + if (ibuf1->x <= 1) { + imb_half_y_no_alloc(ibuf2, ibuf1); + return; + } + if (ibuf1->y <= 1) { + imb_half_x_no_alloc(ibuf2, ibuf1); + return; + } + + if (do_rect) { + unsigned char *cp1, *cp2, *dest; + + cp1 = (unsigned char *)ibuf1->rect; + dest = (unsigned char *)ibuf2->rect; + + for (y = ibuf2->y; y > 0; y--) { + cp2 = cp1 + (ibuf1->x << 2); + for (x = ibuf2->x; x > 0; x--) { + unsigned short p1i[8], p2i[8], desti[4]; + + straight_uchar_to_premul_ushort(p1i, cp1); + straight_uchar_to_premul_ushort(p2i, cp2); + straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4); + straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4); + + desti[0] = ((unsigned int)p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2; + desti[1] = ((unsigned int)p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2; + desti[2] = ((unsigned int)p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2; + desti[3] = ((unsigned int)p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2; + + premul_ushort_to_straight_uchar(dest, desti); + + cp1 += 8; + cp2 += 8; + dest += 4; + } + cp1 = cp2; + if (ibuf1->x & 1) + cp1 += 4; + } + } + + if (do_float) { + float *p1f, *p2f, *destf; + + p1f = ibuf1->rect_float; + destf = ibuf2->rect_float; + 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; + } + p1f = p2f; + if (ibuf1->x & 1) + p1f += 4; + } + } } ImBuf *IMB_onehalf(struct ImBuf *ibuf1) { - struct ImBuf *ibuf2; + struct ImBuf *ibuf2; - if (ibuf1 == NULL) return (NULL); - if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) return (NULL); + if (ibuf1 == NULL) + return (NULL); + if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) + return (NULL); - if (ibuf1->x <= 1) return(IMB_half_y(ibuf1)); - if (ibuf1->y <= 1) return(IMB_half_x(ibuf1)); + if (ibuf1->x <= 1) + return (IMB_half_y(ibuf1)); + if (ibuf1->y <= 1) + return (IMB_half_x(ibuf1)); - ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags); - if (ibuf2 == NULL) return (NULL); + ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags); + if (ibuf2 == NULL) + return (NULL); - imb_onehalf_no_alloc(ibuf2, ibuf1); + imb_onehalf_no_alloc(ibuf2, ibuf1); - return (ibuf2); + return (ibuf2); } /* q_scale_linear_interpolation helper functions */ -static void enlarge_picture_byte( - unsigned char *src, unsigned char *dst, int src_width, - int src_height, int dst_width, int dst_height) +static void enlarge_picture_byte(unsigned char *src, + unsigned char *dst, + int src_width, + int src_height, + int dst_width, + int dst_height) { - double ratiox = (double) (dst_width - 1.0) / (double) (src_width - 1.001); - double ratioy = (double) (dst_height - 1.0) / (double) (src_height - 1.001); - uintptr_t x_src, dx_src, x_dst; - uintptr_t y_src, dy_src, y_dst; - - dx_src = 65536.0 / ratiox; - dy_src = 65536.0 / ratioy; - - y_src = 0; - for (y_dst = 0; y_dst < dst_height; y_dst++) { - unsigned char *line1 = src + (y_src >> 16) * 4 * src_width; - unsigned char *line2 = line1 + 4 * src_width; - uintptr_t weight1y = 65536 - (y_src & 0xffff); - uintptr_t weight2y = 65536 - weight1y; - - if ((y_src >> 16) == src_height - 1) { - line2 = line1; - } - - x_src = 0; - for (x_dst = 0; x_dst < dst_width; x_dst++) { - uintptr_t weight1x = 65536 - (x_src & 0xffff); - uintptr_t weight2x = 65536 - weight1x; - - unsigned long x = (x_src >> 16) * 4; - - *dst++ = ((((line1[x] * weight1y) >> 16) * weight1x) >> 16) + - ((((line2[x] * weight2y) >> 16) * weight1x) >> 16) + - ((((line1[4 + x] * weight1y) >> 16) * weight2x) >> 16) + - ((((line2[4 + x] * weight2y) >> 16) * weight2x) >> 16); - - *dst++ = ((((line1[x + 1] * weight1y) >> 16) * weight1x) >> 16) + - ((((line2[x + 1] * weight2y) >> 16) * weight1x) >> 16) + - ((((line1[4 + x + 1] * weight1y) >> 16) * weight2x) >> 16) + - ((((line2[4 + x + 1] * weight2y) >> 16) * weight2x) >> 16); - - *dst++ = ((((line1[x + 2] * weight1y) >> 16) * weight1x) >> 16) + - ((((line2[x + 2] * weight2y) >> 16) * weight1x) >> 16) + - ((((line1[4 + x + 2] * weight1y) >> 16) * weight2x) >> 16) + - ((((line2[4 + x + 2] * weight2y) >> 16) * weight2x) >> 16); - - *dst++ = ((((line1[x + 3] * weight1y) >> 16) * weight1x) >> 16) + - ((((line2[x + 3] * weight2y) >> 16) * weight1x) >> 16) + - ((((line1[4 + x + 3] * weight1y) >> 16) * weight2x) >> 16) + - ((((line2[4 + x + 3] * weight2y) >> 16) * weight2x) >> 16); - - x_src += dx_src; - } - y_src += dy_src; - } + double ratiox = (double)(dst_width - 1.0) / (double)(src_width - 1.001); + double ratioy = (double)(dst_height - 1.0) / (double)(src_height - 1.001); + uintptr_t x_src, dx_src, x_dst; + uintptr_t y_src, dy_src, y_dst; + + dx_src = 65536.0 / ratiox; + dy_src = 65536.0 / ratioy; + + y_src = 0; + for (y_dst = 0; y_dst < dst_height; y_dst++) { + unsigned char *line1 = src + (y_src >> 16) * 4 * src_width; + unsigned char *line2 = line1 + 4 * src_width; + uintptr_t weight1y = 65536 - (y_src & 0xffff); + uintptr_t weight2y = 65536 - weight1y; + + if ((y_src >> 16) == src_height - 1) { + line2 = line1; + } + + x_src = 0; + for (x_dst = 0; x_dst < dst_width; x_dst++) { + uintptr_t weight1x = 65536 - (x_src & 0xffff); + uintptr_t weight2x = 65536 - weight1x; + + unsigned long x = (x_src >> 16) * 4; + + *dst++ = ((((line1[x] * weight1y) >> 16) * weight1x) >> 16) + + ((((line2[x] * weight2y) >> 16) * weight1x) >> 16) + + ((((line1[4 + x] * weight1y) >> 16) * weight2x) >> 16) + + ((((line2[4 + x] * weight2y) >> 16) * weight2x) >> 16); + + *dst++ = ((((line1[x + 1] * weight1y) >> 16) * weight1x) >> 16) + + ((((line2[x + 1] * weight2y) >> 16) * weight1x) >> 16) + + ((((line1[4 + x + 1] * weight1y) >> 16) * weight2x) >> 16) + + ((((line2[4 + x + 1] * weight2y) >> 16) * weight2x) >> 16); + + *dst++ = ((((line1[x + 2] * weight1y) >> 16) * weight1x) >> 16) + + ((((line2[x + 2] * weight2y) >> 16) * weight1x) >> 16) + + ((((line1[4 + x + 2] * weight1y) >> 16) * weight2x) >> 16) + + ((((line2[4 + x + 2] * weight2y) >> 16) * weight2x) >> 16); + + *dst++ = ((((line1[x + 3] * weight1y) >> 16) * weight1x) >> 16) + + ((((line2[x + 3] * weight2y) >> 16) * weight1x) >> 16) + + ((((line1[4 + x + 3] * weight1y) >> 16) * weight2x) >> 16) + + ((((line2[4 + x + 3] * weight2y) >> 16) * weight2x) >> 16); + + x_src += dx_src; + } + y_src += dy_src; + } } struct scale_outpix_byte { - uintptr_t r; - uintptr_t g; - uintptr_t b; - uintptr_t a; + uintptr_t r; + uintptr_t g; + uintptr_t b; + uintptr_t a; - uintptr_t weight; + uintptr_t weight; }; -static void shrink_picture_byte( - unsigned char *src, unsigned char *dst, int src_width, - int src_height, int dst_width, int dst_height) +static void shrink_picture_byte(unsigned char *src, + unsigned char *dst, + int src_width, + int src_height, + int dst_width, + int dst_height) { - double ratiox = (double) (dst_width) / (double) (src_width); - double ratioy = (double) (dst_height) / (double) (src_height); - uintptr_t x_src, dx_dst, x_dst; - uintptr_t y_src, dy_dst, y_dst; - intptr_t y_counter; - unsigned char *dst_begin = dst; - - struct scale_outpix_byte *dst_line1 = NULL; - struct scale_outpix_byte *dst_line2 = NULL; - - dst_line1 = (struct scale_outpix_byte *) MEM_callocN( - (dst_width + 1) * sizeof(struct scale_outpix_byte), - "shrink_picture_byte 1"); - dst_line2 = (struct scale_outpix_byte *) MEM_callocN( - (dst_width + 1) * sizeof(struct scale_outpix_byte), - "shrink_picture_byte 2"); - - dx_dst = 65536.0 * ratiox; - dy_dst = 65536.0 * ratioy; - - y_dst = 0; - y_counter = 65536; - for (y_src = 0; y_src < src_height; y_src++) { - unsigned char *line = src + y_src * 4 * src_width; - uintptr_t weight1y = 65535 - (y_dst & 0xffff); - uintptr_t weight2y = 65535 - weight1y; - x_dst = 0; - for (x_src = 0; x_src < src_width; x_src++) { - uintptr_t weight1x = 65535 - (x_dst & 0xffff); - uintptr_t weight2x = 65535 - weight1x; - - uintptr_t x = x_dst >> 16; - - uintptr_t w; - - w = (weight1y * weight1x) >> 16; - - /* ensure correct rounding, without this you get ugly banding, or too low color values (ton) */ - dst_line1[x].r += (line[0] * w + 32767) >> 16; - dst_line1[x].g += (line[1] * w + 32767) >> 16; - dst_line1[x].b += (line[2] * w + 32767) >> 16; - dst_line1[x].a += (line[3] * w + 32767) >> 16; - dst_line1[x].weight += w; - - w = (weight2y * weight1x) >> 16; - - dst_line2[x].r += (line[0] * w + 32767) >> 16; - dst_line2[x].g += (line[1] * w + 32767) >> 16; - dst_line2[x].b += (line[2] * w + 32767) >> 16; - dst_line2[x].a += (line[3] * w + 32767) >> 16; - dst_line2[x].weight += w; - - w = (weight1y * weight2x) >> 16; - - dst_line1[x + 1].r += (line[0] * w + 32767) >> 16; - dst_line1[x + 1].g += (line[1] * w + 32767) >> 16; - dst_line1[x + 1].b += (line[2] * w + 32767) >> 16; - dst_line1[x + 1].a += (line[3] * w + 32767) >> 16; - dst_line1[x + 1].weight += w; - - w = (weight2y * weight2x) >> 16; - - dst_line2[x + 1].r += (line[0] * w + 32767) >> 16; - dst_line2[x + 1].g += (line[1] * w + 32767) >> 16; - dst_line2[x + 1].b += (line[2] * w + 32767) >> 16; - dst_line2[x + 1].a += (line[3] * w + 32767) >> 16; - dst_line2[x + 1].weight += w; - - x_dst += dx_dst; - line += 4; - } - - y_dst += dy_dst; - y_counter -= dy_dst; - if (y_counter < 0) { - int val; - uintptr_t x; - struct scale_outpix_byte *temp; - - y_counter += 65536; - - for (x = 0; x < dst_width; x++) { - uintptr_t f = 0x80000000UL / dst_line1[x].weight; - *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val; - *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val; - *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val; - *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val; - } - memset(dst_line1, 0, dst_width * - sizeof(struct scale_outpix_byte)); - temp = dst_line1; - dst_line1 = dst_line2; - dst_line2 = temp; - } - } - if (dst - dst_begin < dst_width * dst_height * 4) { - int val; - uintptr_t x; - for (x = 0; x < dst_width; x++) { - uintptr_t f = 0x80000000UL / dst_line1[x].weight; - *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val; - *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val; - *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val; - *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val; - } - } - MEM_freeN(dst_line1); - MEM_freeN(dst_line2); + double ratiox = (double)(dst_width) / (double)(src_width); + double ratioy = (double)(dst_height) / (double)(src_height); + uintptr_t x_src, dx_dst, x_dst; + uintptr_t y_src, dy_dst, y_dst; + intptr_t y_counter; + unsigned char *dst_begin = dst; + + struct scale_outpix_byte *dst_line1 = NULL; + struct scale_outpix_byte *dst_line2 = NULL; + + dst_line1 = (struct scale_outpix_byte *)MEM_callocN( + (dst_width + 1) * sizeof(struct scale_outpix_byte), "shrink_picture_byte 1"); + dst_line2 = (struct scale_outpix_byte *)MEM_callocN( + (dst_width + 1) * sizeof(struct scale_outpix_byte), "shrink_picture_byte 2"); + + dx_dst = 65536.0 * ratiox; + dy_dst = 65536.0 * ratioy; + + y_dst = 0; + y_counter = 65536; + for (y_src = 0; y_src < src_height; y_src++) { + unsigned char *line = src + y_src * 4 * src_width; + uintptr_t weight1y = 65535 - (y_dst & 0xffff); + uintptr_t weight2y = 65535 - weight1y; + x_dst = 0; + for (x_src = 0; x_src < src_width; x_src++) { + uintptr_t weight1x = 65535 - (x_dst & 0xffff); + uintptr_t weight2x = 65535 - weight1x; + + uintptr_t x = x_dst >> 16; + + uintptr_t w; + + w = (weight1y * weight1x) >> 16; + + /* ensure correct rounding, without this you get ugly banding, or too low color values (ton) */ + dst_line1[x].r += (line[0] * w + 32767) >> 16; + dst_line1[x].g += (line[1] * w + 32767) >> 16; + dst_line1[x].b += (line[2] * w + 32767) >> 16; + dst_line1[x].a += (line[3] * w + 32767) >> 16; + dst_line1[x].weight += w; + + w = (weight2y * weight1x) >> 16; + + dst_line2[x].r += (line[0] * w + 32767) >> 16; + dst_line2[x].g += (line[1] * w + 32767) >> 16; + dst_line2[x].b += (line[2] * w + 32767) >> 16; + dst_line2[x].a += (line[3] * w + 32767) >> 16; + dst_line2[x].weight += w; + + w = (weight1y * weight2x) >> 16; + + dst_line1[x + 1].r += (line[0] * w + 32767) >> 16; + dst_line1[x + 1].g += (line[1] * w + 32767) >> 16; + dst_line1[x + 1].b += (line[2] * w + 32767) >> 16; + dst_line1[x + 1].a += (line[3] * w + 32767) >> 16; + dst_line1[x + 1].weight += w; + + w = (weight2y * weight2x) >> 16; + + dst_line2[x + 1].r += (line[0] * w + 32767) >> 16; + dst_line2[x + 1].g += (line[1] * w + 32767) >> 16; + dst_line2[x + 1].b += (line[2] * w + 32767) >> 16; + dst_line2[x + 1].a += (line[3] * w + 32767) >> 16; + dst_line2[x + 1].weight += w; + + x_dst += dx_dst; + line += 4; + } + + y_dst += dy_dst; + y_counter -= dy_dst; + if (y_counter < 0) { + int val; + uintptr_t x; + struct scale_outpix_byte *temp; + + y_counter += 65536; + + for (x = 0; x < dst_width; x++) { + uintptr_t f = 0x80000000UL / dst_line1[x].weight; + *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val; + *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val; + *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val; + *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val; + } + memset(dst_line1, 0, dst_width * sizeof(struct scale_outpix_byte)); + temp = dst_line1; + dst_line1 = dst_line2; + dst_line2 = temp; + } + } + if (dst - dst_begin < dst_width * dst_height * 4) { + int val; + uintptr_t x; + for (x = 0; x < dst_width; x++) { + uintptr_t f = 0x80000000UL / dst_line1[x].weight; + *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val; + *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val; + *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val; + *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val; + } + } + MEM_freeN(dst_line1); + MEM_freeN(dst_line2); } - -static void q_scale_byte(unsigned char *in, unsigned char *out, int in_width, - int in_height, int dst_width, int dst_height) +static void q_scale_byte(unsigned char *in, + unsigned char *out, + int in_width, + int in_height, + int dst_width, + int dst_height) { - if (dst_width > in_width && dst_height > in_height) { - enlarge_picture_byte(in, out, in_width, in_height, - dst_width, dst_height); - } - else if (dst_width < in_width && dst_height < in_height) { - shrink_picture_byte(in, out, in_width, in_height, - dst_width, dst_height); - } + if (dst_width > in_width && dst_height > in_height) { + enlarge_picture_byte(in, out, in_width, in_height, dst_width, dst_height); + } + else if (dst_width < in_width && dst_height < in_height) { + shrink_picture_byte(in, out, in_width, in_height, dst_width, dst_height); + } } static void enlarge_picture_float( - float *src, float *dst, int src_width, - int src_height, int dst_width, int dst_height) + float *src, float *dst, int src_width, int src_height, int dst_width, int dst_height) { - double ratiox = (double) (dst_width - 1.0) / (double) (src_width - 1.001); - double ratioy = (double) (dst_height - 1.0) / (double) (src_height - 1.001); - uintptr_t x_dst; - uintptr_t y_dst; - double x_src, dx_src; - double y_src, dy_src; - - dx_src = 1.0 / ratiox; - dy_src = 1.0 / ratioy; - - y_src = 0; - for (y_dst = 0; y_dst < dst_height; y_dst++) { - float *line1 = src + ((int) y_src) * 4 * src_width; - const float *line2 = line1 + 4 * src_width; - const float weight1y = (float)(1.0 - (y_src - (int) y_src)); - const float weight2y = 1.0f - weight1y; - - if ((int) y_src == src_height - 1) { - line2 = line1; - } - - x_src = 0; - for (x_dst = 0; x_dst < dst_width; x_dst++) { - const float weight1x = (float)(1.0 - (x_src - (int) x_src)); - const float weight2x = (float)(1.0f - weight1x); - - const float w11 = weight1y * weight1x; - const float w21 = weight2y * weight1x; - const float w12 = weight1y * weight2x; - const float w22 = weight2y * weight2x; - - uintptr_t x = ((int) x_src) * 4; - - *dst++ = line1[x] * w11 + - line2[x] * w21 + - line1[4 + x] * w12 + - line2[4 + x] * w22; - - *dst++ = line1[x + 1] * w11 + - line2[x + 1] * w21 + - line1[4 + x + 1] * w12 + - line2[4 + x + 1] * w22; - - *dst++ = line1[x + 2] * w11 + - line2[x + 2] * w21 + - line1[4 + x + 2] * w12 + - line2[4 + x + 2] * w22; - - *dst++ = line1[x + 3] * w11 + - line2[x + 3] * w21 + - line1[4 + x + 3] * w12 + - line2[4 + x + 3] * w22; - - x_src += dx_src; - } - y_src += dy_src; - } + double ratiox = (double)(dst_width - 1.0) / (double)(src_width - 1.001); + double ratioy = (double)(dst_height - 1.0) / (double)(src_height - 1.001); + uintptr_t x_dst; + uintptr_t y_dst; + double x_src, dx_src; + double y_src, dy_src; + + dx_src = 1.0 / ratiox; + dy_src = 1.0 / ratioy; + + y_src = 0; + for (y_dst = 0; y_dst < dst_height; y_dst++) { + float *line1 = src + ((int)y_src) * 4 * src_width; + const float *line2 = line1 + 4 * src_width; + const float weight1y = (float)(1.0 - (y_src - (int)y_src)); + const float weight2y = 1.0f - weight1y; + + if ((int)y_src == src_height - 1) { + line2 = line1; + } + + x_src = 0; + for (x_dst = 0; x_dst < dst_width; x_dst++) { + const float weight1x = (float)(1.0 - (x_src - (int)x_src)); + const float weight2x = (float)(1.0f - weight1x); + + const float w11 = weight1y * weight1x; + const float w21 = weight2y * weight1x; + const float w12 = weight1y * weight2x; + const float w22 = weight2y * weight2x; + + uintptr_t x = ((int)x_src) * 4; + + *dst++ = line1[x] * w11 + line2[x] * w21 + line1[4 + x] * w12 + line2[4 + x] * w22; + + *dst++ = line1[x + 1] * w11 + line2[x + 1] * w21 + line1[4 + x + 1] * w12 + + line2[4 + x + 1] * w22; + + *dst++ = line1[x + 2] * w11 + line2[x + 2] * w21 + line1[4 + x + 2] * w12 + + line2[4 + x + 2] * w22; + + *dst++ = line1[x + 3] * w11 + line2[x + 3] * w21 + line1[4 + x + 3] * w12 + + line2[4 + x + 3] * w22; + + x_src += dx_src; + } + y_src += dy_src; + } } struct scale_outpix_float { - float r; - float g; - float b; - float a; + float r; + float g; + float b; + float a; - float weight; + float weight; }; static void shrink_picture_float( - const float *src, float *dst, int src_width, - int src_height, int dst_width, int dst_height) + const float *src, float *dst, int src_width, int src_height, int dst_width, int dst_height) { - double ratiox = (double) (dst_width) / (double) (src_width); - double ratioy = (double) (dst_height) / (double) (src_height); - uintptr_t x_src; - uintptr_t y_src; - float dx_dst, x_dst; - float dy_dst, y_dst; - float y_counter; - const float *dst_begin = dst; - - struct scale_outpix_float *dst_line1; - struct scale_outpix_float *dst_line2; - - dst_line1 = (struct scale_outpix_float *) MEM_callocN( - (dst_width + 1) * sizeof(struct scale_outpix_float), - "shrink_picture_float 1"); - dst_line2 = (struct scale_outpix_float *) MEM_callocN( - (dst_width + 1) * sizeof(struct scale_outpix_float), - "shrink_picture_float 2"); - - dx_dst = ratiox; - dy_dst = ratioy; - - y_dst = 0; - y_counter = 1.0; - for (y_src = 0; y_src < src_height; y_src++) { - const float *line = src + y_src * 4 * src_width; - uintptr_t weight1y = 1.0f - (y_dst - (int) y_dst); - uintptr_t weight2y = 1.0f - weight1y; - x_dst = 0; - for (x_src = 0; x_src < src_width; x_src++) { - uintptr_t weight1x = 1.0f - (x_dst - (int) x_dst); - uintptr_t weight2x = 1.0f - weight1x; - - uintptr_t x = (int) x_dst; - - float w; - - w = weight1y * weight1x; - - dst_line1[x].r += line[0] * w; - dst_line1[x].g += line[1] * w; - dst_line1[x].b += line[2] * w; - dst_line1[x].a += line[3] * w; - dst_line1[x].weight += w; - - w = weight2y * weight1x; - - dst_line2[x].r += line[0] * w; - dst_line2[x].g += line[1] * w; - dst_line2[x].b += line[2] * w; - dst_line2[x].a += line[3] * w; - dst_line2[x].weight += w; - - w = weight1y * weight2x; - - dst_line1[x + 1].r += line[0] * w; - dst_line1[x + 1].g += line[1] * w; - dst_line1[x + 1].b += line[2] * w; - dst_line1[x + 1].a += line[3] * w; - dst_line1[x + 1].weight += w; - - w = weight2y * weight2x; - - dst_line2[x + 1].r += line[0] * w; - dst_line2[x + 1].g += line[1] * w; - dst_line2[x + 1].b += line[2] * w; - dst_line2[x + 1].a += line[3] * w; - dst_line2[x + 1].weight += w; - - x_dst += dx_dst; - line += 4; - } - - y_dst += dy_dst; - y_counter -= dy_dst; - if (y_counter < 0) { - uintptr_t x; - struct scale_outpix_float *temp; - - y_counter += 1.0f; - - for (x = 0; x < dst_width; x++) { - float f = 1.0f / dst_line1[x].weight; - *dst++ = dst_line1[x].r * f; - *dst++ = dst_line1[x].g * f; - *dst++ = dst_line1[x].b * f; - *dst++ = dst_line1[x].a * f; - } - memset(dst_line1, 0, dst_width * - sizeof(struct scale_outpix_float)); - temp = dst_line1; - dst_line1 = dst_line2; - dst_line2 = temp; - } - } - if (dst - dst_begin < dst_width * dst_height * 4) { - uintptr_t x; - for (x = 0; x < dst_width; x++) { - float f = 1.0f / dst_line1[x].weight; - *dst++ = dst_line1[x].r * f; - *dst++ = dst_line1[x].g * f; - *dst++ = dst_line1[x].b * f; - *dst++ = dst_line1[x].a * f; - } - } - MEM_freeN(dst_line1); - MEM_freeN(dst_line2); + double ratiox = (double)(dst_width) / (double)(src_width); + double ratioy = (double)(dst_height) / (double)(src_height); + uintptr_t x_src; + uintptr_t y_src; + float dx_dst, x_dst; + float dy_dst, y_dst; + float y_counter; + const float *dst_begin = dst; + + struct scale_outpix_float *dst_line1; + struct scale_outpix_float *dst_line2; + + dst_line1 = (struct scale_outpix_float *)MEM_callocN( + (dst_width + 1) * sizeof(struct scale_outpix_float), "shrink_picture_float 1"); + dst_line2 = (struct scale_outpix_float *)MEM_callocN( + (dst_width + 1) * sizeof(struct scale_outpix_float), "shrink_picture_float 2"); + + dx_dst = ratiox; + dy_dst = ratioy; + + y_dst = 0; + y_counter = 1.0; + for (y_src = 0; y_src < src_height; y_src++) { + const float *line = src + y_src * 4 * src_width; + uintptr_t weight1y = 1.0f - (y_dst - (int)y_dst); + uintptr_t weight2y = 1.0f - weight1y; + x_dst = 0; + for (x_src = 0; x_src < src_width; x_src++) { + uintptr_t weight1x = 1.0f - (x_dst - (int)x_dst); + uintptr_t weight2x = 1.0f - weight1x; + + uintptr_t x = (int)x_dst; + + float w; + + w = weight1y * weight1x; + + dst_line1[x].r += line[0] * w; + dst_line1[x].g += line[1] * w; + dst_line1[x].b += line[2] * w; + dst_line1[x].a += line[3] * w; + dst_line1[x].weight += w; + + w = weight2y * weight1x; + + dst_line2[x].r += line[0] * w; + dst_line2[x].g += line[1] * w; + dst_line2[x].b += line[2] * w; + dst_line2[x].a += line[3] * w; + dst_line2[x].weight += w; + + w = weight1y * weight2x; + + dst_line1[x + 1].r += line[0] * w; + dst_line1[x + 1].g += line[1] * w; + dst_line1[x + 1].b += line[2] * w; + dst_line1[x + 1].a += line[3] * w; + dst_line1[x + 1].weight += w; + + w = weight2y * weight2x; + + dst_line2[x + 1].r += line[0] * w; + dst_line2[x + 1].g += line[1] * w; + dst_line2[x + 1].b += line[2] * w; + dst_line2[x + 1].a += line[3] * w; + dst_line2[x + 1].weight += w; + + x_dst += dx_dst; + line += 4; + } + + y_dst += dy_dst; + y_counter -= dy_dst; + if (y_counter < 0) { + uintptr_t x; + struct scale_outpix_float *temp; + + y_counter += 1.0f; + + for (x = 0; x < dst_width; x++) { + float f = 1.0f / dst_line1[x].weight; + *dst++ = dst_line1[x].r * f; + *dst++ = dst_line1[x].g * f; + *dst++ = dst_line1[x].b * f; + *dst++ = dst_line1[x].a * f; + } + memset(dst_line1, 0, dst_width * sizeof(struct scale_outpix_float)); + temp = dst_line1; + dst_line1 = dst_line2; + dst_line2 = temp; + } + } + if (dst - dst_begin < dst_width * dst_height * 4) { + uintptr_t x; + for (x = 0; x < dst_width; x++) { + float f = 1.0f / dst_line1[x].weight; + *dst++ = dst_line1[x].r * f; + *dst++ = dst_line1[x].g * f; + *dst++ = dst_line1[x].b * f; + *dst++ = dst_line1[x].a * f; + } + } + MEM_freeN(dst_line1); + MEM_freeN(dst_line2); } - -static void q_scale_float(float *in, float *out, int in_width, - int in_height, int dst_width, int dst_height) +static void q_scale_float( + float *in, float *out, int in_width, int in_height, int dst_width, int dst_height) { - if (dst_width > in_width && dst_height > in_height) { - enlarge_picture_float(in, out, in_width, in_height, - dst_width, dst_height); - } - else if (dst_width < in_width && dst_height < in_height) { - shrink_picture_float(in, out, in_width, in_height, - dst_width, dst_height); - } + if (dst_width > in_width && dst_height > in_height) { + enlarge_picture_float(in, out, in_width, in_height, dst_width, dst_height); + } + else if (dst_width < in_width && dst_height < in_height) { + shrink_picture_float(in, out, in_width, in_height, dst_width, dst_height); + } } /** @@ -832,708 +847,724 @@ static void q_scale_float(float *in, float *out, int in_width, * * NOTE: disabled, due to unacceptable inaccuracy and quality loss, see bug #18609 (ton) */ -static bool q_scale_linear_interpolation( - struct ImBuf *ibuf, int newx, int newy) +static bool q_scale_linear_interpolation(struct ImBuf *ibuf, int newx, int newy) { - if ((newx >= ibuf->x && newy <= ibuf->y) || - (newx <= ibuf->x && newy >= ibuf->y)) - { - return false; - } - - if (ibuf->rect) { - unsigned char *newrect = - MEM_mallocN(newx * newy * sizeof(int), "q_scale rect"); - q_scale_byte((unsigned char *)ibuf->rect, newrect, ibuf->x, ibuf->y, - newx, newy); - - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = (unsigned int *) newrect; - } - if (ibuf->rect_float) { - float *newrect = - MEM_mallocN(newx * newy * 4 * sizeof(float), - "q_scale rectfloat"); - q_scale_float(ibuf->rect_float, newrect, ibuf->x, ibuf->y, - newx, newy); - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = newrect; - } - ibuf->x = newx; - ibuf->y = newy; - - return true; + if ((newx >= ibuf->x && newy <= ibuf->y) || (newx <= ibuf->x && newy >= ibuf->y)) { + return false; + } + + if (ibuf->rect) { + unsigned char *newrect = MEM_mallocN(newx * newy * sizeof(int), "q_scale rect"); + q_scale_byte((unsigned char *)ibuf->rect, newrect, ibuf->x, ibuf->y, newx, newy); + + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *)newrect; + } + if (ibuf->rect_float) { + float *newrect = MEM_mallocN(newx * newy * 4 * sizeof(float), "q_scale rectfloat"); + q_scale_float(ibuf->rect_float, newrect, ibuf->x, ibuf->y, newx, newy); + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = newrect; + } + ibuf->x = newx; + ibuf->y = newy; + + return true; } static ImBuf *scaledownx(struct ImBuf *ibuf, int newx) { - const int do_rect = (ibuf->rect != NULL); - const int do_float = (ibuf->rect_float != NULL); - const size_t rect_size = ibuf->x * ibuf->y * 4; - - uchar *rect, *_newrect, *newrect; - float *rectf, *_newrectf, *newrectf; - float sample, add, val[4], nval[4], valf[4], nvalf[4]; - int x, y; - - rectf = _newrectf = newrectf = NULL; - rect = _newrect = newrect = NULL; - nval[0] = nval[1] = nval[2] = nval[3] = 0.0f; - nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f; - - if (!do_rect && !do_float) return (ibuf); - - if (do_rect) { - _newrect = MEM_mallocN(newx * ibuf->y * sizeof(uchar) * 4, "scaledownx"); - if (_newrect == NULL) return(ibuf); - } - if (do_float) { - _newrectf = MEM_mallocN(newx * ibuf->y * sizeof(float) * 4, "scaledownxf"); - if (_newrectf == NULL) { - if (_newrect) MEM_freeN(_newrect); - return(ibuf); - } - } - - add = (ibuf->x - 0.01) / newx; - - if (do_rect) { - rect = (uchar *) ibuf->rect; - newrect = _newrect; - } - if (do_float) { - rectf = ibuf->rect_float; - newrectf = _newrectf; - } - - for (y = ibuf->y; y > 0; y--) { - sample = 0.0f; - val[0] = val[1] = val[2] = val[3] = 0.0f; - valf[0] = valf[1] = valf[2] = valf[3] = 0.0f; - - for (x = newx; x > 0; x--) { - if (do_rect) { - nval[0] = -val[0] * sample; - nval[1] = -val[1] * sample; - nval[2] = -val[2] * sample; - nval[3] = -val[3] * sample; - } - if (do_float) { - nvalf[0] = -valf[0] * sample; - nvalf[1] = -valf[1] * sample; - nvalf[2] = -valf[2] * sample; - nvalf[3] = -valf[3] * sample; - } - - sample += add; - - while (sample >= 1.0f) { - sample -= 1.0f; - - if (do_rect) { - nval[0] += rect[0]; - nval[1] += rect[1]; - nval[2] += rect[2]; - nval[3] += rect[3]; - rect += 4; - } - if (do_float) { - nvalf[0] += rectf[0]; - nvalf[1] += rectf[1]; - nvalf[2] += rectf[2]; - nvalf[3] += rectf[3]; - rectf += 4; - } - } - - if (do_rect) { - val[0] = rect[0]; val[1] = rect[1]; val[2] = rect[2]; val[3] = rect[3]; - rect += 4; - - newrect[0] = ((nval[0] + sample * val[0]) / add + 0.5f); - newrect[1] = ((nval[1] + sample * val[1]) / add + 0.5f); - newrect[2] = ((nval[2] + sample * val[2]) / add + 0.5f); - newrect[3] = ((nval[3] + sample * val[3]) / add + 0.5f); - - newrect += 4; - } - if (do_float) { - - valf[0] = rectf[0]; valf[1] = rectf[1]; valf[2] = rectf[2]; valf[3] = rectf[3]; - rectf += 4; - - newrectf[0] = ((nvalf[0] + sample * valf[0]) / add); - newrectf[1] = ((nvalf[1] + sample * valf[1]) / add); - newrectf[2] = ((nvalf[2] + sample * valf[2]) / add); - newrectf[3] = ((nvalf[3] + sample * valf[3]) / add); - - newrectf += 4; - } - - sample -= 1.0f; - } - } - - if (do_rect) { - // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); - BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug [#26502] */ - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = (unsigned int *) _newrect; - } - if (do_float) { - // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); - BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug [#26502] */ - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = _newrectf; - } - (void)rect_size; /* UNUSED in release builds */ - - ibuf->x = newx; - return(ibuf); + const int do_rect = (ibuf->rect != NULL); + const int do_float = (ibuf->rect_float != NULL); + const size_t rect_size = ibuf->x * ibuf->y * 4; + + uchar *rect, *_newrect, *newrect; + float *rectf, *_newrectf, *newrectf; + float sample, add, val[4], nval[4], valf[4], nvalf[4]; + int x, y; + + rectf = _newrectf = newrectf = NULL; + rect = _newrect = newrect = NULL; + nval[0] = nval[1] = nval[2] = nval[3] = 0.0f; + nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f; + + if (!do_rect && !do_float) + return (ibuf); + + if (do_rect) { + _newrect = MEM_mallocN(newx * ibuf->y * sizeof(uchar) * 4, "scaledownx"); + if (_newrect == NULL) + return (ibuf); + } + if (do_float) { + _newrectf = MEM_mallocN(newx * ibuf->y * sizeof(float) * 4, "scaledownxf"); + if (_newrectf == NULL) { + if (_newrect) + MEM_freeN(_newrect); + return (ibuf); + } + } + + add = (ibuf->x - 0.01) / newx; + + if (do_rect) { + rect = (uchar *)ibuf->rect; + newrect = _newrect; + } + if (do_float) { + rectf = ibuf->rect_float; + newrectf = _newrectf; + } + + for (y = ibuf->y; y > 0; y--) { + sample = 0.0f; + val[0] = val[1] = val[2] = val[3] = 0.0f; + valf[0] = valf[1] = valf[2] = valf[3] = 0.0f; + + for (x = newx; x > 0; x--) { + if (do_rect) { + nval[0] = -val[0] * sample; + nval[1] = -val[1] * sample; + nval[2] = -val[2] * sample; + nval[3] = -val[3] * sample; + } + if (do_float) { + nvalf[0] = -valf[0] * sample; + nvalf[1] = -valf[1] * sample; + nvalf[2] = -valf[2] * sample; + nvalf[3] = -valf[3] * sample; + } + + sample += add; + + while (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + nval[0] += rect[0]; + nval[1] += rect[1]; + nval[2] += rect[2]; + nval[3] += rect[3]; + rect += 4; + } + if (do_float) { + nvalf[0] += rectf[0]; + nvalf[1] += rectf[1]; + nvalf[2] += rectf[2]; + nvalf[3] += rectf[3]; + rectf += 4; + } + } + + if (do_rect) { + val[0] = rect[0]; + val[1] = rect[1]; + val[2] = rect[2]; + val[3] = rect[3]; + rect += 4; + + newrect[0] = ((nval[0] + sample * val[0]) / add + 0.5f); + newrect[1] = ((nval[1] + sample * val[1]) / add + 0.5f); + newrect[2] = ((nval[2] + sample * val[2]) / add + 0.5f); + newrect[3] = ((nval[3] + sample * val[3]) / add + 0.5f); + + newrect += 4; + } + if (do_float) { + + valf[0] = rectf[0]; + valf[1] = rectf[1]; + valf[2] = rectf[2]; + valf[3] = rectf[3]; + rectf += 4; + + newrectf[0] = ((nvalf[0] + sample * valf[0]) / add); + newrectf[1] = ((nvalf[1] + sample * valf[1]) / add); + newrectf[2] = ((nvalf[2] + sample * valf[2]) / add); + newrectf[3] = ((nvalf[3] + sample * valf[3]) / add); + + newrectf += 4; + } + + sample -= 1.0f; + } + } + + if (do_rect) { + // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); + BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug [#26502] */ + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *)_newrect; + } + if (do_float) { + // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); + BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug [#26502] */ + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = _newrectf; + } + (void)rect_size; /* UNUSED in release builds */ + + ibuf->x = newx; + return (ibuf); } - static ImBuf *scaledowny(struct ImBuf *ibuf, int newy) { - const int do_rect = (ibuf->rect != NULL); - const int do_float = (ibuf->rect_float != NULL); - const size_t rect_size = ibuf->x * ibuf->y * 4; - - uchar *rect, *_newrect, *newrect; - float *rectf, *_newrectf, *newrectf; - float sample, add, val[4], nval[4], valf[4], nvalf[4]; - int x, y, skipx; - - rectf = _newrectf = newrectf = NULL; - rect = _newrect = newrect = NULL; - nval[0] = nval[1] = nval[2] = nval[3] = 0.0f; - nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f; - - if (!do_rect && !do_float) return (ibuf); - - if (do_rect) { - _newrect = MEM_mallocN(newy * ibuf->x * sizeof(uchar) * 4, "scaledowny"); - if (_newrect == NULL) return(ibuf); - } - if (do_float) { - _newrectf = MEM_mallocN(newy * ibuf->x * sizeof(float) * 4, "scaledownyf"); - if (_newrectf == NULL) { - if (_newrect) MEM_freeN(_newrect); - return(ibuf); - } - } - - add = (ibuf->y - 0.01) / newy; - skipx = 4 * ibuf->x; - - for (x = skipx - 4; x >= 0; x -= 4) { - if (do_rect) { - rect = ((uchar *) ibuf->rect) + x; - newrect = _newrect + x; - } - if (do_float) { - rectf = ibuf->rect_float + x; - newrectf = _newrectf + x; - } - - sample = 0.0f; - val[0] = val[1] = val[2] = val[3] = 0.0f; - valf[0] = valf[1] = valf[2] = valf[3] = 0.0f; - - for (y = newy; y > 0; y--) { - if (do_rect) { - nval[0] = -val[0] * sample; - nval[1] = -val[1] * sample; - nval[2] = -val[2] * sample; - nval[3] = -val[3] * sample; - } - if (do_float) { - nvalf[0] = -valf[0] * sample; - nvalf[1] = -valf[1] * sample; - nvalf[2] = -valf[2] * sample; - nvalf[3] = -valf[3] * sample; - } - - sample += add; - - while (sample >= 1.0f) { - sample -= 1.0f; - - if (do_rect) { - nval[0] += rect[0]; - nval[1] += rect[1]; - nval[2] += rect[2]; - nval[3] += rect[3]; - rect += skipx; - } - if (do_float) { - nvalf[0] += rectf[0]; - nvalf[1] += rectf[1]; - nvalf[2] += rectf[2]; - nvalf[3] += rectf[3]; - rectf += skipx; - } - } - - if (do_rect) { - val[0] = rect[0]; val[1] = rect[1]; val[2] = rect[2]; val[3] = rect[3]; - rect += skipx; - - newrect[0] = ((nval[0] + sample * val[0]) / add + 0.5f); - newrect[1] = ((nval[1] + sample * val[1]) / add + 0.5f); - newrect[2] = ((nval[2] + sample * val[2]) / add + 0.5f); - newrect[3] = ((nval[3] + sample * val[3]) / add + 0.5f); - - newrect += skipx; - } - if (do_float) { - - valf[0] = rectf[0]; valf[1] = rectf[1]; valf[2] = rectf[2]; valf[3] = rectf[3]; - rectf += skipx; - - newrectf[0] = ((nvalf[0] + sample * valf[0]) / add); - newrectf[1] = ((nvalf[1] + sample * valf[1]) / add); - newrectf[2] = ((nvalf[2] + sample * valf[2]) / add); - newrectf[3] = ((nvalf[3] + sample * valf[3]) / add); - - newrectf += skipx; - } - - sample -= 1.0f; - } - } - - if (do_rect) { - // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); - BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug [#26502] */ - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = (unsigned int *) _newrect; - } - if (do_float) { - // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); - BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug [#26502] */ - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = (float *) _newrectf; - } - (void)rect_size; /* UNUSED in release builds */ - - ibuf->y = newy; - return(ibuf); + const int do_rect = (ibuf->rect != NULL); + const int do_float = (ibuf->rect_float != NULL); + const size_t rect_size = ibuf->x * ibuf->y * 4; + + uchar *rect, *_newrect, *newrect; + float *rectf, *_newrectf, *newrectf; + float sample, add, val[4], nval[4], valf[4], nvalf[4]; + int x, y, skipx; + + rectf = _newrectf = newrectf = NULL; + rect = _newrect = newrect = NULL; + nval[0] = nval[1] = nval[2] = nval[3] = 0.0f; + nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f; + + if (!do_rect && !do_float) + return (ibuf); + + if (do_rect) { + _newrect = MEM_mallocN(newy * ibuf->x * sizeof(uchar) * 4, "scaledowny"); + if (_newrect == NULL) + return (ibuf); + } + if (do_float) { + _newrectf = MEM_mallocN(newy * ibuf->x * sizeof(float) * 4, "scaledownyf"); + if (_newrectf == NULL) { + if (_newrect) + MEM_freeN(_newrect); + return (ibuf); + } + } + + add = (ibuf->y - 0.01) / newy; + skipx = 4 * ibuf->x; + + for (x = skipx - 4; x >= 0; x -= 4) { + if (do_rect) { + rect = ((uchar *)ibuf->rect) + x; + newrect = _newrect + x; + } + if (do_float) { + rectf = ibuf->rect_float + x; + newrectf = _newrectf + x; + } + + sample = 0.0f; + val[0] = val[1] = val[2] = val[3] = 0.0f; + valf[0] = valf[1] = valf[2] = valf[3] = 0.0f; + + for (y = newy; y > 0; y--) { + if (do_rect) { + nval[0] = -val[0] * sample; + nval[1] = -val[1] * sample; + nval[2] = -val[2] * sample; + nval[3] = -val[3] * sample; + } + if (do_float) { + nvalf[0] = -valf[0] * sample; + nvalf[1] = -valf[1] * sample; + nvalf[2] = -valf[2] * sample; + nvalf[3] = -valf[3] * sample; + } + + sample += add; + + while (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + nval[0] += rect[0]; + nval[1] += rect[1]; + nval[2] += rect[2]; + nval[3] += rect[3]; + rect += skipx; + } + if (do_float) { + nvalf[0] += rectf[0]; + nvalf[1] += rectf[1]; + nvalf[2] += rectf[2]; + nvalf[3] += rectf[3]; + rectf += skipx; + } + } + + if (do_rect) { + val[0] = rect[0]; + val[1] = rect[1]; + val[2] = rect[2]; + val[3] = rect[3]; + rect += skipx; + + newrect[0] = ((nval[0] + sample * val[0]) / add + 0.5f); + newrect[1] = ((nval[1] + sample * val[1]) / add + 0.5f); + newrect[2] = ((nval[2] + sample * val[2]) / add + 0.5f); + newrect[3] = ((nval[3] + sample * val[3]) / add + 0.5f); + + newrect += skipx; + } + if (do_float) { + + valf[0] = rectf[0]; + valf[1] = rectf[1]; + valf[2] = rectf[2]; + valf[3] = rectf[3]; + rectf += skipx; + + newrectf[0] = ((nvalf[0] + sample * valf[0]) / add); + newrectf[1] = ((nvalf[1] + sample * valf[1]) / add); + newrectf[2] = ((nvalf[2] + sample * valf[2]) / add); + newrectf[3] = ((nvalf[3] + sample * valf[3]) / add); + + newrectf += skipx; + } + + sample -= 1.0f; + } + } + + if (do_rect) { + // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); + BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug [#26502] */ + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *)_newrect; + } + if (do_float) { + // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); + BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug [#26502] */ + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = (float *)_newrectf; + } + (void)rect_size; /* UNUSED in release builds */ + + ibuf->y = newy; + return (ibuf); } - static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) { - uchar *rect, *_newrect = NULL, *newrect; - float *rectf, *_newrectf = NULL, *newrectf; - float sample, add; - float val_a, nval_a, diff_a; - float val_b, nval_b, diff_b; - float val_g, nval_g, diff_g; - float val_r, nval_r, diff_r; - float val_af, nval_af, diff_af; - float val_bf, nval_bf, diff_bf; - float val_gf, nval_gf, diff_gf; - float val_rf, nval_rf, diff_rf; - int x, y; - bool do_rect = false, do_float = false; - - val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; - val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; - val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; - val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; - if (ibuf == NULL) return(NULL); - if (ibuf->rect == NULL && ibuf->rect_float == NULL) return (ibuf); - - if (ibuf->rect) { - do_rect = true; - _newrect = MEM_mallocN(newx * ibuf->y * sizeof(int), "scaleupx"); - if (_newrect == NULL) return(ibuf); - } - if (ibuf->rect_float) { - do_float = true; - _newrectf = MEM_mallocN(newx * ibuf->y * sizeof(float) * 4, "scaleupxf"); - if (_newrectf == NULL) { - if (_newrect) MEM_freeN(_newrect); - return(ibuf); - } - } - - add = (ibuf->x - 1.001) / (newx - 1.0); - - rect = (uchar *) ibuf->rect; - rectf = (float *) ibuf->rect_float; - newrect = _newrect; - newrectf = _newrectf; - - for (y = ibuf->y; y > 0; y--) { - - sample = 0; - - if (do_rect) { - val_a = rect[0]; - nval_a = rect[4]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = rect[1]; - nval_b = rect[5]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = rect[2]; - nval_g = rect[6]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = rect[3]; - nval_r = rect[7]; - diff_r = nval_r - val_r; - val_r += 0.5f; - - rect += 8; - } - if (do_float) { - val_af = rectf[0]; - nval_af = rectf[4]; - diff_af = nval_af - val_af; - - val_bf = rectf[1]; - nval_bf = rectf[5]; - diff_bf = nval_bf - val_bf; - - val_gf = rectf[2]; - nval_gf = rectf[6]; - diff_gf = nval_gf - val_gf; - - val_rf = rectf[3]; - nval_rf = rectf[7]; - diff_rf = nval_rf - val_rf; - - rectf += 8; - } - for (x = newx; x > 0; x--) { - if (sample >= 1.0f) { - sample -= 1.0f; - - if (do_rect) { - val_a = nval_a; - nval_a = rect[0]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = nval_b; - nval_b = rect[1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = nval_g; - nval_g = rect[2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = nval_r; - nval_r = rect[3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - rect += 4; - } - if (do_float) { - val_af = nval_af; - nval_af = rectf[0]; - diff_af = nval_af - val_af; - - val_bf = nval_bf; - nval_bf = rectf[1]; - diff_bf = nval_bf - val_bf; - - val_gf = nval_gf; - nval_gf = rectf[2]; - diff_gf = nval_gf - val_gf; - - val_rf = nval_rf; - nval_rf = rectf[3]; - diff_rf = nval_rf - val_rf; - rectf += 4; - } - } - if (do_rect) { - newrect[0] = val_a + sample * diff_a; - newrect[1] = val_b + sample * diff_b; - newrect[2] = val_g + sample * diff_g; - newrect[3] = val_r + sample * diff_r; - newrect += 4; - } - if (do_float) { - newrectf[0] = val_af + sample * diff_af; - newrectf[1] = val_bf + sample * diff_bf; - newrectf[2] = val_gf + sample * diff_gf; - newrectf[3] = val_rf + sample * diff_rf; - newrectf += 4; - } - sample += add; - } - } - - if (do_rect) { - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = (unsigned int *) _newrect; - } - if (do_float) { - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = (float *) _newrectf; - } - - ibuf->x = newx; - return(ibuf); + uchar *rect, *_newrect = NULL, *newrect; + float *rectf, *_newrectf = NULL, *newrectf; + float sample, add; + float val_a, nval_a, diff_a; + float val_b, nval_b, diff_b; + float val_g, nval_g, diff_g; + float val_r, nval_r, diff_r; + float val_af, nval_af, diff_af; + float val_bf, nval_bf, diff_bf; + float val_gf, nval_gf, diff_gf; + float val_rf, nval_rf, diff_rf; + int x, y; + bool do_rect = false, do_float = false; + + val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; + val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; + val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; + val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; + if (ibuf == NULL) + return (NULL); + if (ibuf->rect == NULL && ibuf->rect_float == NULL) + return (ibuf); + + if (ibuf->rect) { + do_rect = true; + _newrect = MEM_mallocN(newx * ibuf->y * sizeof(int), "scaleupx"); + if (_newrect == NULL) + return (ibuf); + } + if (ibuf->rect_float) { + do_float = true; + _newrectf = MEM_mallocN(newx * ibuf->y * sizeof(float) * 4, "scaleupxf"); + if (_newrectf == NULL) { + if (_newrect) + MEM_freeN(_newrect); + return (ibuf); + } + } + + add = (ibuf->x - 1.001) / (newx - 1.0); + + rect = (uchar *)ibuf->rect; + rectf = (float *)ibuf->rect_float; + newrect = _newrect; + newrectf = _newrectf; + + for (y = ibuf->y; y > 0; y--) { + + sample = 0; + + if (do_rect) { + val_a = rect[0]; + nval_a = rect[4]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = rect[1]; + nval_b = rect[5]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = rect[2]; + nval_g = rect[6]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = rect[3]; + nval_r = rect[7]; + diff_r = nval_r - val_r; + val_r += 0.5f; + + rect += 8; + } + if (do_float) { + val_af = rectf[0]; + nval_af = rectf[4]; + diff_af = nval_af - val_af; + + val_bf = rectf[1]; + nval_bf = rectf[5]; + diff_bf = nval_bf - val_bf; + + val_gf = rectf[2]; + nval_gf = rectf[6]; + diff_gf = nval_gf - val_gf; + + val_rf = rectf[3]; + nval_rf = rectf[7]; + diff_rf = nval_rf - val_rf; + + rectf += 8; + } + for (x = newx; x > 0; x--) { + if (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + val_a = nval_a; + nval_a = rect[0]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = nval_b; + nval_b = rect[1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = nval_g; + nval_g = rect[2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = nval_r; + nval_r = rect[3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + rect += 4; + } + if (do_float) { + val_af = nval_af; + nval_af = rectf[0]; + diff_af = nval_af - val_af; + + val_bf = nval_bf; + nval_bf = rectf[1]; + diff_bf = nval_bf - val_bf; + + val_gf = nval_gf; + nval_gf = rectf[2]; + diff_gf = nval_gf - val_gf; + + val_rf = nval_rf; + nval_rf = rectf[3]; + diff_rf = nval_rf - val_rf; + rectf += 4; + } + } + if (do_rect) { + newrect[0] = val_a + sample * diff_a; + newrect[1] = val_b + sample * diff_b; + newrect[2] = val_g + sample * diff_g; + newrect[3] = val_r + sample * diff_r; + newrect += 4; + } + if (do_float) { + newrectf[0] = val_af + sample * diff_af; + newrectf[1] = val_bf + sample * diff_bf; + newrectf[2] = val_gf + sample * diff_gf; + newrectf[3] = val_rf + sample * diff_rf; + newrectf += 4; + } + sample += add; + } + } + + if (do_rect) { + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *)_newrect; + } + if (do_float) { + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = (float *)_newrectf; + } + + ibuf->x = newx; + return (ibuf); } static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) { - uchar *rect, *_newrect = NULL, *newrect; - float *rectf, *_newrectf = NULL, *newrectf; - float sample, add; - float val_a, nval_a, diff_a; - float val_b, nval_b, diff_b; - float val_g, nval_g, diff_g; - float val_r, nval_r, diff_r; - float val_af, nval_af, diff_af; - float val_bf, nval_bf, diff_bf; - float val_gf, nval_gf, diff_gf; - float val_rf, nval_rf, diff_rf; - int x, y, skipx; - bool do_rect = false, do_float = false; - - val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; - val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; - val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; - val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; - if (ibuf == NULL) return(NULL); - if (ibuf->rect == NULL && ibuf->rect_float == NULL) return (ibuf); - - if (ibuf->rect) { - do_rect = true; - _newrect = MEM_mallocN(ibuf->x * newy * sizeof(int), "scaleupy"); - if (_newrect == NULL) return(ibuf); - } - if (ibuf->rect_float) { - do_float = true; - _newrectf = MEM_mallocN(ibuf->x * newy * sizeof(float) * 4, "scaleupyf"); - if (_newrectf == NULL) { - if (_newrect) MEM_freeN(_newrect); - return(ibuf); - } - } - - add = (ibuf->y - 1.001) / (newy - 1.0); - skipx = 4 * ibuf->x; - - rect = (uchar *) ibuf->rect; - rectf = (float *) ibuf->rect_float; - newrect = _newrect; - newrectf = _newrectf; - - for (x = ibuf->x; x > 0; x--) { - - sample = 0; - if (do_rect) { - rect = ((uchar *)ibuf->rect) + 4 * (x - 1); - newrect = _newrect + 4 * (x - 1); - - val_a = rect[0]; - nval_a = rect[skipx]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = rect[1]; - nval_b = rect[skipx + 1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = rect[2]; - nval_g = rect[skipx + 2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = rect[3]; - nval_r = rect[skipx + 3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - - rect += 2 * skipx; - } - if (do_float) { - rectf = ibuf->rect_float + 4 * (x - 1); - newrectf = _newrectf + 4 * (x - 1); - - val_af = rectf[0]; - nval_af = rectf[skipx]; - diff_af = nval_af - val_af; - - val_bf = rectf[1]; - nval_bf = rectf[skipx + 1]; - diff_bf = nval_bf - val_bf; - - val_gf = rectf[2]; - nval_gf = rectf[skipx + 2]; - diff_gf = nval_gf - val_gf; - - val_rf = rectf[3]; - nval_rf = rectf[skipx + 3]; - diff_rf = nval_rf - val_rf; - - rectf += 2 * skipx; - } - - for (y = newy; y > 0; y--) { - if (sample >= 1.0f) { - sample -= 1.0f; - - if (do_rect) { - val_a = nval_a; - nval_a = rect[0]; - diff_a = nval_a - val_a; - val_a += 0.5f; - - val_b = nval_b; - nval_b = rect[1]; - diff_b = nval_b - val_b; - val_b += 0.5f; - - val_g = nval_g; - nval_g = rect[2]; - diff_g = nval_g - val_g; - val_g += 0.5f; - - val_r = nval_r; - nval_r = rect[3]; - diff_r = nval_r - val_r; - val_r += 0.5f; - rect += skipx; - } - if (do_float) { - val_af = nval_af; - nval_af = rectf[0]; - diff_af = nval_af - val_af; - - val_bf = nval_bf; - nval_bf = rectf[1]; - diff_bf = nval_bf - val_bf; - - val_gf = nval_gf; - nval_gf = rectf[2]; - diff_gf = nval_gf - val_gf; - - val_rf = nval_rf; - nval_rf = rectf[3]; - diff_rf = nval_rf - val_rf; - rectf += skipx; - } - } - if (do_rect) { - newrect[0] = val_a + sample * diff_a; - newrect[1] = val_b + sample * diff_b; - newrect[2] = val_g + sample * diff_g; - newrect[3] = val_r + sample * diff_r; - newrect += skipx; - } - if (do_float) { - newrectf[0] = val_af + sample * diff_af; - newrectf[1] = val_bf + sample * diff_bf; - newrectf[2] = val_gf + sample * diff_gf; - newrectf[3] = val_rf + sample * diff_rf; - newrectf += skipx; - } - sample += add; - } - } - - if (do_rect) { - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = (unsigned int *) _newrect; - } - if (do_float) { - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = (float *) _newrectf; - } - - ibuf->y = newy; - return(ibuf); + uchar *rect, *_newrect = NULL, *newrect; + float *rectf, *_newrectf = NULL, *newrectf; + float sample, add; + float val_a, nval_a, diff_a; + float val_b, nval_b, diff_b; + float val_g, nval_g, diff_g; + float val_r, nval_r, diff_r; + float val_af, nval_af, diff_af; + float val_bf, nval_bf, diff_bf; + float val_gf, nval_gf, diff_gf; + float val_rf, nval_rf, diff_rf; + int x, y, skipx; + bool do_rect = false, do_float = false; + + val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; + val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; + val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; + val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; + if (ibuf == NULL) + return (NULL); + if (ibuf->rect == NULL && ibuf->rect_float == NULL) + return (ibuf); + + if (ibuf->rect) { + do_rect = true; + _newrect = MEM_mallocN(ibuf->x * newy * sizeof(int), "scaleupy"); + if (_newrect == NULL) + return (ibuf); + } + if (ibuf->rect_float) { + do_float = true; + _newrectf = MEM_mallocN(ibuf->x * newy * sizeof(float) * 4, "scaleupyf"); + if (_newrectf == NULL) { + if (_newrect) + MEM_freeN(_newrect); + return (ibuf); + } + } + + add = (ibuf->y - 1.001) / (newy - 1.0); + skipx = 4 * ibuf->x; + + rect = (uchar *)ibuf->rect; + rectf = (float *)ibuf->rect_float; + newrect = _newrect; + newrectf = _newrectf; + + for (x = ibuf->x; x > 0; x--) { + + sample = 0; + if (do_rect) { + rect = ((uchar *)ibuf->rect) + 4 * (x - 1); + newrect = _newrect + 4 * (x - 1); + + val_a = rect[0]; + nval_a = rect[skipx]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = rect[1]; + nval_b = rect[skipx + 1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = rect[2]; + nval_g = rect[skipx + 2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = rect[3]; + nval_r = rect[skipx + 3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + + rect += 2 * skipx; + } + if (do_float) { + rectf = ibuf->rect_float + 4 * (x - 1); + newrectf = _newrectf + 4 * (x - 1); + + val_af = rectf[0]; + nval_af = rectf[skipx]; + diff_af = nval_af - val_af; + + val_bf = rectf[1]; + nval_bf = rectf[skipx + 1]; + diff_bf = nval_bf - val_bf; + + val_gf = rectf[2]; + nval_gf = rectf[skipx + 2]; + diff_gf = nval_gf - val_gf; + + val_rf = rectf[3]; + nval_rf = rectf[skipx + 3]; + diff_rf = nval_rf - val_rf; + + rectf += 2 * skipx; + } + + for (y = newy; y > 0; y--) { + if (sample >= 1.0f) { + sample -= 1.0f; + + if (do_rect) { + val_a = nval_a; + nval_a = rect[0]; + diff_a = nval_a - val_a; + val_a += 0.5f; + + val_b = nval_b; + nval_b = rect[1]; + diff_b = nval_b - val_b; + val_b += 0.5f; + + val_g = nval_g; + nval_g = rect[2]; + diff_g = nval_g - val_g; + val_g += 0.5f; + + val_r = nval_r; + nval_r = rect[3]; + diff_r = nval_r - val_r; + val_r += 0.5f; + rect += skipx; + } + if (do_float) { + val_af = nval_af; + nval_af = rectf[0]; + diff_af = nval_af - val_af; + + val_bf = nval_bf; + nval_bf = rectf[1]; + diff_bf = nval_bf - val_bf; + + val_gf = nval_gf; + nval_gf = rectf[2]; + diff_gf = nval_gf - val_gf; + + val_rf = nval_rf; + nval_rf = rectf[3]; + diff_rf = nval_rf - val_rf; + rectf += skipx; + } + } + if (do_rect) { + newrect[0] = val_a + sample * diff_a; + newrect[1] = val_b + sample * diff_b; + newrect[2] = val_g + sample * diff_g; + newrect[3] = val_r + sample * diff_r; + newrect += skipx; + } + if (do_float) { + newrectf[0] = val_af + sample * diff_af; + newrectf[1] = val_bf + sample * diff_bf; + newrectf[2] = val_gf + sample * diff_gf; + newrectf[3] = val_rf + sample * diff_rf; + newrectf += skipx; + } + sample += add; + } + } + + if (do_rect) { + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *)_newrect; + } + if (do_float) { + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = (float *)_newrectf; + } + + ibuf->y = newy; + return (ibuf); } static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy) { - int *zbuf, *newzbuf, *_newzbuf = NULL; - float *zbuf_float, *newzbuf_float, *_newzbuf_float = NULL; - int x, y; - int ofsx, ofsy, stepx, stepy; - - if (ibuf->zbuf) { - _newzbuf = MEM_mallocN(newx * newy * sizeof(int), __func__); - if (_newzbuf == NULL) { - IMB_freezbufImBuf(ibuf); - } - } - - if (ibuf->zbuf_float) { - _newzbuf_float = MEM_mallocN((size_t)newx * newy * sizeof(float), __func__); - if (_newzbuf_float == NULL) { - IMB_freezbuffloatImBuf(ibuf); - } - } - - if (!_newzbuf && !_newzbuf_float) { - return; - } - - stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5; - stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5; - ofsy = 32768; - - newzbuf = _newzbuf; - newzbuf_float = _newzbuf_float; - - for (y = newy; y > 0; y--, ofsy += stepy) { - if (newzbuf) { - zbuf = ibuf->zbuf; - zbuf += (ofsy >> 16) * ibuf->x; - ofsx = 32768; - for (x = newx; x > 0; x--, ofsx += stepx) { - *newzbuf++ = zbuf[ofsx >> 16]; - } - } - - if (newzbuf_float) { - zbuf_float = ibuf->zbuf_float; - zbuf_float += (ofsy >> 16) * ibuf->x; - ofsx = 32768; - for (x = newx; x > 0; x--, ofsx += stepx) { - *newzbuf_float++ = zbuf_float[ofsx >> 16]; - } - } - } - - if (_newzbuf) { - IMB_freezbufImBuf(ibuf); - ibuf->mall |= IB_zbuf; - ibuf->zbuf = _newzbuf; - } - - if (_newzbuf_float) { - IMB_freezbuffloatImBuf(ibuf); - ibuf->mall |= IB_zbuffloat; - ibuf->zbuf_float = _newzbuf_float; - } + int *zbuf, *newzbuf, *_newzbuf = NULL; + float *zbuf_float, *newzbuf_float, *_newzbuf_float = NULL; + int x, y; + int ofsx, ofsy, stepx, stepy; + + if (ibuf->zbuf) { + _newzbuf = MEM_mallocN(newx * newy * sizeof(int), __func__); + if (_newzbuf == NULL) { + IMB_freezbufImBuf(ibuf); + } + } + + if (ibuf->zbuf_float) { + _newzbuf_float = MEM_mallocN((size_t)newx * newy * sizeof(float), __func__); + if (_newzbuf_float == NULL) { + IMB_freezbuffloatImBuf(ibuf); + } + } + + if (!_newzbuf && !_newzbuf_float) { + return; + } + + stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5; + stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5; + ofsy = 32768; + + newzbuf = _newzbuf; + newzbuf_float = _newzbuf_float; + + for (y = newy; y > 0; y--, ofsy += stepy) { + if (newzbuf) { + zbuf = ibuf->zbuf; + zbuf += (ofsy >> 16) * ibuf->x; + ofsx = 32768; + for (x = newx; x > 0; x--, ofsx += stepx) { + *newzbuf++ = zbuf[ofsx >> 16]; + } + } + + if (newzbuf_float) { + zbuf_float = ibuf->zbuf_float; + zbuf_float += (ofsy >> 16) * ibuf->x; + ofsx = 32768; + for (x = newx; x > 0; x--, ofsx += stepx) { + *newzbuf_float++ = zbuf_float[ofsx >> 16]; + } + } + } + + if (_newzbuf) { + IMB_freezbufImBuf(ibuf); + ibuf->mall |= IB_zbuf; + ibuf->zbuf = _newzbuf; + } + + if (_newzbuf_float) { + IMB_freezbuffloatImBuf(ibuf); + ibuf->mall |= IB_zbuffloat; + ibuf->zbuf_float = _newzbuf_float; + } } /** @@ -1541,33 +1572,39 @@ static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy) */ bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) { - if (ibuf == NULL) return false; - if (ibuf->rect == NULL && ibuf->rect_float == NULL) return false; - - if (newx == ibuf->x && newy == ibuf->y) { - return false; - } - - /* scaleup / scaledown functions below change ibuf->x and ibuf->y - * so we first scale the Z-buffer (if any) */ - scalefast_Z_ImBuf(ibuf, newx, newy); - - /* try to scale common cases in a fast way */ - /* disabled, quality loss is unacceptable, see report #18609 (ton) */ - if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) { - return true; - } - - if (newx && (newx < ibuf->x)) scaledownx(ibuf, newx); - if (newy && (newy < ibuf->y)) scaledowny(ibuf, newy); - if (newx && (newx > ibuf->x)) scaleupx(ibuf, newx); - if (newy && (newy > ibuf->y)) scaleupy(ibuf, newy); - - return true; + if (ibuf == NULL) + return false; + if (ibuf->rect == NULL && ibuf->rect_float == NULL) + return false; + + if (newx == ibuf->x && newy == ibuf->y) { + return false; + } + + /* scaleup / scaledown functions below change ibuf->x and ibuf->y + * so we first scale the Z-buffer (if any) */ + scalefast_Z_ImBuf(ibuf, newx, newy); + + /* try to scale common cases in a fast way */ + /* disabled, quality loss is unacceptable, see report #18609 (ton) */ + if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) { + return true; + } + + if (newx && (newx < ibuf->x)) + scaledownx(ibuf, newx); + if (newy && (newy < ibuf->y)) + scaledowny(ibuf, newy); + if (newx && (newx > ibuf->x)) + scaleupx(ibuf, newx); + if (newy && (newy > ibuf->y)) + scaleupy(ibuf, newy); + + return true; } struct imbufRGBA { - float r, g, b, a; + float r, g, b, a; }; /** @@ -1575,189 +1612,204 @@ struct imbufRGBA { */ bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) { - unsigned int *rect, *_newrect, *newrect; - struct imbufRGBA *rectf, *_newrectf, *newrectf; - int x, y; - bool do_float = false, do_rect = false; - size_t ofsx, ofsy, stepx, stepy; - - rect = NULL; _newrect = NULL; newrect = NULL; - rectf = NULL; _newrectf = NULL; newrectf = NULL; - - if (ibuf == NULL) return false; - if (ibuf->rect) do_rect = true; - if (ibuf->rect_float) do_float = true; - if (do_rect == false && do_float == false) return false; - - if (newx == ibuf->x && newy == ibuf->y) return false; - - if (do_rect) { - _newrect = MEM_mallocN(newx * newy * sizeof(int), "scalefastimbuf"); - if (_newrect == NULL) return false; - newrect = _newrect; - } - - if (do_float) { - _newrectf = MEM_mallocN(newx * newy * sizeof(float) * 4, "scalefastimbuf f"); - if (_newrectf == NULL) { - if (_newrect) MEM_freeN(_newrect); - return false; - } - newrectf = _newrectf; - } - - stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5; - stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5; - ofsy = 32768; - - for (y = newy; y > 0; y--, ofsy += stepy) { - if (do_rect) { - rect = ibuf->rect; - rect += (ofsy >> 16) * ibuf->x; - ofsx = 32768; - - for (x = newx; x > 0; x--, ofsx += stepx) { - *newrect++ = rect[ofsx >> 16]; - } - } - - if (do_float) { - rectf = (struct imbufRGBA *)ibuf->rect_float; - rectf += (ofsy >> 16) * ibuf->x; - ofsx = 32768; - - for (x = newx; x > 0; x--, ofsx += stepx) { - *newrectf++ = rectf[ofsx >> 16]; - } - } - } - - if (do_rect) { - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = _newrect; - } - - if (do_float) { - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = (float *)_newrectf; - } - - scalefast_Z_ImBuf(ibuf, newx, newy); - - ibuf->x = newx; - ibuf->y = newy; - return true; + unsigned int *rect, *_newrect, *newrect; + struct imbufRGBA *rectf, *_newrectf, *newrectf; + int x, y; + bool do_float = false, do_rect = false; + size_t ofsx, ofsy, stepx, stepy; + + rect = NULL; + _newrect = NULL; + newrect = NULL; + rectf = NULL; + _newrectf = NULL; + newrectf = NULL; + + if (ibuf == NULL) + return false; + if (ibuf->rect) + do_rect = true; + if (ibuf->rect_float) + do_float = true; + if (do_rect == false && do_float == false) + return false; + + if (newx == ibuf->x && newy == ibuf->y) + return false; + + if (do_rect) { + _newrect = MEM_mallocN(newx * newy * sizeof(int), "scalefastimbuf"); + if (_newrect == NULL) + return false; + newrect = _newrect; + } + + if (do_float) { + _newrectf = MEM_mallocN(newx * newy * sizeof(float) * 4, "scalefastimbuf f"); + if (_newrectf == NULL) { + if (_newrect) + MEM_freeN(_newrect); + return false; + } + newrectf = _newrectf; + } + + stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5; + stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5; + ofsy = 32768; + + for (y = newy; y > 0; y--, ofsy += stepy) { + if (do_rect) { + rect = ibuf->rect; + rect += (ofsy >> 16) * ibuf->x; + ofsx = 32768; + + for (x = newx; x > 0; x--, ofsx += stepx) { + *newrect++ = rect[ofsx >> 16]; + } + } + + if (do_float) { + rectf = (struct imbufRGBA *)ibuf->rect_float; + rectf += (ofsy >> 16) * ibuf->x; + ofsx = 32768; + + for (x = newx; x > 0; x--, ofsx += stepx) { + *newrectf++ = rectf[ofsx >> 16]; + } + } + } + + if (do_rect) { + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = _newrect; + } + + if (do_float) { + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = (float *)_newrectf; + } + + scalefast_Z_ImBuf(ibuf, newx, newy); + + ibuf->x = newx; + ibuf->y = newy; + return true; } /* ******** threaded scaling ******** */ typedef struct ScaleTreadInitData { - ImBuf *ibuf; + ImBuf *ibuf; - unsigned int newx; - unsigned int newy; + unsigned int newx; + unsigned int newy; - unsigned char *byte_buffer; - float *float_buffer; + unsigned char *byte_buffer; + float *float_buffer; } ScaleTreadInitData; typedef struct ScaleThreadData { - ImBuf *ibuf; + ImBuf *ibuf; - unsigned int newx; - unsigned int newy; + unsigned int newx; + unsigned int newy; - int start_line; - int tot_line; + int start_line; + int tot_line; - unsigned char *byte_buffer; - float *float_buffer; + unsigned char *byte_buffer; + float *float_buffer; } ScaleThreadData; static void scale_thread_init(void *data_v, int start_line, int tot_line, void *init_data_v) { - ScaleThreadData *data = (ScaleThreadData *) data_v; - ScaleTreadInitData *init_data = (ScaleTreadInitData *) init_data_v; + ScaleThreadData *data = (ScaleThreadData *)data_v; + ScaleTreadInitData *init_data = (ScaleTreadInitData *)init_data_v; - data->ibuf = init_data->ibuf; + data->ibuf = init_data->ibuf; - data->newx = init_data->newx; - data->newy = init_data->newy; + data->newx = init_data->newx; + data->newy = init_data->newy; - data->start_line = start_line; - data->tot_line = tot_line; + data->start_line = start_line; + data->tot_line = tot_line; - data->byte_buffer = init_data->byte_buffer; - data->float_buffer = init_data->float_buffer; + data->byte_buffer = init_data->byte_buffer; + data->float_buffer = init_data->float_buffer; } static void *do_scale_thread(void *data_v) { - ScaleThreadData *data = (ScaleThreadData *) data_v; - ImBuf *ibuf = data->ibuf; - int i; - float factor_x = (float) ibuf->x / data->newx; - float factor_y = (float) ibuf->y / data->newy; - - for (i = 0; i < data->tot_line; i++) { - int y = data->start_line + i; - int x; - - for (x = 0; x < data->newx; x++) { - float u = (float) x * factor_x; - float v = (float) y * factor_y; - int offset = y * data->newx + x; - - if (data->byte_buffer) { - unsigned char *pixel = data->byte_buffer + 4 * offset; - BLI_bilinear_interpolation_char((unsigned char *) ibuf->rect, pixel, ibuf->x, ibuf->y, 4, u, v); - } - - if (data->float_buffer) { - float *pixel = data->float_buffer + ibuf->channels * offset; - BLI_bilinear_interpolation_fl(ibuf->rect_float, pixel, ibuf->x, ibuf->y, ibuf->channels, u, v); - } - } - } - - return NULL; + ScaleThreadData *data = (ScaleThreadData *)data_v; + ImBuf *ibuf = data->ibuf; + int i; + float factor_x = (float)ibuf->x / data->newx; + float factor_y = (float)ibuf->y / data->newy; + + for (i = 0; i < data->tot_line; i++) { + int y = data->start_line + i; + int x; + + for (x = 0; x < data->newx; x++) { + float u = (float)x * factor_x; + float v = (float)y * factor_y; + int offset = y * data->newx + x; + + if (data->byte_buffer) { + unsigned char *pixel = data->byte_buffer + 4 * offset; + BLI_bilinear_interpolation_char( + (unsigned char *)ibuf->rect, pixel, ibuf->x, ibuf->y, 4, u, v); + } + + if (data->float_buffer) { + float *pixel = data->float_buffer + ibuf->channels * offset; + BLI_bilinear_interpolation_fl( + ibuf->rect_float, pixel, ibuf->x, ibuf->y, ibuf->channels, u, v); + } + } + } + + return NULL; } void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy) { - ScaleTreadInitData init_data = {NULL}; + ScaleTreadInitData init_data = {NULL}; - /* prepare initialization data */ - init_data.ibuf = ibuf; + /* prepare initialization data */ + init_data.ibuf = ibuf; - init_data.newx = newx; - init_data.newy = newy; + init_data.newx = newx; + init_data.newy = newy; - if (ibuf->rect) - init_data.byte_buffer = MEM_mallocN(4 * newx * newy * sizeof(char), "threaded scale byte buffer"); + if (ibuf->rect) + init_data.byte_buffer = MEM_mallocN(4 * newx * newy * sizeof(char), + "threaded scale byte buffer"); - if (ibuf->rect_float) - init_data.float_buffer = MEM_mallocN(ibuf->channels * newx * newy * sizeof(float), "threaded scale float buffer"); + if (ibuf->rect_float) + init_data.float_buffer = MEM_mallocN(ibuf->channels * newx * newy * sizeof(float), + "threaded scale float buffer"); - /* actual scaling threads */ - IMB_processor_apply_threaded(newy, sizeof(ScaleThreadData), &init_data, - scale_thread_init, do_scale_thread); + /* actual scaling threads */ + IMB_processor_apply_threaded( + newy, sizeof(ScaleThreadData), &init_data, scale_thread_init, do_scale_thread); - /* alter image buffer */ - ibuf->x = newx; - ibuf->y = newy; + /* alter image buffer */ + ibuf->x = newx; + ibuf->y = newy; - if (ibuf->rect) { - imb_freerectImBuf(ibuf); - ibuf->mall |= IB_rect; - ibuf->rect = (unsigned int *) init_data.byte_buffer; - } + if (ibuf->rect) { + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *)init_data.byte_buffer; + } - if (ibuf->rect_float) { - imb_freerectfloatImBuf(ibuf); - ibuf->mall |= IB_rectfloat; - ibuf->rect_float = init_data.float_buffer; - } + if (ibuf->rect_float) { + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = init_data.float_buffer; + } } diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c index 52f1de1794d..30356fd4e4e 100644 --- a/source/blender/imbuf/intern/stereoimbuf.c +++ b/source/blender/imbuf/intern/stereoimbuf.c @@ -48,1237 +48,1298 @@ static void imb_stereo3d_write_doit(struct Stereo3DData *s3d_data, struct Stereo static void imb_stereo3d_read_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d); typedef struct Stereo3DData { - struct { float *left, *right, *stereo; } rectf; - struct { uchar *left, *right, *stereo; } rect; - size_t x, y, channels; - bool is_float; + struct { + float *left, *right, *stereo; + } rectf; + struct { + uchar *left, *right, *stereo; + } rect; + size_t x, y, channels; + bool is_float; } Stereo3DData; static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode) { - int x, y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width; - - int anaglyph_encoding[3][3] = { - {0, 1, 1}, - {1, 0, 1}, - {0, 0, 1}, - }; - - int r, g, b; - - r = anaglyph_encoding[mode][0]; - g = anaglyph_encoding[mode][1]; - b = anaglyph_encoding[mode][2]; - - if (s3d->is_float) { - float *rect_left = s3d->rectf.left; - float *rect_right = s3d->rectf.right; - float *rect_to = s3d->rectf.stereo; - - if (channels == 3) { - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * 3; - float *from[2] = { - rect_left + stride_from * y * 3, - rect_right + stride_from * y * 3, - }; - - for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { - to[0] = from[r][0]; - to[1] = from[g][1]; - to[2] = from[b][2]; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * 4; - float *from[2] = { - rect_left + stride_from * y * 4, - rect_right + stride_from * y * 4, - }; - - for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { - to[0] = from[r][0]; - to[1] = from[g][1]; - to[2] = from[b][2]; - to[3] = MAX2(from[0][3], from[1][3]); - } - } - } - } - else { - uchar *rect_left = s3d->rect.left; - uchar *rect_right = s3d->rect.right; - uchar *rect_to = s3d->rect.stereo; - - if (channels == 3) { - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * 3; - uchar *from[2] = { - rect_left + stride_from * y * 3, - rect_right + stride_from * y * 3, - }; - - for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { - to[0] = from[r][0]; - to[1] = from[g][1]; - to[2] = from[b][2]; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * 4; - uchar *from[2] = { - rect_left + stride_from * y * 4, - rect_right + stride_from * y * 4, - }; - - for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { - to[0] = from[r][0]; - to[1] = from[g][1]; - to[2] = from[b][2]; - to[3] = MAX2(from[0][3], from[1][3]); - } - } - } - } + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + int anaglyph_encoding[3][3] = { + {0, 1, 1}, + {1, 0, 1}, + {0, 0, 1}, + }; + + int r, g, b; + + r = anaglyph_encoding[mode][0]; + g = anaglyph_encoding[mode][1]; + b = anaglyph_encoding[mode][2]; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 3; + float *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 4; + float *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + to[3] = MAX2(from[0][3], from[1][3]); + } + } + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 3; + uchar *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 4; + uchar *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + to[0] = from[r][0]; + to[1] = from[g][1]; + to[2] = from[b][2]; + to[3] = MAX2(from[0][3], from[1][3]); + } + } + } + } } -static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap) +static void imb_stereo3d_write_interlace(Stereo3DData *s3d, + enum eStereo3dInterlaceType mode, + const bool swap) { - int x, y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width; - - if (s3d->is_float) { - const float *rect_left = s3d->rectf.left; - const float *rect_right = s3d->rectf.right; - float *rect_to = s3d->rectf.stereo; - - switch (mode) { - case S3D_INTERLACE_ROW: - { - char i = (char) swap; - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * channels; - const float *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - memcpy(to, from[i], sizeof(float) * channels * stride_from); - i = !i; - } - break; - } - case S3D_INTERLACE_COLUMN: - { - if (channels == 1) { - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y; - const float *from[2] = { - rect_left + stride_from * y, - rect_right + stride_from * y, - }; - - char i = (char) swap; - for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { - to[0] = from[i][0]; - i = !i; - } - } - } - else if (channels == 3) { - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * 3; - const float *from[2] = { - rect_left + stride_from * y * 3, - rect_right + stride_from * y * 3, - }; - - char i = (char) swap; - for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { - copy_v3_v3(to, from[i]); - i = !i; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * channels; - const float *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - - char i = (char) swap; - for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { - copy_v4_v4(to, from[i]); - i = !i; - } - } - } - break; - } - case S3D_INTERLACE_CHECKERBOARD: - { - if (channels == 1) { - char i = (char) swap; - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y; - const float *from[2] = { - rect_left + stride_from * y, - rect_right + stride_from * y, - }; - char j = i; - for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { - to[0] = from[j][0]; - j = !j; - } - i = !i; - } - } - else if (channels == 3) { - char i = (char) swap; - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * 3; - const float *from[2] = { - rect_left + stride_from * y * 3, - rect_right + stride_from * y * 3, - }; - char j = i; - for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { - copy_v3_v3(to, from[j]); - j = !j; - } - i = !i; - } - } - else if (channels == 4) { - char i = (char) swap; - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * 4; - const float *from[2] = { - rect_left + stride_from * y * 4, - rect_right + stride_from * y * 4, - }; - char j = i; - for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { - copy_v4_v4(to, from[j]); - j = !j; - } - i = !i; - } - } - break; - } - default: - { - break; - } - } - } - else { - const uchar *rect_left = s3d->rect.left; - const uchar *rect_right = s3d->rect.right; - uchar *rect_to = s3d->rect.stereo; - - switch (mode) { - case S3D_INTERLACE_ROW: - { - char i = (char) swap; - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * channels; - const uchar *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - memcpy(to, from[i], sizeof(uchar) * channels * stride_from); - i = !i; - } - break; - } - case S3D_INTERLACE_COLUMN: - { - if (channels == 1) { - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y; - const uchar *from[2] = { - rect_left + stride_from * y, - rect_right + stride_from * y, - }; - char i = (char) swap; - for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { - to[0] = from[i][0]; - i = !i; - } - } - } - else if (channels == 3) { - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * 3; - const uchar *from[2] = { - rect_left + stride_from * y * 3, - rect_right + stride_from * y * 3, - }; - char i = (char) swap; - for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { - copy_v3_v3_uchar(to, from[i]); - i = !i; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * 4; - const uchar *from[2] = { - rect_left + stride_from * y * 4, - rect_right + stride_from * y * 4, - }; - char i = (char) swap; - for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { - copy_v4_v4_uchar(to, from[i]); - i = !i; - } - } - } - break; - } - case S3D_INTERLACE_CHECKERBOARD: - { - if (channels == 1) { - char i = (char) swap; - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y; - const uchar *from[2] = { - rect_left + stride_from * y, - rect_right + stride_from * y, - }; - char j = i; - for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { - to[0] = from[j][0]; - j = !j; - } - i = !i; - } - } - else if (channels == 3) { - char i = (char) swap; - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * 3; - const uchar *from[2] = { - rect_left + stride_from * y * 3, - rect_right + stride_from * y * 3, - }; - char j = i; - for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { - copy_v3_v3_uchar(to, from[j]); - j = !j; - } - i = !i; - } - } - else if (channels == 4) { - char i = (char) swap; - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * 4; - const uchar *from[2] = { - rect_left + stride_from * y * 4, - rect_right + stride_from * y * 4, - }; - char j = i; - for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { - copy_v4_v4_uchar(to, from[j]); - j = !j; - } - i = !i; - } - } - break; - } - default: - { - break; - } - } - } + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + const float *rect_left = s3d->rectf.left; + const float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: { + char i = (char)swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + memcpy(to, from[i], sizeof(float) * channels * stride_from); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: { + if (channels == 1) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y; + const float *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + + char i = (char)swap; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[i][0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 3; + const float *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + + char i = (char)swap; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3(to, from[i]); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + char i = (char)swap; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4(to, from[i]); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: { + if (channels == 1) { + char i = (char)swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y; + const float *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[j][0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char)swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 3; + const float *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3(to, from[j]); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char)swap; + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * 4; + const float *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4(to, from[j]); + j = !j; + } + i = !i; + } + } + break; + } + default: { + break; + } + } + } + else { + const uchar *rect_left = s3d->rect.left; + const uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: { + char i = (char)swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * channels; + const uchar *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + memcpy(to, from[i], sizeof(uchar) * channels * stride_from); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: { + if (channels == 1) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y; + const uchar *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + char i = (char)swap; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[i][0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 3; + const uchar *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + char i = (char)swap; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3_uchar(to, from[i]); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 4; + const uchar *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + char i = (char)swap; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4_uchar(to, from[i]); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: { + if (channels == 1) { + char i = (char)swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y; + const uchar *from[2] = { + rect_left + stride_from * y, + rect_right + stride_from * y, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) { + to[0] = from[j][0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char)swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 3; + const uchar *from[2] = { + rect_left + stride_from * y * 3, + rect_right + stride_from * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) { + copy_v3_v3_uchar(to, from[j]); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char)swap; + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * 4; + const uchar *from[2] = { + rect_left + stride_from * y * 4, + rect_right + stride_from * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) { + copy_v4_v4_uchar(to, from[j]); + j = !j; + } + i = !i; + } + } + break; + } + default: { + break; + } + } + } } /* stereo3d output (s3d->rectf.stereo) is always unsqueezed */ static void imb_stereo3d_write_sidebyside(Stereo3DData *s3d, const bool crosseyed) { - int y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width * 2; - - const int l = (int) crosseyed; - const int r = !l; - - if (s3d->is_float) { - const float *rect_left = s3d->rectf.left; - const float *rect_right = s3d->rectf.right; - float *rect_to = s3d->rectf.stereo; - - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * channels; - const float *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - - memcpy(to, from[l], sizeof(float) * channels * stride_from); - memcpy(to + channels * stride_from, from[r], sizeof(float) * channels * stride_from); - } - } - else { - const uchar *rect_left = s3d->rect.left; - const uchar *rect_right = s3d->rect.right; - uchar *rect_to = s3d->rect.stereo; - - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * channels; - const uchar *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - - memcpy(to, from[l], sizeof(uchar) * channels * stride_from); - memcpy(to + channels * stride_from, from[r], sizeof(uchar) * channels * stride_from); - } - } + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width * 2; + + const int l = (int)crosseyed; + const int r = !l; + + if (s3d->is_float) { + const float *rect_left = s3d->rectf.left; + const float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[l], sizeof(float) * channels * stride_from); + memcpy(to + channels * stride_from, from[r], sizeof(float) * channels * stride_from); + } + } + else { + const uchar *rect_left = s3d->rect.left; + const uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * channels; + const uchar *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[l], sizeof(uchar) * channels * stride_from); + memcpy(to + channels * stride_from, from[r], sizeof(uchar) * channels * stride_from); + } + } } /* stereo3d output (s3d->rectf.stereo) is always unsqueezed */ static void imb_stereo3d_write_topbottom(Stereo3DData *s3d) { - int y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width; - - if (s3d->is_float) { - const float *rect_left = s3d->rectf.left; - const float *rect_right = s3d->rectf.right; - float *rect_to = s3d->rectf.stereo; - - for (y = 0; y < height; y++) { - float *to = rect_to + stride_to * y * channels; - const float *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - - memcpy(to, from[1], sizeof(float) * channels * stride_from); - memcpy(to + channels * height * stride_from, from[0], sizeof(float) * channels * stride_from); - } - } - else { - const uchar *rect_left = s3d->rect.left; - const uchar *rect_right = s3d->rect.right; - uchar *rect_to = s3d->rect.stereo; - - for (y = 0; y < height; y++) { - uchar *to = rect_to + stride_to * y * channels; - const uchar *from[2] = { - rect_left + stride_from * y * channels, - rect_right + stride_from * y * channels, - }; - - memcpy(to, from[1], sizeof(uchar) * channels * stride_from); - memcpy(to + channels * height * stride_from, from[0], sizeof(uchar) * channels * stride_from); - } - } + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + const float *rect_left = s3d->rectf.left; + const float *rect_right = s3d->rectf.right; + float *rect_to = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + float *to = rect_to + stride_to * y * channels; + const float *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[1], sizeof(float) * channels * stride_from); + memcpy( + to + channels * height * stride_from, from[0], sizeof(float) * channels * stride_from); + } + } + else { + const uchar *rect_left = s3d->rect.left; + const uchar *rect_right = s3d->rect.right; + uchar *rect_to = s3d->rect.stereo; + + for (y = 0; y < height; y++) { + uchar *to = rect_to + stride_to * y * channels; + const uchar *from[2] = { + rect_left + stride_from * y * channels, + rect_right + stride_from * y * channels, + }; + + memcpy(to, from[1], sizeof(uchar) * channels * stride_from); + memcpy( + to + channels * height * stride_from, from[0], sizeof(uchar) * channels * stride_from); + } + } } /**************************** dimension utils ****************************************/ -void IMB_stereo3d_write_dimensions( - const char mode, const bool is_squeezed, const size_t width, const size_t height, - size_t *r_width, size_t *r_height) +void IMB_stereo3d_write_dimensions(const char mode, + const bool is_squeezed, + const size_t width, + const size_t height, + size_t *r_width, + size_t *r_height) { - switch (mode) { - case S3D_DISPLAY_SIDEBYSIDE: - { - *r_width = is_squeezed ? width : width * 2; - *r_height = height; - break; - } - case S3D_DISPLAY_TOPBOTTOM: - { - *r_width = width; - *r_height = is_squeezed ? height : height * 2; - break; - } - case S3D_DISPLAY_ANAGLYPH: - case S3D_DISPLAY_INTERLACE: - default: - { - *r_width = width; - *r_height = height; - break; - } - } + switch (mode) { + case S3D_DISPLAY_SIDEBYSIDE: { + *r_width = is_squeezed ? width : width * 2; + *r_height = height; + break; + } + case S3D_DISPLAY_TOPBOTTOM: { + *r_width = width; + *r_height = is_squeezed ? height : height * 2; + break; + } + case S3D_DISPLAY_ANAGLYPH: + case S3D_DISPLAY_INTERLACE: + default: { + *r_width = width; + *r_height = height; + break; + } + } } -void IMB_stereo3d_read_dimensions( - const char mode, const bool is_squeezed, const size_t width, const size_t height, - size_t *r_width, size_t *r_height) +void IMB_stereo3d_read_dimensions(const char mode, + const bool is_squeezed, + const size_t width, + const size_t height, + size_t *r_width, + size_t *r_height) { - switch (mode) { - case S3D_DISPLAY_SIDEBYSIDE: - { - *r_width = is_squeezed ? width / 2 : width; - *r_height = height; - break; - } - case S3D_DISPLAY_TOPBOTTOM: - { - *r_width = width; - *r_height = is_squeezed ? height / 2 : height; - break; - } - case S3D_DISPLAY_ANAGLYPH: - case S3D_DISPLAY_INTERLACE: - default: - { - *r_width = width; - *r_height = height; - break; - } - } + switch (mode) { + case S3D_DISPLAY_SIDEBYSIDE: { + *r_width = is_squeezed ? width / 2 : width; + *r_height = height; + break; + } + case S3D_DISPLAY_TOPBOTTOM: { + *r_width = width; + *r_height = is_squeezed ? height / 2 : height; + break; + } + case S3D_DISPLAY_ANAGLYPH: + case S3D_DISPLAY_INTERLACE: + default: { + *r_width = width; + *r_height = height; + break; + } + } } /**************************** un/squeeze frame ****************************************/ -static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf, Stereo3dFormat *s3d, const size_t x, const size_t y) +static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf, + Stereo3dFormat *s3d, + const size_t x, + const size_t y) { - if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) - return; + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; - if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) - return; + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; - IMB_scaleImBuf_threaded(ibuf, x, y); + IMB_scaleImBuf_threaded(ibuf, x, y); } -static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf, Stereo3dFormat *s3d, const size_t x, const size_t y) +static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf, + Stereo3dFormat *s3d, + const size_t x, + const size_t y) { - if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) - return; + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; - if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) - return; + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; - IMB_scaleImBuf_threaded(ibuf, x, y); + IMB_scaleImBuf_threaded(ibuf, x, y); } -static void imb_stereo3d_squeeze_rectf(float *rectf, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) +static void imb_stereo3d_squeeze_rectf( + float *rectf, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) { - ImBuf *ibuf; - size_t width, height; - - if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) - return; - - if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) - return; - - /* creates temporary imbuf to store the rectf */ - IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); - ibuf = IMB_allocImBuf(width, height, channels, IB_rectfloat); - - IMB_buffer_float_from_float( - ibuf->rect_float, rectf, channels, - IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, - width, height, width, width); - - IMB_scaleImBuf_threaded(ibuf, x, y); - memcpy(rectf, ibuf->rect_float, x * y * sizeof(float[4])); - IMB_freeImBuf(ibuf); + ImBuf *ibuf; + size_t width, height; + + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; + + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; + + /* creates temporary imbuf to store the rectf */ + IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); + ibuf = IMB_allocImBuf(width, height, channels, IB_rectfloat); + + IMB_buffer_float_from_float(ibuf->rect_float, + rectf, + channels, + IB_PROFILE_LINEAR_RGB, + IB_PROFILE_LINEAR_RGB, + false, + width, + height, + width, + width); + + IMB_scaleImBuf_threaded(ibuf, x, y); + memcpy(rectf, ibuf->rect_float, x * y * sizeof(float[4])); + IMB_freeImBuf(ibuf); } -static void imb_stereo3d_squeeze_rect(int *rect, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) +static void imb_stereo3d_squeeze_rect( + int *rect, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) { - ImBuf *ibuf; - size_t width, height; - - if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) - return; - - if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) - return; - - /* creates temporary imbuf to store the rectf */ - IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); - ibuf = IMB_allocImBuf(width, height, channels, IB_rect); - - IMB_buffer_byte_from_byte( - (unsigned char *)ibuf->rect, (unsigned char *)rect, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, - width, height, width, width); - - IMB_scaleImBuf_threaded(ibuf, x, y); - memcpy(rect, ibuf->rect, x * y * sizeof(unsigned int)); - IMB_freeImBuf(ibuf); + ImBuf *ibuf; + size_t width, height; + + if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) + return; + + if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) + return; + + /* creates temporary imbuf to store the rectf */ + IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); + ibuf = IMB_allocImBuf(width, height, channels, IB_rect); + + IMB_buffer_byte_from_byte((unsigned char *)ibuf->rect, + (unsigned char *)rect, + IB_PROFILE_SRGB, + IB_PROFILE_SRGB, + false, + width, + height, + width, + width); + + IMB_scaleImBuf_threaded(ibuf, x, y); + memcpy(rect, ibuf->rect, x * y * sizeof(unsigned int)); + IMB_freeImBuf(ibuf); } - /*************************** preparing to call the write functions **************************/ -static void imb_stereo3d_data_initialize( - Stereo3DData *s3d_data, const bool is_float, - const size_t x, const size_t y, const size_t channels, - int *rect_left, int *rect_right, int *rect_stereo, - float *rectf_left, float *rectf_right, float *rectf_stereo) +static void imb_stereo3d_data_initialize(Stereo3DData *s3d_data, + const bool is_float, + const size_t x, + const size_t y, + const size_t channels, + int *rect_left, + int *rect_right, + int *rect_stereo, + float *rectf_left, + float *rectf_right, + float *rectf_stereo) { - s3d_data->is_float = is_float; - s3d_data->x = x; - s3d_data->y = y; - s3d_data->channels = channels; - s3d_data->rect.left = (uchar *)rect_left; - s3d_data->rect.right = (uchar *)rect_right; - s3d_data->rect.stereo = (uchar *)rect_stereo; - s3d_data->rectf.left = rectf_left; - s3d_data->rectf.right = rectf_right; - s3d_data->rectf.stereo = rectf_stereo; + s3d_data->is_float = is_float; + s3d_data->x = x; + s3d_data->y = y; + s3d_data->channels = channels; + s3d_data->rect.left = (uchar *)rect_left; + s3d_data->rect.right = (uchar *)rect_right; + s3d_data->rect.stereo = (uchar *)rect_stereo; + s3d_data->rectf.left = rectf_left; + s3d_data->rectf.right = rectf_right; + s3d_data->rectf.stereo = rectf_stereo; } -int *IMB_stereo3d_from_rect( - ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, - int *rect_left, int *rect_right) +int *IMB_stereo3d_from_rect(ImageFormatData *im_format, + const size_t x, + const size_t y, + const size_t channels, + int *rect_left, + int *rect_right) { - int *r_rect; - Stereo3DData s3d_data = {{NULL}}; - size_t width, height; - const bool is_float = im_format->depth > 8; + int *r_rect; + Stereo3DData s3d_data = {{NULL}}; + size_t width, height; + const bool is_float = im_format->depth > 8; - IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, x, y, &width, &height); - r_rect = MEM_mallocN(channels * sizeof(int) * width * height, __func__); + IMB_stereo3d_write_dimensions( + im_format->stereo3d_format.display_mode, false, x, y, &width, &height); + r_rect = MEM_mallocN(channels * sizeof(int) * width * height, __func__); - imb_stereo3d_data_initialize(&s3d_data, is_float, x, y, channels, rect_left, rect_right, r_rect, NULL, NULL, NULL); - imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_rect(r_rect, &im_format->stereo3d_format, x, y, channels); + imb_stereo3d_data_initialize( + &s3d_data, is_float, x, y, channels, rect_left, rect_right, r_rect, NULL, NULL, NULL); + imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); + imb_stereo3d_squeeze_rect(r_rect, &im_format->stereo3d_format, x, y, channels); - return r_rect; + return r_rect; } -float *IMB_stereo3d_from_rectf( - ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, - float *rectf_left, float *rectf_right) +float *IMB_stereo3d_from_rectf(ImageFormatData *im_format, + const size_t x, + const size_t y, + const size_t channels, + float *rectf_left, + float *rectf_right) { - float *r_rectf; - Stereo3DData s3d_data = {{NULL}}; - size_t width, height; - const bool is_float = im_format->depth > 8; + float *r_rectf; + Stereo3DData s3d_data = {{NULL}}; + size_t width, height; + const bool is_float = im_format->depth > 8; - IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, x, y, &width, &height); - r_rectf = MEM_mallocN(channels * sizeof(float) * width * height, __func__); + IMB_stereo3d_write_dimensions( + im_format->stereo3d_format.display_mode, false, x, y, &width, &height); + r_rectf = MEM_mallocN(channels * sizeof(float) * width * height, __func__); - imb_stereo3d_data_initialize(&s3d_data, is_float, x, y, channels, NULL, NULL, NULL, rectf_left, rectf_right, r_rectf); - imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_rectf(r_rectf, &im_format->stereo3d_format, x, y, channels); + imb_stereo3d_data_initialize( + &s3d_data, is_float, x, y, channels, NULL, NULL, NULL, rectf_left, rectf_right, r_rectf); + imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); + imb_stereo3d_squeeze_rectf(r_rectf, &im_format->stereo3d_format, x, y, channels); - return r_rectf; + return r_rectf; } /* left/right are always float */ ImBuf *IMB_stereo3d_ImBuf(ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right) { - ImBuf *ibuf_stereo = NULL; - Stereo3DData s3d_data = {{NULL}}; - size_t width, height; - const bool is_float = im_format->depth > 8; - - IMB_stereo3d_write_dimensions(im_format->stereo3d_format.display_mode, false, ibuf_left->x, ibuf_left->y, &width, &height); - ibuf_stereo = IMB_allocImBuf(width, height, ibuf_left->planes, (is_float ? IB_rectfloat : IB_rect)); - - ibuf_stereo->rect_colorspace = ibuf_left->rect_colorspace; - ibuf_stereo->float_colorspace = ibuf_left->float_colorspace; - - ibuf_stereo->flags = ibuf_left->flags; - - imb_stereo3d_data_initialize( - &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 4, - (int *)ibuf_left->rect, (int *)ibuf_right->rect, (int *)ibuf_stereo->rect, - ibuf_left->rect_float, ibuf_right->rect_float, ibuf_stereo->rect_float); - - imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y); - - return ibuf_stereo; + ImBuf *ibuf_stereo = NULL; + Stereo3DData s3d_data = {{NULL}}; + size_t width, height; + const bool is_float = im_format->depth > 8; + + IMB_stereo3d_write_dimensions( + im_format->stereo3d_format.display_mode, false, ibuf_left->x, ibuf_left->y, &width, &height); + ibuf_stereo = IMB_allocImBuf( + width, height, ibuf_left->planes, (is_float ? IB_rectfloat : IB_rect)); + + ibuf_stereo->rect_colorspace = ibuf_left->rect_colorspace; + ibuf_stereo->float_colorspace = ibuf_left->float_colorspace; + + ibuf_stereo->flags = ibuf_left->flags; + + imb_stereo3d_data_initialize(&s3d_data, + is_float, + ibuf_left->x, + ibuf_left->y, + 4, + (int *)ibuf_left->rect, + (int *)ibuf_right->rect, + (int *)ibuf_stereo->rect, + ibuf_left->rect_float, + ibuf_right->rect_float, + ibuf_stereo->rect_float); + + imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); + imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y); + + return ibuf_stereo; } static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d) { - switch (s3d->display_mode) { - case S3D_DISPLAY_ANAGLYPH: - imb_stereo3d_write_anaglyph(s3d_data, s3d->anaglyph_type); - break; - case S3D_DISPLAY_INTERLACE: - imb_stereo3d_write_interlace(s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0); - break; - case S3D_DISPLAY_SIDEBYSIDE: - imb_stereo3d_write_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0); - break; - case S3D_DISPLAY_TOPBOTTOM: - imb_stereo3d_write_topbottom(s3d_data); - break; - default: - break; - } + switch (s3d->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + imb_stereo3d_write_anaglyph(s3d_data, s3d->anaglyph_type); + break; + case S3D_DISPLAY_INTERLACE: + imb_stereo3d_write_interlace( + s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0); + break; + case S3D_DISPLAY_SIDEBYSIDE: + imb_stereo3d_write_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0); + break; + case S3D_DISPLAY_TOPBOTTOM: + imb_stereo3d_write_topbottom(s3d_data); + break; + default: + break; + } } /******************************** reading stereo imbufs **********************/ static void imb_stereo3d_read_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode) { - int x, y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width; - - int anaglyph_encoding[3][3] = { - {0, 1, 1}, - {1, 0, 1}, - {0, 0, 1}, - }; - - int r, g, b; - - r = anaglyph_encoding[mode][0]; - g = anaglyph_encoding[mode][1]; - b = anaglyph_encoding[mode][2]; - - if (s3d->is_float) { - float *rect_left = s3d->rectf.left; - float *rect_right = s3d->rectf.right; - float *rect_from = s3d->rectf.stereo; - - if (channels == 3) { - for (y = 0; y < height; y++) { - float *from = rect_from + stride_from * y * 3; - float *to[2] = { - rect_left + stride_to * y * 3, - rect_right + stride_to * y * 3, - }; - - for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { - to[r][0] = from[0]; - to[g][1] = from[1]; - to[b][2] = from[2]; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - float *from = rect_from + stride_from * y * 4; - float *to[2] = { - rect_left + stride_to * y * 4, - rect_right + stride_to * y * 4, - }; - - for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { - to[r][0] = from[0]; - to[g][1] = from[1]; - to[b][2] = from[2]; - to[0][3] = to[1][3] = from[3]; - } - } - } - } - else { - uchar *rect_left = s3d->rect.left; - uchar *rect_right = s3d->rect.right; - uchar *rect_from = s3d->rect.stereo; - - if (channels == 3) { - for (y = 0; y < height; y++) { - uchar *from = rect_from + stride_from * y * 3; - uchar *to[2] = { - rect_left + stride_to * y * 3, - rect_right + stride_to * y * 3, - }; - - for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { - to[r][0] = from[0]; - to[g][1] = from[1]; - to[b][2] = from[2]; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - uchar *from = rect_from + stride_from * y * 4; - uchar *to[2] = { - rect_left + stride_to * y * 4, - rect_right + stride_to * y * 4, - }; - - for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { - to[r][0] = from[0]; - to[g][1] = from[1]; - to[b][2] = from[2]; - to[0][3] = to[1][3] = from[3]; - } - } - } - } + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + int anaglyph_encoding[3][3] = { + {0, 1, 1}, + {1, 0, 1}, + {0, 0, 1}, + }; + + int r, g, b; + + r = anaglyph_encoding[mode][0]; + g = anaglyph_encoding[mode][1]; + b = anaglyph_encoding[mode][2]; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + float *rect_from = s3d->rectf.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + float *from = rect_from + stride_from * y * 3; + float *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + float *from = rect_from + stride_from * y * 4; + float *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + to[0][3] = to[1][3] = from[3]; + } + } + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + uchar *rect_from = s3d->rect.stereo; + + if (channels == 3) { + for (y = 0; y < height; y++) { + uchar *from = rect_from + stride_from * y * 3; + uchar *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + uchar *from = rect_from + stride_from * y * 4; + uchar *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + to[r][0] = from[0]; + to[g][1] = from[1]; + to[b][2] = from[2]; + to[0][3] = to[1][3] = from[3]; + } + } + } + } } -static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap) +static void imb_stereo3d_read_interlace(Stereo3DData *s3d, + enum eStereo3dInterlaceType mode, + const bool swap) { - int x, y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width; - - if (s3d->is_float) { - float *rect_left = s3d->rectf.left; - float *rect_right = s3d->rectf.right; - const float *rect_from = s3d->rectf.stereo; - - switch (mode) { - case S3D_INTERLACE_ROW: - { - char i = (char) swap; - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * channels; - float *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - memcpy(to[i], from, sizeof(float) * channels * stride_to); - i = !i; - } - break; - } - case S3D_INTERLACE_COLUMN: - { - if (channels == 1) { - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y; - float *to[2] = { - rect_left + stride_to * y, - rect_right + stride_to * y, - }; - - char i = (char) swap; - for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { - to[i][0] = from[0]; - i = !i; - } - } - } - else if (channels == 3) { - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 3; - float *to[2] = { - rect_left + stride_to * y * 3, - rect_right + stride_to * y * 3, - }; - - char i = (char) swap; - for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { - copy_v3_v3(to[i], from); - i = !i; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * channels; - float *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - - char i = (char) swap; - for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { - copy_v4_v4(to[i], from); - i = !i; - } - } - } - break; - } - case S3D_INTERLACE_CHECKERBOARD: - { - if (channels == 1) { - char i = (char) swap; - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y; - float *to[2] = { - rect_left + stride_to * y, - rect_right + stride_to * y, - }; - char j = i; - for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { - to[j][0] = from[0]; - j = !j; - } - i = !i; - } - } - else if (channels == 3) { - char i = (char) swap; - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 3; - float *to[2] = { - rect_left + stride_to * y * 3, - rect_right + stride_to * y * 3, - }; - char j = i; - for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { - copy_v3_v3(to[j], from); - j = !j; - } - i = !i; - } - } - else if (channels == 4) { - char i = (char) swap; - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 4; - float *to[2] = { - rect_left + stride_to * y * 4, - rect_right + stride_to * y * 4, - }; - char j = i; - for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { - copy_v4_v4(to[j], from); - j = !j; - } - i = !i; - } - } - break; - } - default: - { - break; - } - } - } - else { - uchar *rect_left = s3d->rect.right; - uchar *rect_right = s3d->rect.left; - const uchar *rect_from = s3d->rect.stereo; - - switch (mode) { - case S3D_INTERLACE_ROW: - { - char i = (char) swap; - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * channels; - uchar *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - memcpy(to[i], from, sizeof(uchar) * channels * stride_to); - i = !i; - } - break; - } - case S3D_INTERLACE_COLUMN: - { - if (channels == 1) { - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y; - uchar *to[2] = { - rect_left + stride_to * y, - rect_right + stride_to * y, - }; - char i = (char) swap; - for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { - to[i][0] = from[0]; - i = !i; - } - } - } - else if (channels == 3) { - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 3; - uchar *to[2] = { - rect_left + stride_to * y * 3, - rect_right + stride_to * y * 3, - }; - char i = (char) swap; - for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { - copy_v3_v3_uchar(to[i], from); - i = !i; - } - } - } - else if (channels == 4) { - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 4; - uchar *to[2] = { - rect_left + stride_to * y * 4, - rect_right + stride_to * y * 4, - }; - char i = (char) swap; - for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { - copy_v4_v4_uchar(to[i], from); - i = !i; - } - } - } - break; - } - case S3D_INTERLACE_CHECKERBOARD: - { - if (channels == 1) { - char i = (char) swap; - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y; - uchar *to[2] = { - rect_left + stride_to * y, - rect_right + stride_to * y, - }; - char j = i; - for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { - to[j][0] = from[0]; - j = !j; - } - i = !i; - } - } - else if (channels == 3) { - char i = (char) swap; - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 3; - uchar *to[2] = { - rect_left + stride_to * y * 3, - rect_right + stride_to * y * 3, - }; - char j = i; - for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { - copy_v3_v3_uchar(to[j], from); - j = !j; - } - i = !i; - } - } - else if (channels == 4) { - char i = (char) swap; - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 4; - uchar *to[2] = { - rect_left + stride_to * y * 4, - rect_right + stride_to * y * 4, - }; - char j = i; - for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { - copy_v4_v4_uchar(to[j], from); - j = !j; - } - i = !i; - } - } - break; - } - default: - { - break; - } - } - } + int x, y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + const float *rect_from = s3d->rectf.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: { + char i = (char)swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + memcpy(to[i], from, sizeof(float) * channels * stride_to); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: { + if (channels == 1) { + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y; + float *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + + char i = (char)swap; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[i][0] = from[0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * 3; + float *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + + char i = (char)swap; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3(to[i], from); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + char i = (char)swap; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4(to[i], from); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: { + if (channels == 1) { + char i = (char)swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y; + float *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + char j = i; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[j][0] = from[0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char)swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * 3; + float *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3(to[j], from); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char)swap; + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * 4; + float *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4(to[j], from); + j = !j; + } + i = !i; + } + } + break; + } + default: { + break; + } + } + } + else { + uchar *rect_left = s3d->rect.right; + uchar *rect_right = s3d->rect.left; + const uchar *rect_from = s3d->rect.stereo; + + switch (mode) { + case S3D_INTERLACE_ROW: { + char i = (char)swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * channels; + uchar *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + memcpy(to[i], from, sizeof(uchar) * channels * stride_to); + i = !i; + } + break; + } + case S3D_INTERLACE_COLUMN: { + if (channels == 1) { + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y; + uchar *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + char i = (char)swap; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[i][0] = from[0]; + i = !i; + } + } + } + else if (channels == 3) { + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 3; + uchar *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + char i = (char)swap; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3_uchar(to[i], from); + i = !i; + } + } + } + else if (channels == 4) { + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 4; + uchar *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + char i = (char)swap; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4_uchar(to[i], from); + i = !i; + } + } + } + break; + } + case S3D_INTERLACE_CHECKERBOARD: { + if (channels == 1) { + char i = (char)swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y; + uchar *to[2] = { + rect_left + stride_to * y, + rect_right + stride_to * y, + }; + char j = i; + for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) { + to[j][0] = from[0]; + j = !j; + } + i = !i; + } + } + else if (channels == 3) { + char i = (char)swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 3; + uchar *to[2] = { + rect_left + stride_to * y * 3, + rect_right + stride_to * y * 3, + }; + char j = i; + for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) { + copy_v3_v3_uchar(to[j], from); + j = !j; + } + i = !i; + } + } + else if (channels == 4) { + char i = (char)swap; + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * 4; + uchar *to[2] = { + rect_left + stride_to * y * 4, + rect_right + stride_to * y * 4, + }; + char j = i; + for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) { + copy_v4_v4_uchar(to[j], from); + j = !j; + } + i = !i; + } + } + break; + } + default: { + break; + } + } + } } /* stereo input (s3d->rectf.stereo) is always unsqueezed */ static void imb_stereo3d_read_sidebyside(Stereo3DData *s3d, const bool crosseyed) { - int y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width * 2; - const int stride_to = width; - - const int l = (int) crosseyed; - const int r = !l; - - if (s3d->is_float) { - float *rect_left = s3d->rectf.left; - float *rect_right = s3d->rectf.right; - const float *rect_from = s3d->rectf.stereo; - - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * channels; - float *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - - memcpy(to[l], from, sizeof(float) * channels * stride_to); - memcpy(to[r], from + channels * stride_to, sizeof(float) * channels * stride_to); - } - } - else { - uchar *rect_left = s3d->rect.left; - uchar *rect_right = s3d->rect.right; - const uchar *rect_from = s3d->rect.stereo; - - /* always RGBA input/output */ - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * channels; - uchar *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - - memcpy(to[l], from, sizeof(uchar) * channels * stride_to); - memcpy(to[r], from + channels * stride_to, sizeof(uchar) * channels * stride_to); - } - } + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width * 2; + const int stride_to = width; + + const int l = (int)crosseyed; + const int r = !l; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + const float *rect_from = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[l], from, sizeof(float) * channels * stride_to); + memcpy(to[r], from + channels * stride_to, sizeof(float) * channels * stride_to); + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + const uchar *rect_from = s3d->rect.stereo; + + /* always RGBA input/output */ + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * channels; + uchar *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[l], from, sizeof(uchar) * channels * stride_to); + memcpy(to[r], from + channels * stride_to, sizeof(uchar) * channels * stride_to); + } + } } /* stereo input (s3d->rectf.stereo) is always unsqueezed */ static void imb_stereo3d_read_topbottom(Stereo3DData *s3d) { - int y; - size_t width = s3d->x; - size_t height = s3d->y; - const size_t channels = s3d->channels; - - const int stride_from = width; - const int stride_to = width; - - if (s3d->is_float) { - float *rect_left = s3d->rectf.left; - float *rect_right = s3d->rectf.right; - const float *rect_from = s3d->rectf.stereo; - - for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * channels; - float *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - - memcpy(to[1], from, sizeof(float) * channels * stride_to); - memcpy(to[0], from + channels * height * stride_to, sizeof(float) * channels * stride_to); - } - } - else { - uchar *rect_left = s3d->rect.left; - uchar *rect_right = s3d->rect.right; - const uchar *rect_from = s3d->rect.stereo; - - for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * channels; - uchar *to[2] = { - rect_left + stride_to * y * channels, - rect_right + stride_to * y * channels, - }; - - memcpy(to[1], from, sizeof(uchar) * channels * stride_to); - memcpy(to[0], from + channels * height * stride_to, sizeof(uchar) * channels * stride_to); - } - } + int y; + size_t width = s3d->x; + size_t height = s3d->y; + const size_t channels = s3d->channels; + + const int stride_from = width; + const int stride_to = width; + + if (s3d->is_float) { + float *rect_left = s3d->rectf.left; + float *rect_right = s3d->rectf.right; + const float *rect_from = s3d->rectf.stereo; + + for (y = 0; y < height; y++) { + const float *from = rect_from + stride_from * y * channels; + float *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[1], from, sizeof(float) * channels * stride_to); + memcpy(to[0], from + channels * height * stride_to, sizeof(float) * channels * stride_to); + } + } + else { + uchar *rect_left = s3d->rect.left; + uchar *rect_right = s3d->rect.right; + const uchar *rect_from = s3d->rect.stereo; + + for (y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from * y * channels; + uchar *to[2] = { + rect_left + stride_to * y * channels, + rect_right + stride_to * y * channels, + }; + + memcpy(to[1], from, sizeof(uchar) * channels * stride_to); + memcpy(to[0], from + channels * height * stride_to, sizeof(uchar) * channels * stride_to); + } + } } - /*************************** preparing to call the read functions **************************/ /* reading a stereo encoded ibuf (*left) and generating two ibufs from it (*left and *right) */ -void IMB_ImBufFromStereo3d( - Stereo3dFormat *s3d, ImBuf *ibuf_stereo3d, - ImBuf **r_ibuf_left, ImBuf **r_ibuf_right) +void IMB_ImBufFromStereo3d(Stereo3dFormat *s3d, + ImBuf *ibuf_stereo3d, + ImBuf **r_ibuf_left, + ImBuf **r_ibuf_right) { - Stereo3DData s3d_data = {{NULL}}; - ImBuf *ibuf_left, *ibuf_right; - size_t width, height; - const bool is_float = (ibuf_stereo3d->rect_float != NULL); - - IMB_stereo3d_read_dimensions( - s3d->display_mode, ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), ibuf_stereo3d->x, ibuf_stereo3d->y, - &width, &height); - - ibuf_left = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect)); - ibuf_right = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect)); - - ibuf_left->flags = ibuf_stereo3d->flags; - ibuf_right->flags = ibuf_stereo3d->flags; - - /* we always work with unsqueezed formats */ - IMB_stereo3d_write_dimensions( - s3d->display_mode, ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), ibuf_stereo3d->x, ibuf_stereo3d->y, - &width, &height); - imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height); - - imb_stereo3d_data_initialize( - &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 4, - (int *)ibuf_left->rect, (int *)ibuf_right->rect, (int *)ibuf_stereo3d->rect, - ibuf_left->rect_float, ibuf_right->rect_float, ibuf_stereo3d->rect_float); - - imb_stereo3d_read_doit(&s3d_data, s3d); - - if (ibuf_stereo3d->flags & (IB_zbuf | IB_zbuffloat)) { - if (is_float) { - addzbuffloatImBuf(ibuf_left); - addzbuffloatImBuf(ibuf_right); - } - else { - addzbufImBuf(ibuf_left); - addzbufImBuf(ibuf_right); - } - - imb_stereo3d_data_initialize( - &s3d_data, is_float, ibuf_left->x, ibuf_left->y, 1, - (int *)ibuf_left->zbuf, (int *)ibuf_right->zbuf, (int *)ibuf_stereo3d->zbuf, - ibuf_left->zbuf_float, ibuf_right->zbuf_float, ibuf_stereo3d->zbuf_float); - - imb_stereo3d_read_doit(&s3d_data, s3d); - } - - IMB_freeImBuf(ibuf_stereo3d); - - *r_ibuf_left = ibuf_left; - *r_ibuf_right = ibuf_right; + Stereo3DData s3d_data = {{NULL}}; + ImBuf *ibuf_left, *ibuf_right; + size_t width, height; + const bool is_float = (ibuf_stereo3d->rect_float != NULL); + + IMB_stereo3d_read_dimensions(s3d->display_mode, + ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), + ibuf_stereo3d->x, + ibuf_stereo3d->y, + &width, + &height); + + ibuf_left = IMB_allocImBuf( + width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect)); + ibuf_right = IMB_allocImBuf( + width, height, ibuf_stereo3d->planes, (is_float ? IB_rectfloat : IB_rect)); + + ibuf_left->flags = ibuf_stereo3d->flags; + ibuf_right->flags = ibuf_stereo3d->flags; + + /* we always work with unsqueezed formats */ + IMB_stereo3d_write_dimensions(s3d->display_mode, + ((s3d->flag & S3D_SQUEEZED_FRAME) == 0), + ibuf_stereo3d->x, + ibuf_stereo3d->y, + &width, + &height); + imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height); + + imb_stereo3d_data_initialize(&s3d_data, + is_float, + ibuf_left->x, + ibuf_left->y, + 4, + (int *)ibuf_left->rect, + (int *)ibuf_right->rect, + (int *)ibuf_stereo3d->rect, + ibuf_left->rect_float, + ibuf_right->rect_float, + ibuf_stereo3d->rect_float); + + imb_stereo3d_read_doit(&s3d_data, s3d); + + if (ibuf_stereo3d->flags & (IB_zbuf | IB_zbuffloat)) { + if (is_float) { + addzbuffloatImBuf(ibuf_left); + addzbuffloatImBuf(ibuf_right); + } + else { + addzbufImBuf(ibuf_left); + addzbufImBuf(ibuf_right); + } + + imb_stereo3d_data_initialize(&s3d_data, + is_float, + ibuf_left->x, + ibuf_left->y, + 1, + (int *)ibuf_left->zbuf, + (int *)ibuf_right->zbuf, + (int *)ibuf_stereo3d->zbuf, + ibuf_left->zbuf_float, + ibuf_right->zbuf_float, + ibuf_stereo3d->zbuf_float); + + imb_stereo3d_read_doit(&s3d_data, s3d); + } + + IMB_freeImBuf(ibuf_stereo3d); + + *r_ibuf_left = ibuf_left; + *r_ibuf_right = ibuf_right; } static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d) { - switch (s3d->display_mode) { - case S3D_DISPLAY_ANAGLYPH: - imb_stereo3d_read_anaglyph(s3d_data, s3d->anaglyph_type); - break; - case S3D_DISPLAY_INTERLACE: - imb_stereo3d_read_interlace(s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0); - break; - case S3D_DISPLAY_SIDEBYSIDE: - imb_stereo3d_read_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0); - break; - case S3D_DISPLAY_TOPBOTTOM: - imb_stereo3d_read_topbottom(s3d_data); - break; - default: - break; - } + switch (s3d->display_mode) { + case S3D_DISPLAY_ANAGLYPH: + imb_stereo3d_read_anaglyph(s3d_data, s3d->anaglyph_type); + break; + case S3D_DISPLAY_INTERLACE: + imb_stereo3d_read_interlace( + s3d_data, s3d->interlace_type, (s3d->flag & S3D_INTERLACE_SWAP) != 0); + break; + case S3D_DISPLAY_SIDEBYSIDE: + imb_stereo3d_read_sidebyside(s3d_data, (s3d->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0); + break; + case S3D_DISPLAY_TOPBOTTOM: + imb_stereo3d_read_topbottom(s3d_data); + break; + default: + break; + } } diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index fa477037f72..c80e3a0c07d 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -21,7 +21,6 @@ * \ingroup imbuf */ - #ifdef WIN32 # include #endif @@ -47,659 +46,706 @@ /***/ typedef struct TARGA { - unsigned char numid; - unsigned char maptyp; - unsigned char imgtyp; - short maporig; - short mapsize; - unsigned char mapbits; - short xorig; - short yorig; - short xsize; - short ysize; - unsigned char pixsize; - unsigned char imgdes; + unsigned char numid; + unsigned char maptyp; + unsigned char imgtyp; + short maporig; + short mapsize; + unsigned char mapbits; + short xorig; + short yorig; + short xsize; + short ysize; + unsigned char pixsize; + unsigned char imgdes; } TARGA; /***/ static int tga_out1(unsigned int data, FILE *file) { - uchar *p; + uchar *p; - p = (uchar *) &data; - if (putc(p[0], file) == EOF) return EOF; - return ~EOF; + p = (uchar *)&data; + if (putc(p[0], file) == EOF) + return EOF; + return ~EOF; } static int tga_out2(unsigned int data, FILE *file) { - uchar *p; - - p = (uchar *) &data; - if (putc(p[0], file) == EOF) return EOF; - if (putc(p[1], file) == EOF) return EOF; - return ~EOF; + uchar *p; + + p = (uchar *)&data; + if (putc(p[0], file) == EOF) + return EOF; + if (putc(p[1], file) == EOF) + return EOF; + return ~EOF; } - static int tga_out3(unsigned int data, FILE *file) { - uchar *p; - - p = (uchar *) &data; - if (putc(p[2], file) == EOF) return EOF; - if (putc(p[1], file) == EOF) return EOF; - if (putc(p[0], file) == EOF) return EOF; - return ~EOF; + uchar *p; + + p = (uchar *)&data; + if (putc(p[2], file) == EOF) + return EOF; + if (putc(p[1], file) == EOF) + return EOF; + if (putc(p[0], file) == EOF) + return EOF; + return ~EOF; } - static int tga_out4(unsigned int data, FILE *file) { - uchar *p; - - p = (uchar *) &data; - /* order = bgra */ - if (putc(p[2], file) == EOF) return EOF; - if (putc(p[1], file) == EOF) return EOF; - if (putc(p[0], file) == EOF) return EOF; - if (putc(p[3], file) == EOF) return EOF; - return ~EOF; + uchar *p; + + p = (uchar *)&data; + /* order = bgra */ + if (putc(p[2], file) == EOF) + return EOF; + if (putc(p[1], file) == EOF) + return EOF; + if (putc(p[0], file) == EOF) + return EOF; + if (putc(p[3], file) == EOF) + return EOF; + return ~EOF; } static bool makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE *)) { - register int last, this; - register int copy, bytes; - register unsigned int *rect, *rectstart, *temp; - int y; - - for (y = 0; y < ibuf->y; y++) { - bytes = ibuf->x - 1; - rectstart = rect = ibuf->rect + (y * ibuf->x); - last = *rect++; - this = *rect++; - copy = last ^ this; - while (bytes > 0) { - if (copy) { - do { - last = this; - this = *rect++; - if (last == this) { - if (this == rect[-3]) { /* three the same? */ - bytes--; /* set bytes */ - break; - } - } - } while (--bytes != 0); - - copy = rect - rectstart; - copy--; - if (bytes) copy -= 2; - - temp = rect; - rect = rectstart; - - while (copy) { - last = copy; - if (copy >= 128) last = 128; - copy -= last; - if (fputc(last - 1, file) == EOF) return 0; - do { - if (out(*rect++, file) == EOF) return 0; - } while (--last != 0); - } - rectstart = rect; - rect = temp; - last = this; - - copy = 0; - } - else { - while (*rect++ == this) { /* seek for first different byte */ - if (--bytes == 0) break; /* oor end of line */ - } - rect--; - copy = rect - rectstart; - rectstart = rect; - bytes--; - this = *rect++; - - while (copy) { - if (copy > 128) { - if (fputc(255, file) == EOF) return 0; - copy -= 128; - } - else { - if (copy == 1) { - if (fputc(0, file) == EOF) return 0; - } - else if (fputc(127 + copy, file) == EOF) return 0; - copy = 0; - } - if (out(last, file) == EOF) return 0; - } - copy = 1; - } - } - } - return 1; + register int last, this; + register int copy, bytes; + register unsigned int *rect, *rectstart, *temp; + int y; + + for (y = 0; y < ibuf->y; y++) { + bytes = ibuf->x - 1; + rectstart = rect = ibuf->rect + (y * ibuf->x); + last = *rect++; + this = *rect++; + copy = last ^ this; + while (bytes > 0) { + if (copy) { + do { + last = this; + this = *rect++; + if (last == this) { + if (this == rect[-3]) { /* three the same? */ + bytes--; /* set bytes */ + break; + } + } + } while (--bytes != 0); + + copy = rect - rectstart; + copy--; + if (bytes) + copy -= 2; + + temp = rect; + rect = rectstart; + + while (copy) { + last = copy; + if (copy >= 128) + last = 128; + copy -= last; + if (fputc(last - 1, file) == EOF) + return 0; + do { + if (out(*rect++, file) == EOF) + return 0; + } while (--last != 0); + } + rectstart = rect; + rect = temp; + last = this; + + copy = 0; + } + else { + while (*rect++ == this) { /* seek for first different byte */ + if (--bytes == 0) + break; /* oor end of line */ + } + rect--; + copy = rect - rectstart; + rectstart = rect; + bytes--; + this = *rect++; + + while (copy) { + if (copy > 128) { + if (fputc(255, file) == EOF) + return 0; + copy -= 128; + } + else { + if (copy == 1) { + if (fputc(0, file) == EOF) + return 0; + } + else if (fputc(127 + copy, file) == EOF) + return 0; + copy = 0; + } + if (out(last, file) == EOF) + return 0; + } + copy = 1; + } + } + } + return 1; } static bool dumptarga(struct ImBuf *ibuf, FILE *file) { - int size; - uchar *rect; - - if (ibuf == NULL) return 0; - if (ibuf->rect == NULL) return 0; - - size = ibuf->x * ibuf->y; - rect = (uchar *) ibuf->rect; - - if (ibuf->planes <= 8) { - while (size > 0) { - if (putc(*rect, file) == EOF) return 0; - size--; - rect += 4; - } - } - else if (ibuf->planes <= 16) { - while (size > 0) { - putc(rect[0], file); - if (putc(rect[1], file) == EOF) return 0; - size--; - rect += 4; - } - } - else if (ibuf->planes <= 24) { - while (size > 0) { - putc(rect[2], file); - putc(rect[1], file); - if (putc(rect[0], file) == EOF) return 0; - size--; - rect += 4; - } - } - else if (ibuf->planes <= 32) { - while (size > 0) { - putc(rect[2], file); - putc(rect[1], file); - putc(rect[0], file); - if (putc(rect[3], file) == EOF) return 0; - size--; - rect += 4; - } - } - else { - return 0; - } - - return 1; + int size; + uchar *rect; + + if (ibuf == NULL) + return 0; + if (ibuf->rect == NULL) + return 0; + + size = ibuf->x * ibuf->y; + rect = (uchar *)ibuf->rect; + + if (ibuf->planes <= 8) { + while (size > 0) { + if (putc(*rect, file) == EOF) + return 0; + size--; + rect += 4; + } + } + else if (ibuf->planes <= 16) { + while (size > 0) { + putc(rect[0], file); + if (putc(rect[1], file) == EOF) + return 0; + size--; + rect += 4; + } + } + else if (ibuf->planes <= 24) { + while (size > 0) { + putc(rect[2], file); + putc(rect[1], file); + if (putc(rect[0], file) == EOF) + return 0; + size--; + rect += 4; + } + } + else if (ibuf->planes <= 32) { + while (size > 0) { + putc(rect[2], file); + putc(rect[1], file); + putc(rect[0], file); + if (putc(rect[3], file) == EOF) + return 0; + size--; + rect += 4; + } + } + else { + return 0; + } + + return 1; } - int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags) { - char buf[20] = {0}; - FILE *fildes; - bool ok = false; - - (void)flags; /* unused */ - - buf[16] = (ibuf->planes + 0x7) & ~0x7; - if (ibuf->planes > 8) { - buf[2] = 10; - } - else { - buf[2] = 11; - } - - if (ibuf->foptions.flag & RAWTGA) buf[2] &= ~8; - - buf[8] = 0; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; - - buf[12] = ibuf->x & 0xff; - buf[13] = ibuf->x >> 8; - buf[14] = ibuf->y & 0xff; - buf[15] = ibuf->y >> 8; - - /* Don't forget to indicate that your 32 bit - * targa uses 8 bits for the alpha channel! */ - if (ibuf->planes == 32) { - buf[17] |= 0x08; - } - fildes = BLI_fopen(name, "wb"); - if (!fildes) return 0; - - if (fwrite(buf, 1, 18, fildes) != 18) { - fclose(fildes); - return 0; - } - - if (ibuf->foptions.flag & RAWTGA) { - ok = dumptarga(ibuf, fildes); - } - else { - switch ((ibuf->planes + 7) >> 3) { - case 1: - ok = makebody_tga(ibuf, fildes, tga_out1); - break; - case 2: - ok = makebody_tga(ibuf, fildes, tga_out2); - break; - case 3: - ok = makebody_tga(ibuf, fildes, tga_out3); - break; - case 4: - ok = makebody_tga(ibuf, fildes, tga_out4); - break; - } - } - - fclose(fildes); - return ok; + char buf[20] = {0}; + FILE *fildes; + bool ok = false; + + (void)flags; /* unused */ + + buf[16] = (ibuf->planes + 0x7) & ~0x7; + if (ibuf->planes > 8) { + buf[2] = 10; + } + else { + buf[2] = 11; + } + + if (ibuf->foptions.flag & RAWTGA) + buf[2] &= ~8; + + buf[8] = 0; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; + + buf[12] = ibuf->x & 0xff; + buf[13] = ibuf->x >> 8; + buf[14] = ibuf->y & 0xff; + buf[15] = ibuf->y >> 8; + + /* Don't forget to indicate that your 32 bit + * targa uses 8 bits for the alpha channel! */ + if (ibuf->planes == 32) { + buf[17] |= 0x08; + } + fildes = BLI_fopen(name, "wb"); + if (!fildes) + return 0; + + if (fwrite(buf, 1, 18, fildes) != 18) { + fclose(fildes); + return 0; + } + + if (ibuf->foptions.flag & RAWTGA) { + ok = dumptarga(ibuf, fildes); + } + else { + switch ((ibuf->planes + 7) >> 3) { + case 1: + ok = makebody_tga(ibuf, fildes, tga_out1); + break; + case 2: + ok = makebody_tga(ibuf, fildes, tga_out2); + break; + case 3: + ok = makebody_tga(ibuf, fildes, tga_out3); + break; + case 4: + ok = makebody_tga(ibuf, fildes, tga_out4); + break; + } + } + + fclose(fildes); + return ok; } - static int checktarga(TARGA *tga, const unsigned char *mem) { - tga->numid = mem[0]; - tga->maptyp = mem[1]; - tga->imgtyp = mem[2]; - - tga->maporig = GSS(mem + 3); - tga->mapsize = GSS(mem + 5); - tga->mapbits = mem[7]; - tga->xorig = GSS(mem + 8); - tga->yorig = GSS(mem + 10); - tga->xsize = GSS(mem + 12); - tga->ysize = GSS(mem + 14); - tga->pixsize = mem[16]; - tga->imgdes = mem[17]; - - if (tga->maptyp > 1) return 0; - switch (tga->imgtyp) { - case 1: /* raw cmap */ - case 2: /* raw rgb */ - case 3: /* raw b&w */ - case 9: /* cmap */ - case 10: /* rgb */ - case 11: /* b&w */ - break; - default: - return 0; - } - if (tga->mapsize && tga->mapbits > 32) return 0; - if (tga->xsize <= 0) return 0; - if (tga->ysize <= 0) return 0; - if (tga->pixsize > 32) return 0; - if (tga->pixsize == 0) return 0; - return 1; + tga->numid = mem[0]; + tga->maptyp = mem[1]; + tga->imgtyp = mem[2]; + + tga->maporig = GSS(mem + 3); + tga->mapsize = GSS(mem + 5); + tga->mapbits = mem[7]; + tga->xorig = GSS(mem + 8); + tga->yorig = GSS(mem + 10); + tga->xsize = GSS(mem + 12); + tga->ysize = GSS(mem + 14); + tga->pixsize = mem[16]; + tga->imgdes = mem[17]; + + if (tga->maptyp > 1) + return 0; + switch (tga->imgtyp) { + case 1: /* raw cmap */ + case 2: /* raw rgb */ + case 3: /* raw b&w */ + case 9: /* cmap */ + case 10: /* rgb */ + case 11: /* b&w */ + break; + default: + return 0; + } + if (tga->mapsize && tga->mapbits > 32) + return 0; + if (tga->xsize <= 0) + return 0; + if (tga->ysize <= 0) + return 0; + if (tga->pixsize > 32) + return 0; + if (tga->pixsize == 0) + return 0; + return 1; } int imb_is_a_targa(const unsigned char *buf) { - TARGA tga; + TARGA tga; - return checktarga(&tga, buf); + return checktarga(&tga, buf); } static void complete_partial_load(struct ImBuf *ibuf, unsigned int *rect) { - int size = (ibuf->x * ibuf->y) - (rect - ibuf->rect); - if (size) { - printf("decodetarga: incomplete file, %.1f%% missing\n", 100 * ((float)size / (ibuf->x * ibuf->y))); - - /* not essential but makes displaying partially rendered TGA's less ugly */ - memset(rect, 0, size); - } - else { - /* shouldn't happen */ - printf("decodetarga: incomplete file, all pixels written\n"); - } + int size = (ibuf->x * ibuf->y) - (rect - ibuf->rect); + if (size) { + printf("decodetarga: incomplete file, %.1f%% missing\n", + 100 * ((float)size / (ibuf->x * ibuf->y))); + + /* not essential but makes displaying partially rendered TGA's less ugly */ + memset(rect, 0, size); + } + else { + /* shouldn't happen */ + printf("decodetarga: incomplete file, all pixels written\n"); + } } static void decodetarga(struct ImBuf *ibuf, const unsigned char *mem, size_t mem_size, int psize) { - const unsigned char *mem_end = mem + mem_size; - int count, col, size; - unsigned int *rect; - uchar *cp = (uchar *) &col; - - if (ibuf == NULL) return; - if (ibuf->rect == NULL) return; - - size = ibuf->x * ibuf->y; - rect = ibuf->rect; - - /* set alpha */ - cp[0] = 0xff; - cp[1] = cp[2] = 0; - - while (size > 0) { - count = *mem++; - - if (mem > mem_end) - goto partial_load; - - if (count >= 128) { - /*if (count == 128) printf("TARGA: 128 in file !\n");*/ - count -= 127; - - if (psize & 2) { - if (psize & 1) { - /* order = bgra */ - cp[0] = mem[3]; - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ - mem += 4; - } - else { - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ - mem += 3; - } - } - else { - if (psize & 1) { - cp[0] = mem[0]; - cp[1] = mem[1]; - mem += 2; - } - else { - col = *mem++; - } - } - - size -= count; - if (size >= 0) { - while (count > 0) { - *rect++ = col; - count--; - } - } - } - else { - count++; - size -= count; - if (size >= 0) { - while (count > 0) { - if (psize & 2) { - if (psize & 1) { - /* order = bgra */ - cp[0] = mem[3]; - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ - mem += 4; - } - else { - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ - mem += 3; - } - } - else { - if (psize & 1) { - cp[0] = mem[0]; - cp[1] = mem[1]; - mem += 2; - } - else { - col = *mem++; - } - } - *rect++ = col; - count--; - - if (mem > mem_end) - goto partial_load; - } - - if (mem > mem_end) - goto partial_load; - } - } - } - if (size) { - printf("decodetarga: count would overwrite %d pixels\n", -size); - } - return; + const unsigned char *mem_end = mem + mem_size; + int count, col, size; + unsigned int *rect; + uchar *cp = (uchar *)&col; + + if (ibuf == NULL) + return; + if (ibuf->rect == NULL) + return; + + size = ibuf->x * ibuf->y; + rect = ibuf->rect; + + /* set alpha */ + cp[0] = 0xff; + cp[1] = cp[2] = 0; + + while (size > 0) { + count = *mem++; + + if (mem > mem_end) + goto partial_load; + + if (count >= 128) { + /*if (count == 128) printf("TARGA: 128 in file !\n");*/ + count -= 127; + + if (psize & 2) { + if (psize & 1) { + /* order = bgra */ + cp[0] = mem[3]; + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ + mem += 4; + } + else { + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ + mem += 3; + } + } + else { + if (psize & 1) { + cp[0] = mem[0]; + cp[1] = mem[1]; + mem += 2; + } + else { + col = *mem++; + } + } + + size -= count; + if (size >= 0) { + while (count > 0) { + *rect++ = col; + count--; + } + } + } + else { + count++; + size -= count; + if (size >= 0) { + while (count > 0) { + if (psize & 2) { + if (psize & 1) { + /* order = bgra */ + cp[0] = mem[3]; + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ + mem += 4; + } + else { + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ + mem += 3; + } + } + else { + if (psize & 1) { + cp[0] = mem[0]; + cp[1] = mem[1]; + mem += 2; + } + else { + col = *mem++; + } + } + *rect++ = col; + count--; + + if (mem > mem_end) + goto partial_load; + } + + if (mem > mem_end) + goto partial_load; + } + } + } + if (size) { + printf("decodetarga: count would overwrite %d pixels\n", -size); + } + return; partial_load: - complete_partial_load(ibuf, rect); + complete_partial_load(ibuf, rect); } static void ldtarga(struct ImBuf *ibuf, const unsigned char *mem, size_t mem_size, int psize) { - const unsigned char *mem_end = mem + mem_size; - int col, size; - unsigned int *rect; - uchar *cp = (uchar *) &col; - - if (ibuf == NULL) return; - if (ibuf->rect == NULL) return; - - size = ibuf->x * ibuf->y; - rect = ibuf->rect; - - /* set alpha */ - cp[0] = 0xff; - cp[1] = cp[2] = 0; - - while (size > 0) { - if (mem > mem_end) - goto partial_load; - - if (psize & 2) { - if (psize & 1) { - /* order = bgra */ - cp[0] = mem[3]; - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ - mem += 4; - } - else { - /* set alpha for 24 bits colors */ - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ - mem += 3; - } - } - else { - if (psize & 1) { - cp[0] = mem[0]; - cp[1] = mem[1]; - mem += 2; - } - else { - col = *mem++; - } - } - *rect++ = col; - size--; - } - return; + const unsigned char *mem_end = mem + mem_size; + int col, size; + unsigned int *rect; + uchar *cp = (uchar *)&col; + + if (ibuf == NULL) + return; + if (ibuf->rect == NULL) + return; + + size = ibuf->x * ibuf->y; + rect = ibuf->rect; + + /* set alpha */ + cp[0] = 0xff; + cp[1] = cp[2] = 0; + + while (size > 0) { + if (mem > mem_end) + goto partial_load; + + if (psize & 2) { + if (psize & 1) { + /* order = bgra */ + cp[0] = mem[3]; + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ + mem += 4; + } + else { + /* set alpha for 24 bits colors */ + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/ + mem += 3; + } + } + else { + if (psize & 1) { + cp[0] = mem[0]; + cp[1] = mem[1]; + mem += 2; + } + else { + col = *mem++; + } + } + *rect++ = col; + size--; + } + return; partial_load: - complete_partial_load(ibuf, rect); + complete_partial_load(ibuf, rect); } - -ImBuf *imb_loadtarga(const unsigned char *mem, size_t mem_size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_loadtarga(const unsigned char *mem, + size_t mem_size, + int flags, + char colorspace[IM_MAX_SPACE]) { - TARGA tga; - struct ImBuf *ibuf; - int count, size; - unsigned int *rect, *cmap = NULL /*, mincol = 0*/, cmap_max = 0; - int32_t cp_data; - uchar *cp = (uchar *) &cp_data; - - if (checktarga(&tga, mem) == 0) { - return NULL; - } - - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, tga.pixsize, 0); - else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect); - - if (ibuf == NULL) return NULL; - ibuf->ftype = IMB_FTYPE_TGA; - if (tga.imgtyp < 4) - ibuf->foptions.flag |= RAWTGA; - mem = mem + 18 + tga.numid; - - cp[0] = 0xff; - cp[1] = cp[2] = 0; - - if (tga.mapsize) { - /* load color map */ - /*mincol = tga.maporig;*/ /*UNUSED*/ - cmap_max = tga.mapsize; - cmap = MEM_callocN(sizeof(unsigned int) * cmap_max, "targa cmap"); - - for (count = 0; count < cmap_max; count++) { - switch (tga.mapbits >> 3) { - case 4: - cp[0] = mem[3]; - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - mem += 4; - break; - case 3: - cp[1] = mem[0]; - cp[2] = mem[1]; - cp[3] = mem[2]; - mem += 3; - break; - case 2: - cp[1] = mem[1]; - cp[0] = mem[0]; - mem += 2; - break; - case 1: - cp_data = *mem++; - break; - } - cmap[count] = cp_data; - } - - size = 0; - for (int cmap_index = cmap_max - 1; cmap_index > 0; cmap_index >>= 1) { - size++; - } - ibuf->planes = size; - - if (tga.mapbits != 32) { /* set alpha bits */ - cmap[0] &= BIG_LONG(0x00ffffffl); - } - } - - if (flags & IB_test) { - if (cmap) { - MEM_freeN(cmap); - } - return ibuf; - } - - if (tga.imgtyp != 1 && tga.imgtyp != 9) { /* happens sometimes (beuh) */ - if (cmap) { - MEM_freeN(cmap); - cmap = NULL; - } - } - - switch (tga.imgtyp) { - case 1: - case 2: - case 3: - if (tga.pixsize <= 8) ldtarga(ibuf, mem, mem_size, 0); - else if (tga.pixsize <= 16) ldtarga(ibuf, mem, mem_size, 1); - else if (tga.pixsize <= 24) ldtarga(ibuf, mem, mem_size, 2); - else if (tga.pixsize <= 32) ldtarga(ibuf, mem, mem_size, 3); - break; - case 9: - case 10: - case 11: - if (tga.pixsize <= 8) decodetarga(ibuf, mem, mem_size, 0); - else if (tga.pixsize <= 16) decodetarga(ibuf, mem, mem_size, 1); - else if (tga.pixsize <= 24) decodetarga(ibuf, mem, mem_size, 2); - else if (tga.pixsize <= 32) decodetarga(ibuf, mem, mem_size, 3); - break; - } - - if (cmap) { - /* apply color map */ - rect = ibuf->rect; - for (size = ibuf->x * ibuf->y; size > 0; --size, ++rect) { - int cmap_index = *rect; - if (cmap_index >= 0 && cmap_index < cmap_max) { - *rect = cmap[cmap_index]; - } - } - - MEM_freeN(cmap); - } - - if (tga.pixsize == 16) { - unsigned int col; - rect = ibuf->rect; - for (size = ibuf->x * ibuf->y; size > 0; --size, ++rect) { - col = *rect; - cp = (uchar *)rect; - mem = (uchar *)&col; - - cp[3] = ((mem[1] << 1) & 0xf8); - cp[2] = ((mem[0] & 0xe0) >> 2) + ((mem[1] & 0x03) << 6); - cp[1] = ((mem[0] << 3) & 0xf8); - cp[1] += cp[1] >> 5; - cp[2] += cp[2] >> 5; - cp[3] += cp[3] >> 5; - cp[0] = 0xff; - } - ibuf->planes = 24; - } - - if (tga.imgtyp == 3 || tga.imgtyp == 11) { - uchar *crect; - unsigned int *lrect, col; - - crect = (uchar *) ibuf->rect; - lrect = (unsigned int *) ibuf->rect; - - for (size = ibuf->x * ibuf->y; size > 0; size--) { - col = *lrect++; - - crect[0] = 255; - crect[1] = crect[2] = crect[3] = col; - crect += 4; - } - } - - if (tga.imgdes & 0x20) { - IMB_flipy(ibuf); - } - - if (ibuf->rect) - IMB_convert_rgba_to_abgr(ibuf); - - return ibuf; + TARGA tga; + struct ImBuf *ibuf; + int count, size; + unsigned int *rect, *cmap = NULL /*, mincol = 0*/, cmap_max = 0; + int32_t cp_data; + uchar *cp = (uchar *)&cp_data; + + if (checktarga(&tga, mem) == 0) { + return NULL; + } + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + if (flags & IB_test) + ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, tga.pixsize, 0); + else + ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect); + + if (ibuf == NULL) + return NULL; + ibuf->ftype = IMB_FTYPE_TGA; + if (tga.imgtyp < 4) + ibuf->foptions.flag |= RAWTGA; + mem = mem + 18 + tga.numid; + + cp[0] = 0xff; + cp[1] = cp[2] = 0; + + if (tga.mapsize) { + /* load color map */ + /*mincol = tga.maporig;*/ /*UNUSED*/ + cmap_max = tga.mapsize; + cmap = MEM_callocN(sizeof(unsigned int) * cmap_max, "targa cmap"); + + for (count = 0; count < cmap_max; count++) { + switch (tga.mapbits >> 3) { + case 4: + cp[0] = mem[3]; + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + mem += 4; + break; + case 3: + cp[1] = mem[0]; + cp[2] = mem[1]; + cp[3] = mem[2]; + mem += 3; + break; + case 2: + cp[1] = mem[1]; + cp[0] = mem[0]; + mem += 2; + break; + case 1: + cp_data = *mem++; + break; + } + cmap[count] = cp_data; + } + + size = 0; + for (int cmap_index = cmap_max - 1; cmap_index > 0; cmap_index >>= 1) { + size++; + } + ibuf->planes = size; + + if (tga.mapbits != 32) { /* set alpha bits */ + cmap[0] &= BIG_LONG(0x00ffffffl); + } + } + + if (flags & IB_test) { + if (cmap) { + MEM_freeN(cmap); + } + return ibuf; + } + + if (tga.imgtyp != 1 && tga.imgtyp != 9) { /* happens sometimes (beuh) */ + if (cmap) { + MEM_freeN(cmap); + cmap = NULL; + } + } + + switch (tga.imgtyp) { + case 1: + case 2: + case 3: + if (tga.pixsize <= 8) + ldtarga(ibuf, mem, mem_size, 0); + else if (tga.pixsize <= 16) + ldtarga(ibuf, mem, mem_size, 1); + else if (tga.pixsize <= 24) + ldtarga(ibuf, mem, mem_size, 2); + else if (tga.pixsize <= 32) + ldtarga(ibuf, mem, mem_size, 3); + break; + case 9: + case 10: + case 11: + if (tga.pixsize <= 8) + decodetarga(ibuf, mem, mem_size, 0); + else if (tga.pixsize <= 16) + decodetarga(ibuf, mem, mem_size, 1); + else if (tga.pixsize <= 24) + decodetarga(ibuf, mem, mem_size, 2); + else if (tga.pixsize <= 32) + decodetarga(ibuf, mem, mem_size, 3); + break; + } + + if (cmap) { + /* apply color map */ + rect = ibuf->rect; + for (size = ibuf->x * ibuf->y; size > 0; --size, ++rect) { + int cmap_index = *rect; + if (cmap_index >= 0 && cmap_index < cmap_max) { + *rect = cmap[cmap_index]; + } + } + + MEM_freeN(cmap); + } + + if (tga.pixsize == 16) { + unsigned int col; + rect = ibuf->rect; + for (size = ibuf->x * ibuf->y; size > 0; --size, ++rect) { + col = *rect; + cp = (uchar *)rect; + mem = (uchar *)&col; + + cp[3] = ((mem[1] << 1) & 0xf8); + cp[2] = ((mem[0] & 0xe0) >> 2) + ((mem[1] & 0x03) << 6); + cp[1] = ((mem[0] << 3) & 0xf8); + cp[1] += cp[1] >> 5; + cp[2] += cp[2] >> 5; + cp[3] += cp[3] >> 5; + cp[0] = 0xff; + } + ibuf->planes = 24; + } + + if (tga.imgtyp == 3 || tga.imgtyp == 11) { + uchar *crect; + unsigned int *lrect, col; + + crect = (uchar *)ibuf->rect; + lrect = (unsigned int *)ibuf->rect; + + for (size = ibuf->x * ibuf->y; size > 0; size--) { + col = *lrect++; + + crect[0] = 255; + crect[1] = crect[2] = crect[3] = col; + crect += 4; + } + } + + if (tga.imgdes & 0x20) { + IMB_flipy(ibuf); + } + + if (ibuf->rect) + IMB_convert_rgba_to_abgr(ibuf); + + return ibuf; } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 6c71aa06583..fc5bfe42d60 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -36,7 +36,7 @@ #include "BLI_threads.h" #include BLI_SYSTEM_PID_H -#include "DNA_space_types.h" /* For FILE_MAX_LIBEXTRA */ +#include "DNA_space_types.h" /* For FILE_MAX_LIBEXTRA */ #include "BLO_readfile.h" @@ -53,13 +53,13 @@ #include #ifdef WIN32 - /* Need to include windows.h so _WIN32_IE is defined. */ +/* Need to include windows.h so _WIN32_IE is defined. */ # include # ifndef _WIN32_IE - /* Minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already. */ +/* Minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already. */ # define _WIN32_IE 0x0400 # endif - /* For SHGetSpecialFolderPath, has to be done before BLI_winstuff +/* For SHGetSpecialFolderPath, has to be done before BLI_winstuff * because 'near' is disabled through BLI_windstuff */ # include # include /* chdir */ @@ -68,7 +68,7 @@ #endif #if defined(WIN32) || defined(__APPLE__) - /* pass */ +/* pass */ #else # define USE_FREEDESKTOP #endif @@ -84,554 +84,665 @@ static bool get_thumb_dir(char *dir, ThumbSize size) { - char *s = dir; - const char *subdir; + char *s = dir; + const char *subdir; #ifdef WIN32 - wchar_t dir_16[MAX_PATH]; - /* yes, applications shouldn't store data there, but so does GIMP :)*/ - SHGetSpecialFolderPathW(0, dir_16, CSIDL_PROFILE, 0); - conv_utf_16_to_8(dir_16, dir, FILE_MAX); - s += strlen(dir); + wchar_t dir_16[MAX_PATH]; + /* yes, applications shouldn't store data there, but so does GIMP :)*/ + SHGetSpecialFolderPathW(0, dir_16, CSIDL_PROFILE, 0); + conv_utf_16_to_8(dir_16, dir, FILE_MAX); + s += strlen(dir); #else -#if defined(USE_FREEDESKTOP) - const char *home_cache = BLI_getenv("XDG_CACHE_HOME"); - const char *home = home_cache ? home_cache : BLI_getenv("HOME"); -#else - const char *home = BLI_getenv("HOME"); -#endif - if (!home) return 0; - s += BLI_strncpy_rlen(s, home, FILE_MAX); - -#ifdef USE_FREEDESKTOP - if (!home_cache) { - s += BLI_strncpy_rlen(s, "/.cache", FILE_MAX - (s - dir)); - } -#endif +# if defined(USE_FREEDESKTOP) + const char *home_cache = BLI_getenv("XDG_CACHE_HOME"); + const char *home = home_cache ? home_cache : BLI_getenv("HOME"); +# else + const char *home = BLI_getenv("HOME"); +# endif + if (!home) + return 0; + s += BLI_strncpy_rlen(s, home, FILE_MAX); + +# ifdef USE_FREEDESKTOP + if (!home_cache) { + s += BLI_strncpy_rlen(s, "/.cache", FILE_MAX - (s - dir)); + } +# endif #endif - switch (size) { - case THB_NORMAL: - subdir = "/" THUMBNAILS "/normal/"; - break; - case THB_LARGE: - subdir = "/" THUMBNAILS "/large/"; - break; - case THB_FAIL: - subdir = "/" THUMBNAILS "/fail/blender/"; - break; - default: - return 0; /* unknown size */ - } - - s += BLI_strncpy_rlen(s, subdir, FILE_MAX - (s - dir)); - (void)s; - - return 1; + switch (size) { + case THB_NORMAL: + subdir = "/" THUMBNAILS "/normal/"; + break; + case THB_LARGE: + subdir = "/" THUMBNAILS "/large/"; + break; + case THB_FAIL: + subdir = "/" THUMBNAILS "/fail/blender/"; + break; + default: + return 0; /* unknown size */ + } + + s += BLI_strncpy_rlen(s, subdir, FILE_MAX - (s - dir)); + (void)s; + + return 1; } #undef THUMBNAILS - /** ----- begin of adapted code from glib --- * The following code is adapted from function g_escape_uri_string from the gnome glib * Source: http://svn.gnome.org/viewcvs/glib/trunk/glib/gconvert.c?view=markup * released under the Gnu General Public License. */ typedef enum { - UNSAFE_ALL = 0x1, /* Escape all unsafe characters */ - UNSAFE_ALLOW_PLUS = 0x2, /* Allows '+' */ - UNSAFE_PATH = 0x8, /* Allows '/', '&', '=', ':', '@', '+', '$' and ',' */ - UNSAFE_HOST = 0x10, /* Allows '/' and ':' and '@' */ - UNSAFE_SLASHES = 0x20, /* Allows all characters except for '/' and '%' */ + UNSAFE_ALL = 0x1, /* Escape all unsafe characters */ + UNSAFE_ALLOW_PLUS = 0x2, /* Allows '+' */ + UNSAFE_PATH = 0x8, /* Allows '/', '&', '=', ':', '@', '+', '$' and ',' */ + UNSAFE_HOST = 0x10, /* Allows '/' and ':' and '@' */ + UNSAFE_SLASHES = 0x20, /* Allows all characters except for '/' and '%' */ } UnsafeCharacterSet; static const unsigned char acceptable[96] = { - /* A table of the ASCII chars from space (32) to DEL (127) */ - /* ! " # $ % & ' ( ) * + , - . / */ - 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C, - /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ - 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20, - /* @ A B C D E F G H I J K L M N O */ - 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, - /* P Q R S T U V W X Y Z [ \ ] ^ _ */ - 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F, - /* ` a b c d e f g h i j k l m n o */ - 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, - /* p q r s t u v w x y z { | } ~ DEL */ - 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20, + /* A table of the ASCII chars from space (32) to DEL (127) */ + /* ! " # $ % & ' ( ) * + , - . / */ + 0x00, + 0x3F, + 0x20, + 0x20, + 0x28, + 0x00, + 0x2C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x2A, + 0x28, + 0x3F, + 0x3F, + 0x1C, + /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x38, + 0x20, + 0x20, + 0x2C, + 0x20, + 0x20, + /* @ A B C D E F G H I J K L M N O */ + 0x38, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + /* P Q R S T U V W X Y Z [ \ ] ^ _ */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x20, + 0x20, + 0x20, + 0x20, + 0x3F, + /* ` a b c d e f g h i j k l m n o */ + 0x20, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + /* p q r s t u v w x y z { | } ~ DEL */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x20, + 0x20, + 0x20, + 0x3F, + 0x20, }; static const char hex[17] = "0123456789abcdef"; /* Note: This escape function works on file: URIs, but if you want to * escape something else, please read RFC-2396 */ -static void escape_uri_string(const char *string, char *escaped_string, int escaped_string_size, UnsafeCharacterSet mask) +static void escape_uri_string(const char *string, + char *escaped_string, + int escaped_string_size, + UnsafeCharacterSet mask) { -#define ACCEPTABLE(a) ((a) >= 32 && (a) < 128 && (acceptable[(a) - 32] & use_mask)) - - const char *p; - char *q; - int c; - UnsafeCharacterSet use_mask; - use_mask = mask; - - BLI_assert(escaped_string_size > 0); - - /* space for \0 */ - escaped_string_size -= 1; - - for (q = escaped_string, p = string; (*p != '\0') && escaped_string_size; p++) { - c = (unsigned char) *p; - - if (!ACCEPTABLE(c)) { - if (escaped_string_size < 3) { - break; - } - - *q++ = '%'; /* means hex coming */ - *q++ = hex[c >> 4]; - *q++ = hex[c & 15]; - escaped_string_size -= 3; - } - else { - *q++ = *p; - escaped_string_size -= 1; - } - } - - *q = '\0'; +#define ACCEPTABLE(a) ((a) >= 32 && (a) < 128 && (acceptable[(a)-32] & use_mask)) + + const char *p; + char *q; + int c; + UnsafeCharacterSet use_mask; + use_mask = mask; + + BLI_assert(escaped_string_size > 0); + + /* space for \0 */ + escaped_string_size -= 1; + + for (q = escaped_string, p = string; (*p != '\0') && escaped_string_size; p++) { + c = (unsigned char)*p; + + if (!ACCEPTABLE(c)) { + if (escaped_string_size < 3) { + break; + } + + *q++ = '%'; /* means hex coming */ + *q++ = hex[c >> 4]; + *q++ = hex[c & 15]; + escaped_string_size -= 3; + } + else { + *q++ = *p; + escaped_string_size -= 1; + } + } + + *q = '\0'; } /** ----- end of adapted code from glib --- */ static bool thumbhash_from_path(const char *UNUSED(path), ThumbSource source, char *r_hash) { - switch (source) { - case THB_SOURCE_FONT: - return IMB_thumb_load_font_get_hash(r_hash); - default: - r_hash[0] = '\0'; - return false; - } + switch (source) { + case THB_SOURCE_FONT: + return IMB_thumb_load_font_get_hash(r_hash); + default: + r_hash[0] = '\0'; + return false; + } } static bool uri_from_filename(const char *path, char *uri) { - char orig_uri[URI_MAX]; - const char *dirstart = path; + char orig_uri[URI_MAX]; + const char *dirstart = path; #ifdef WIN32 - { - char vol[3]; - - BLI_strncpy(orig_uri, "file:///", FILE_MAX); - if (strlen(path) < 2 && path[1] != ':') { - /* not a correct absolute path */ - return 0; - } - /* on windows, using always uppercase drive/volume letter in uri */ - vol[0] = (unsigned char)toupper(path[0]); - vol[1] = ':'; - vol[2] = '\0'; - strcat(orig_uri, vol); - dirstart += 2; - } - strcat(orig_uri, dirstart); - BLI_str_replace_char(orig_uri, '\\', '/'); + { + char vol[3]; + + BLI_strncpy(orig_uri, "file:///", FILE_MAX); + if (strlen(path) < 2 && path[1] != ':') { + /* not a correct absolute path */ + return 0; + } + /* on windows, using always uppercase drive/volume letter in uri */ + vol[0] = (unsigned char)toupper(path[0]); + vol[1] = ':'; + vol[2] = '\0'; + strcat(orig_uri, vol); + dirstart += 2; + } + strcat(orig_uri, dirstart); + BLI_str_replace_char(orig_uri, '\\', '/'); #else - BLI_snprintf(orig_uri, URI_MAX, "file://%s", dirstart); + BLI_snprintf(orig_uri, URI_MAX, "file://%s", dirstart); #endif - escape_uri_string(orig_uri, uri, URI_MAX, UNSAFE_PATH); + escape_uri_string(orig_uri, uri, URI_MAX, UNSAFE_PATH); - return 1; + return 1; } static bool thumbpathname_from_uri( - const char *uri, char *r_path, const int path_len, char *r_name, int name_len, ThumbSize size) + const char *uri, char *r_path, const int path_len, char *r_name, int name_len, ThumbSize size) { - char name_buff[40]; - - if (r_path && !r_name) { - r_name = name_buff; - name_len = sizeof(name_buff); - } - - if (r_name) { - char hexdigest[33]; - unsigned char digest[16]; - BLI_hash_md5_buffer(uri, strlen(uri), digest); - hexdigest[0] = '\0'; - BLI_snprintf(r_name, name_len, "%s.png", BLI_hash_md5_to_hexdigest(digest, hexdigest)); -// printf("%s: '%s' --> '%s'\n", __func__, uri, r_name); - } - - if (r_path) { - char tmppath[FILE_MAX]; - - if (get_thumb_dir(tmppath, size)) { - BLI_snprintf(r_path, path_len, "%s%s", tmppath, r_name); -// printf("%s: '%s' --> '%s'\n", __func__, uri, r_path); - return true; - } - } - return false; + char name_buff[40]; + + if (r_path && !r_name) { + r_name = name_buff; + name_len = sizeof(name_buff); + } + + if (r_name) { + char hexdigest[33]; + unsigned char digest[16]; + BLI_hash_md5_buffer(uri, strlen(uri), digest); + hexdigest[0] = '\0'; + BLI_snprintf(r_name, name_len, "%s.png", BLI_hash_md5_to_hexdigest(digest, hexdigest)); + // printf("%s: '%s' --> '%s'\n", __func__, uri, r_name); + } + + if (r_path) { + char tmppath[FILE_MAX]; + + if (get_thumb_dir(tmppath, size)) { + BLI_snprintf(r_path, path_len, "%s%s", tmppath, r_name); + // printf("%s: '%s' --> '%s'\n", __func__, uri, r_path); + return true; + } + } + return false; } static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_len) { - thumbpathname_from_uri(uri, NULL, 0, thumb, thumb_len, THB_FAIL); + thumbpathname_from_uri(uri, NULL, 0, thumb, thumb_len, THB_FAIL); } static bool thumbpath_from_uri(const char *uri, char *path, const int path_len, ThumbSize size) { - return thumbpathname_from_uri(uri, path, path_len, NULL, 0, size); + return thumbpathname_from_uri(uri, path, path_len, NULL, 0, size); } void IMB_thumb_makedirs(void) { - char tpath[FILE_MAX]; -#if 0 /* UNUSED */ - if (get_thumb_dir(tpath, THB_NORMAL)) { - BLI_dir_create_recursive(tpath); - } + char tpath[FILE_MAX]; +#if 0 /* UNUSED */ + if (get_thumb_dir(tpath, THB_NORMAL)) { + BLI_dir_create_recursive(tpath); + } #endif - if (get_thumb_dir(tpath, THB_LARGE)) { - BLI_dir_create_recursive(tpath); - } - if (get_thumb_dir(tpath, THB_FAIL)) { - BLI_dir_create_recursive(tpath); - } + if (get_thumb_dir(tpath, THB_LARGE)) { + BLI_dir_create_recursive(tpath); + } + if (get_thumb_dir(tpath, THB_FAIL)) { + BLI_dir_create_recursive(tpath); + } } /* create thumbnail for file and returns new imbuf for thumbnail */ -static ImBuf *thumb_create_ex( - const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash, - const char *blen_group, const char *blen_id, - ThumbSize size, ThumbSource source, ImBuf *img) +static ImBuf *thumb_create_ex(const char *file_path, + const char *uri, + const char *thumb, + const bool use_hash, + const char *hash, + const char *blen_group, + const char *blen_id, + ThumbSize size, + ThumbSource source, + ImBuf *img) { - char desc[URI_MAX + 22]; - char tpath[FILE_MAX]; - char tdir[FILE_MAX]; - char temp[FILE_MAX]; - char mtime[40] = "0"; /* in case we can't stat the file */ - char cwidth[40] = "0"; /* in case images have no data */ - char cheight[40] = "0"; - short tsize = 128; - short ex, ey; - float scaledx, scaledy; - BLI_stat_t info; - - switch (size) { - case THB_NORMAL: - tsize = PREVIEW_RENDER_DEFAULT_HEIGHT; - break; - case THB_LARGE: - tsize = PREVIEW_RENDER_DEFAULT_HEIGHT * 2; - break; - case THB_FAIL: - tsize = 1; - break; - default: - return NULL; /* unknown size */ - } - - /* exception, skip images over 100mb */ - if (source == THB_SOURCE_IMAGE) { - const size_t file_size = BLI_file_size(file_path); - if (file_size != -1 && file_size > THUMB_SIZE_MAX) { - // printf("file too big: %d, skipping %s\n", (int)size, file_path); - return NULL; - } - } - - if (get_thumb_dir(tdir, size)) { - BLI_snprintf(tpath, FILE_MAX, "%s%s", tdir, thumb); -// thumb[8] = '\0'; /* shorten for tempname, not needed anymore */ - BLI_snprintf(temp, FILE_MAX, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb); - if (BLI_path_ncmp(file_path, tdir, sizeof(tdir)) == 0) { - return NULL; - } - if (size == THB_FAIL) { - img = IMB_allocImBuf(1, 1, 32, IB_rect | IB_metadata); - if (!img) return NULL; - } - else { - if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { - /* only load if we didn't give an image */ - if (img == NULL) { - switch (source) { - case THB_SOURCE_IMAGE: - img = IMB_loadiffname(file_path, IB_rect | IB_metadata, NULL); - break; - case THB_SOURCE_BLEND: - img = IMB_thumb_load_blend(file_path, blen_group, blen_id); - break; - case THB_SOURCE_FONT: - img = IMB_thumb_load_font(file_path, tsize, tsize); - break; - default: - BLI_assert(0); /* This should never happen */ - } - } - - if (img != NULL) { - if (BLI_stat(file_path, &info) != -1) { - BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime); - } - BLI_snprintf(cwidth, sizeof(cwidth), "%d", img->x); - BLI_snprintf(cheight, sizeof(cheight), "%d", img->y); - } - } - else if (THB_SOURCE_MOVIE == source) { - struct anim *anim = NULL; - anim = IMB_open_anim(file_path, IB_rect | IB_metadata, 0, NULL); - if (anim != NULL) { - img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); - if (img == NULL) { - printf("not an anim; %s\n", file_path); - } - else { - IMB_freeImBuf(img); - img = IMB_anim_previewframe(anim); - } - IMB_free_anim(anim); - } - if (BLI_stat(file_path, &info) != -1) { - BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime); - } - } - if (!img) return NULL; - - if (img->x > img->y) { - scaledx = (float)tsize; - scaledy = ( (float)img->y / (float)img->x) * tsize; - } - else { - scaledy = (float)tsize; - scaledx = ( (float)img->x / (float)img->y) * tsize; - } - ex = (short)scaledx; - ey = (short)scaledy; - - /* save some time by only scaling byte buf */ - if (img->rect_float) { - if (img->rect == NULL) { - IMB_rect_from_float(img); - } - - imb_freerectfloatImBuf(img); - } - - IMB_scaleImBuf(img, ex, ey); - } - BLI_snprintf(desc, sizeof(desc), "Thumbnail for %s", uri); - IMB_metadata_ensure(&img->metadata); - IMB_metadata_set_field(img->metadata, "Software", "Blender"); - IMB_metadata_set_field(img->metadata, "Thumb::URI", uri); - IMB_metadata_set_field(img->metadata, "Description", desc); - IMB_metadata_set_field(img->metadata, "Thumb::MTime", mtime); - if (use_hash) { - IMB_metadata_set_field(img->metadata, "X-Blender::Hash", hash); - } - if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { - IMB_metadata_set_field(img->metadata, "Thumb::Image::Width", cwidth); - IMB_metadata_set_field(img->metadata, "Thumb::Image::Height", cheight); - } - img->ftype = IMB_FTYPE_PNG; - img->planes = 32; - - /* If we generated from a 16bit PNG e.g., we have a float rect, not a byte one - fix this. */ - IMB_rect_from_float(img); - imb_freerectfloatImBuf(img); - - if (IMB_saveiff(img, temp, IB_rect | IB_metadata)) { + char desc[URI_MAX + 22]; + char tpath[FILE_MAX]; + char tdir[FILE_MAX]; + char temp[FILE_MAX]; + char mtime[40] = "0"; /* in case we can't stat the file */ + char cwidth[40] = "0"; /* in case images have no data */ + char cheight[40] = "0"; + short tsize = 128; + short ex, ey; + float scaledx, scaledy; + BLI_stat_t info; + + switch (size) { + case THB_NORMAL: + tsize = PREVIEW_RENDER_DEFAULT_HEIGHT; + break; + case THB_LARGE: + tsize = PREVIEW_RENDER_DEFAULT_HEIGHT * 2; + break; + case THB_FAIL: + tsize = 1; + break; + default: + return NULL; /* unknown size */ + } + + /* exception, skip images over 100mb */ + if (source == THB_SOURCE_IMAGE) { + const size_t file_size = BLI_file_size(file_path); + if (file_size != -1 && file_size > THUMB_SIZE_MAX) { + // printf("file too big: %d, skipping %s\n", (int)size, file_path); + return NULL; + } + } + + if (get_thumb_dir(tdir, size)) { + BLI_snprintf(tpath, FILE_MAX, "%s%s", tdir, thumb); + // thumb[8] = '\0'; /* shorten for tempname, not needed anymore */ + BLI_snprintf(temp, FILE_MAX, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb); + if (BLI_path_ncmp(file_path, tdir, sizeof(tdir)) == 0) { + return NULL; + } + if (size == THB_FAIL) { + img = IMB_allocImBuf(1, 1, 32, IB_rect | IB_metadata); + if (!img) + return NULL; + } + else { + if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { + /* only load if we didn't give an image */ + if (img == NULL) { + switch (source) { + case THB_SOURCE_IMAGE: + img = IMB_loadiffname(file_path, IB_rect | IB_metadata, NULL); + break; + case THB_SOURCE_BLEND: + img = IMB_thumb_load_blend(file_path, blen_group, blen_id); + break; + case THB_SOURCE_FONT: + img = IMB_thumb_load_font(file_path, tsize, tsize); + break; + default: + BLI_assert(0); /* This should never happen */ + } + } + + if (img != NULL) { + if (BLI_stat(file_path, &info) != -1) { + BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime); + } + BLI_snprintf(cwidth, sizeof(cwidth), "%d", img->x); + BLI_snprintf(cheight, sizeof(cheight), "%d", img->y); + } + } + else if (THB_SOURCE_MOVIE == source) { + struct anim *anim = NULL; + anim = IMB_open_anim(file_path, IB_rect | IB_metadata, 0, NULL); + if (anim != NULL) { + img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); + if (img == NULL) { + printf("not an anim; %s\n", file_path); + } + else { + IMB_freeImBuf(img); + img = IMB_anim_previewframe(anim); + } + IMB_free_anim(anim); + } + if (BLI_stat(file_path, &info) != -1) { + BLI_snprintf(mtime, sizeof(mtime), "%ld", (long int)info.st_mtime); + } + } + if (!img) + return NULL; + + if (img->x > img->y) { + scaledx = (float)tsize; + scaledy = ((float)img->y / (float)img->x) * tsize; + } + else { + scaledy = (float)tsize; + scaledx = ((float)img->x / (float)img->y) * tsize; + } + ex = (short)scaledx; + ey = (short)scaledy; + + /* save some time by only scaling byte buf */ + if (img->rect_float) { + if (img->rect == NULL) { + IMB_rect_from_float(img); + } + + imb_freerectfloatImBuf(img); + } + + IMB_scaleImBuf(img, ex, ey); + } + BLI_snprintf(desc, sizeof(desc), "Thumbnail for %s", uri); + IMB_metadata_ensure(&img->metadata); + IMB_metadata_set_field(img->metadata, "Software", "Blender"); + IMB_metadata_set_field(img->metadata, "Thumb::URI", uri); + IMB_metadata_set_field(img->metadata, "Description", desc); + IMB_metadata_set_field(img->metadata, "Thumb::MTime", mtime); + if (use_hash) { + IMB_metadata_set_field(img->metadata, "X-Blender::Hash", hash); + } + if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) { + IMB_metadata_set_field(img->metadata, "Thumb::Image::Width", cwidth); + IMB_metadata_set_field(img->metadata, "Thumb::Image::Height", cheight); + } + img->ftype = IMB_FTYPE_PNG; + img->planes = 32; + + /* If we generated from a 16bit PNG e.g., we have a float rect, not a byte one - fix this. */ + IMB_rect_from_float(img); + imb_freerectfloatImBuf(img); + + if (IMB_saveiff(img, temp, IB_rect | IB_metadata)) { #ifndef WIN32 - chmod(temp, S_IRUSR | S_IWUSR); + chmod(temp, S_IRUSR | S_IWUSR); #endif - // printf("%s saving thumb: '%s'\n", __func__, tpath); + // printf("%s saving thumb: '%s'\n", __func__, tpath); - BLI_rename(temp, tpath); - } - } - return img; + BLI_rename(temp, tpath); + } + } + return img; } -static ImBuf *thumb_create_or_fail( - const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash, - const char *blen_group, const char *blen_id, ThumbSize size, ThumbSource source) +static ImBuf *thumb_create_or_fail(const char *file_path, + const char *uri, + const char *thumb, + const bool use_hash, + const char *hash, + const char *blen_group, + const char *blen_id, + ThumbSize size, + ThumbSource source) { - ImBuf *img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, blen_group, blen_id, size, source, NULL); - - if (!img) { - /* thumb creation failed, write fail thumb */ - img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, blen_group, blen_id, THB_FAIL, source, NULL); - if (img) { - /* we don't need failed thumb anymore */ - IMB_freeImBuf(img); - img = NULL; - } - } - - return img; + ImBuf *img = thumb_create_ex( + file_path, uri, thumb, use_hash, hash, blen_group, blen_id, size, source, NULL); + + if (!img) { + /* thumb creation failed, write fail thumb */ + img = thumb_create_ex( + file_path, uri, thumb, use_hash, hash, blen_group, blen_id, THB_FAIL, source, NULL); + if (img) { + /* we don't need failed thumb anymore */ + IMB_freeImBuf(img); + img = NULL; + } + } + + return img; } ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img) { - char uri[URI_MAX] = ""; - char thumb_name[40]; + char uri[URI_MAX] = ""; + char thumb_name[40]; - if (!uri_from_filename(path, uri)) { - return NULL; - } - thumbname_from_uri(uri, thumb_name, sizeof(thumb_name)); + if (!uri_from_filename(path, uri)) { + return NULL; + } + thumbname_from_uri(uri, thumb_name, sizeof(thumb_name)); - return thumb_create_ex(path, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img); + return thumb_create_ex( + path, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img); } /* read thumbnail for file and returns new imbuf for thumbnail */ ImBuf *IMB_thumb_read(const char *path, ThumbSize size) { - char thumb[FILE_MAX]; - char uri[URI_MAX]; - ImBuf *img = NULL; - - if (!uri_from_filename(path, uri)) { - return NULL; - } - if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { - img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); - } - - return img; + char thumb[FILE_MAX]; + char uri[URI_MAX]; + ImBuf *img = NULL; + + if (!uri_from_filename(path, uri)) { + return NULL; + } + if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { + img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); + } + + return img; } /* delete all thumbs for the file */ void IMB_thumb_delete(const char *path, ThumbSize size) { - char thumb[FILE_MAX]; - char uri[URI_MAX]; - - if (!uri_from_filename(path, uri)) { - return; - } - if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { - if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) { - return; - } - if (BLI_exists(thumb)) { - BLI_delete(thumb, false, false); - } - } + char thumb[FILE_MAX]; + char uri[URI_MAX]; + + if (!uri_from_filename(path, uri)) { + return; + } + if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { + if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) { + return; + } + if (BLI_exists(thumb)) { + BLI_delete(thumb, false, false); + } + } } - /* create the thumb if necessary and manage failed and old thumbs */ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source) { - char thumb_path[FILE_MAX]; - char thumb_name[40]; - char uri[URI_MAX]; - char path_buff[FILE_MAX_LIBEXTRA]; - const char *file_path; - const char *path; - BLI_stat_t st; - ImBuf *img = NULL; - char *blen_group = NULL, *blen_id = NULL; - - path = file_path = org_path; - if (source == THB_SOURCE_BLEND) { - if (BLO_library_path_explode(path, path_buff, &blen_group, &blen_id)) { - if (blen_group) { - if (!blen_id) { - /* No preview for blen groups */ - return NULL; - } - file_path = path_buff; /* path needs to be a valid file! */ - } - } - } - - if (BLI_stat(file_path, &st) == -1) { - return NULL; - } - if (!uri_from_filename(path, uri)) { - return NULL; - } - if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), THB_FAIL)) { - /* failure thumb exists, don't try recreating */ - if (BLI_exists(thumb_path)) { - /* clear out of date fail case (note for blen IDs we use blender file itself here) */ - if (BLI_file_older(thumb_path, file_path)) { - BLI_delete(thumb_path, false, false); - } - else { - return NULL; - } - } - } - - if (thumbpathname_from_uri(uri, thumb_path, sizeof(thumb_path), thumb_name, sizeof(thumb_name), size)) { - if (BLI_path_ncmp(path, thumb_path, sizeof(thumb_path)) == 0) { - img = IMB_loadiffname(path, IB_rect, NULL); - } - else { - img = IMB_loadiffname(thumb_path, IB_rect | IB_metadata, NULL); - if (img) { - bool regenerate = false; - - char mtime[40]; - char thumb_hash[33]; - char thumb_hash_curr[33]; - - const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash); - - if (IMB_metadata_get_field(img->metadata, "Thumb::MTime", mtime, sizeof(mtime))) { - regenerate = (st.st_mtime != atol(mtime)); - } - else { - /* illegal thumb, regenerate it! */ - regenerate = true; - } - - if (use_hash && !regenerate) { - if (IMB_metadata_get_field(img->metadata, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) { - regenerate = !STREQ(thumb_hash, thumb_hash_curr); - } - else { - regenerate = true; - } - } - - if (regenerate) { - /* recreate all thumbs */ - IMB_freeImBuf(img); - img = NULL; - IMB_thumb_delete(path, THB_NORMAL); - IMB_thumb_delete(path, THB_LARGE); - IMB_thumb_delete(path, THB_FAIL); - img = thumb_create_or_fail( - file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source); - } - } - else { - char thumb_hash[33]; - const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash); - - img = thumb_create_or_fail( - file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source); - } - } - } - - /* Our imbuf **must** have a valid rect (i.e. 8-bits/channels) data, we rely on this in draw code. - * However, in some cases we may end loading 16bits PNGs, which generated float buffers. - * This should be taken care of in generation step, but add also a safeguard here! */ - if (img) { - IMB_rect_from_float(img); - imb_freerectfloatImBuf(img); - } - - return img; + char thumb_path[FILE_MAX]; + char thumb_name[40]; + char uri[URI_MAX]; + char path_buff[FILE_MAX_LIBEXTRA]; + const char *file_path; + const char *path; + BLI_stat_t st; + ImBuf *img = NULL; + char *blen_group = NULL, *blen_id = NULL; + + path = file_path = org_path; + if (source == THB_SOURCE_BLEND) { + if (BLO_library_path_explode(path, path_buff, &blen_group, &blen_id)) { + if (blen_group) { + if (!blen_id) { + /* No preview for blen groups */ + return NULL; + } + file_path = path_buff; /* path needs to be a valid file! */ + } + } + } + + if (BLI_stat(file_path, &st) == -1) { + return NULL; + } + if (!uri_from_filename(path, uri)) { + return NULL; + } + if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), THB_FAIL)) { + /* failure thumb exists, don't try recreating */ + if (BLI_exists(thumb_path)) { + /* clear out of date fail case (note for blen IDs we use blender file itself here) */ + if (BLI_file_older(thumb_path, file_path)) { + BLI_delete(thumb_path, false, false); + } + else { + return NULL; + } + } + } + + if (thumbpathname_from_uri( + uri, thumb_path, sizeof(thumb_path), thumb_name, sizeof(thumb_name), size)) { + if (BLI_path_ncmp(path, thumb_path, sizeof(thumb_path)) == 0) { + img = IMB_loadiffname(path, IB_rect, NULL); + } + else { + img = IMB_loadiffname(thumb_path, IB_rect | IB_metadata, NULL); + if (img) { + bool regenerate = false; + + char mtime[40]; + char thumb_hash[33]; + char thumb_hash_curr[33]; + + const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash); + + if (IMB_metadata_get_field(img->metadata, "Thumb::MTime", mtime, sizeof(mtime))) { + regenerate = (st.st_mtime != atol(mtime)); + } + else { + /* illegal thumb, regenerate it! */ + regenerate = true; + } + + if (use_hash && !regenerate) { + if (IMB_metadata_get_field( + img->metadata, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) { + regenerate = !STREQ(thumb_hash, thumb_hash_curr); + } + else { + regenerate = true; + } + } + + if (regenerate) { + /* recreate all thumbs */ + IMB_freeImBuf(img); + img = NULL; + IMB_thumb_delete(path, THB_NORMAL); + IMB_thumb_delete(path, THB_LARGE); + IMB_thumb_delete(path, THB_FAIL); + img = thumb_create_or_fail( + file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source); + } + } + else { + char thumb_hash[33]; + const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash); + + img = thumb_create_or_fail( + file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source); + } + } + } + + /* Our imbuf **must** have a valid rect (i.e. 8-bits/channels) data, we rely on this in draw code. + * However, in some cases we may end loading 16bits PNGs, which generated float buffers. + * This should be taken care of in generation step, but add also a safeguard here! */ + if (img) { + IMB_rect_from_float(img); + imb_freerectfloatImBuf(img); + } + + return img; } /* ***** Threading ***** */ @@ -641,71 +752,71 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source */ static struct IMBThumbLocks { - GSet *locked_paths; - int lock_counter; - ThreadCondition cond; + GSet *locked_paths; + int lock_counter; + ThreadCondition cond; } thumb_locks = {0}; void IMB_thumb_locks_acquire(void) { - BLI_thread_lock(LOCK_IMAGE); - - if (thumb_locks.lock_counter == 0) { - BLI_assert(thumb_locks.locked_paths == NULL); - thumb_locks.locked_paths = BLI_gset_str_new(__func__); - BLI_condition_init(&thumb_locks.cond); - } - thumb_locks.lock_counter++; - - BLI_assert(thumb_locks.locked_paths != NULL); - BLI_assert(thumb_locks.lock_counter > 0); - BLI_thread_unlock(LOCK_IMAGE); + BLI_thread_lock(LOCK_IMAGE); + + if (thumb_locks.lock_counter == 0) { + BLI_assert(thumb_locks.locked_paths == NULL); + thumb_locks.locked_paths = BLI_gset_str_new(__func__); + BLI_condition_init(&thumb_locks.cond); + } + thumb_locks.lock_counter++; + + BLI_assert(thumb_locks.locked_paths != NULL); + BLI_assert(thumb_locks.lock_counter > 0); + BLI_thread_unlock(LOCK_IMAGE); } void IMB_thumb_locks_release(void) { - BLI_thread_lock(LOCK_IMAGE); - BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + BLI_thread_lock(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); - thumb_locks.lock_counter--; - if (thumb_locks.lock_counter == 0) { - BLI_gset_free(thumb_locks.locked_paths, MEM_freeN); - thumb_locks.locked_paths = NULL; - BLI_condition_end(&thumb_locks.cond); - } + thumb_locks.lock_counter--; + if (thumb_locks.lock_counter == 0) { + BLI_gset_free(thumb_locks.locked_paths, MEM_freeN); + thumb_locks.locked_paths = NULL; + BLI_condition_end(&thumb_locks.cond); + } - BLI_thread_unlock(LOCK_IMAGE); + BLI_thread_unlock(LOCK_IMAGE); } void IMB_thumb_path_lock(const char *path) { - void *key = BLI_strdup(path); + void *key = BLI_strdup(path); - BLI_thread_lock(LOCK_IMAGE); - BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + BLI_thread_lock(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); - if (thumb_locks.locked_paths) { - while (!BLI_gset_add(thumb_locks.locked_paths, key)) { - BLI_condition_wait_global_mutex(&thumb_locks.cond, LOCK_IMAGE); - } - } + if (thumb_locks.locked_paths) { + while (!BLI_gset_add(thumb_locks.locked_paths, key)) { + BLI_condition_wait_global_mutex(&thumb_locks.cond, LOCK_IMAGE); + } + } - BLI_thread_unlock(LOCK_IMAGE); + BLI_thread_unlock(LOCK_IMAGE); } void IMB_thumb_path_unlock(const char *path) { - const void *key = path; + const void *key = path; - BLI_thread_lock(LOCK_IMAGE); - BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + BLI_thread_lock(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); - if (thumb_locks.locked_paths) { - if (!BLI_gset_remove(thumb_locks.locked_paths, key, MEM_freeN)) { - BLI_assert(0); - } - BLI_condition_notify_all(&thumb_locks.cond); - } + if (thumb_locks.locked_paths) { + if (!BLI_gset_remove(thumb_locks.locked_paths, key, MEM_freeN)) { + BLI_assert(0); + } + BLI_condition_notify_all(&thumb_locks.cond); + } - BLI_thread_unlock(LOCK_IMAGE); + BLI_thread_unlock(LOCK_IMAGE); } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index 92005371c2a..20a419d1a16 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -18,13 +18,12 @@ * \ingroup imbuf */ - #include #include #include "BLI_utildefines.h" #include "BLI_linklist.h" -#include "BLI_listbase.h" /* Needed due to import of BLO_readfile.h */ +#include "BLI_listbase.h" /* Needed due to import of BLO_readfile.h */ #include "BLO_blend_defs.h" #include "BLO_readfile.h" @@ -33,7 +32,7 @@ #include "BKE_icons.h" #include "BKE_main.h" -#include "DNA_ID.h" /* For preview images... */ +#include "DNA_ID.h" /* For preview images... */ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -43,70 +42,70 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id) { - ImBuf *ima = NULL; - - if (blen_group && blen_id) { - LinkNode *ln, *names, *lp, *previews = NULL; - struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, NULL); - int idcode = BKE_idcode_from_name(blen_group); - int i, nprevs, nnames; - - if (libfiledata == NULL) { - return ima; - } - - /* Note: we should handle all previews for a same group at once, would avoid reopening .blend file - * for each and every ID. However, this adds some complexity, so keep it for later. */ - names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames); - previews = BLO_blendhandle_get_previews(libfiledata, idcode, &nprevs); - - BLO_blendhandle_close(libfiledata); - - if (!previews || (nnames != nprevs)) { - if (previews != 0) { - /* No previews at all is not a bug! */ - printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs); - } - BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, free); - return ima; - } - - for (i = 0, ln = names, lp = previews; i < nnames; i++, ln = ln->next, lp = lp->next) { - const char *blockname = ln->link; - PreviewImage *img = lp->link; - - if (STREQ(blockname, blen_id)) { - if (img) { - unsigned int w = img->w[ICON_SIZE_PREVIEW]; - unsigned int h = img->h[ICON_SIZE_PREVIEW]; - unsigned int *rect = img->rect[ICON_SIZE_PREVIEW]; - - if (w > 0 && h > 0 && rect) { - /* first allocate imbuf for copying preview into it */ - ima = IMB_allocImBuf(w, h, 32, IB_rect); - memcpy(ima->rect, rect, w * h * sizeof(unsigned int)); - } - } - break; - } - } - - BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, free); - } - else { - BlendThumbnail *data; - - data = BLO_thumbnail_from_file(blen_path); - ima = BKE_main_thumbnail_to_imbuf(NULL, data); - - if (data) { - MEM_freeN(data); - } - } - - return ima; + ImBuf *ima = NULL; + + if (blen_group && blen_id) { + LinkNode *ln, *names, *lp, *previews = NULL; + struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, NULL); + int idcode = BKE_idcode_from_name(blen_group); + int i, nprevs, nnames; + + if (libfiledata == NULL) { + return ima; + } + + /* Note: we should handle all previews for a same group at once, would avoid reopening .blend file + * for each and every ID. However, this adds some complexity, so keep it for later. */ + names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames); + previews = BLO_blendhandle_get_previews(libfiledata, idcode, &nprevs); + + BLO_blendhandle_close(libfiledata); + + if (!previews || (nnames != nprevs)) { + if (previews != 0) { + /* No previews at all is not a bug! */ + printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs); + } + BLI_linklist_free(previews, BKE_previewimg_freefunc); + BLI_linklist_free(names, free); + return ima; + } + + for (i = 0, ln = names, lp = previews; i < nnames; i++, ln = ln->next, lp = lp->next) { + const char *blockname = ln->link; + PreviewImage *img = lp->link; + + if (STREQ(blockname, blen_id)) { + if (img) { + unsigned int w = img->w[ICON_SIZE_PREVIEW]; + unsigned int h = img->h[ICON_SIZE_PREVIEW]; + unsigned int *rect = img->rect[ICON_SIZE_PREVIEW]; + + if (w > 0 && h > 0 && rect) { + /* first allocate imbuf for copying preview into it */ + ima = IMB_allocImBuf(w, h, 32, IB_rect); + memcpy(ima->rect, rect, w * h * sizeof(unsigned int)); + } + } + break; + } + } + + BLI_linklist_free(previews, BKE_previewimg_freefunc); + BLI_linklist_free(names, free); + } + else { + BlendThumbnail *data; + + data = BLO_thumbnail_from_file(blen_path); + ima = BKE_main_thumbnail_to_imbuf(NULL, data); + + if (data) { + MEM_freeN(data); + } + } + + return ima; } /* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */ @@ -114,54 +113,55 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect) { - unsigned char *px = (unsigned char *)thumb; - int margin_l = MARGIN; - int margin_b = MARGIN; - int margin_r = width - MARGIN; - int margin_t = height - MARGIN; - - if (aspect < 1.0f) { - margin_l = (int)((width - ((float)width * aspect)) / 2.0f); - margin_l += MARGIN; - CLAMP(margin_l, MARGIN, (width / 2)); - margin_r = width - margin_l; - } - else if (aspect > 1.0f) { - margin_b = (int)((height - ((float)height / aspect)) / 2.0f); - margin_b += MARGIN; - CLAMP(margin_b, MARGIN, (height / 2)); - margin_t = height - margin_b; - } - - { - int x, y; - int stride_x = (margin_r - margin_l) - 2; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++, px += 4) { - int hline = 0, vline = 0; - if ((x > margin_l && x < margin_r) && (y > margin_b && y < margin_t)) { - /* interior. skip */ - x += stride_x; - px += stride_x * 4; - } - else if ((hline = (((x == margin_l || x == margin_r)) && y >= margin_b && y <= margin_t)) || - (vline = (((y == margin_b || y == margin_t)) && x >= margin_l && x <= margin_r))) - { - /* dashed line */ - if ((hline && y % 2) || (vline && x % 2)) { - px[0] = px[1] = px[2] = 0; - px[3] = 255; - } - } - else { - /* outside, fill in alpha, like passepartout */ - px[0] *= 0.5f; - px[1] *= 0.5f; - px[2] *= 0.5f; - px[3] = (px[3] * 0.5f) + 96; - } - } - } - } + unsigned char *px = (unsigned char *)thumb; + int margin_l = MARGIN; + int margin_b = MARGIN; + int margin_r = width - MARGIN; + int margin_t = height - MARGIN; + + if (aspect < 1.0f) { + margin_l = (int)((width - ((float)width * aspect)) / 2.0f); + margin_l += MARGIN; + CLAMP(margin_l, MARGIN, (width / 2)); + margin_r = width - margin_l; + } + else if (aspect > 1.0f) { + margin_b = (int)((height - ((float)height / aspect)) / 2.0f); + margin_b += MARGIN; + CLAMP(margin_b, MARGIN, (height / 2)); + margin_t = height - margin_b; + } + + { + int x, y; + int stride_x = (margin_r - margin_l) - 2; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++, px += 4) { + int hline = 0, vline = 0; + if ((x > margin_l && x < margin_r) && (y > margin_b && y < margin_t)) { + /* interior. skip */ + x += stride_x; + px += stride_x * 4; + } + else if ((hline = (((x == margin_l || x == margin_r)) && y >= margin_b && + y <= margin_t)) || + (vline = (((y == margin_b || y == margin_t)) && x >= margin_l && + x <= margin_r))) { + /* dashed line */ + if ((hline && y % 2) || (vline && x % 2)) { + px[0] = px[1] = px[2] = 0; + px[3] = 255; + } + } + else { + /* outside, fill in alpha, like passepartout */ + px[0] *= 0.5f; + px[1] *= 0.5f; + px[2] *= 0.5f; + px[3] = (px[3] * 0.5f) + 96; + } + } + } + } } diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c index ec45749e513..1213927d329 100644 --- a/source/blender/imbuf/intern/thumbs_font.c +++ b/source/blender/imbuf/intern/thumbs_font.c @@ -28,7 +28,6 @@ #include "IMB_thumbs.h" - /* XXX, bad level call */ #include "../../blenfont/BLF_api.h" #include "../../blentranslation/BLT_translation.h" @@ -44,51 +43,57 @@ static const char *thumb_str[] = { struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y) { - const int font_size = y / 4; + const int font_size = y / 4; - struct ImBuf *ibuf; - float font_color[4]; + struct ImBuf *ibuf; + float font_color[4]; - /* create a white image (theme color is used for drawing) */ - font_color[0] = font_color[1] = font_color[2] = 1.0f; + /* create a white image (theme color is used for drawing) */ + font_color[0] = font_color[1] = font_color[2] = 1.0f; - /* fill with zero alpha */ - font_color[3] = 0.0f; + /* fill with zero alpha */ + font_color[3] = 0.0f; - ibuf = IMB_allocImBuf(x, y, 32, IB_rect | IB_metadata); - IMB_rectfill(ibuf, font_color); + ibuf = IMB_allocImBuf(x, y, 32, IB_rect | IB_metadata); + IMB_rectfill(ibuf, font_color); - /* draw with full alpha */ - font_color[3] = 1.0f; + /* draw with full alpha */ + font_color[3] = 1.0f; - BLF_thumb_preview( - filename, thumb_str, ARRAY_SIZE(thumb_str), - font_color, font_size, - (unsigned char *)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels); + BLF_thumb_preview(filename, + thumb_str, + ARRAY_SIZE(thumb_str), + font_color, + font_size, + (unsigned char *)ibuf->rect, + ibuf->x, + ibuf->y, + ibuf->channels); - return ibuf; + return ibuf; } bool IMB_thumb_load_font_get_hash(char *r_hash) { - char buf[1024]; - char *str = buf; - size_t len = 0; + char buf[1024]; + char *str = buf; + size_t len = 0; - int draw_str_lines = ARRAY_SIZE(thumb_str); - int i; + int draw_str_lines = ARRAY_SIZE(thumb_str); + int i; - unsigned char digest[16]; + unsigned char digest[16]; - len += BLI_strncpy_rlen(str + len, THUMB_DEFAULT_HASH, sizeof(buf) - len); + len += BLI_strncpy_rlen(str + len, THUMB_DEFAULT_HASH, sizeof(buf) - len); - for (i = 0; (i < draw_str_lines) && (len < sizeof(buf)); i++) { - len += BLI_strncpy_rlen(str + len, BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, thumb_str[i]), sizeof(buf) - len); - } + for (i = 0; (i < draw_str_lines) && (len < sizeof(buf)); i++) { + len += BLI_strncpy_rlen( + str + len, BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, thumb_str[i]), sizeof(buf) - len); + } - BLI_hash_md5_buffer(str, len, digest); - r_hash[0] = '\0'; - BLI_hash_md5_to_hexdigest(digest, r_hash); + BLI_hash_md5_buffer(str, len, digest); + r_hash[0] = '\0'; + BLI_hash_md5_to_hexdigest(digest, r_hash); - return true; + return true; } diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 928f1ef7a54..1f2b63a3749 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -18,7 +18,6 @@ * \ingroup imbuf */ - /** * Provides TIFF file loading and saving for Blender, via libtiff. * @@ -55,7 +54,7 @@ #include "tiffio.h" #ifdef WIN32 -#include "utfconv.h" +# include "utfconv.h" #endif /*********************** @@ -64,42 +63,38 @@ /* Reading and writing of an in-memory TIFF file. */ static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n); static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n); -static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence); -static int imb_tiff_CloseProc(thandle_t handle); -static toff_t imb_tiff_SizeProc(thandle_t handle); -static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize); -static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size); - +static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence); +static int imb_tiff_CloseProc(thandle_t handle); +static toff_t imb_tiff_SizeProc(thandle_t handle); +static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize); +static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size); /* Structure for in-memory TIFF file. */ typedef struct ImbTIFFMemFile { - const unsigned char *mem; /* Location of first byte of TIFF file. */ - toff_t offset; /* Current offset within the file. */ - tsize_t size; /* Size of the TIFF file. */ + const unsigned char *mem; /* Location of first byte of TIFF file. */ + toff_t offset; /* Current offset within the file. */ + tsize_t size; /* Size of the TIFF file. */ } ImbTIFFMemFile; #define IMB_TIFF_GET_MEMFILE(x) ((ImbTIFFMemFile *)(x)) - - /***************************** * Function implementations. * *****************************/ - static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) { - (void)fd; - (void)base; - (void)size; + (void)fd; + (void)base; + (void)size; } static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize) { - (void)fd; - (void)pbase; - (void)psize; + (void)fd; + (void)pbase; + (void)psize; - return (0); + return (0); } /** @@ -114,40 +109,38 @@ static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize) */ static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n) { - tsize_t nRemaining, nCopy; - ImbTIFFMemFile *mfile; - void *srcAddr; - - /* get the pointer to the in-memory file */ - mfile = IMB_TIFF_GET_MEMFILE(handle); - if (!mfile || !mfile->mem) { - fprintf(stderr, "imb_tiff_ReadProc: !mfile || !mfile->mem!\n"); - return 0; - } - - /* find the actual number of bytes to read (copy) */ - nCopy = n; - if ((tsize_t)mfile->offset >= mfile->size) - nRemaining = 0; - else - nRemaining = mfile->size - mfile->offset; - - if (nCopy > nRemaining) - nCopy = nRemaining; - - /* on EOF, return immediately and read (copy) nothing */ - if (nCopy <= 0) - return (0); - - /* all set -> do the read (copy) */ - srcAddr = (void *)(&(mfile->mem[mfile->offset])); - memcpy((void *)data, srcAddr, nCopy); - mfile->offset += nCopy; /* advance file ptr by copied bytes */ - return nCopy; + tsize_t nRemaining, nCopy; + ImbTIFFMemFile *mfile; + void *srcAddr; + + /* get the pointer to the in-memory file */ + mfile = IMB_TIFF_GET_MEMFILE(handle); + if (!mfile || !mfile->mem) { + fprintf(stderr, "imb_tiff_ReadProc: !mfile || !mfile->mem!\n"); + return 0; + } + + /* find the actual number of bytes to read (copy) */ + nCopy = n; + if ((tsize_t)mfile->offset >= mfile->size) + nRemaining = 0; + else + nRemaining = mfile->size - mfile->offset; + + if (nCopy > nRemaining) + nCopy = nRemaining; + + /* on EOF, return immediately and read (copy) nothing */ + if (nCopy <= 0) + return (0); + + /* all set -> do the read (copy) */ + srcAddr = (void *)(&(mfile->mem[mfile->offset])); + memcpy((void *)data, srcAddr, nCopy); + mfile->offset += nCopy; /* advance file ptr by copied bytes */ + return nCopy; } - - /** * Writes data to an in-memory TIFF file. * @@ -156,16 +149,14 @@ static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n) */ static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n) { - (void)handle; - (void)data; - (void)n; + (void)handle; + (void)data; + (void)n; - printf("imb_tiff_WriteProc: this function should not be called.\n"); - return (-1); + printf("imb_tiff_WriteProc: this function should not be called.\n"); + return (-1); } - - /** * Seeks to a new location in an in-memory TIFF file. * @@ -182,39 +173,37 @@ static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n) */ static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence) { - ImbTIFFMemFile *mfile; - toff_t new_offset; - - /* get the pointer to the in-memory file */ - mfile = IMB_TIFF_GET_MEMFILE(handle); - if (!mfile || !mfile->mem) { - fprintf(stderr, "imb_tiff_SeekProc: !mfile || !mfile->mem!\n"); - return (-1); - } - - /* find the location we plan to seek to */ - switch (whence) { - case SEEK_SET: - new_offset = ofs; - break; - case SEEK_CUR: - new_offset = mfile->offset + ofs; - break; - default: - /* no other types are supported - return an error */ - fprintf(stderr, - "imb_tiff_SeekProc: " - "Unsupported TIFF SEEK type.\n"); - return (-1); - } - - /* set the new location */ - mfile->offset = new_offset; - return mfile->offset; + ImbTIFFMemFile *mfile; + toff_t new_offset; + + /* get the pointer to the in-memory file */ + mfile = IMB_TIFF_GET_MEMFILE(handle); + if (!mfile || !mfile->mem) { + fprintf(stderr, "imb_tiff_SeekProc: !mfile || !mfile->mem!\n"); + return (-1); + } + + /* find the location we plan to seek to */ + switch (whence) { + case SEEK_SET: + new_offset = ofs; + break; + case SEEK_CUR: + new_offset = mfile->offset + ofs; + break; + default: + /* no other types are supported - return an error */ + fprintf(stderr, + "imb_tiff_SeekProc: " + "Unsupported TIFF SEEK type.\n"); + return (-1); + } + + /* set the new location */ + mfile->offset = new_offset; + return mfile->offset; } - - /** * Closes (virtually) an in-memory TIFF file. * @@ -229,25 +218,23 @@ static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence) */ static int imb_tiff_CloseProc(thandle_t handle) { - ImbTIFFMemFile *mfile; + ImbTIFFMemFile *mfile; - /* get the pointer to the in-memory file */ - mfile = IMB_TIFF_GET_MEMFILE(handle); - if (!mfile || !mfile->mem) { - fprintf(stderr, "imb_tiff_CloseProc: !mfile || !mfile->mem!\n"); - return (0); - } + /* get the pointer to the in-memory file */ + mfile = IMB_TIFF_GET_MEMFILE(handle); + if (!mfile || !mfile->mem) { + fprintf(stderr, "imb_tiff_CloseProc: !mfile || !mfile->mem!\n"); + return (0); + } - /* virtually close the file */ - mfile->mem = NULL; - mfile->offset = 0; - mfile->size = 0; + /* virtually close the file */ + mfile->mem = NULL; + mfile->offset = 0; + mfile->size = 0; - return (0); + return (0); } - - /** * Returns the size of an in-memory TIFF file in bytes. * @@ -255,31 +242,36 @@ static int imb_tiff_CloseProc(thandle_t handle) */ static toff_t imb_tiff_SizeProc(thandle_t handle) { - ImbTIFFMemFile *mfile; + ImbTIFFMemFile *mfile; - /* get the pointer to the in-memory file */ - mfile = IMB_TIFF_GET_MEMFILE(handle); - if (!mfile || !mfile->mem) { - fprintf(stderr, "imb_tiff_SizeProc: !mfile || !mfile->mem!\n"); - return (0); - } + /* get the pointer to the in-memory file */ + mfile = IMB_TIFF_GET_MEMFILE(handle); + if (!mfile || !mfile->mem) { + fprintf(stderr, "imb_tiff_SizeProc: !mfile || !mfile->mem!\n"); + return (0); + } - /* return the size */ - return (toff_t)(mfile->size); + /* return the size */ + return (toff_t)(mfile->size); } static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char *mem, size_t size) { - /* open the TIFF client layer interface to the in-memory file */ - memFile->mem = mem; - memFile->offset = 0; - memFile->size = size; - - return TIFFClientOpen("(Blender TIFF Interface Layer)", - "r", (thandle_t)(memFile), - imb_tiff_ReadProc, imb_tiff_WriteProc, - imb_tiff_SeekProc, imb_tiff_CloseProc, - imb_tiff_SizeProc, imb_tiff_DummyMapProc, imb_tiff_DummyUnmapProc); + /* open the TIFF client layer interface to the in-memory file */ + memFile->mem = mem; + memFile->offset = 0; + memFile->size = size; + + return TIFFClientOpen("(Blender TIFF Interface Layer)", + "r", + (thandle_t)(memFile), + imb_tiff_ReadProc, + imb_tiff_WriteProc, + imb_tiff_SeekProc, + imb_tiff_CloseProc, + imb_tiff_SizeProc, + imb_tiff_DummyMapProc, + imb_tiff_DummyUnmapProc); } /** @@ -297,70 +289,76 @@ static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char * * AFAICT, libtiff doesn't provide a method to do this automatically, and * hence my manual comparison. - Jonathan Merritt (lancelet) 4th Sept 2005. */ -#define IMB_TIFF_NCB 4 /* number of comparison bytes used */ +#define IMB_TIFF_NCB 4 /* number of comparison bytes used */ int imb_is_a_tiff(const unsigned char *mem) { - char big_endian[IMB_TIFF_NCB] = { 0x4d, 0x4d, 0x00, 0x2a }; - char lil_endian[IMB_TIFF_NCB] = { 0x49, 0x49, 0x2a, 0x00 }; + char big_endian[IMB_TIFF_NCB] = {0x4d, 0x4d, 0x00, 0x2a}; + char lil_endian[IMB_TIFF_NCB] = {0x49, 0x49, 0x2a, 0x00}; - return ((memcmp(big_endian, mem, IMB_TIFF_NCB) == 0) || - (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0)); + return ((memcmp(big_endian, mem, IMB_TIFF_NCB) == 0) || + (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0)); } -static void scanline_contig_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int spp) +static void scanline_contig_16bit(float *rectf, + const unsigned short *sbuf, + int scanline_w, + int spp) { - int i; - for (i = 0; i < scanline_w; i++) { - rectf[i * 4 + 0] = sbuf[i * spp + 0] / 65535.0; - rectf[i * 4 + 1] = (spp >= 3) ? sbuf[i * spp + 1] / 65535.0 : sbuf[i * spp + 0] / 65535.0; - rectf[i * 4 + 2] = (spp >= 3) ? sbuf[i * spp + 2] / 65535.0 : sbuf[i * spp + 0] / 65535.0; - rectf[i * 4 + 3] = (spp == 4) ? (sbuf[i * spp + 3] / 65535.0) : 1.0; - } + int i; + for (i = 0; i < scanline_w; i++) { + rectf[i * 4 + 0] = sbuf[i * spp + 0] / 65535.0; + rectf[i * 4 + 1] = (spp >= 3) ? sbuf[i * spp + 1] / 65535.0 : sbuf[i * spp + 0] / 65535.0; + rectf[i * 4 + 2] = (spp >= 3) ? sbuf[i * spp + 2] / 65535.0 : sbuf[i * spp + 0] / 65535.0; + rectf[i * 4 + 3] = (spp == 4) ? (sbuf[i * spp + 3] / 65535.0) : 1.0; + } } static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp) { - int i; - for (i = 0; i < scanline_w; i++) { - rectf[i * 4 + 0] = fbuf[i * spp + 0]; - rectf[i * 4 + 1] = (spp >= 3) ? fbuf[i * spp + 1] : fbuf[i * spp + 0]; - rectf[i * 4 + 2] = (spp >= 3) ? fbuf[i * spp + 2] : fbuf[i * spp + 0]; - rectf[i * 4 + 3] = (spp == 4) ? fbuf[i * spp + 3] : 1.0f; - } + int i; + for (i = 0; i < scanline_w; i++) { + rectf[i * 4 + 0] = fbuf[i * spp + 0]; + rectf[i * 4 + 1] = (spp >= 3) ? fbuf[i * spp + 1] : fbuf[i * spp + 0]; + rectf[i * 4 + 2] = (spp >= 3) ? fbuf[i * spp + 2] : fbuf[i * spp + 0]; + rectf[i * 4 + 3] = (spp == 4) ? fbuf[i * spp + 3] : 1.0f; + } } -static void scanline_separate_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int chan) +static void scanline_separate_16bit(float *rectf, + const unsigned short *sbuf, + int scanline_w, + int chan) { - int i; - for (i = 0; i < scanline_w; i++) - rectf[i * 4 + chan] = sbuf[i] / 65535.0; + int i; + for (i = 0; i < scanline_w; i++) + rectf[i * 4 + chan] = sbuf[i] / 65535.0; } static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan) { - int i; - for (i = 0; i < scanline_w; i++) - rectf[i * 4 + chan] = fbuf[i]; + int i; + for (i = 0; i < scanline_w; i++) + rectf[i * 4 + chan] = fbuf[i]; } static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image) { - uint16 unit; - float xres; - float yres; - - TIFFGetFieldDefaulted(image, TIFFTAG_RESOLUTIONUNIT, &unit); - TIFFGetFieldDefaulted(image, TIFFTAG_XRESOLUTION, &xres); - TIFFGetFieldDefaulted(image, TIFFTAG_YRESOLUTION, &yres); - - if (unit == RESUNIT_CENTIMETER) { - ibuf->ppm[0] = (double)xres * 100.0; - ibuf->ppm[1] = (double)yres * 100.0; - } - else { - ibuf->ppm[0] = (double)xres / 0.0254; - ibuf->ppm[1] = (double)yres / 0.0254; - } + uint16 unit; + float xres; + float yres; + + TIFFGetFieldDefaulted(image, TIFFTAG_RESOLUTIONUNIT, &unit); + TIFFGetFieldDefaulted(image, TIFFTAG_XRESOLUTION, &xres); + TIFFGetFieldDefaulted(image, TIFFTAG_YRESOLUTION, &yres); + + if (unit == RESUNIT_CENTIMETER) { + ibuf->ppm[0] = (double)xres * 100.0; + ibuf->ppm[1] = (double)yres * 100.0; + } + else { + ibuf->ppm[0] = (double)xres / 0.0254; + ibuf->ppm[1] = (double)yres / 0.0254; + } } /* @@ -370,147 +368,144 @@ static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image) */ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image) { - ImBuf *tmpibuf = NULL; - int success = 0; - short bitspersample, spp, config; - size_t scanline; - int ib_flag = 0, row, chan; - float *fbuf = NULL; - unsigned short *sbuf = NULL; - - TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample); - TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */ - TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config); - - if (spp == 4) { - /* HACK: this is really tricky hack, which is only needed to force libtiff - * do not touch RGB channels when there's alpha channel present - * The thing is: libtiff will premul RGB if alpha mode is set to - * unassociated, which really conflicts with blender's assumptions - * - * Alternative would be to unpremul after load, but it'll be really - * lossy and unwanted behavior - * - * So let's keep this thing here for until proper solution is found (sergey) - */ - - unsigned short extraSampleTypes[1]; - extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA; - TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes); - } - - imb_read_tiff_resolution(ibuf, image); - - scanline = TIFFScanlineSize(image); - - if (bitspersample == 32) { - ib_flag = IB_rectfloat; - fbuf = (float *)_TIFFmalloc(scanline); - if (!fbuf) { - goto cleanup; - } - } - else if (bitspersample == 16) { - ib_flag = IB_rectfloat; - sbuf = (unsigned short *)_TIFFmalloc(scanline); - if (!sbuf) { - goto cleanup; - } - } - else { - ib_flag = IB_rect; - } - - tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag); - if (!tmpibuf) { - goto cleanup; - } - - /* simple RGBA image */ - if (!(bitspersample == 32 || bitspersample == 16)) { - success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0); - } - /* contiguous channels: RGBRGBRGB */ - else if (config == PLANARCONFIG_CONTIG) { - for (row = 0; row < ibuf->y; row++) { - size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1)); - - if (bitspersample == 32) { - success |= TIFFReadScanline(image, fbuf, row, 0); - scanline_contig_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, spp); - - } - else if (bitspersample == 16) { - success |= TIFFReadScanline(image, sbuf, row, 0); - scanline_contig_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, spp); - } - } - /* separate channels: RRRGGGBBB */ - } - else if (config == PLANARCONFIG_SEPARATE) { - - /* imbufs always have 4 channels of data, so we iterate over all of them - * but only fill in from the TIFF scanline where necessary. */ - for (chan = 0; chan < 4; chan++) { - for (row = 0; row < ibuf->y; row++) { - size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1)); - - if (bitspersample == 32) { - if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ - copy_vn_fl(fbuf, ibuf->x, 1.0f); - else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ - success |= TIFFReadScanline(image, fbuf, row, 0); - else - success |= TIFFReadScanline(image, fbuf, row, chan); - scanline_separate_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, chan); - - } - else if (bitspersample == 16) { - if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ - copy_vn_ushort(sbuf, ibuf->x, 65535); - else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ - success |= TIFFReadScanline(image, fbuf, row, 0); - else - success |= TIFFReadScanline(image, sbuf, row, chan); - scanline_separate_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, chan); - - } - } - } - } - - if (success) { - /* Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) */ - if (bitspersample < 16) - if (ENDIAN_ORDER == B_ENDIAN) - IMB_convert_rgba_to_abgr(tmpibuf); - - /* assign rect last */ - if (tmpibuf->rect_float) - ibuf->rect_float = tmpibuf->rect_float; - else - ibuf->rect = tmpibuf->rect; - ibuf->mall |= ib_flag; - ibuf->flags |= ib_flag; - - tmpibuf->mall &= ~ib_flag; - } + ImBuf *tmpibuf = NULL; + int success = 0; + short bitspersample, spp, config; + size_t scanline; + int ib_flag = 0, row, chan; + float *fbuf = NULL; + unsigned short *sbuf = NULL; + + TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample); + TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */ + TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config); + + if (spp == 4) { + /* HACK: this is really tricky hack, which is only needed to force libtiff + * do not touch RGB channels when there's alpha channel present + * The thing is: libtiff will premul RGB if alpha mode is set to + * unassociated, which really conflicts with blender's assumptions + * + * Alternative would be to unpremul after load, but it'll be really + * lossy and unwanted behavior + * + * So let's keep this thing here for until proper solution is found (sergey) + */ + + unsigned short extraSampleTypes[1]; + extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA; + TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes); + } + + imb_read_tiff_resolution(ibuf, image); + + scanline = TIFFScanlineSize(image); + + if (bitspersample == 32) { + ib_flag = IB_rectfloat; + fbuf = (float *)_TIFFmalloc(scanline); + if (!fbuf) { + goto cleanup; + } + } + else if (bitspersample == 16) { + ib_flag = IB_rectfloat; + sbuf = (unsigned short *)_TIFFmalloc(scanline); + if (!sbuf) { + goto cleanup; + } + } + else { + ib_flag = IB_rect; + } + + tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag); + if (!tmpibuf) { + goto cleanup; + } + + /* simple RGBA image */ + if (!(bitspersample == 32 || bitspersample == 16)) { + success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0); + } + /* contiguous channels: RGBRGBRGB */ + else if (config == PLANARCONFIG_CONTIG) { + for (row = 0; row < ibuf->y; row++) { + size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1)); + + if (bitspersample == 32) { + success |= TIFFReadScanline(image, fbuf, row, 0); + scanline_contig_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, spp); + } + else if (bitspersample == 16) { + success |= TIFFReadScanline(image, sbuf, row, 0); + scanline_contig_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, spp); + } + } + /* separate channels: RRRGGGBBB */ + } + else if (config == PLANARCONFIG_SEPARATE) { + + /* imbufs always have 4 channels of data, so we iterate over all of them + * but only fill in from the TIFF scanline where necessary. */ + for (chan = 0; chan < 4; chan++) { + for (row = 0; row < ibuf->y; row++) { + size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1)); + + if (bitspersample == 32) { + if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ + copy_vn_fl(fbuf, ibuf->x, 1.0f); + else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ + success |= TIFFReadScanline(image, fbuf, row, 0); + else + success |= TIFFReadScanline(image, fbuf, row, chan); + scanline_separate_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, chan); + } + else if (bitspersample == 16) { + if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ + copy_vn_ushort(sbuf, ibuf->x, 65535); + else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ + success |= TIFFReadScanline(image, fbuf, row, 0); + else + success |= TIFFReadScanline(image, sbuf, row, chan); + scanline_separate_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, chan); + } + } + } + } + + if (success) { + /* Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) */ + if (bitspersample < 16) + if (ENDIAN_ORDER == B_ENDIAN) + IMB_convert_rgba_to_abgr(tmpibuf); + + /* assign rect last */ + if (tmpibuf->rect_float) + ibuf->rect_float = tmpibuf->rect_float; + else + ibuf->rect = tmpibuf->rect; + ibuf->mall |= ib_flag; + ibuf->flags |= ib_flag; + + tmpibuf->mall &= ~ib_flag; + } cleanup: - if (bitspersample == 32) - _TIFFfree(fbuf); - else if (bitspersample == 16) - _TIFFfree(sbuf); + if (bitspersample == 32) + _TIFFfree(fbuf); + else if (bitspersample == 16) + _TIFFfree(sbuf); - IMB_freeImBuf(tmpibuf); + IMB_freeImBuf(tmpibuf); - return success; + return success; } void imb_inittiff(void) { - if (!(G.debug & G_DEBUG)) - TIFFSetErrorHandler(NULL); + if (!(G.debug & G_DEBUG)) + TIFFSetErrorHandler(NULL); } /** @@ -522,165 +517,177 @@ void imb_inittiff(void) * * \return: A newly allocated ImBuf structure if successful, otherwise NULL. */ -ImBuf *imb_loadtiff(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_loadtiff(const unsigned char *mem, + size_t size, + int flags, + char colorspace[IM_MAX_SPACE]) { - TIFF *image = NULL; - ImBuf *ibuf = NULL, *hbuf; - ImbTIFFMemFile memFile; - uint32 width, height; - char *format = NULL; - int level; - short spp; - int ib_depth; - int found; - - /* check whether or not we have a TIFF file */ - if (size < IMB_TIFF_NCB) { - fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n"); - return NULL; - } - if (imb_is_a_tiff(mem) == 0) - return NULL; - - /* both 8 and 16 bit PNGs are default to standard byte colorspace */ - colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - - image = imb_tiff_client_open(&memFile, mem, size); - - if (image == NULL) { - printf("imb_loadtiff: could not open TIFF IO layer.\n"); - return NULL; - } - - /* allocate the image buffer */ - TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); - TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); - - ib_depth = (spp == 3) ? 24 : 32; - - ibuf = IMB_allocImBuf(width, height, ib_depth, 0); - if (ibuf) { - ibuf->ftype = IMB_FTYPE_TIF; - } - else { - fprintf(stderr, - "imb_loadtiff: could not allocate memory for TIFF " - "image.\n"); - TIFFClose(image); - return NULL; - } - - /* get alpha mode from file header */ - if (flags & IB_alphamode_detect) { - if (spp == 4) { - unsigned short extra, *extraSampleTypes; - - found = TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes); - - if (found && (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)) { - ibuf->flags |= IB_alphamode_premul; - } - } - } - - /* if testing, we're done */ - if (flags & IB_test) { - TIFFClose(image); - return ibuf; - } - - /* detect if we are reading a tiled/mipmapped texture, in that case - * we don't read pixels but leave it to the cache to load tiles */ - if (flags & IB_tilecache) { - format = NULL; - TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format); - - if (format && STREQ(format, "Plain Texture") && TIFFIsTiled(image)) { - int numlevel = TIFFNumberOfDirectories(image); - - /* create empty mipmap levels in advance */ - for (level = 0; level < numlevel; level++) { - if (!TIFFSetDirectory(image, level)) - break; - - if (level > 0) { - width = (width > 1) ? width / 2 : 1; - height = (height > 1) ? height / 2 : 1; - - hbuf = IMB_allocImBuf(width, height, 32, 0); - hbuf->miplevel = level; - hbuf->ftype = ibuf->ftype; - ibuf->mipmap[level - 1] = hbuf; - } - else - hbuf = ibuf; - - hbuf->flags |= IB_tilecache; - - TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex); - TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley); - - hbuf->xtiles = ceil(hbuf->x / (float)hbuf->tilex); - hbuf->ytiles = ceil(hbuf->y / (float)hbuf->tiley); - - imb_addtilesImBuf(hbuf); - - ibuf->miptot++; - } - } - } - - /* read pixels */ - if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) { - fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n"); - TIFFClose(image); - return NULL; - } - - /* close the client layer interface to the in-memory file */ - TIFFClose(image); - - /* return successfully */ - return ibuf; + TIFF *image = NULL; + ImBuf *ibuf = NULL, *hbuf; + ImbTIFFMemFile memFile; + uint32 width, height; + char *format = NULL; + int level; + short spp; + int ib_depth; + int found; + + /* check whether or not we have a TIFF file */ + if (size < IMB_TIFF_NCB) { + fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n"); + return NULL; + } + if (imb_is_a_tiff(mem) == 0) + return NULL; + + /* both 8 and 16 bit PNGs are default to standard byte colorspace */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + image = imb_tiff_client_open(&memFile, mem, size); + + if (image == NULL) { + printf("imb_loadtiff: could not open TIFF IO layer.\n"); + return NULL; + } + + /* allocate the image buffer */ + TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); + TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); + + ib_depth = (spp == 3) ? 24 : 32; + + ibuf = IMB_allocImBuf(width, height, ib_depth, 0); + if (ibuf) { + ibuf->ftype = IMB_FTYPE_TIF; + } + else { + fprintf(stderr, + "imb_loadtiff: could not allocate memory for TIFF " + "image.\n"); + TIFFClose(image); + return NULL; + } + + /* get alpha mode from file header */ + if (flags & IB_alphamode_detect) { + if (spp == 4) { + unsigned short extra, *extraSampleTypes; + + found = TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes); + + if (found && (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)) { + ibuf->flags |= IB_alphamode_premul; + } + } + } + + /* if testing, we're done */ + if (flags & IB_test) { + TIFFClose(image); + return ibuf; + } + + /* detect if we are reading a tiled/mipmapped texture, in that case + * we don't read pixels but leave it to the cache to load tiles */ + if (flags & IB_tilecache) { + format = NULL; + TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format); + + if (format && STREQ(format, "Plain Texture") && TIFFIsTiled(image)) { + int numlevel = TIFFNumberOfDirectories(image); + + /* create empty mipmap levels in advance */ + for (level = 0; level < numlevel; level++) { + if (!TIFFSetDirectory(image, level)) + break; + + if (level > 0) { + width = (width > 1) ? width / 2 : 1; + height = (height > 1) ? height / 2 : 1; + + hbuf = IMB_allocImBuf(width, height, 32, 0); + hbuf->miplevel = level; + hbuf->ftype = ibuf->ftype; + ibuf->mipmap[level - 1] = hbuf; + } + else + hbuf = ibuf; + + hbuf->flags |= IB_tilecache; + + TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex); + TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley); + + hbuf->xtiles = ceil(hbuf->x / (float)hbuf->tilex); + hbuf->ytiles = ceil(hbuf->y / (float)hbuf->tiley); + + imb_addtilesImBuf(hbuf); + + ibuf->miptot++; + } + } + } + + /* read pixels */ + if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) { + fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n"); + TIFFClose(image); + return NULL; + } + + /* close the client layer interface to the in-memory file */ + TIFFClose(image); + + /* return successfully */ + return ibuf; } -void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect) +void imb_loadtiletiff( + ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect) { - TIFF *image = NULL; - uint32 width, height; - ImbTIFFMemFile memFile; - - image = imb_tiff_client_open(&memFile, mem, size); - - if (image == NULL) { - printf("imb_loadtiff: could not open TIFF IO layer for loading mipmap level.\n"); - return; - } - - if (TIFFSetDirectory(image, ibuf->miplevel)) { /* allocate the image buffer */ - TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); - - if (width == ibuf->x && height == ibuf->y) { - if (rect) { - /* tiff pixels are bottom to top, tiles are top to bottom */ - if (TIFFReadRGBATile(image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) { - if (ibuf->tiley > ibuf->y) - memmove(rect, rect + ibuf->tilex * (ibuf->tiley - ibuf->y), sizeof(int) * ibuf->tilex * ibuf->y); - } - else - printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel); - } - } - else - printf("imb_loadtiff: mipmap level %d has unexpected size %ux%u instead of %dx%d\n", ibuf->miplevel, width, height, ibuf->x, ibuf->y); - } - else - printf("imb_loadtiff: could not find mipmap level %d\n", ibuf->miplevel); - - /* close the client layer interface to the in-memory file */ - TIFFClose(image); + TIFF *image = NULL; + uint32 width, height; + ImbTIFFMemFile memFile; + + image = imb_tiff_client_open(&memFile, mem, size); + + if (image == NULL) { + printf("imb_loadtiff: could not open TIFF IO layer for loading mipmap level.\n"); + return; + } + + if (TIFFSetDirectory(image, ibuf->miplevel)) { /* allocate the image buffer */ + TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); + + if (width == ibuf->x && height == ibuf->y) { + if (rect) { + /* tiff pixels are bottom to top, tiles are top to bottom */ + if (TIFFReadRGBATile( + image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) { + if (ibuf->tiley > ibuf->y) + memmove(rect, + rect + ibuf->tilex * (ibuf->tiley - ibuf->y), + sizeof(int) * ibuf->tilex * ibuf->y); + } + else + printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel); + } + } + else + printf("imb_loadtiff: mipmap level %d has unexpected size %ux%u instead of %dx%d\n", + ibuf->miplevel, + width, + height, + ibuf->x, + ibuf->y); + } + else + printf("imb_loadtiff: could not find mipmap level %d\n", ibuf->miplevel); + + /* close the client layer interface to the in-memory file */ + TIFFClose(image); } /** @@ -701,210 +708,202 @@ void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx int imb_savetiff(ImBuf *ibuf, const char *name, int flags) { - TIFF *image = NULL; - uint16 samplesperpixel, bitspersample; - size_t npixels; - unsigned char *pixels = NULL; - unsigned char *from = NULL, *to = NULL; - unsigned short *pixels16 = NULL, *to16 = NULL; - float *fromf = NULL; - float xres, yres; - int x, y, from_i, to_i, i; - int compress_mode = COMPRESSION_NONE; - - /* check for a valid number of bytes per pixel. Like the PNG writer, - * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding - * to gray, RGB, RGBA respectively. */ - samplesperpixel = (uint16)((ibuf->planes + 7) >> 3); - if ((samplesperpixel > 4) || (samplesperpixel == 2)) { - fprintf(stderr, - "imb_savetiff: unsupported number of bytes per " - "pixel: %d\n", samplesperpixel); - return (0); - } - - if ((ibuf->foptions.flag & TIF_16BIT) && ibuf->rect_float) - bitspersample = 16; - else - bitspersample = 8; - - if (ibuf->foptions.flag & TIF_COMPRESS_DEFLATE) - compress_mode = COMPRESSION_DEFLATE; - else if (ibuf->foptions.flag & TIF_COMPRESS_LZW) - compress_mode = COMPRESSION_LZW; - else if (ibuf->foptions.flag & TIF_COMPRESS_PACKBITS) - compress_mode = COMPRESSION_PACKBITS; - - /* open TIFF file for writing */ - if (flags & IB_mem) { - /* bork at the creation of a TIFF in memory */ - fprintf(stderr, - "imb_savetiff: creation of in-memory TIFF files is " - "not yet supported.\n"); - return (0); - } - else { - /* create image as a file */ + TIFF *image = NULL; + uint16 samplesperpixel, bitspersample; + size_t npixels; + unsigned char *pixels = NULL; + unsigned char *from = NULL, *to = NULL; + unsigned short *pixels16 = NULL, *to16 = NULL; + float *fromf = NULL; + float xres, yres; + int x, y, from_i, to_i, i; + int compress_mode = COMPRESSION_NONE; + + /* check for a valid number of bytes per pixel. Like the PNG writer, + * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding + * to gray, RGB, RGBA respectively. */ + samplesperpixel = (uint16)((ibuf->planes + 7) >> 3); + if ((samplesperpixel > 4) || (samplesperpixel == 2)) { + fprintf(stderr, + "imb_savetiff: unsupported number of bytes per " + "pixel: %d\n", + samplesperpixel); + return (0); + } + + if ((ibuf->foptions.flag & TIF_16BIT) && ibuf->rect_float) + bitspersample = 16; + else + bitspersample = 8; + + if (ibuf->foptions.flag & TIF_COMPRESS_DEFLATE) + compress_mode = COMPRESSION_DEFLATE; + else if (ibuf->foptions.flag & TIF_COMPRESS_LZW) + compress_mode = COMPRESSION_LZW; + else if (ibuf->foptions.flag & TIF_COMPRESS_PACKBITS) + compress_mode = COMPRESSION_PACKBITS; + + /* open TIFF file for writing */ + if (flags & IB_mem) { + /* bork at the creation of a TIFF in memory */ + fprintf(stderr, + "imb_savetiff: creation of in-memory TIFF files is " + "not yet supported.\n"); + return (0); + } + else { + /* create image as a file */ #ifdef WIN32 - wchar_t *wname = alloc_utf16_from_8(name, 0); - image = TIFFOpenW(wname, "w"); - free(wname); + wchar_t *wname = alloc_utf16_from_8(name, 0); + image = TIFFOpenW(wname, "w"); + free(wname); #else - image = TIFFOpen(name, "w"); + image = TIFFOpen(name, "w"); #endif - } - if (image == NULL) { - fprintf(stderr, - "imb_savetiff: could not open TIFF for writing.\n"); - return (0); - } - - /* allocate array for pixel data */ - npixels = ibuf->x * ibuf->y; - if (bitspersample == 16) - pixels16 = (unsigned short *)_TIFFmalloc(npixels * - samplesperpixel * sizeof(unsigned short)); - else - pixels = (unsigned char *)_TIFFmalloc(npixels * - samplesperpixel * sizeof(unsigned char)); - - if (pixels == NULL && pixels16 == NULL) { - fprintf(stderr, - "imb_savetiff: could not allocate pixels array.\n"); - TIFFClose(image); - return (0); - } - - /* setup pointers */ - if (bitspersample == 16) { - fromf = ibuf->rect_float; - to16 = pixels16; - } - else { - from = (unsigned char *)ibuf->rect; - to = pixels; - } - - /* setup samples per pixel */ - TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample); - TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); - - if (samplesperpixel == 4) { - unsigned short extraSampleTypes[1]; - - if (bitspersample == 16) - extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA; - else - extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA; - - /* RGBA images */ - TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, - extraSampleTypes); - TIFFSetField(image, TIFFTAG_PHOTOMETRIC, - PHOTOMETRIC_RGB); - } - else if (samplesperpixel == 3) { - /* RGB images */ - TIFFSetField(image, TIFFTAG_PHOTOMETRIC, - PHOTOMETRIC_RGB); - } - else if (samplesperpixel == 1) { - /* grayscale images, 1 channel */ - TIFFSetField(image, TIFFTAG_PHOTOMETRIC, - PHOTOMETRIC_MINISBLACK); - } - - /* copy pixel data. While copying, we flip the image vertically. */ - const int channels_in_float = ibuf->channels ? ibuf->channels : 4; - for (x = 0; x < ibuf->x; x++) { - for (y = 0; y < ibuf->y; y++) { - from_i = ((size_t)channels_in_float) * (y * ibuf->x + x); - to_i = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x); - - if (pixels16) { - /* convert from float source */ - float rgb[4]; - - if (channels_in_float == 3 || channels_in_float == 4) { - if (ibuf->float_colorspace || - (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) - { - /* Float buffer was managed already, no need in color - * space conversion. - */ - copy_v3_v3(rgb, &fromf[from_i]); - } - else { - /* Standard linear-to-srgb conversion if float buffer - * wasn't managed. - */ - linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); - } - if (channels_in_float == 4) { - rgb[3] = fromf[from_i + 3]; - } - else { - rgb[3] = 1.0f; - } - } - else { - if (ibuf->float_colorspace || - (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) - { - rgb[0] = fromf[from_i]; - } - else { - rgb[0] = linearrgb_to_srgb(fromf[from_i]); - } - rgb[1] = rgb[2] = rgb[0]; - rgb[3] = 1.0f; - } - - for (i = 0; i < samplesperpixel; i++, to_i++) - to16[to_i] = unit_float_to_ushort_clamp(rgb[i]); - } - else { - for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) - to[to_i] = from[from_i]; - } - } - } - - /* write the actual TIFF file */ - TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x); - TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y); - TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y); - TIFFSetField(image, TIFFTAG_COMPRESSION, compress_mode); - TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); - TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - - - if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) { - xres = (float)(ibuf->ppm[0] * 0.0254); - yres = (float)(ibuf->ppm[1] * 0.0254); - } - else { - xres = yres = IMB_DPI_DEFAULT; - } - - TIFFSetField(image, TIFFTAG_XRESOLUTION, xres); - TIFFSetField(image, TIFFTAG_YRESOLUTION, yres); - TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); - if (TIFFWriteEncodedStrip(image, 0, - (bitspersample == 16) ? (unsigned char *)pixels16 : pixels, - (size_t)ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) == -1) - { - fprintf(stderr, - "imb_savetiff: Could not write encoded TIFF.\n"); - TIFFClose(image); - if (pixels) _TIFFfree(pixels); - if (pixels16) _TIFFfree(pixels16); - return (1); - } - - /* close the TIFF file */ - TIFFClose(image); - if (pixels) _TIFFfree(pixels); - if (pixels16) _TIFFfree(pixels16); - return (1); + } + if (image == NULL) { + fprintf(stderr, "imb_savetiff: could not open TIFF for writing.\n"); + return (0); + } + + /* allocate array for pixel data */ + npixels = ibuf->x * ibuf->y; + if (bitspersample == 16) + pixels16 = (unsigned short *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned short)); + else + pixels = (unsigned char *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned char)); + + if (pixels == NULL && pixels16 == NULL) { + fprintf(stderr, "imb_savetiff: could not allocate pixels array.\n"); + TIFFClose(image); + return (0); + } + + /* setup pointers */ + if (bitspersample == 16) { + fromf = ibuf->rect_float; + to16 = pixels16; + } + else { + from = (unsigned char *)ibuf->rect; + to = pixels; + } + + /* setup samples per pixel */ + TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample); + TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); + + if (samplesperpixel == 4) { + unsigned short extraSampleTypes[1]; + + if (bitspersample == 16) + extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA; + else + extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA; + + /* RGBA images */ + TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes); + TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + } + else if (samplesperpixel == 3) { + /* RGB images */ + TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + } + else if (samplesperpixel == 1) { + /* grayscale images, 1 channel */ + TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + } + + /* copy pixel data. While copying, we flip the image vertically. */ + const int channels_in_float = ibuf->channels ? ibuf->channels : 4; + for (x = 0; x < ibuf->x; x++) { + for (y = 0; y < ibuf->y; y++) { + from_i = ((size_t)channels_in_float) * (y * ibuf->x + x); + to_i = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x); + + if (pixels16) { + /* convert from float source */ + float rgb[4]; + + if (channels_in_float == 3 || channels_in_float == 4) { + if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) { + /* Float buffer was managed already, no need in color + * space conversion. + */ + copy_v3_v3(rgb, &fromf[from_i]); + } + else { + /* Standard linear-to-srgb conversion if float buffer + * wasn't managed. + */ + linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); + } + if (channels_in_float == 4) { + rgb[3] = fromf[from_i + 3]; + } + else { + rgb[3] = 1.0f; + } + } + else { + if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) { + rgb[0] = fromf[from_i]; + } + else { + rgb[0] = linearrgb_to_srgb(fromf[from_i]); + } + rgb[1] = rgb[2] = rgb[0]; + rgb[3] = 1.0f; + } + + for (i = 0; i < samplesperpixel; i++, to_i++) + to16[to_i] = unit_float_to_ushort_clamp(rgb[i]); + } + else { + for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) + to[to_i] = from[from_i]; + } + } + } + + /* write the actual TIFF file */ + TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x); + TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y); + TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y); + TIFFSetField(image, TIFFTAG_COMPRESSION, compress_mode); + TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) { + xres = (float)(ibuf->ppm[0] * 0.0254); + yres = (float)(ibuf->ppm[1] * 0.0254); + } + else { + xres = yres = IMB_DPI_DEFAULT; + } + + TIFFSetField(image, TIFFTAG_XRESOLUTION, xres); + TIFFSetField(image, TIFFTAG_YRESOLUTION, yres); + TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + if (TIFFWriteEncodedStrip(image, + 0, + (bitspersample == 16) ? (unsigned char *)pixels16 : pixels, + (size_t)ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) == + -1) { + fprintf(stderr, "imb_savetiff: Could not write encoded TIFF.\n"); + TIFFClose(image); + if (pixels) + _TIFFfree(pixels); + if (pixels16) + _TIFFfree(pixels16); + return (1); + } + + /* close the TIFF file */ + TIFFClose(image); + if (pixels) + _TIFFfree(pixels); + if (pixels16) + _TIFFfree(pixels16); + return (1); } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index ba541dc6e91..50aaa16c3fe 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -22,7 +22,6 @@ * \ingroup imbuf */ - #ifdef _WIN32 # include #endif @@ -41,9 +40,9 @@ #include "IMB_anim.h" #ifdef WITH_FFMPEG -# include "BLI_string.h" /* BLI_vsnprintf */ +# include "BLI_string.h" /* BLI_vsnprintf */ -# include "BKE_global.h" /* G.debug */ +# include "BKE_global.h" /* G.debug */ # include # include @@ -56,338 +55,327 @@ #define UTIL_DEBUG 0 const char *imb_ext_image[] = { - ".png", - ".tga", - ".bmp", - ".jpg", ".jpeg", - ".sgi", ".rgb", ".rgba", + ".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", ".rgba", #ifdef WITH_TIFF - ".tif", ".tiff", ".tx", + ".tif", ".tiff", ".tx", #endif #ifdef WITH_OPENJPEG - ".jp2", - ".j2c", + ".jp2", ".j2c", #endif #ifdef WITH_HDR - ".hdr", + ".hdr", #endif #ifdef WITH_DDS - ".dds", + ".dds", #endif #ifdef WITH_CINEON - ".dpx", - ".cin", + ".dpx", ".cin", #endif #ifdef WITH_OPENEXR - ".exr", + ".exr", #endif #ifdef WITH_OPENIMAGEIO - ".psd", ".pdd", ".psb", + ".psd", ".pdd", ".psb", #endif - NULL, + NULL, }; const char *imb_ext_image_filepath_only[] = { #ifdef WITH_OPENIMAGEIO - ".psd", ".pdd", ".psb", + ".psd", + ".pdd", + ".psb", #endif - NULL, + NULL, }; const char *imb_ext_movie[] = { - ".avi", - ".flc", - ".mov", - ".movie", - ".mp4", - ".m4v", - ".m2v", - ".m2t", - ".m2ts", - ".mts", - ".ts", - ".mv", - ".avs", - ".wmv", - ".ogv", - ".ogg", - ".r3d", - ".dv", - ".mpeg", - ".mpg", - ".mpg2", - ".vob", - ".mkv", - ".flv", - ".divx", - ".xvid", - ".mxf", - ".webm", - NULL, + ".avi", ".flc", ".mov", ".movie", ".mp4", ".m4v", ".m2v", ".m2t", ".m2ts", ".mts", + ".ts", ".mv", ".avs", ".wmv", ".ogv", ".ogg", ".r3d", ".dv", ".mpeg", ".mpg", + ".mpg2", ".vob", ".mkv", ".flv", ".divx", ".xvid", ".mxf", ".webm", NULL, }; /* sort of wrong being here... */ const char *imb_ext_audio[] = { - ".wav", - ".ogg", - ".oga", - ".mp3", - ".mp2", - ".ac3", - ".aac", - ".flac", - ".wma", - ".eac3", - ".aif", - ".aiff", - ".m4a", - ".mka", - NULL, + ".wav", + ".ogg", + ".oga", + ".mp3", + ".mp2", + ".ac3", + ".aac", + ".flac", + ".wma", + ".eac3", + ".aif", + ".aiff", + ".m4a", + ".mka", + NULL, }; int IMB_ispic_type(const char *name) { - /* increased from 32 to 64 because of the bitmaps header size */ + /* increased from 32 to 64 because of the bitmaps header size */ #define HEADER_SIZE 64 - unsigned char buf[HEADER_SIZE]; - const ImFileType *type; - BLI_stat_t st; - int fp; + unsigned char buf[HEADER_SIZE]; + const ImFileType *type; + BLI_stat_t st; + int fp; - BLI_assert(!BLI_path_is_rel(name)); + BLI_assert(!BLI_path_is_rel(name)); - if (UTIL_DEBUG) printf("%s: loading %s\n", __func__, name); + if (UTIL_DEBUG) + printf("%s: loading %s\n", __func__, name); - if (BLI_stat(name, &st) == -1) - return false; - if (((st.st_mode) & S_IFMT) != S_IFREG) - return false; + if (BLI_stat(name, &st) == -1) + return false; + if (((st.st_mode) & S_IFMT) != S_IFREG) + return false; - if ((fp = BLI_open(name, O_BINARY | O_RDONLY, 0)) == -1) - return false; + if ((fp = BLI_open(name, O_BINARY | O_RDONLY, 0)) == -1) + return false; - memset(buf, 0, sizeof(buf)); - if (read(fp, buf, HEADER_SIZE) <= 0) { - close(fp); - return false; - } + memset(buf, 0, sizeof(buf)); + if (read(fp, buf, HEADER_SIZE) <= 0) { + close(fp); + return false; + } - close(fp); + close(fp); - /* XXX move this exception */ - if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0) - return IMB_FTYPE_JPG; + /* XXX move this exception */ + if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0) + return IMB_FTYPE_JPG; - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->is_a) { - if (type->is_a(buf)) { - return type->filetype; - } - } - else if (type->is_a_filepath) { - if (type->is_a_filepath(name)) { - return type->filetype; - } - } - } + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->is_a) { + if (type->is_a(buf)) { + return type->filetype; + } + } + else if (type->is_a_filepath) { + if (type->is_a_filepath(name)) { + return type->filetype; + } + } + } - return 0; + return 0; #undef HEADER_SIZE } bool IMB_ispic(const char *name) { - return (IMB_ispic_type(name) != 0); + return (IMB_ispic_type(name) != 0); } static int isavi(const char *name) { #ifdef WITH_AVI - return AVI_is_avi(name); + return AVI_is_avi(name); #else - (void)name; - return false; + (void)name; + return false; #endif } #ifdef WITH_FFMPEG /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */ -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmissing-format-attribute" -#endif +# ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-format-attribute" +# endif static char ffmpeg_last_error[1024]; static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) { - if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { - size_t n; - va_list args_cpy; - - va_copy(args_cpy, arg); - n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, args_cpy); - va_end(args_cpy); - - /* strip trailing \n */ - ffmpeg_last_error[n - 1] = '\0'; - } - - if (G.debug & G_DEBUG_FFMPEG) { - /* call default logger to print all message to console */ - av_log_default_callback(ptr, level, format, arg); - } + if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { + size_t n; + va_list args_cpy; + + va_copy(args_cpy, arg); + n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, args_cpy); + va_end(args_cpy); + + /* strip trailing \n */ + ffmpeg_last_error[n - 1] = '\0'; + } + + if (G.debug & G_DEBUG_FFMPEG) { + /* call default logger to print all message to console */ + av_log_default_callback(ptr, level, format, arg); + } } -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif +# ifdef __GNUC__ +# pragma GCC diagnostic pop +# endif void IMB_ffmpeg_init(void) { - av_register_all(); - avdevice_register_all(); + av_register_all(); + avdevice_register_all(); - ffmpeg_last_error[0] = '\0'; + ffmpeg_last_error[0] = '\0'; - if (G.debug & G_DEBUG_FFMPEG) - av_log_set_level(AV_LOG_DEBUG); + if (G.debug & G_DEBUG_FFMPEG) + av_log_set_level(AV_LOG_DEBUG); - /* set own callback which could store last error to report to UI */ - av_log_set_callback(ffmpeg_log_callback); + /* set own callback which could store last error to report to UI */ + av_log_set_callback(ffmpeg_log_callback); } const char *IMB_ffmpeg_last_error(void) { - return ffmpeg_last_error; + return ffmpeg_last_error; } static int isffmpeg(const char *filename) { - AVFormatContext *pFormatCtx = NULL; - unsigned int i; - int videoStream; - AVCodec *pCodec; - AVCodecContext *pCodecCtx; - - if (BLI_path_extension_check_n( - filename, - ".swf", ".jpg", ".png", ".dds", ".tga", ".bmp", ".tif", ".exr", ".cin", ".wav", NULL)) - { - return 0; - } - - if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) { - if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n"); - return 0; - } - - if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { - if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n"); - avformat_close_input(&pFormatCtx); - return 0; - } - - if (UTIL_DEBUG) av_dump_format(pFormatCtx, 0, filename, 0); - - - /* Find the first video stream */ - videoStream = -1; - for (i = 0; i < pFormatCtx->nb_streams; i++) - if (pFormatCtx->streams[i] && - pFormatCtx->streams[i]->codec && - (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)) - { - videoStream = i; - break; - } - - if (videoStream == -1) { - avformat_close_input(&pFormatCtx); - return 0; - } - - pCodecCtx = pFormatCtx->streams[videoStream]->codec; - - /* Find the decoder for the video stream */ - pCodec = avcodec_find_decoder(pCodecCtx->codec_id); - if (pCodec == NULL) { - avformat_close_input(&pFormatCtx); - return 0; - } - - if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { - avformat_close_input(&pFormatCtx); - return 0; - } - - avcodec_close(pCodecCtx); - avformat_close_input(&pFormatCtx); - - return 1; + AVFormatContext *pFormatCtx = NULL; + unsigned int i; + int videoStream; + AVCodec *pCodec; + AVCodecContext *pCodecCtx; + + if (BLI_path_extension_check_n(filename, + ".swf", + ".jpg", + ".png", + ".dds", + ".tga", + ".bmp", + ".tif", + ".exr", + ".cin", + ".wav", + NULL)) { + return 0; + } + + if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) { + if (UTIL_DEBUG) + fprintf(stderr, "isffmpeg: av_open_input_file failed\n"); + return 0; + } + + if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { + if (UTIL_DEBUG) + fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n"); + avformat_close_input(&pFormatCtx); + return 0; + } + + if (UTIL_DEBUG) + av_dump_format(pFormatCtx, 0, filename, 0); + + /* Find the first video stream */ + videoStream = -1; + for (i = 0; i < pFormatCtx->nb_streams; i++) + if (pFormatCtx->streams[i] && pFormatCtx->streams[i]->codec && + (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)) { + videoStream = i; + break; + } + + if (videoStream == -1) { + avformat_close_input(&pFormatCtx); + return 0; + } + + pCodecCtx = pFormatCtx->streams[videoStream]->codec; + + /* Find the decoder for the video stream */ + pCodec = avcodec_find_decoder(pCodecCtx->codec_id); + if (pCodec == NULL) { + avformat_close_input(&pFormatCtx); + return 0; + } + + if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { + avformat_close_input(&pFormatCtx); + return 0; + } + + avcodec_close(pCodecCtx); + avformat_close_input(&pFormatCtx); + + return 1; } #endif int imb_get_anim_type(const char *name) { - int type; - BLI_stat_t st; + int type; + BLI_stat_t st; - BLI_assert(!BLI_path_is_rel(name)); + BLI_assert(!BLI_path_is_rel(name)); - if (UTIL_DEBUG) printf("%s: %s\n", __func__, name); + if (UTIL_DEBUG) + printf("%s: %s\n", __func__, name); #ifndef _WIN32 -# ifdef WITH_FFMPEG - /* stat test below fails on large files > 4GB */ - if (isffmpeg(name)) return (ANIM_FFMPEG); -# endif - if (BLI_stat(name, &st) == -1) return(0); - if (((st.st_mode) & S_IFMT) != S_IFREG) return(0); - - if (isavi(name)) return (ANIM_AVI); - - if (ismovie(name)) return (ANIM_MOVIE); +# ifdef WITH_FFMPEG + /* stat test below fails on large files > 4GB */ + if (isffmpeg(name)) + return (ANIM_FFMPEG); +# endif + if (BLI_stat(name, &st) == -1) + return (0); + if (((st.st_mode) & S_IFMT) != S_IFREG) + return (0); + + if (isavi(name)) + return (ANIM_AVI); + + if (ismovie(name)) + return (ANIM_MOVIE); #else - if (BLI_stat(name, &st) == -1) return(0); - if (((st.st_mode) & S_IFMT) != S_IFREG) return(0); - - if (ismovie(name)) return (ANIM_MOVIE); -# ifdef WITH_FFMPEG - if (isffmpeg(name)) return (ANIM_FFMPEG); -# endif - - - if (isavi(name)) return (ANIM_AVI); + if (BLI_stat(name, &st) == -1) + return (0); + if (((st.st_mode) & S_IFMT) != S_IFREG) + return (0); + + if (ismovie(name)) + return (ANIM_MOVIE); +# ifdef WITH_FFMPEG + if (isffmpeg(name)) + return (ANIM_FFMPEG); +# endif + + if (isavi(name)) + return (ANIM_AVI); #endif - type = IMB_ispic(name); - if (type) { - return ANIM_SEQUENCE; - } + type = IMB_ispic(name); + if (type) { + return ANIM_SEQUENCE; + } - return ANIM_NONE; + return ANIM_NONE; } bool IMB_isanim(const char *filename) { - int type; + int type; - type = imb_get_anim_type(filename); + type = imb_get_anim_type(filename); - return (type && type != ANIM_SEQUENCE); + return (type && type != ANIM_SEQUENCE); } bool IMB_isfloat(ImBuf *ibuf) { - const ImFileType *type; - - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->ftype(type, ibuf)) { - return (type->flag & IM_FTYPE_FLOAT) != 0; - } - } - return false; + const ImFileType *type; + + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->ftype(type, ibuf)) { + return (type->flag & IM_FTYPE_FLOAT) != 0; + } + } + return false; } diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index d6f2f801725..e93df7b73ba 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -22,7 +22,6 @@ * \ingroup imbuf */ - #include #include #include @@ -39,53 +38,54 @@ static bool prepare_write_imbuf(const ImFileType *type, ImBuf *ibuf) { - return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf); + return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf); } short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) { - const ImFileType *type; + const ImFileType *type; - errno = 0; + errno = 0; - BLI_assert(!BLI_path_is_rel(name)); + BLI_assert(!BLI_path_is_rel(name)); - if (ibuf == NULL) return (false); - ibuf->flags = flags; + if (ibuf == NULL) + return (false); + ibuf->flags = flags; - for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { - if (type->save && type->ftype(type, ibuf)) { - short result = false; + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->save && type->ftype(type, ibuf)) { + short result = false; - prepare_write_imbuf(type, ibuf); + prepare_write_imbuf(type, ibuf); - result = type->save(ibuf, name, flags); + result = type->save(ibuf, name, flags); - return result; - } - } + return result; + } + } - fprintf(stderr, "Couldn't save picture.\n"); + fprintf(stderr, "Couldn't save picture.\n"); - return false; + return false; } bool IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf) { - bool changed = false; - - if (isfloat) { - /* pass */ - } - else { - if (ibuf->rect == NULL && ibuf->rect_float) { - ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE); - IMB_rect_from_float(ibuf); - if (ibuf->rect != NULL) { - changed = true; - } - } - } - - return changed; + bool changed = false; + + if (isfloat) { + /* pass */ + } + else { + if (ibuf->rect == NULL && ibuf->rect_float) { + ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE); + IMB_rect_from_float(ibuf); + if (ibuf->rect != NULL) { + changed = true; + } + } + } + + return changed; } -- cgit v1.2.3