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:
342cc2633f

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.
This commit is contained in:
Dalai Felinto 2013-10-08 21:17:24 +00:00
parent 590f58d455
commit 4abb8fde95
26 changed files with 646 additions and 73 deletions

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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"))

View File

@ -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()

View File

@ -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()

View File

@ -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}

View File

@ -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);
/**
*

View File

@ -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)
};

View File

@ -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);

View File

@ -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;

View File

@ -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
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}
#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, 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();
}

View File

@ -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}")

View File

@ -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])

View File

@ -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"

View File

@ -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 */

View File

@ -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

View File

@ -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,11 @@ 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;
}
}
@ -129,7 +133,38 @@ 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 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;
}
}
}
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_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);

View File

@ -97,6 +97,16 @@ const char *imb_ext_image[] = {
#endif
#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;
}
}
}

View File

@ -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;

View File

@ -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

View File

@ -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()

View File

@ -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[] = {

View File

@ -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()

View File

@ -129,6 +129,7 @@ endif()
bf_intern_utfconv
bf_imbuf_cineon
bf_imbuf_openexr
bf_imbuf_openimageio
extern_openjpeg
extern_redcode
bf_imbuf_dds

View File

@ -912,6 +912,7 @@ endif()
bf_avi
bf_imbuf_cineon
bf_imbuf_openexr
bf_imbuf_openimageio
bf_imbuf_dds
bf_collada
bf_intern_bsp