diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2013-10-09 01:17:24 +0400 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2013-10-09 01:17:24 +0400 |
commit | 4abb8fde95260e692b3cd5b5b2f8bcd1d1f3be3b (patch) | |
tree | 9c3d68aa7abd18ddfef5b3af643b8a7556903e18 /source/blender/imbuf/intern/readimage.c | |
parent | 590f58d45583f36522ffbcebd68b4a6c921bebeb (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/imbuf/intern/readimage.c')
-rw-r--r-- | source/blender/imbuf/intern/readimage.c | 134 |
1 files changed, 86 insertions, 48 deletions
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); |