Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2013-10-09 01:17:24 +0400
committerDalai Felinto <dfelinto@gmail.com>2013-10-09 01:17:24 +0400
commit4abb8fde95260e692b3cd5b5b2f8bcd1d1f3be3b (patch)
tree9c3d68aa7abd18ddfef5b3af643b8a7556903e18 /source/blender
parent590f58d45583f36522ffbcebd68b4a6c921bebeb (diff)
Photoshop PSD support
We now support the combined layer of Photoshop files (stored as layer 0 in the file). This way users can keep their files as multilayer PSD and Blender always handle them as flat images. For perfect alpha this requires an OpenImageIO update: https://github.com/OpenImageIO/oiio/commit/342cc2633ff590a3bb278481c61ae798c7148361 Photoshop sample files: https://github.com/OpenImageIO/oiio-images Brecht has some pending fixes to push for OIIO as well, so we may as well wait to update our libraries. What works: =========== * 8bit images (with or without alpha) * 16bits images (alpha discarded) * Photoshop files saved with 'Maximum Compatibility' * Cycles, Blender internal, BGE (and player) Known limitations (due to OIIO dependency): ========================= * Images with less than 4 channels show a wrong thumbnail (bug may be in OIIO) * Packed images are not supported * We do not write PSD files. Note: old Blenders have support for PSD via Quicktime library. But due to license issues this was discontinued. Many thanks for Brecht van Lommel for reviewing the patch, suggesting multiple improvements and to help solving the alpha issue.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/image.c6
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt3
-rw-r--r--source/blender/imbuf/CMakeLists.txt9
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h7
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h3
-rw-r--r--source/blender/imbuf/intern/colormanagement.c4
-rw-r--r--source/blender/imbuf/intern/filetype.c43
-rw-r--r--source/blender/imbuf/intern/oiio/CMakeLists.txt54
-rw-r--r--source/blender/imbuf/intern/oiio/SConscript47
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp257
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.h53
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_stub.cpp35
-rw-r--r--source/blender/imbuf/intern/readimage.c134
-rw-r--r--source/blender/imbuf/intern/util.c23
-rw-r--r--source/blender/imbuf/intern/writeimage.c2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c8
-rw-r--r--source/blender/python/intern/CMakeLists.txt4
22 files changed, 635 insertions, 72 deletions
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()