6#include <OpenImageIO/imagebuf.h>
7#include <OpenImageIO/imagebufalgo.h>
36 return "ImBufMemWriter";
49 size_t end = offset +
size;
50 while (end > ibuf_->encoded_buffer_size) {
57 memcpy(ibuf_->encoded_buffer.data + offset, buf,
size);
59 ibuf_->encoded_size = std::max<size_t>(end, ibuf_->encoded_size);
64 size_t size()
const override
66 return ibuf_->encoded_size;
78 if (components == 3) {
80 pixels[
i * 4 + 3] = alpha;
83 else if (components == 1) {
85 pixels[
i * 4 + 3] = alpha;
86 pixels[
i * 4 + 2] = pixels[
i * 4 + 0];
87 pixels[
i * 4 + 1] = pixels[
i * 4 + 0];
90 else if (components == 2) {
92 pixels[
i * 4 + 3] = pixels[
i * 4 + 1];
93 pixels[
i * 4 + 2] = pixels[
i * 4 + 0];
94 pixels[
i * 4 + 1] = pixels[
i * 4 + 0];
101 ImageInput *
in,
int width,
int height,
int channels,
int flags,
bool use_all_planes)
104 constexpr bool is_float =
sizeof(
T) > 1;
106 const uint ibuf_flags = (flags &
IB_test) ? 0 : format_flag;
107 const int planes = use_all_planes ? 32 : 8 * channels;
120 const stride_t ibuf_xstride =
sizeof(
T) * 4;
121 const stride_t ibuf_ystride = ibuf_xstride * width;
122 const TypeDesc format = is_float ? TypeDesc::FLOAT : TypeDesc::UINT8;
125 void *ibuf_data = rect + ((stride_t(height) - 1) * ibuf_ystride);
127 bool ok =
in->read_image(
128 0, 0, 0, channels,
format, ibuf_data, ibuf_xstride, -ibuf_ystride, AutoStride);
130 fprintf(stderr,
"ImageInput::read_image() failed: %s\n",
in->geterror().c_str());
137 const T alpha_fill = is_float ? 1.0f : 0xFF;
145 const ImageSpec &spec,
153 string ics = spec.get_string_attribute(
"oiio:ColorSpace");
163 const ImageSpec &spec =
in->spec();
164 const int width = spec.width;
165 const int height = spec.height;
166 const bool has_alpha = spec.alpha_channel != -1;
167 const bool is_float = spec.format.basesize() > 1;
170 const int channels = spec.nchannels <= 4 ? spec.nchannels : 4;
177 ImBuf *ibuf =
nullptr;
192 double x_res = spec.get_float_attribute(
"XResolution", 0.0f);
193 double y_res = spec.get_float_attribute(
"YResolution", 0.0f);
195 if (!(x_res > 0.0f && y_res > 0.0f)) {
196 x_res = spec.get_int_attribute(
"XResolution", 0);
197 y_res = spec.get_int_attribute(
"YResolution", 0);
200 if (x_res > 0.0f && y_res > 0.0f) {
202 auto unit = spec.get_string_attribute(
"ResolutionUnit",
"");
203 if (
ELEM(unit,
"in",
"inch")) {
204 scale = 100.0 / 2.54;
206 else if (unit ==
"cm") {
209 ibuf->
ppm[0] = scale * x_res;
210 ibuf->
ppm[1] = scale * y_res;
218 for (
const auto &attrib : spec.extra_attribs) {
219 if (attrib.name().find(
"ICCProfile") != string::npos) {
236 const ImageSpec &config,
237 Filesystem::IOMemReader &mem_reader,
238 ImageSpec &r_newspec)
242 if (!(
in &&
in->valid_file(&mem_reader))) {
247 in->set_ioproxy(&mem_reader);
248 bool ok =
in->open(
"", r_newspec, config);
258 ImageSpec config, spec;
261 Filesystem::IOMemReader mem_reader(cspan<uchar>(mem, mem_size));
263 return in &&
in->valid_file(&mem_reader);
267 const ImageSpec &config,
269 ImageSpec &r_newspec)
289 ImageBuf final_buf{};
291#if OIIO_VERSION_MAJOR >= 3
292 const size_t original_channels_count = orig_buf.nchannels();
294 const int original_channels_count = orig_buf.nchannels();
297 if (original_channels_count > 1 && file_spec.nchannels == 1) {
300 float weights[4] = {0.0f, 0.0f, 0.0f, 0.0f};
302 ImageBufAlgo::channel_sum(final_buf, orig_buf, {weights, original_channels_count});
304 else if (original_channels_count == 1 && file_spec.nchannels > 1) {
309 const int channel_order[] = {0, 0, 0, -1};
310 const float channel_values[] = {0.0f, 0.0f, 0.0f, 1.0f};
311 const std::string channel_names[] = {
"R",
"G",
"B",
"A"};
312 ImageBufAlgo::channels(final_buf,
315 cspan<int>(channel_order, file_spec.nchannels),
316 cspan<float>(channel_values, file_spec.nchannels),
317 cspan<std::string>(channel_names, file_spec.nchannels));
319 else if (original_channels_count != file_spec.nchannels) {
321 int channel_order[4];
322 for (
int i = 0;
i < 4;
i++) {
326 const bool channel_exists =
i + 1 <= original_channels_count;
327 channel_order[
i] = channel_exists ?
i : -1;
329 const float channel_values[] = {0.0f, 0.0f, 0.0f, 1.0f};
330 const std::string channel_names[] = {
"R",
"G",
"B",
"A"};
331 ImageBufAlgo::channels(final_buf,
334 cspan<int>(channel_order, file_spec.nchannels),
335 cspan<float>(channel_values, file_spec.nchannels),
336 cspan<std::string>(channel_names, file_spec.nchannels));
339 final_buf = std::move(orig_buf);
342 bool write_ok =
false;
343 bool close_ok =
false;
349 out->set_ioproxy(&writer);
350 if (
out->open(
"", file_spec)) {
351 write_ok = final_buf.write(
out.get());
352 close_ok =
out->close();
356 if (
out->open(filepath, file_spec)) {
357 write_ok = final_buf.write(
out.get());
358 close_ok =
out->close();
362 return write_ok && close_ok;
375 const int width = ibuf->
x;
376 const int height = ibuf->
y;
377 const bool use_float = prefer_float && (ibuf->
float_buffer.
data !=
nullptr);
383 ctx.
mem_spec = ImageSpec(width, height, mem_channels, TypeDesc::FLOAT);
386 const int mem_channels = 4;
390 ctx.
mem_spec = ImageSpec(width, height, mem_channels, TypeDesc::UINT8);
401 const int width = ctx.
ibuf->
x;
402 const int height = ctx.
ibuf->
y;
403 ImageSpec file_spec(width, height, file_channels, data_format);
419 if (
char *colon = strchr(prop->name,
':')) {
420 std::string prefix(prop->name, colon);
421 Strutil::to_lower(prefix);
422 if (prefix ==
"oiio" ||
423 (!
STREQ(prefix.c_str(), ctx.
file_format) && OIIO::is_imageio_format_name(prefix)))
430 file_spec.attribute(prop->name,
IDP_String(prop));
438 file_spec.attribute(
"ResolutionUnit",
"m");
439 file_spec.attribute(
"XResolution",
int(
round(ctx.
ibuf->
ppm[0])));
440 file_spec.attribute(
"YResolution",
int(
round(ctx.
ibuf->
ppm[1])));
444 file_spec.attribute(
"ResolutionUnit",
"in");
445 file_spec.attribute(
"XResolution",
float(ctx.
ibuf->
ppm[0] * 0.0254));
446 file_spec.attribute(
"YResolution",
float(ctx.
ibuf->
ppm[1] * 0.0254));
#define LISTBASE_FOREACH(type, var, list)
char * STRNCPY(char(&dst)[N], const char *src)
ID and Library types, which are fundamental for SDNA.
BLI_INLINE void IMB_colormanagement_get_luminance_coefficients(float r_rgb[3])
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
@ IB_uninitialized_pixels
bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
bool imb_addencodedbufferImBuf(ImBuf *ibuf)
size_t write(const void *buf, size_t size) override
size_t pwrite(const void *buf, size_t size, int64_t offset) override
const char * proxytype() const override
size_t size() const override
ImBufMemWriter(ImBuf *ibuf)
bool imb_oiio_write(const WriteContext &ctx, const char *filepath, const ImageSpec &file_spec)
WriteContext imb_create_write_context(const char *file_format, ImBuf *ibuf, int flags, bool prefer_float)
static unique_ptr< ImageInput > get_oiio_reader(const char *format, const ImageSpec &config, Filesystem::IOMemReader &mem_reader, ImageSpec &r_newspec)
ImBuf * imb_oiio_read(const ReadContext &ctx, const ImageSpec &config, ImFileColorSpace &r_colorspace, ImageSpec &r_newspec)
bool imb_oiio_check(const uchar *mem, size_t mem_size, const char *file_format)
ImageSpec imb_create_write_spec(const WriteContext &ctx, int file_channels, TypeDesc data_format)
static ImBuf * get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, ImFileColorSpace &r_colorspace)
static ImBuf * load_pixels(ImageInput *in, int width, int height, int channels, int flags, bool use_all_planes)
static void fill_all_channels(T *pixels, int width, int height, int components, T alpha)
static void set_file_colorspace(ImFileColorSpace &r_colorspace, const ReadContext &ctx, const ImageSpec &spec, bool is_float)
ImBufFloatBuffer float_buffer
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
char metadata_colorspace[IM_MAX_SPACE]
bool use_metadata_colorspace
const eImbFileType file_type
OIIO::stride_t mem_ystride
OIIO::stride_t mem_xstride