Blender  V2.93
openimageio_api.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2013 Blender Foundation
17  * All rights reserved.
18  */
19 
24 #include <set>
25 
26 #if defined(WIN32)
27 # include "utfconv.h"
28 # define _USE_MATH_DEFINES
29 #endif
30 
31 // NOTE: Keep first, BLI_path_util conflicts with OIIO's format.
32 #include "openimageio_api.h"
33 #include <OpenImageIO/imageio.h>
34 #include <memory>
35 
36 #include "MEM_guardedalloc.h"
37 
38 #include "BLI_blenlib.h"
39 
40 #include "IMB_allocimbuf.h"
41 #include "IMB_colormanagement.h"
43 #include "IMB_imbuf.h"
44 #include "IMB_imbuf_types.h"
45 
46 OIIO_NAMESPACE_USING
47 
48 using std::string;
49 using std::unique_ptr;
50 
51 using uchar = unsigned char;
52 
53 template<class T, class Q>
54 static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha)
55 {
56  if (components == 2) {
57  for (int i = width * height - 1; i >= 0; i--) {
58  pixels[i * 4 + 3] = pixels[i * 2 + 1];
59  pixels[i * 4 + 2] = pixels[i * 2 + 0];
60  pixels[i * 4 + 1] = pixels[i * 2 + 0];
61  pixels[i * 4 + 0] = pixels[i * 2 + 0];
62  }
63  }
64  else if (components == 3) {
65  for (int i = width * height - 1; i >= 0; i--) {
66  pixels[i * 4 + 3] = alpha;
67  pixels[i * 4 + 2] = pixels[i * 3 + 2];
68  pixels[i * 4 + 1] = pixels[i * 3 + 1];
69  pixels[i * 4 + 0] = pixels[i * 3 + 0];
70  }
71  }
72  else if (components == 1) {
73  for (int i = width * height - 1; i >= 0; i--) {
74  pixels[i * 4 + 3] = alpha;
75  pixels[i * 4 + 2] = pixels[i];
76  pixels[i * 4 + 1] = pixels[i];
77  pixels[i * 4 + 0] = pixels[i];
78  }
79  }
80 }
81 
83  ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
84 {
85  ImBuf *ibuf;
86  int scanlinesize = width * components * sizeof(uchar);
87 
88  /* allocate the memory for the image */
89  ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect);
90 
91  try {
92  if (!in->read_image(TypeDesc::UINT8,
93  (uchar *)ibuf->rect + (height - 1) * scanlinesize,
94  AutoStride,
95  -scanlinesize,
96  AutoStride)) {
97  std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl
98  << in->geterror() << std::endl;
99 
100  if (ibuf) {
101  IMB_freeImBuf(ibuf);
102  }
103 
104  return nullptr;
105  }
106  }
107  catch (const std::exception &exc) {
108  std::cerr << exc.what() << std::endl;
109  if (ibuf) {
110  IMB_freeImBuf(ibuf);
111  }
112 
113  return nullptr;
114  }
115 
116  /* ImBuf always needs 4 channels */
117  fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF);
118 
119  return ibuf;
120 }
121 
123  ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
124 {
125  ImBuf *ibuf;
126  int scanlinesize = width * components * sizeof(float);
127 
128  /* allocate the memory for the image */
129  ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat);
130 
131  try {
132  if (!in->read_image(TypeDesc::FLOAT,
133  (uchar *)ibuf->rect_float + (height - 1) * scanlinesize,
134  AutoStride,
135  -scanlinesize,
136  AutoStride)) {
137  std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl
138  << in->geterror() << std::endl;
139 
140  if (ibuf) {
141  IMB_freeImBuf(ibuf);
142  }
143 
144  return nullptr;
145  }
146  }
147  catch (const std::exception &exc) {
148  std::cerr << exc.what() << std::endl;
149  if (ibuf) {
150  IMB_freeImBuf(ibuf);
151  }
152 
153  return nullptr;
154  }
155 
156  /* ImBuf always needs 4 channels */
157  fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f);
158 
159  /* Note: Photoshop 16 bit files never has alpha with it,
160  * so no need to handle associated/unassociated alpha. */
161  return ibuf;
162 }
163 
164 extern "C" {
165 
166 bool imb_is_a_photoshop(const unsigned char *mem, size_t size)
167 {
168  const unsigned char magic[4] = {'8', 'B', 'P', 'S'};
169  if (size < sizeof(magic)) {
170  return false;
171  }
172  return memcmp(magic, mem, sizeof(magic)) == 0;
173 }
174 
175 int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags)
176 {
177  if (flags & IB_mem) {
178  std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory"
179  << " currently not supported" << std::endl;
181  ibuf->encodedsize = 0;
182  return 0;
183  }
184 
185  return 0;
186 }
187 
188 struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE])
189 {
190  struct ImBuf *ibuf = nullptr;
191  int width, height, components;
192  bool is_float, is_alpha, is_half;
193  int basesize;
194  char file_colorspace[IM_MAX_SPACE];
195  const bool is_colorspace_manually_set = (colorspace[0] != '\0');
196 
197  /* load image from file through OIIO */
198  if (IMB_ispic_type_matches(filename, IMB_FTYPE_PSD) == 0) {
199  return nullptr;
200  }
201 
203 
204  unique_ptr<ImageInput> in(ImageInput::create(filename));
205  if (!in) {
206  std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl
207  << OIIO_NAMESPACE::geterror() << std::endl;
208  return nullptr;
209  }
210 
211  ImageSpec spec, config;
212  config.attribute("oiio:UnassociatedAlpha", (int)1);
213 
214  if (!in->open(filename, spec, config)) {
215  std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl
216  << in->geterror() << std::endl;
217  return nullptr;
218  }
219 
220  if (!is_colorspace_manually_set) {
221  string ics = spec.get_string_attribute("oiio:ColorSpace");
222  BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE);
223 
224  /* only use colorspaces exis */
225  if (colormanage_colorspace_get_named(file_colorspace)) {
226  strcpy(colorspace, file_colorspace);
227  }
228  else {
229  std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace
230  << "\") not supported in existent OCIO configuration file. Fallback "
231  << "to system default colorspace (\"" << colorspace << "\")." << std::endl;
232  }
233  }
234 
235  width = spec.width;
236  height = spec.height;
237  components = spec.nchannels;
238  is_alpha = spec.alpha_channel != -1;
239  basesize = spec.format.basesize();
240  is_float = basesize > 1;
241  is_half = spec.format == TypeDesc::HALF;
242 
243  /* we only handle certain number of components */
244  if (!(components >= 1 && components <= 4)) {
245  if (in) {
246  in->close();
247  }
248  return nullptr;
249  }
250 
251  if (is_float) {
252  ibuf = imb_oiio_load_image_float(in.get(), width, height, components, flags, is_alpha);
253  }
254  else {
255  ibuf = imb_oiio_load_image(in.get(), width, height, components, flags, is_alpha);
256  }
257 
258  if (in) {
259  in->close();
260  }
261 
262  if (!ibuf) {
263  return nullptr;
264  }
265 
266  /* ImBuf always needs 4 channels */
267  ibuf->ftype = IMB_FTYPE_PSD;
268  ibuf->channels = 4;
269  ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize;
270  ibuf->flags |= (is_float && is_half) ? IB_halffloat : 0;
271 
272  try {
273  return ibuf;
274  }
275  catch (const std::exception &exc) {
276  std::cerr << exc.what() << std::endl;
277  if (ibuf) {
278  IMB_freeImBuf(ibuf);
279  }
280 
281  return nullptr;
282  }
283 }
284 
286 {
287  return openimageio_version();
288 }
289 
290 } /* export "C" */
typedef float(TangentPoint)[2]
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned char uchar
Definition: BLI_sys_types.h:86
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
Header file for allocimbuf.c.
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:65
bool IMB_ispic_type_matches(const char *filepath, int filetype)
Definition: util.c:175
Contains defines and structs used throughout the imbuf module.
@ IB_halffloat
@ IB_rectfloat
@ IB_mem
@ IB_rect
Read Guarded memory(de)allocation.
bool imb_addencodedbufferImBuf(ImBuf *ibuf)
Definition: allocimbuf.c:306
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void colorspace_set_default_role(char *colorspace, int size, int role)
ColorSpace * colormanage_colorspace_get_named(const char *name)
@ HALF
Definition: curve_bevel.c:43
static CCL_NAMESPACE_BEGIN const double alpha
#define T
int imb_save_photoshop(struct ImBuf *ibuf, const char *, int flags)
static ImBuf * imb_oiio_load_image_float(ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
struct ImBuf * imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE])
bool imb_is_a_photoshop(const unsigned char *mem, size_t size)
int OIIO_getVersionHex(void)
static ImBuf * imb_oiio_load_image(ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
unsigned char uchar
static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha)
int channels
unsigned char planes
enum eImbFileType ftype
unsigned int * rect
unsigned int encodedsize
float * rect_float
static int magic(const Tex *tex, const float texvec[3], TexResult *texres)