diff options
26 files changed, 645 insertions, 72 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8863c03bff4..e88a5e0eea7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,7 @@ option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) option(WITH_IMAGE_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org)" ON) option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON) +option(WITH_IMAGE_PSD "Enable Photoshop PSD Support" ON) option(WITH_IMAGE_DDS "Enable DDS Image Support" ON) option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON) option(WITH_IMAGE_HDR "Enable HDR Image Support" ON) @@ -441,6 +442,11 @@ if(NOT WITH_PYTHON) set(WITH_CYCLES OFF) endif() +# auto enable openimageio for photoshop psd +if(WITH_IMAGE_PSD) + set(WITH_OPENIMAGEIO ON) +endif() + # enable boost for cycles, booleans, audaspace or i18n # otherwise if the user disabled if(NOT WITH_BOOST) @@ -2297,6 +2303,7 @@ if(FIRST_RUN) info_cfg_option(WITH_IMAGE_OPENJPEG) info_cfg_option(WITH_IMAGE_REDCODE) info_cfg_option(WITH_IMAGE_TIFF) + info_cfg_option(WITH_IMAGE_PSD) info_cfg_text("Audio:") info_cfg_option(WITH_OPENAL) diff --git a/SConstruct b/SConstruct index f95a2903db1..539414d6fba 100644 --- a/SConstruct +++ b/SConstruct @@ -246,6 +246,7 @@ if 'blenderlite' in B.targets: target_env_defs['WITH_BF_CYCLES'] = False target_env_defs['WITH_BF_OPENAL'] = False target_env_defs['WITH_BF_OPENEXR'] = False + target_env_defs['WITH_BF_PSD'] = False target_env_defs['WITH_BF_OPENMP'] = False target_env_defs['WITH_BF_ICONV'] = False target_env_defs['WITH_BF_INTERNATIONAL'] = False diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 7e327028a01..307f93dd606 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -117,6 +117,10 @@ if(WITH_IMAGE_OPENEXR) add_subdirectory(imbuf/intern/openexr) endif() +if(WITH_IMAGE_PSD) + add_subdirectory(imbuf/intern/oiio) +endif() + if(WITH_IMAGE_DDS) add_subdirectory(imbuf/intern/dds) endif() diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 2bf6304b04b..a11d705398f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1250,6 +1250,12 @@ static int do_add_image_extension(char *string, const char imtype, const ImageFo } } #endif +#ifdef WITH_PSD + else if (imtype == R_IMF_IMTYPE_PSD) { + if (!BLI_testextensie(string, ".psd")) + extension = ".psd"; + } +#endif #ifdef WITH_OPENEXR else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { if (!BLI_testextensie(string, ".exr")) diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt index b30f008e1bf..74f3a425c25 100644 --- a/source/blender/editors/space_file/CMakeLists.txt +++ b/source/blender/editors/space_file/CMakeLists.txt @@ -58,6 +58,10 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_IMAGE_PSD) + add_definitions(-DWITH_PSD) +endif() + if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index 6509af179e7..fdc1960d128 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -58,6 +58,9 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_IMAGE_PSD) + add_definitions(-DWITH_PSD) +endif() if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index 29ed8c95fc6..58738155c50 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -105,6 +105,15 @@ if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() + +if(WITH_IMAGE_PSD) + add_definitions(-DWITH_PSD) +else() + list(APPEND SRC + intern/oiio/openimageio_stub.cpp + ) +endif() + if(WITH_IMAGE_OPENJPEG) list(APPEND INC_SYS ${OPENJPEG_INCLUDE_DIRS} diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 8c2e79ab7d8..c70ab5d7189 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -429,7 +429,7 @@ 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, 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); /** * diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 1734073dd6c..df9101247d5 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -180,6 +180,10 @@ typedef struct ImBuf { */ #define IB_CUSTOM_FLAGS_MASK 0x7ff +#ifdef WITH_PSD +#define PSD (1 << 31) +#endif + #define PNG (1 << 30) #define TGA (1 << 28) #define JPG (1 << 27) @@ -273,6 +277,9 @@ extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; +/* image formats that can only be loaded via filepath */ +extern const char *imb_ext_image_filepath_only[]; + enum { IMB_COLORMANAGE_IS_DATA = (1 << 0) }; diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 3c8b29cf68a..9327c15c415 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -39,8 +39,10 @@ typedef struct ImFileType { void (*exit)(void); int (*is_a)(unsigned char *buf); + int (*is_a_filepath)(const char *name); int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf); struct ImBuf *(*load)(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, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect); @@ -50,6 +52,7 @@ typedef struct ImFileType { } ImFileType; extern ImFileType IMB_FILE_TYPES[]; +extern ImFileType *IMB_FILE_TYPES_LAST; void imb_filetypes_init(void); void imb_filetypes_exit(void); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 366c2922739..61051464c7f 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1915,7 +1915,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo * we need to allocate byte buffer and store color managed * image there */ - for (type = IMB_FILE_TYPES; type->is_a; type++) { + 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; @@ -2451,7 +2451,7 @@ void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSetting { ImFileType *type; - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->save && type->ftype(type, ibuf)) { const char *role_colorspace; diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index 37070c7e2bf..4db47646092 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -39,6 +39,10 @@ #include "openexr/openexr_api.h" #endif +#ifdef WITH_PSD +#include "oiio/openimageio_api.h" +#endif + #ifdef WITH_DDS #include "dds/dds_api.h" #endif @@ -71,41 +75,46 @@ void quicktime_exit(void); #endif ImFileType IMB_FILE_TYPES[] = { - {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_targa, NULL, imb_ftype_default, imb_loadtarga, NULL, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_iris, NULL, imb_ftype_iris, imb_loadiris, NULL, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, #ifdef WITH_CINEON - {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_load_dpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, - {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_load_cineon, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_dpx, NULL, imb_ftype_default, imb_load_dpx, NULL, imb_save_dpx, NULL, IM_FTYPE_FLOAT, 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, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_TIFF - {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, + {imb_inittiff, NULL, imb_is_a_tiff, NULL, imb_ftype_default, imb_loadtiff, NULL, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_HDR - {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_a_hdr, NULL, imb_ftype_default, imb_loadhdr, NULL, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENEXR - {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT}, + {imb_initopenexr, NULL, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENJPEG - {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_jp2, NULL, NULL, imb_ftype_default, imb_jp2_decode, NULL, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_DDS - {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_QUICKTIME - {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE}, + {quicktime_init, quicktime_exit, imb_is_a_quicktime, NULL, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE}, +#endif +#ifdef WITH_PSD + {NULL, NULL, NULL, imb_is_a_photoshop, imb_ftype_default, NULL, imb_load_photoshop, NULL, NULL, IM_FTYPE_FLOAT, PSD, COLOR_ROLE_DEFAULT_FLOAT}, #endif - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0} + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0} }; - + +ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES)/sizeof(ImFileType)-1]; + void imb_filetypes_init(void) { ImFileType *type; - for (type = IMB_FILE_TYPES; type->is_a; type++) + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->init) type->init(); } @@ -114,7 +123,7 @@ void imb_filetypes_exit(void) { ImFileType *type; - for (type = IMB_FILE_TYPES; type->is_a; type++) + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->exit) type->exit(); } diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt new file mode 100644 index 00000000000..f5ee5eb6589 --- /dev/null +++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt @@ -0,0 +1,54 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + .. + ../.. + ../../../blenkernel + ../../../blenlib + ../../../makesdna + ../../../../../intern/guardedalloc + ../../../../../intern/utfconv +) + +set(INC_SYS + +) + +set(SRC + openimageio_api.h + + openimageio_api.cpp +) + +if(WITH_IMAGE_PSD) + list(APPEND INC_SYS + ${OPENIMAGEIO_INCLUDE_DIRS} + ) + add_definitions(-DWITH_PSD) +endif() + +blender_add_lib(bf_imbuf_openimageio "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/oiio/SConscript b/source/blender/imbuf/intern/oiio/SConscript new file mode 100644 index 00000000000..124f8fbdfce --- /dev/null +++ b/source/blender/imbuf/intern/oiio/SConscript @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): +# +# ***** END GPL LICENSE BLOCK ***** + +Import ('env') + +source_files = ['openimageio_api.cpp'] + +incs = ['.', + '../../../blenkernel', + '../../', + '..', + '../../../blenlib', + 'intern/include', + '#/intern/guardedalloc', + '../../../makesdna', + '#/intern/utfconv'] + +defs = ['WITH_PSD'] + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): + incs.append(env['BF_PTHREADS_INC']) + +env.BlenderLib ('bf_imbuf_openimageio', source_files, incs, defs, libtype=['core','player'], priority = [225,180]) diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp new file mode 100644 index 00000000000..3253cf9da08 --- /dev/null +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -0,0 +1,257 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Dalai Felinto and Brecht van Lommel + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/oiio/openimageio_api.h + * \ingroup openimageio + */ + +#include <set> + +#include <openimageio_api.h> +#include <OpenImageIO/imageio.h> + +OIIO_NAMESPACE_USING + +#if defined (WIN32) && !defined(FREE_WINDOWS) +#include "utfconv.h" +#endif + +extern "C" +{ +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" +} + +using namespace std; + +typedef unsigned char uchar; + +template <class T, class Q> +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]; + } + } + +} + +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 + { + in->read_image(TypeDesc::UINT8, + (uchar *)ibuf->rect + (height-1) * scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); + } + 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) +{ + 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 + { + in->read_image(TypeDesc::FLOAT, + (uchar *)ibuf->rect_float + (height-1) * scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); + } + 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" +{ + +int imb_is_a_photoshop(const char *filename) +{ + const char *photoshop_extension[] = { + ".psd", + ".pdd", + ".psb", + NULL + }; + + return BLI_testextensie_array(filename, photoshop_extension); +} + +int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags) +{ + if (flags & IB_mem) { + printf("Photoshop PSD-save: Create PSD in memory CURRENTLY NOT SUPPORTED !\n"); + 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]) +{ + ImageInput *in = NULL; + struct ImBuf *ibuf = NULL; + int width, height, components; + bool is_float, is_alpha; + TypeDesc typedesc; + int basesize; + + /* 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); + + in = ImageInput::create(filename); + if (!in) return NULL; + + ImageSpec spec, config; + config.attribute ("oiio:UnassociatedAlpha", (int) 1); + + if(!in->open(filename, spec, config)) { + delete in; + return NULL; + } + + string ics = spec.get_string_attribute("oiio:ColorSpace"); + BLI_strncpy(colorspace, ics.c_str(), IM_MAX_SPACE); + + 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(); + delete in; + } + return NULL; + } + + if (is_float) + ibuf = imb_oiio_load_image_float(in, width, height, components, flags, is_alpha); + else + ibuf = imb_oiio_load_image(in, width, height, components, flags, is_alpha); + + if (in) { + in->close(); + delete in; + } + + if (!ibuf) + return NULL; + + /* ImBuf always needs 4 channels */ + ibuf->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 (0); + } +} + +} // export "C" + + diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h new file mode 100644 index 00000000000..ce96e277f7f --- /dev/null +++ b/source/blender/imbuf/intern/oiio/openimageio_api.h @@ -0,0 +1,53 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/oiio/openimageio_api.h + * \ingroup openimageio + */ + + +#ifndef __OIIO_API_H__ +#define __OIIO_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +int imb_is_a_photoshop (const char *name); + +int imb_save_photoshop (struct ImBuf *ibuf, const char *name, int flags); + +struct ImBuf *imb_load_photoshop (const char *name, int flags, char *colorspace); + +#ifdef __cplusplus +} + +#endif + +#endif /* __OIIO_API_H */ diff --git a/source/blender/imbuf/intern/oiio/openimageio_stub.cpp b/source/blender/imbuf/intern/oiio/openimageio_stub.cpp new file mode 100644 index 00000000000..b57de0b24a7 --- /dev/null +++ b/source/blender/imbuf/intern/oiio/openimageio_stub.cpp @@ -0,0 +1,35 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +/** \file blender/imbuf/intern/oiio/openimageio_api.h + * \ingroup openimageio + */ + +#include "openimageio_api.h" + +#endif diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index d73fa9a7ab7..6988687e4ed 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -56,6 +56,53 @@ #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]) +{ + int alpha_flags; + + if (colorspace) { + if (ibuf->rect) { + /* 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(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; @@ -70,54 +117,36 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co if (colorspace) BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->load) { ibuf = type->load(mem, size, flags, effective_colorspace); if (ibuf) { - int alpha_flags; - - if (colorspace) { - if (ibuf->rect) { - /* 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); + 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) +{ + ImBuf *ibuf; + 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; } } @@ -129,7 +158,13 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co return NULL; } -ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr) +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_testextensie_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 *ibuf; unsigned char *mem; @@ -137,6 +172,9 @@ ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const if (file == -1) return NULL; + if (imb_is_filepath_format(filepath)) + return IMB_ibImageFromFile(filepath, flags, colorspace, descr); + size = BLI_file_descriptor_size(file); mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); @@ -179,7 +217,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_S file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); if (file < 0) return NULL; - ibuf = IMB_loadifffile(file, flags, colorspace, filepath_tx); + ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath_tx); if (ibuf) { BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); @@ -206,7 +244,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags) file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); if (file < 0) return NULL; - ibuf = IMB_loadifffile(file, 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)); @@ -234,7 +272,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int return; } - for (type = IMB_FILE_TYPES; type->is_a; type++) + 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); diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index a4b0e61d544..434a1717bc8 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -98,6 +98,16 @@ const char *imb_ext_image[] = { #ifdef WITH_OPENEXR ".exr", #endif +#ifdef WITH_PSD + ".psd", ".pdd", ".psb", +#endif + NULL +}; + +const char *imb_ext_image_filepath_only[] = { +#ifdef WITH_PSD + ".psd", ".pdd", ".psb", +#endif NULL }; @@ -188,9 +198,16 @@ static int IMB_ispic_name(const char *name) if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0) return JPG; - for (type = IMB_FILE_TYPES; type->is_a; type++) { - if (type->is_a(buf)) { - 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; + } } } diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 5d785e08212..1519fc1990d 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -67,7 +67,7 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) if (ibuf == NULL) return (FALSE); ibuf->flags = flags; - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->save && type->ftype(type, ibuf)) { ImBuf *write_ibuf; short result = FALSE; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e8f55ac047c..35bd4650776 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -316,6 +316,7 @@ typedef struct ImageFormatData { #define R_IMF_IMTYPE_H264 31 #define R_IMF_IMTYPE_XVID 32 #define R_IMF_IMTYPE_THEORA 33 +#define R_IMF_IMTYPE_PSD 34 #define R_IMF_IMTYPE_INVALID 255 diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index d901897cbc4..9554941ec1f 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -164,6 +164,10 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_IMAGE_PSD) + add_definitions(-DWITH_PSD) +endif() + if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 0cfb399c470..9414591eaf9 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -219,6 +219,13 @@ EnumPropertyItem snap_uv_element_items[] = { # define R_IMF_ENUM_TIFF #endif +#ifdef WITH_PSD +# define R_IMF_ENUM_PSD {R_IMF_IMTYPE_PSD, "PSD", ICON_FILE_IMAGE, "Photosp PSD", \ + "Output image in Photoshop PSD format"}, +#else +# define R_IMF_ENUM_PSD +#endif + #define IMAGE_TYPE_ITEMS_IMAGE_ONLY \ R_IMF_ENUM_BMP \ @@ -236,6 +243,7 @@ EnumPropertyItem snap_uv_element_items[] = { R_IMF_ENUM_EXR \ R_IMF_ENUM_HDR \ R_IMF_ENUM_TIFF \ + R_IMF_ENUM_PSD \ EnumPropertyItem image_only_type_items[] = { diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index aae0f926e81..072c73d3d49 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -174,6 +174,10 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_IMAGE_PSD) + add_definitions(-DWITH_PSD) +endif() + if(WITH_IMAGE_OPENJPEG) add_definitions(-DWITH_OPENJPEG) endif() diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index d91319d7477..67009bf2c8b 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -129,6 +129,7 @@ endif() bf_intern_utfconv bf_imbuf_cineon bf_imbuf_openexr + bf_imbuf_openimageio extern_openjpeg extern_redcode bf_imbuf_dds diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index b24339cff1b..8e0ba6684ab 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -912,6 +912,7 @@ endif() bf_avi bf_imbuf_cineon bf_imbuf_openexr + bf_imbuf_openimageio bf_imbuf_dds bf_collada bf_intern_bsp |