Blender  V3.3
openimageio_api.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2013 Blender Foundation. All rights reserved. */
3 
8 #include <set>
9 
10 #if defined(WIN32)
11 # include "utfconv.h"
12 # define _USE_MATH_DEFINES
13 #endif
14 
15 /* NOTE: Keep first, #BLI_path_util conflicts with OIIO's format. */
16 #include "openimageio_api.h"
17 #include <OpenImageIO/imageio.h>
18 #include <memory>
19 
20 #include "MEM_guardedalloc.h"
21 
22 #include "BLI_blenlib.h"
23 
24 #include "IMB_allocimbuf.h"
25 #include "IMB_colormanagement.h"
27 #include "IMB_imbuf.h"
28 #include "IMB_imbuf_types.h"
29 
30 OIIO_NAMESPACE_USING
31 
32 using std::string;
33 using std::unique_ptr;
34 
35 using uchar = unsigned char;
36 
37 template<class T, class Q>
38 static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha)
39 {
40  if (components == 2) {
41  for (int i = width * height - 1; i >= 0; i--) {
42  pixels[i * 4 + 3] = pixels[i * 2 + 1];
43  pixels[i * 4 + 2] = pixels[i * 2 + 0];
44  pixels[i * 4 + 1] = pixels[i * 2 + 0];
45  pixels[i * 4 + 0] = pixels[i * 2 + 0];
46  }
47  }
48  else if (components == 3) {
49  for (int i = width * height - 1; i >= 0; i--) {
50  pixels[i * 4 + 3] = alpha;
51  pixels[i * 4 + 2] = pixels[i * 3 + 2];
52  pixels[i * 4 + 1] = pixels[i * 3 + 1];
53  pixels[i * 4 + 0] = pixels[i * 3 + 0];
54  }
55  }
56  else if (components == 1) {
57  for (int i = width * height - 1; i >= 0; i--) {
58  pixels[i * 4 + 3] = alpha;
59  pixels[i * 4 + 2] = pixels[i];
60  pixels[i * 4 + 1] = pixels[i];
61  pixels[i * 4 + 0] = pixels[i];
62  }
63  }
64 }
65 
67  ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
68 {
69  ImBuf *ibuf;
70  int scanlinesize = width * components * sizeof(uchar);
71 
72  /* allocate the memory for the image */
73  ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect);
74 
75  try {
76  if (!in->read_image(TypeDesc::UINT8,
77  (uchar *)ibuf->rect + (height - 1) * scanlinesize,
78  AutoStride,
79  -scanlinesize,
80  AutoStride)) {
81  std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl
82  << in->geterror() << std::endl;
83 
84  if (ibuf) {
85  IMB_freeImBuf(ibuf);
86  }
87 
88  return nullptr;
89  }
90  }
91  catch (const std::exception &exc) {
92  std::cerr << exc.what() << std::endl;
93  if (ibuf) {
94  IMB_freeImBuf(ibuf);
95  }
96 
97  return nullptr;
98  }
99 
100  /* ImBuf always needs 4 channels */
101  fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF);
102 
103  return ibuf;
104 }
105 
107  ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
108 {
109  ImBuf *ibuf;
110  int scanlinesize = width * components * sizeof(float);
111 
112  /* allocate the memory for the image */
113  ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat);
114 
115  try {
116  if (!in->read_image(TypeDesc::FLOAT,
117  (uchar *)ibuf->rect_float + (height - 1) * scanlinesize,
118  AutoStride,
119  -scanlinesize,
120  AutoStride)) {
121  std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl
122  << in->geterror() << std::endl;
123 
124  if (ibuf) {
125  IMB_freeImBuf(ibuf);
126  }
127 
128  return nullptr;
129  }
130  }
131  catch (const std::exception &exc) {
132  std::cerr << exc.what() << std::endl;
133  if (ibuf) {
134  IMB_freeImBuf(ibuf);
135  }
136 
137  return nullptr;
138  }
139 
140  /* ImBuf always needs 4 channels */
141  fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f);
142 
143  /* NOTE: Photoshop 16 bit files never has alpha with it,
144  * so no need to handle associated/unassociated alpha. */
145  return ibuf;
146 }
147 
148 extern "C" {
149 
150 bool imb_is_a_photoshop(const unsigned char *mem, size_t size)
151 {
152  const unsigned char magic[4] = {'8', 'B', 'P', 'S'};
153  if (size < sizeof(magic)) {
154  return false;
155  }
156  return memcmp(magic, mem, sizeof(magic)) == 0;
157 }
158 
159 int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags)
160 {
161  if (flags & IB_mem) {
162  std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory"
163  << " currently not supported" << std::endl;
165  ibuf->encodedsize = 0;
166  return 0;
167  }
168 
169  return 0;
170 }
171 
172 struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE])
173 {
174  struct ImBuf *ibuf = nullptr;
175  int width, height, components;
176  bool is_float, is_alpha, is_half;
177  int basesize;
178  char file_colorspace[IM_MAX_SPACE];
179  const bool is_colorspace_manually_set = (colorspace[0] != '\0');
180 
181  /* load image from file through OIIO */
182  if (IMB_ispic_type_matches(filename, IMB_FTYPE_PSD) == 0) {
183  return nullptr;
184  }
185 
187 
188  unique_ptr<ImageInput> in(ImageInput::create(filename));
189  if (!in) {
190  std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl
191  << OIIO_NAMESPACE::geterror() << std::endl;
192  return nullptr;
193  }
194 
195  ImageSpec spec, config;
196  config.attribute("oiio:UnassociatedAlpha", (int)1);
197 
198  if (!in->open(filename, spec, config)) {
199  std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl
200  << in->geterror() << std::endl;
201  return nullptr;
202  }
203 
204  if (!is_colorspace_manually_set) {
205  string ics = spec.get_string_attribute("oiio:ColorSpace");
206  BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE);
207 
208  /* Only use color-spaces exist. */
209  if (colormanage_colorspace_get_named(file_colorspace)) {
210  strcpy(colorspace, file_colorspace);
211  }
212  else {
213  std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace
214  << "\") not supported in existent OCIO configuration file. Fallback "
215  << "to system default colorspace (\"" << colorspace << "\")." << std::endl;
216  }
217  }
218 
219  width = spec.width;
220  height = spec.height;
221  components = spec.nchannels;
222  is_alpha = spec.alpha_channel != -1;
223  basesize = spec.format.basesize();
224  is_float = basesize > 1;
225  is_half = spec.format == TypeDesc::HALF;
226 
227  /* we only handle certain number of components */
228  if (!(components >= 1 && components <= 4)) {
229  if (in) {
230  in->close();
231  }
232  return nullptr;
233  }
234 
235  if (is_float) {
236  ibuf = imb_oiio_load_image_float(in.get(), width, height, components, flags, is_alpha);
237  }
238  else {
239  ibuf = imb_oiio_load_image(in.get(), width, height, components, flags, is_alpha);
240  }
241 
242  if (in) {
243  in->close();
244  }
245 
246  if (!ibuf) {
247  return nullptr;
248  }
249 
250  /* ImBuf always needs 4 channels */
251  ibuf->ftype = IMB_FTYPE_PSD;
252  ibuf->channels = 4;
253  ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize;
254  ibuf->flags |= (is_float && is_half) ? IB_halffloat : 0;
255 
256  try {
257  return ibuf;
258  }
259  catch (const std::exception &exc) {
260  std::cerr << exc.what() << std::endl;
261  if (ibuf) {
262  IMB_freeImBuf(ibuf);
263  }
264 
265  return nullptr;
266  }
267 }
268 
270 {
271  return openimageio_version();
272 }
273 
274 } /* export "C" */
typedef float(TangentPoint)[2]
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned char uchar
Definition: BLI_sys_types.h:70
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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
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:500
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:49
bool IMB_ispic_type_matches(const char *filepath, int filetype)
Definition: util.c:161
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:287
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:29
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
#define T
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
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)
@ FLOAT
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)