6#include <OpenImageIO/imagebuf.h>
7#include <OpenImageIO/imagebufalgo.h>
42 return "ImBufMemWriter";
55 size_t end = offset +
size;
56 while (end > ibuf_->encoded_buffer_size) {
63 memcpy(ibuf_->encoded_buffer.data + offset, buf,
size);
65 ibuf_->encoded_size = std::max<size_t>(end, ibuf_->encoded_size);
70 size_t size()
const override
72 return ibuf_->encoded_size;
84 if (components == 3) {
86 pixels[
i * 4 + 3] = alpha;
89 else if (components == 1) {
91 pixels[
i * 4 + 3] = alpha;
92 pixels[
i * 4 + 2] = pixels[
i * 4 + 0];
93 pixels[
i * 4 + 1] = pixels[
i * 4 + 0];
96 else if (components == 2) {
98 pixels[
i * 4 + 3] = pixels[
i * 4 + 1];
99 pixels[
i * 4 + 2] = pixels[
i * 4 + 0];
100 pixels[
i * 4 + 1] = pixels[
i * 4 + 0];
107 ImageInput *
in,
int width,
int height,
int channels,
int flags,
bool use_all_planes)
110 constexpr bool is_float =
sizeof(
T) > 1;
112 const uint ibuf_flags = (flags &
IB_test) ? 0 : format_flag;
113 const int planes = use_all_planes ? 32 : 8 * channels;
126 const stride_t ibuf_xstride =
sizeof(
T) * 4;
127 const stride_t ibuf_ystride = ibuf_xstride * width;
128 const TypeDesc
format = is_float ? TypeDesc::FLOAT : TypeDesc::UINT8;
131 void *ibuf_data = rect + ((stride_t(height) - 1) * ibuf_ystride);
133 bool ok =
in->read_image(
134 0, 0, 0, channels,
format, ibuf_data, ibuf_xstride, -ibuf_ystride, AutoStride);
143 const T alpha_fill = is_float ? 1.0f : 0xFF;
151 const ImageSpec &spec,
159 string ics = spec.get_string_attribute(
"oiio:ColorSpace");
165 if (spec.getattribute(
"CICP", TypeDesc(TypeDesc::INT, 4), cicp,
true)) {
180 const ImageSpec &spec =
in->spec();
181 const int width = spec.width;
182 const int height = spec.height;
183 const bool has_alpha = spec.alpha_channel != -1;
184 const bool is_float = spec.format.basesize() > 1;
187 const int channels = spec.nchannels <= 4 ? spec.nchannels : 4;
194 ImBuf *ibuf =
nullptr;
209 double x_res = spec.get_float_attribute(
"XResolution", 0.0f);
210 double y_res = spec.get_float_attribute(
"YResolution", 0.0f);
212 if (!(x_res > 0.0f && y_res > 0.0f)) {
213 x_res = spec.get_int_attribute(
"XResolution", 0);
214 y_res = spec.get_int_attribute(
"YResolution", 0);
217 if (x_res > 0.0f && y_res > 0.0f) {
219 auto unit = spec.get_string_attribute(
"ResolutionUnit",
"");
220 if (
ELEM(unit,
"in",
"inch")) {
221 scale = 100.0 / 2.54;
223 else if (unit ==
"cm") {
226 ibuf->
ppm[0] = scale * x_res;
227 ibuf->
ppm[1] = scale * y_res;
235 for (
const auto &attrib : spec.extra_attribs) {
236 if (attrib.name().find(
"ICCProfile") != string::npos) {
253 const ImageSpec &config,
254 Filesystem::IOMemReader &mem_reader,
255 ImageSpec &r_newspec)
259 if (!(
in &&
in->valid_file(&mem_reader))) {
264 in->set_ioproxy(&mem_reader);
265 bool ok =
in->open(
"", r_newspec, config);
275 ImageSpec config, spec;
278 Filesystem::IOMemReader mem_reader(cspan<uchar>(mem, mem_size));
280 return in &&
in->valid_file(&mem_reader);
284 const ImageSpec &config,
286 ImageSpec &r_newspec)
306 ImageBuf final_buf{};
308#if OIIO_VERSION_MAJOR >= 3
309 const size_t original_channels_count = orig_buf.nchannels();
311 const int original_channels_count = orig_buf.nchannels();
314 if (original_channels_count > 1 && file_spec.nchannels == 1) {
317 float weights[4] = {0.0f, 0.0f, 0.0f, 0.0f};
319 ImageBufAlgo::channel_sum(final_buf, orig_buf, {weights, original_channels_count});
321 else if (original_channels_count == 1 && file_spec.nchannels > 1) {
326 const int channel_order[] = {0, 0, 0, -1};
327 const float channel_values[] = {0.0f, 0.0f, 0.0f, 1.0f};
328 const std::string channel_names[] = {
"R",
"G",
"B",
"A"};
329 ImageBufAlgo::channels(final_buf,
332 cspan<int>(channel_order, file_spec.nchannels),
333 cspan<float>(channel_values, file_spec.nchannels),
334 cspan<std::string>(channel_names, file_spec.nchannels));
336 else if (original_channels_count != file_spec.nchannels) {
338 int channel_order[4];
339 for (
int i = 0;
i < 4;
i++) {
343 const bool channel_exists =
i + 1 <= original_channels_count;
344 channel_order[
i] = channel_exists ?
i : -1;
346 const float channel_values[] = {0.0f, 0.0f, 0.0f, 1.0f};
347 const std::string channel_names[] = {
"R",
"G",
"B",
"A"};
348 ImageBufAlgo::channels(final_buf,
351 cspan<int>(channel_order, file_spec.nchannels),
352 cspan<float>(channel_values, file_spec.nchannels),
353 cspan<std::string>(channel_names, file_spec.nchannels));
356 final_buf = std::move(orig_buf);
359 bool write_ok =
false;
360 bool close_ok =
false;
366 out->set_ioproxy(&writer);
367 if (
out->open(
"", file_spec)) {
368 write_ok = final_buf.write(
out.get());
369 close_ok =
out->close();
373 if (
out->open(filepath, file_spec)) {
374 write_ok = final_buf.write(
out.get());
375 close_ok =
out->close();
379 const bool all_ok = write_ok && close_ok;
398 const int width = ibuf->
x;
399 const int height = ibuf->
y;
400 const bool use_float = prefer_float && (ibuf->
float_buffer.
data !=
nullptr);
406 ctx.
mem_spec = ImageSpec(width, height, mem_channels, TypeDesc::FLOAT);
409 const int mem_channels = 4;
413 ctx.
mem_spec = ImageSpec(width, height, mem_channels, TypeDesc::UINT8);
424 const int width = ctx.
ibuf->
x;
425 const int height = ctx.
ibuf->
y;
426 ImageSpec file_spec(width, height, file_channels, data_format);
442 if (
char *colon = strchr(prop->name,
':')) {
443 std::string prefix(prop->name, colon);
444 Strutil::to_lower(prefix);
445 if (prefix ==
"oiio" ||
446 (!
STREQ(prefix.c_str(), ctx.
file_format) && OIIO::is_imageio_format_name(prefix)))
461 file_spec.attribute(
"ResolutionUnit",
"m");
462 file_spec.attribute(
"XResolution",
int(
round(ctx.
ibuf->
ppm[0])));
463 file_spec.attribute(
"YResolution",
int(
round(ctx.
ibuf->
ppm[1])));
467 file_spec.attribute(
"ResolutionUnit",
"in");
468 file_spec.attribute(
"XResolution",
float(ctx.
ibuf->
ppm[0] * 0.0254));
469 file_spec.attribute(
"YResolution",
float(ctx.
ibuf->
ppm[1] * 0.0254));
480 file_spec.attribute(
"ICCProfile",
481 OIIO::TypeDesc(OIIO::TypeDesc::UINT8, icc_profile.
size()),
492 file_spec.attribute(
"CICP", TypeDesc(TypeDesc::INT, 4), cicp);
#define IDP_string_get(prop)
blender::ocio::ColorSpace ColorSpace
#define LISTBASE_FOREACH(type, var, list)
#define STRNCPY_UTF8(dst, src)
#define CLOG_ERROR(clg_ref,...)
ID and Library types, which are fundamental for SDNA.
bool IMB_colormanagement_space_to_cicp(const ColorSpace *colorspace, const ColorManagedFileOutput output, const bool rgb_matrix, int cicp[4])
const char * IMB_colormanagement_colorspace_get_name(const ColorSpace *colorspace)
blender::Vector< char > IMB_colormanagement_space_to_icc_profile(const ColorSpace *colorspace)
const ColorSpace * IMB_colormanagement_space_from_cicp(const int cicp[4], const ColorManagedFileOutput output)
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)
static CLG_LogRef LOG_WRITE
static CLG_LogRef LOG_READ
const ColorSpace * colorspace
const ColorSpace * colorspace
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