Blender  V2.93
image_oiio.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2020 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/image_oiio.h"
18 
19 #include "util/util_image.h"
20 #include "util/util_logging.h"
21 #include "util/util_path.h"
22 
24 
25 OIIOImageLoader::OIIOImageLoader(const string &filepath) : filepath(filepath)
26 {
27 }
28 
30 {
31 }
32 
34 {
35  /* Perform preliminary checks, with meaningful logging. */
36  if (!path_exists(filepath.string())) {
37  VLOG(1) << "File '" << filepath.string() << "' does not exist.";
38  return false;
39  }
40  if (path_is_directory(filepath.string())) {
41  VLOG(1) << "File '" << filepath.string() << "' is a directory, can't use as image.";
42  return false;
43  }
44 
45  unique_ptr<ImageInput> in(ImageInput::create(filepath.string()));
46 
47  if (!in) {
48  return false;
49  }
50 
51  ImageSpec spec;
52  if (!in->open(filepath.string(), spec)) {
53  return false;
54  }
55 
56  metadata.width = spec.width;
57  metadata.height = spec.height;
58  metadata.depth = spec.depth;
59  metadata.compress_as_srgb = false;
60 
61  /* Check the main format, and channel formats. */
62  size_t channel_size = spec.format.basesize();
63 
64  bool is_float = false;
65  bool is_half = false;
66 
67  if (spec.format.is_floating_point()) {
68  is_float = true;
69  }
70 
71  for (size_t channel = 0; channel < spec.channelformats.size(); channel++) {
72  channel_size = max(channel_size, spec.channelformats[channel].basesize());
73  if (spec.channelformats[channel].is_floating_point()) {
74  is_float = true;
75  }
76  }
77 
78  /* check if it's half float */
79  if (spec.format == TypeDesc::HALF && features.has_half_float) {
80  is_half = true;
81  }
82 
83  /* set type and channels */
84  metadata.channels = spec.nchannels;
85 
86  if (is_half) {
87  metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
88  }
89  else if (is_float) {
90  metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
91  }
92  else if (spec.format == TypeDesc::USHORT) {
93  metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT;
94  }
95  else {
96  metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
97  }
98 
99  metadata.colorspace_file_format = in->format_name();
100 
101  in->close();
102 
103  return true;
104 }
105 
106 template<TypeDesc::BASETYPE FileFormat, typename StorageType>
107 static void oiio_load_pixels(const ImageMetaData &metadata,
108  const unique_ptr<ImageInput> &in,
109  StorageType *pixels)
110 {
111  const int width = metadata.width;
112  const int height = metadata.height;
113  const int depth = metadata.depth;
114  const int components = metadata.channels;
115 
116  /* Read pixels through OpenImageIO. */
117  StorageType *readpixels = pixels;
118  vector<StorageType> tmppixels;
119  if (components > 4) {
120  tmppixels.resize(((size_t)width) * height * components);
121  readpixels = &tmppixels[0];
122  }
123 
124  if (depth <= 1) {
125  size_t scanlinesize = ((size_t)width) * components * sizeof(StorageType);
126  in->read_image(FileFormat,
127  (uchar *)readpixels + (height - 1) * scanlinesize,
128  AutoStride,
129  -scanlinesize,
130  AutoStride);
131  }
132  else {
133  in->read_image(FileFormat, (uchar *)readpixels);
134  }
135 
136  if (components > 4) {
137  size_t dimensions = ((size_t)width) * height;
138  for (size_t i = dimensions - 1, pixel = 0; pixel < dimensions; pixel++, i--) {
139  pixels[i * 4 + 3] = tmppixels[i * components + 3];
140  pixels[i * 4 + 2] = tmppixels[i * components + 2];
141  pixels[i * 4 + 1] = tmppixels[i * components + 1];
142  pixels[i * 4 + 0] = tmppixels[i * components + 0];
143  }
144  tmppixels.clear();
145  }
146 
147  /* CMYK to RGBA. */
148  const bool cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
149  if (cmyk) {
150  const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
151 
152  const size_t num_pixels = ((size_t)width) * height * depth;
153  for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
154  float c = util_image_cast_to_float(pixels[i * 4 + 0]);
155  float m = util_image_cast_to_float(pixels[i * 4 + 1]);
156  float y = util_image_cast_to_float(pixels[i * 4 + 2]);
157  float k = util_image_cast_to_float(pixels[i * 4 + 3]);
158  pixels[i * 4 + 0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
159  pixels[i * 4 + 1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
160  pixels[i * 4 + 2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
161  pixels[i * 4 + 3] = one;
162  }
163  }
164 }
165 
167  void *pixels,
168  const size_t,
169  const bool associate_alpha)
170 {
171  unique_ptr<ImageInput> in = NULL;
172 
173  /* NOTE: Error logging is done in meta data acquisition. */
174  if (!path_exists(filepath.string()) || path_is_directory(filepath.string())) {
175  return false;
176  }
177 
178  /* load image from file through OIIO */
179  in = unique_ptr<ImageInput>(ImageInput::create(filepath.string()));
180  if (!in) {
181  return false;
182  }
183 
184  ImageSpec spec = ImageSpec();
185  ImageSpec config = ImageSpec();
186 
187  if (!associate_alpha) {
188  config.attribute("oiio:UnassociatedAlpha", 1);
189  }
190 
191  if (!in->open(filepath.string(), spec, config)) {
192  return false;
193  }
194 
195  switch (metadata.type) {
198  oiio_load_pixels<TypeDesc::UINT8, uchar>(metadata, in, (uchar *)pixels);
199  break;
202  oiio_load_pixels<TypeDesc::USHORT, uint16_t>(metadata, in, (uint16_t *)pixels);
203  break;
206  oiio_load_pixels<TypeDesc::HALF, half>(metadata, in, (half *)pixels);
207  break;
210  oiio_load_pixels<TypeDesc::FLOAT, float>(metadata, in, (float *)pixels);
211  break;
215  break;
216  }
217 
218  in->close();
219  return true;
220 }
221 
222 string OIIOImageLoader::name() const
223 {
224  return path_filename(filepath.string());
225 }
226 
228 {
229  return filepath;
230 }
231 
232 bool OIIOImageLoader::equals(const ImageLoader &other) const
233 {
234  const OIIOImageLoader &other_loader = (const OIIOImageLoader &)other;
235  return filepath == other_loader.filepath;
236 }
237 
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
_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 y
#define USHORT
Definition: GeoCommon.h:21
ImageDataType type
const char * colorspace_file_format
ustring osl_filepath() const override
Definition: image_oiio.cpp:227
bool equals(const ImageLoader &other) const override
Definition: image_oiio.cpp:232
bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) override
Definition: image_oiio.cpp:166
ustring filepath
Definition: image_oiio.h:43
OIIOImageLoader(const string &filepath)
Definition: image_oiio.cpp:25
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override
Definition: image_oiio.cpp:33
string name() const override
Definition: image_oiio.cpp:222
Definition: util_half.h:41
@ HALF
Definition: curve_bevel.c:43
static void oiio_load_pixels(const ImageMetaData &metadata, const unique_ptr< ImageInput > &in, StorageType *pixels)
Definition: image_oiio.cpp:107
#define CCL_NAMESPACE_END
static unsigned c
Definition: RandGen.cpp:97
unsigned short uint16_t
Definition: stdint.h:82
float max
float util_image_cast_to_float(T value)
#define VLOG(severity)
Definition: util_logging.h:50
bool path_is_directory(const string &path)
Definition: util_path.cpp:591
bool path_exists(const string &path)
Definition: util_path.cpp:572
string path_filename(const string &path)
Definition: util_path.cpp:389
@ IMAGE_DATA_NUM_TYPES
Definition: util_texture.h:63
@ IMAGE_DATA_TYPE_BYTE
Definition: util_texture.h:56
@ IMAGE_DATA_TYPE_FLOAT
Definition: util_texture.h:55
@ IMAGE_DATA_TYPE_FLOAT4
Definition: util_texture.h:52
@ IMAGE_DATA_TYPE_USHORT4
Definition: util_texture.h:58
@ IMAGE_DATA_TYPE_USHORT
Definition: util_texture.h:59
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
Definition: util_texture.h:60
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
Definition: util_texture.h:61
@ IMAGE_DATA_TYPE_HALF
Definition: util_texture.h:57
@ IMAGE_DATA_TYPE_BYTE4
Definition: util_texture.h:53
@ IMAGE_DATA_TYPE_HALF4
Definition: util_texture.h:54