main sync #3

Merged
Patrick Busch merged 318 commits from blender/blender:main into main 2023-03-17 15:52:21 +01:00
15 changed files with 558 additions and 333 deletions
Showing only changes of commit 8929ed75d4 - Show all commits

View File

@ -18,6 +18,7 @@ set(INC_SYS
${JPEG_INCLUDE_DIR}
${PNG_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
${OPENIMAGEIO_INCLUDE_DIRS}
)
set(SRC
@ -29,6 +30,7 @@ set(SRC
intern/divers.c
intern/filetype.c
intern/filter.c
intern/format_psd.cc
intern/imageprocess.c
intern/indexer.c
intern/iris.c

View File

@ -678,7 +678,7 @@ void IMB_sampleImageAtLocation(
* \attention defined in readimage.c
*/
struct ImBuf *IMB_loadifffile(
int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr);
int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr);
/**
* \attention defined in scaling.c

View File

@ -318,9 +318,6 @@ extern const char *imb_ext_image[];
extern const char *imb_ext_movie[];
extern const char *imb_ext_audio[];
/** Image formats that can only be loaded via filepath. */
extern const char *imb_ext_image_filepath_only[];
/* -------------------------------------------------------------------- */
/** \name Imbuf Color Management Flag
*

View File

@ -256,3 +256,16 @@ struct ImBuf *imb_load_filepath_thumbnail_webp(const char *filepath,
bool imb_savewebp(struct ImBuf *ibuf, const char *name, int flags);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Format: PSD (#IMB_FTYPE_PSD)
* \{ */
bool imb_is_a_psd(const unsigned char *buf, size_t size);
struct ImBuf *imb_load_psd(const uchar *mem,
size_t size,
int flags,
char colorspace[IM_MAX_SPACE]);
/** \} */

View File

@ -184,9 +184,9 @@ const ImFileType IMB_FILE_TYPES[] = {
{
.init = NULL,
.exit = NULL,
.is_a = imb_is_a_photoshop,
.load = NULL,
.load_filepath = imb_load_photoshop,
.is_a = imb_is_a_psd,
.load = imb_load_psd,
.load_filepath = NULL,
.load_filepath_thumbnail = NULL,
.save = NULL,
.flag = IM_FTYPE_FLOAT,

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "oiio/openimageio_support.hh"
#include "IMB_imbuf_types.h"
OIIO_NAMESPACE_USING
using namespace blender::imbuf;
extern "C" {
bool imb_is_a_psd(const uchar *mem, size_t size)
{
return imb_oiio_check(mem, size, "psd");
}
ImBuf *imb_load_psd(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
ImageSpec config, spec;
config.attribute("oiio:UnassociatedAlpha", 1);
ReadContext ctx{mem, size, "psd", IMB_FTYPE_PSD, flags};
/* PSD should obey color space information embedded in the file. */
ctx.use_embedded_colorspace = true;
return imb_oiio_read(ctx, config, colorspace, spec);
}
}

View File

@ -18,8 +18,10 @@ set(INC_SYS
set(SRC
openimageio_api.h
openimageio_support.hh
openimageio_api.cpp
openimageio_support.cc
)
set(LIB

View File

@ -5,278 +5,16 @@
* \ingroup openimageio
*/
#include <set>
#if defined(WIN32)
# include "utfconv.h"
# define _USE_MATH_DEFINES
#endif
/* NOTE: Keep first, #BLI_path_util conflicts with OIIO's format. */
#include "openimageio_api.h"
#include <OpenImageIO/imageio.h>
#include <memory>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "IMB_allocimbuf.h"
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
OIIO_NAMESPACE_USING
using std::string;
using std::unique_ptr;
using uchar = uchar;
template<class T, class Q>
static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha)
{
if (components == 2) {
for (int i = width * height - 1; i >= 0; i--) {
pixels[i * 4 + 3] = pixels[i * 2 + 1];
pixels[i * 4 + 2] = pixels[i * 2 + 0];
pixels[i * 4 + 1] = pixels[i * 2 + 0];
pixels[i * 4 + 0] = pixels[i * 2 + 0];
}
}
else if (components == 3) {
for (int i = width * height - 1; i >= 0; i--) {
pixels[i * 4 + 3] = alpha;
pixels[i * 4 + 2] = pixels[i * 3 + 2];
pixels[i * 4 + 1] = pixels[i * 3 + 1];
pixels[i * 4 + 0] = pixels[i * 3 + 0];
}
}
else if (components == 1) {
for (int i = width * height - 1; i >= 0; i--) {
pixels[i * 4 + 3] = alpha;
pixels[i * 4 + 2] = pixels[i];
pixels[i * 4 + 1] = pixels[i];
pixels[i * 4 + 0] = pixels[i];
}
}
}
static ImBuf *imb_oiio_load_image(
ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
{
ImBuf *ibuf;
int scanlinesize = width * components * sizeof(uchar);
/* allocate the memory for the image */
ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect);
try {
if (!in->read_image(0,
0,
0,
components,
TypeDesc::UINT8,
(uchar *)ibuf->rect + (height - 1) * scanlinesize,
AutoStride,
-scanlinesize,
AutoStride)) {
std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl
<< in->geterror() << std::endl;
if (ibuf) {
IMB_freeImBuf(ibuf);
}
return nullptr;
}
}
catch (const std::exception &exc) {
std::cerr << exc.what() << std::endl;
if (ibuf) {
IMB_freeImBuf(ibuf);
}
return nullptr;
}
/* ImBuf always needs 4 channels */
fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF);
return ibuf;
}
static ImBuf *imb_oiio_load_image_float(
ImageInput *in, int width, int height, int components, int flags, bool is_alpha)
{
ImBuf *ibuf;
int scanlinesize = width * components * sizeof(float);
/* allocate the memory for the image */
ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat);
try {
if (!in->read_image(0,
0,
0,
components,
TypeDesc::FLOAT,
(uchar *)ibuf->rect_float + (height - 1) * scanlinesize,
AutoStride,
-scanlinesize,
AutoStride)) {
std::cerr << __func__ << ": ImageInput::read_image() failed:" << std::endl
<< in->geterror() << std::endl;
if (ibuf) {
IMB_freeImBuf(ibuf);
}
return nullptr;
}
}
catch (const std::exception &exc) {
std::cerr << exc.what() << std::endl;
if (ibuf) {
IMB_freeImBuf(ibuf);
}
return nullptr;
}
/* ImBuf always needs 4 channels */
fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f);
/* NOTE: Photoshop 16 bit files never has alpha with it,
* so no need to handle associated/unassociated alpha. */
return ibuf;
}
extern "C" {
bool imb_is_a_photoshop(const uchar *mem, size_t size)
{
const uchar magic[4] = {'8', 'B', 'P', 'S'};
if (size < sizeof(magic)) {
return false;
}
return memcmp(magic, mem, sizeof(magic)) == 0;
}
int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags)
{
if (flags & IB_mem) {
std::cerr << __func__ << ": Photoshop PSD-save: Create PSD in memory"
<< " currently not supported" << std::endl;
imb_addencodedbufferImBuf(ibuf);
ibuf->encodedsize = 0;
return 0;
}
return 0;
}
struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = nullptr;
int width, height, components;
bool is_float, is_alpha, is_half;
int basesize;
char file_colorspace[IM_MAX_SPACE];
const bool is_colorspace_manually_set = (colorspace[0] != '\0');
/* load image from file through OIIO */
if (IMB_ispic_type_matches(filename, IMB_FTYPE_PSD) == 0) {
return nullptr;
}
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
unique_ptr<ImageInput> in(ImageInput::create(filename));
if (!in) {
std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl
<< OIIO_NAMESPACE::geterror() << std::endl;
return nullptr;
}
ImageSpec spec, config;
config.attribute("oiio:UnassociatedAlpha", int(1));
if (!in->open(filename, spec, config)) {
std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl
<< in->geterror() << std::endl;
return nullptr;
}
if (!is_colorspace_manually_set) {
string ics = spec.get_string_attribute("oiio:ColorSpace");
BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE);
/* Only use color-spaces exist. */
if (colormanage_colorspace_get_named(file_colorspace)) {
strcpy(colorspace, file_colorspace);
}
else {
std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace
<< "\") not supported in existent OCIO configuration file. Fallback "
<< "to system default colorspace (\"" << colorspace << "\")." << std::endl;
}
}
width = spec.width;
height = spec.height;
components = spec.nchannels;
is_alpha = spec.alpha_channel != -1;
basesize = spec.format.basesize();
is_float = basesize > 1;
is_half = spec.format == TypeDesc::HALF;
/* we only handle certain number of components */
if (!(components >= 1 && components <= 4)) {
if (in) {
in->close();
}
return nullptr;
}
if (is_float) {
ibuf = imb_oiio_load_image_float(in.get(), width, height, components, flags, is_alpha);
}
else {
ibuf = imb_oiio_load_image(in.get(), width, height, components, flags, is_alpha);
}
if (in) {
in->close();
}
if (!ibuf) {
return nullptr;
}
/* ImBuf always needs 4 channels */
ibuf->ftype = IMB_FTYPE_PSD;
ibuf->channels = 4;
ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize;
ibuf->flags |= (is_float && is_half) ? IB_halffloat : 0;
try {
return ibuf;
}
catch (const std::exception &exc) {
std::cerr << exc.what() << std::endl;
if (ibuf) {
IMB_freeImBuf(ibuf);
}
return nullptr;
}
}
int OIIO_getVersionHex(void)
{
return openimageio_version();
}
} /* export "C" */
} /* extern "C" */

View File

@ -7,20 +7,10 @@
#pragma once
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ImBuf;
bool imb_is_a_photoshop(const unsigned char *mem, size_t size);
int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags);
struct ImBuf *imb_load_photoshop(const char *name, int flags, char *colorspace);
int OIIO_getVersionHex(void);
#ifdef __cplusplus

View File

@ -0,0 +1,398 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "openimageio_support.hh"
#include "BLI_blenlib.h"
#include "BKE_idprop.h"
#include "DNA_ID.h" /* ID property definitions. */
#include "IMB_allocimbuf.h"
#include "IMB_colormanagement.h"
#include "IMB_metadata.h"
OIIO_NAMESPACE_USING
using std::string;
using std::unique_ptr;
namespace blender::imbuf {
/* An OIIO IOProxy used during file packing to write into an in-memory #ImBuf buffer. */
class ImBufMemWriter : public Filesystem::IOProxy {
public:
ImBufMemWriter(ImBuf *ibuf) : IOProxy("", Write), ibuf_(ibuf)
{
}
const char *proxytype() const override
{
return "ImBufMemWriter";
}
size_t write(const void *buf, size_t size) override
{
size = pwrite(buf, size, m_pos);
m_pos += size;
return size;
}
size_t pwrite(const void *buf, size_t size, int64_t offset) override
{
/* If buffer is too small increase it. */
size_t end = offset + size;
while (end > ibuf_->encodedbuffersize) {
if (!imb_enlargeencodedbufferImBuf(ibuf_)) {
/* Out of memory. */
return 0;
}
}
memcpy(ibuf_->encodedbuffer + offset, buf, size);
if (end > ibuf_->encodedsize) {
ibuf_->encodedsize = end;
}
return size;
}
size_t size() const override
{
return ibuf_->encodedsize;
}
private:
ImBuf *ibuf_;
};
/* Utility to in-place expand an n-component pixel buffer into a 4-component buffer. */
template<typename T>
static void fill_all_channels(T *pixels, int width, int height, int components, T alpha)
{
const int64_t pixel_count = int64_t(width) * height;
if (components == 3) {
for (int64_t i = 0; i < pixel_count; i++) {
pixels[i * 4 + 3] = alpha;
}
}
else if (components == 1) {
for (int64_t i = 0; i < pixel_count; i++) {
pixels[i * 4 + 3] = alpha;
pixels[i * 4 + 2] = pixels[i * 4 + 0];
pixels[i * 4 + 1] = pixels[i * 4 + 0];
}
}
else if (components == 2) {
for (int64_t i = 0; i < pixel_count; i++) {
pixels[i * 4 + 3] = pixels[i * 4 + 1];
pixels[i * 4 + 2] = pixels[i * 4 + 0];
pixels[i * 4 + 1] = pixels[i * 4 + 0];
}
}
}
template<typename T>
static ImBuf *load_pixels(
ImageInput *in, int width, int height, int channels, int flags, bool use_all_planes)
{
/* Allocate the ImBuf for the image. */
constexpr bool is_float = sizeof(T) > 1;
const uint format_flag = is_float ? IB_rectfloat : IB_rect;
const uint ibuf_flags = (flags & IB_test) ? 0 : format_flag;
const int planes = use_all_planes ? 32 : 8 * channels;
ImBuf *ibuf = IMB_allocImBuf(width, height, planes, ibuf_flags);
if (!ibuf) {
return nullptr;
}
/* No need to load actual pixel data during the test phase. */
if (flags & IB_test) {
return ibuf;
}
/* Calculate an appropriate stride to read n-channels directly into
* the ImBuf 4-channel layout. */
const stride_t ibuf_xstride = sizeof(T) * 4;
const stride_t ibuf_ystride = ibuf_xstride * width;
const TypeDesc format = is_float ? TypeDesc::FLOAT : TypeDesc::UINT8;
uchar *rect = is_float ? reinterpret_cast<uchar *>(ibuf->rect_float) :
reinterpret_cast<uchar *>(ibuf->rect);
void *ibuf_data = rect + ((stride_t(height) - 1) * ibuf_ystride);
bool ok = in->read_image(
0, 0, 0, channels, format, ibuf_data, ibuf_xstride, -ibuf_ystride, AutoStride);
if (!ok) {
fprintf(stderr, "ImageInput::read_image() failed: %s\n", in->geterror().c_str());
IMB_freeImBuf(ibuf);
return nullptr;
}
/* ImBuf always needs 4 channels */
const T alpha_fill = is_float ? 1.0f : 0xFF;
fill_all_channels<T>(reinterpret_cast<T *>(rect), width, height, channels, alpha_fill);
return ibuf;
}
static void set_colorspace_name(char colorspace[IM_MAX_SPACE],
const ReadContext &ctx,
const ImageSpec &spec,
bool is_float)
{
const bool is_colorspace_set = (colorspace[0] != '\0');
if (is_colorspace_set) {
return;
}
/* Use a default role unless otherwise specified. */
if (ctx.use_colorspace_role >= 0) {
colorspace_set_default_role(colorspace, IM_MAX_SPACE, ctx.use_colorspace_role);
}
else if (is_float) {
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
}
else {
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
}
/* Override if necessary. */
if (ctx.use_embedded_colorspace) {
string ics = spec.get_string_attribute("oiio:ColorSpace");
char file_colorspace[IM_MAX_SPACE];
BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE);
/* Only use color-spaces that exist. */
if (colormanage_colorspace_get_named(file_colorspace)) {
BLI_strncpy(colorspace, file_colorspace, IM_MAX_SPACE);
}
}
}
/**
* Get an #ImBuf filled in with pixel data and associated metadata using the provided ImageInput.
*/
static ImBuf *get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, char colorspace[IM_MAX_SPACE])
{
const ImageSpec &spec = in->spec();
const int width = spec.width;
const int height = spec.height;
const int channels = spec.nchannels;
const bool has_alpha = spec.alpha_channel != -1;
const bool is_float = spec.format.basesize() > 1;
if (channels < 1 || channels > 4) {
return nullptr;
}
const bool use_all_planes = has_alpha || ctx.use_all_planes;
ImBuf *ibuf = nullptr;
if (is_float) {
ibuf = load_pixels<float>(in, width, height, channels, ctx.flags, use_all_planes);
ibuf->channels = 4;
}
else {
ibuf = load_pixels<uchar>(in, width, height, channels, ctx.flags, use_all_planes);
}
/* Fill in common ibuf properties. */
if (ibuf) {
ibuf->ftype = ctx.file_type;
ibuf->flags |= (spec.format == TypeDesc::HALF) ? IB_halffloat : 0;
set_colorspace_name(colorspace, ctx, spec, is_float);
float x_res = spec.get_float_attribute("XResolution", 0.0f);
float y_res = spec.get_float_attribute("YResolution", 0.0f);
if (x_res > 0.0f && y_res > 0.0f) {
double scale = 1.0;
auto unit = spec.get_string_attribute("ResolutionUnit", "");
if (unit == "in" || unit == "inch") {
scale = 100.0 / 2.54;
}
else if (unit == "cm") {
scale = 100.0;
}
ibuf->ppm[0] = scale * x_res;
ibuf->ppm[1] = scale * y_res;
}
/* Transfer metadata to the ibuf if necessary. */
if (ctx.flags & IB_metadata) {
IMB_metadata_ensure(&ibuf->metadata);
ibuf->flags |= (spec.extra_attribs.empty()) ? 0 : IB_metadata;
for (const auto &attrib : spec.extra_attribs) {
IMB_metadata_set_field(ibuf->metadata, attrib.name().c_str(), attrib.get_string().c_str());
}
}
}
return ibuf;
}
/**
* Returns an ImageInput for the precise `format` requested using the provided IOMemReader.
* If successful, the ImageInput will be opened and ready for operations. Null will be returned if
* the format was not found or if the open call fails.
*/
static unique_ptr<ImageInput> get_oiio_reader(const char *format,
const ImageSpec &config,
Filesystem::IOMemReader &mem_reader,
ImageSpec &r_newspec)
{
/* Attempt to create a reader based on the passed in format. */
unique_ptr<ImageInput> in = ImageInput::create(format);
if (!in) {
return nullptr;
}
/* Open the reader using the ioproxy. */
in->set_ioproxy(&mem_reader);
bool ok = in->open("", r_newspec, config);
if (!ok) {
in.reset();
}
return in;
}
bool imb_oiio_check(const uchar *mem, size_t mem_size, const char *file_format)
{
ImageSpec config, spec;
/* This memory proxy must remain alive for the full duration of the read. */
Filesystem::IOMemReader mem_reader(cspan<uchar>(mem, mem_size));
unique_ptr<ImageInput> in = get_oiio_reader(file_format, config, mem_reader, spec);
return in ? true : false;
}
ImBuf *imb_oiio_read(const ReadContext &ctx,
const ImageSpec &config,
char colorspace[IM_MAX_SPACE],
ImageSpec &r_newspec)
{
/* This memory proxy must remain alive for the full duration of the read. */
Filesystem::IOMemReader mem_reader(cspan<uchar>(ctx.mem_start, ctx.mem_size));
unique_ptr<ImageInput> in = get_oiio_reader(ctx.file_format, config, mem_reader, r_newspec);
if (!in) {
return nullptr;
}
return get_oiio_ibuf(in.get(), ctx, colorspace);
}
bool imb_oiio_write(const WriteContext &ctx, const char *filepath, const ImageSpec &file_spec)
{
unique_ptr<ImageOutput> out = ImageOutput::create(ctx.file_format);
if (!out) {
return false;
}
auto write_op = [&out, &ctx]() {
return out->write_image(
ctx.mem_format, ctx.mem_start, ctx.mem_xstride, -ctx.mem_ystride, AutoStride);
};
bool ok = false;
if (ctx.flags & IB_mem) {
/* This memory proxy must remain alive for the full duration of the write. */
ImBufMemWriter writer(ctx.ibuf);
imb_addencodedbufferImBuf(ctx.ibuf);
out->set_ioproxy(&writer);
out->open("", file_spec);
ok = write_op();
}
else {
out->open(filepath, file_spec);
ok = write_op();
}
out->close();
return ok;
}
WriteContext imb_create_write_context(const char *file_format,
ImBuf *ibuf,
int flags,
bool prefer_float)
{
WriteContext ctx{};
ctx.file_format = file_format;
ctx.ibuf = ibuf;
ctx.flags = flags;
const int width = ibuf->x;
const int height = ibuf->y;
const bool use_float = prefer_float && (ibuf->rect_float != nullptr);
if (use_float) {
const int mem_channels = ibuf->channels ? ibuf->channels : 4;
ctx.mem_xstride = sizeof(float) * mem_channels;
ctx.mem_ystride = width * ctx.mem_xstride;
ctx.mem_format = TypeDesc::FLOAT;
ctx.mem_start = reinterpret_cast<uchar *>(ibuf->rect_float);
}
else {
const int mem_channels = 4;
ctx.mem_xstride = sizeof(uchar) * mem_channels;
ctx.mem_ystride = width * ctx.mem_xstride;
ctx.mem_format = TypeDesc::UINT8;
ctx.mem_start = reinterpret_cast<uchar *>(ibuf->rect);
}
/* We always write using a negative y-stride so ensure we start at the end. */
ctx.mem_start = ctx.mem_start + ((stride_t(height) - 1) * ctx.mem_ystride);
return ctx;
}
ImageSpec imb_create_write_spec(const WriteContext &ctx, int file_channels, TypeDesc data_format)
{
const int width = ctx.ibuf->x;
const int height = ctx.ibuf->y;
ImageSpec file_spec(width, height, file_channels, data_format);
/* Populate the spec with all common attributes.
*
* Care must be taken with the metadata:
* - It should be processed first, before the "Resolution" metadata below, to
* ensure the proper values end up in the ImageSpec
* - It needs to filter format-specific metadata that may no longer apply to
* the current format being written (e.g. metadata for tiff being written to a png)
*/
if (ctx.ibuf->metadata) {
for (IDProperty *prop = static_cast<IDProperty *>(ctx.ibuf->metadata->data.group.first); prop;
prop = prop->next) {
if (prop->type == IDP_STRING) {
/* If this property has a prefixed name (oiio:, tiff:, etc.) and it belongs to
* oiio or a different format, then skip. */
if (char *colon = strchr(prop->name, ':')) {
std::string prefix(prop->name, colon);
Strutil::to_lower(prefix);
if (prefix == "oiio" ||
(!STREQ(prefix.c_str(), ctx.file_format) && OIIO::is_imageio_format_name(prefix))) {
/* Skip this attribute. */
continue;
}
}
file_spec.attribute(prop->name, IDP_String(prop));
}
}
}
if (ctx.ibuf->ppm[0] > 0.0 && ctx.ibuf->ppm[1] > 0.0) {
/* More OIIO formats support inch than meter. */
file_spec.attribute("ResolutionUnit", "in");
file_spec.attribute("XResolution", float(ctx.ibuf->ppm[0] * 0.0254));
file_spec.attribute("YResolution", float(ctx.ibuf->ppm[1] * 0.0254));
}
return file_spec;
}
} // namespace blender::imbuf

View File

@ -0,0 +1,104 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <memory>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/imageio.h>
#include "BLI_sys_types.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
namespace blender::imbuf {
/**
* Parameters and settings used while reading image formats.
*/
struct ReadContext {
const uchar *mem_start;
const size_t mem_size;
const char *file_format;
const eImbFileType file_type;
const int flags;
/* Override the automatic color-role choice with the value specified here. */
int use_colorspace_role = -1;
/* Allocate and use all ImBuf image planes even if the image has fewer. */
bool use_all_planes = false;
/* Use the colorspace provided in the image metadata when available. */
bool use_embedded_colorspace = false;
};
/**
* Parameters and settings used while writing image formats.
*/
struct WriteContext {
const char *file_format;
ImBuf *ibuf;
OIIO::stride_t mem_xstride;
OIIO::stride_t mem_ystride;
OIIO::TypeDesc mem_format;
uchar *mem_start;
int flags;
};
/**
* Check to see if we can load and open the given file format.
*/
bool imb_oiio_check(const uchar *mem, size_t mem_size, const char *file_format);
/**
* The primary method for reading data into an #ImBuf.
*
* During the `IB_test` phase of loading, the `colorspace` parameter will be populated
* with the appropriate colorspace name.
*
* Upon return, the `r_newspec` parameter will contain image format information
* which can be inspected afterwards if necessary.
*/
ImBuf *imb_oiio_read(const ReadContext &ctx,
const OIIO::ImageSpec &config,
char colorspace[IM_MAX_SPACE],
OIIO::ImageSpec &r_newspec);
/**
* The primary method for writing data from an #ImBuf to either a physical or in-memory
* destination.
*
* The `file_spec` parameter will typically come from #imb_create_write_spec.
*/
bool imb_oiio_write(const WriteContext &ctx,
const char *filepath,
const OIIO::ImageSpec &file_spec);
/**
* Create a #WriteContext based on the provided #ImBuf and format information.
*
* If the provided #ImBuf contains both byte and float buffers, the `prefer_float`
* flag controls which buffer to use. By default, if a float buffer exists it will
* be used.
*/
WriteContext imb_create_write_context(const char *file_format,
ImBuf *ibuf,
int flags,
bool prefer_float = true);
/**
* Returns an ImageSpec filled in with all common attributes associated with the #ImBuf
* provided as part of the #WriteContext.
*
* This includes optional metadata that has been attached to the #ImBuf and which should be
* written to the new file as necessary.
*/
OIIO::ImageSpec imb_create_write_spec(const WriteContext &ctx,
int file_channels,
OIIO::TypeDesc data_format);
} // namespace blender::imbuf

View File

@ -441,7 +441,7 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf)
IDProperty *prop;
for (prop = (IDProperty *)ibuf->metadata->data.group.first; prop; prop = prop->next) {
if (prop->type == IDP_STRING) {
if (prop->type == IDP_STRING && !STREQ(prop->name, "compression")) {
header->insert(prop->name, StringAttribute(IDP_String(prop)));
}
}

View File

@ -114,44 +114,7 @@ ImBuf *IMB_ibImageFromMemory(
return NULL;
}
static ImBuf *IMB_ibImageFromFile(const char *filepath,
int flags,
char colorspace[IM_MAX_SPACE],
const char *descr)
{
ImBuf *ibuf;
const ImFileType *type;
char effective_colorspace[IM_MAX_SPACE] = "";
if (colorspace) {
BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace));
}
for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
if (type->load_filepath) {
ibuf = type->load_filepath(filepath, flags, effective_colorspace);
if (ibuf) {
imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace);
return ibuf;
}
}
}
if ((flags & IB_test) == 0) {
fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr);
}
return NULL;
}
static bool imb_is_filepath_format(const char *filepath)
{
/* return true if this is one of the formats that can't be loaded from memory */
return BLI_path_extension_check_array(filepath, imb_ext_image_filepath_only);
}
ImBuf *IMB_loadifffile(
int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
uchar *mem;
@ -161,10 +124,6 @@ ImBuf *IMB_loadifffile(
return NULL;
}
if (imb_is_filepath_format(filepath)) {
return IMB_ibImageFromFile(filepath, flags, colorspace, descr);
}
size = BLI_file_descriptor_size(file);
imb_mmap_lock();
@ -198,7 +157,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_S
return NULL;
}
ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath);
ibuf = IMB_loadifffile(file, flags, colorspace, filepath);
if (ibuf) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
@ -277,7 +236,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags)
return NULL;
}
ibuf = IMB_loadifffile(file, filepath, flags | IB_test | IB_multilayer, colorspace, filepath);
ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, colorspace, filepath);
if (ibuf) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));

View File

@ -67,13 +67,6 @@ const char *imb_ext_image[] = {
NULL,
};
const char *imb_ext_image_filepath_only[] = {
".psd",
".pdd",
".psb",
NULL,
};
const char *imb_ext_movie[] = {
".avi", ".flc", ".mov", ".movie", ".mp4", ".m4v", ".m2v", ".m2t", ".m2ts", ".mts",
".ts", ".mv", ".avs", ".wmv", ".ogv", ".ogg", ".r3d", ".dv", ".mpeg", ".mpg",

View File

@ -480,7 +480,7 @@ static PyObject *M_imbuf_load(PyObject *UNUSED(self), PyObject *args, PyObject *
return NULL;
}
ImBuf *ibuf = IMB_loadifffile(file, filepath, IB_rect, NULL, filepath);
ImBuf *ibuf = IMB_loadifffile(file, IB_rect, NULL, filepath);
close(file);