24 #include <OpenEXR/OpenEXRConfig.h>
25 #define COMBINED_OPENEXR_VERSION \
26 ((10000 * OPENEXR_VERSION_MAJOR) + (100 * OPENEXR_VERSION_MINOR) + OPENEXR_VERSION_PATCH)
28 #if COMBINED_OPENEXR_VERSION >= 20599
30 # include <Imath/half.h>
31 # include <OpenEXR/ImfFrameBuffer.h>
32 # define exr_file_offset_t uint64_t
35 # include <OpenEXR/half.h>
36 # define exr_file_offset_t Int64
39 #include <OpenEXR/Iex.h>
40 #include <OpenEXR/ImfArray.h>
41 #include <OpenEXR/ImfChannelList.h>
42 #include <OpenEXR/ImfCompression.h>
43 #include <OpenEXR/ImfCompressionAttribute.h>
44 #include <OpenEXR/ImfIO.h>
45 #include <OpenEXR/ImfInputFile.h>
46 #include <OpenEXR/ImfOutputFile.h>
47 #include <OpenEXR/ImfPixelType.h>
48 #include <OpenEXR/ImfPreviewImage.h>
49 #include <OpenEXR/ImfRgbaFile.h>
50 #include <OpenEXR/ImfStandardAttributes.h>
51 #include <OpenEXR/ImfStringAttribute.h>
52 #include <OpenEXR/ImfVersion.h>
55 #include <OpenEXR/ImfInputPart.h>
56 #include <OpenEXR/ImfMultiPartInputFile.h>
57 #include <OpenEXR/ImfMultiPartOutputFile.h>
58 #include <OpenEXR/ImfMultiView.h>
59 #include <OpenEXR/ImfOutputPart.h>
60 #include <OpenEXR/ImfPartHelper.h>
61 #include <OpenEXR/ImfPartType.h>
62 #include <OpenEXR/ImfTiledOutputPart.h>
80 #if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && _MSC_VER < 1900
81 _CRTIMP
void __cdecl _invalid_parameter_noinfo(
void)
105 using namespace Imath;
127 : IStream(
"<memory>"), _exrpos(0), _exrsize(exrsize)
134 if (n + _exrpos <= _exrsize) {
135 memcpy(
c, (
void *)(&_exrbuf[_exrpos]), n);
160 unsigned char *_exrbuf;
171 throw IEX_NAMESPACE::InputExc(
"file not found");
178 if (_mmap_file ==
nullptr) {
179 throw IEX_NAMESPACE::InputExc(
"BLI_mmap_open failed");
197 if (_exrpos + n > _exrsize) {
198 throw Iex::InputExc(
"Unexpected end of file.");
200 memcpy(
c, _exrbuf + _exrpos, n);
203 return _exrpos < _exrsize;
220 unsigned char *_exrbuf;
232 ifs.open(wfilepath, std::ios_base::binary);
235 ifs.open(filepath, std::ios_base::binary);
239 Iex::throwErrnoExc();
246 throw Iex::InputExc(
"Unexpected end of file.");
251 return check_error();
256 return std::streamoff(ifs.tellg());
275 Iex::throwErrnoExc();
295 void write(
const char c[],
int n)
override
298 memcpy(ibuf->encodedbuffer +
offset,
c, n);
300 ibuf->encodedsize += n;
318 while (
size > ibuf->encodedbuffersize) {
320 throw Iex::ErrnoExc(
"Out of memory.");
338 ofs.open(wfilepath, std::ios_base::binary);
341 ofs.open(filepath, std::ios_base::binary);
345 Iex::throwErrnoExc();
349 void write(
const char c[],
int n)
override
358 return std::streamoff(ofs.tellp());
372 Iex::throwErrnoExc();
375 throw Iex::ErrnoExc(
"File output failed.");
405 return Imf::isImfMagic((
const char *)mem);
410 switch (compression) {
412 header->compression() = NO_COMPRESSION;
415 header->compression() = PXR24_COMPRESSION;
418 header->compression() = ZIP_COMPRESSION;
421 header->compression() = PIZ_COMPRESSION;
424 header->compression() = RLE_COMPRESSION;
427 header->compression() = ZIPS_COMPRESSION;
430 header->compression() = B44_COMPRESSION;
433 header->compression() = B44A_COMPRESSION;
435 #if OPENEXR_VERSION_MAJOR > 2 || (OPENEXR_VERSION_MAJOR >= 2 && OPENEXR_VERSION_MINOR >= 2)
437 header->compression() = DWAA_COMPRESSION;
440 header->compression() = DWAB_COMPRESSION;
444 header->compression() = ZIP_COMPRESSION;
461 if (ibuf->
ppm[0] > 0.0) {
463 addXDensity(*header, ibuf->
ppm[0] * 0.0254);
468 const char *propname,
473 header->insert(propname, StringAttribute(prop));
481 const int width = ibuf->
x;
483 OStream *file_stream =
nullptr;
492 header.channels().insert(
"R", Channel(
HALF));
493 header.channels().insert(
"G", Channel(
HALF));
494 header.channels().insert(
"B", Channel(
HALF));
496 header.channels().insert(
"A", Channel(
HALF));
500 header.channels().insert(
"Z", Channel(
Imf::FLOAT));
503 FrameBuffer frameBuffer;
512 OutputFile
file(*file_stream, header);
516 RGBAZ *to = pixels.data();
517 int xstride =
sizeof(
RGBAZ);
518 int ystride = xstride *
width;
521 frameBuffer.insert(
"R", Slice(
HALF, (
char *)&to->
r, xstride, ystride));
522 frameBuffer.insert(
"G", Slice(
HALF, (
char *)&to->
g, xstride, ystride));
523 frameBuffer.insert(
"B", Slice(
HALF, (
char *)&to->
b, xstride, ystride));
525 frameBuffer.insert(
"A", Slice(
HALF, (
char *)&to->
a, xstride, ystride));
528 frameBuffer.insert(
"Z",
532 sizeof(
float) * -
width));
537 for (
int i = ibuf->
y - 1; i >= 0; i--) {
540 for (
int j = ibuf->
x; j > 0; j--) {
553 for (
int i = ibuf->
y - 1; i >= 0; i--) {
556 for (
int j = ibuf->
x; j > 0; j--) {
569 file.setFrameBuffer(frameBuffer);
572 catch (
const std::exception &exc) {
574 printf(
"OpenEXR-save: ERROR: %s\n", exc.what());
588 const int width = ibuf->
x;
590 OStream *file_stream =
nullptr;
599 header.channels().insert(
"R", Channel(
Imf::FLOAT));
600 header.channels().insert(
"G", Channel(
Imf::FLOAT));
601 header.channels().insert(
"B", Channel(
Imf::FLOAT));
603 header.channels().insert(
"A", Channel(
Imf::FLOAT));
606 header.channels().insert(
"Z", Channel(
Imf::FLOAT));
609 FrameBuffer frameBuffer;
618 OutputFile
file(*file_stream, header);
621 int ystride = -xstride *
width;
624 float *rect[4] = {
nullptr,
nullptr,
nullptr,
nullptr};
626 rect[1] = (
channels >= 2) ? rect[0] + 1 : rect[0];
627 rect[2] = (
channels >= 3) ? rect[0] + 2 : rect[0];
632 frameBuffer.insert(
"R", Slice(
Imf::FLOAT, (
char *)rect[0], xstride, ystride));
633 frameBuffer.insert(
"G", Slice(
Imf::FLOAT, (
char *)rect[1], xstride, ystride));
634 frameBuffer.insert(
"B", Slice(
Imf::FLOAT, (
char *)rect[2], xstride, ystride));
636 frameBuffer.insert(
"A", Slice(
Imf::FLOAT, (
char *)rect[3], xstride, ystride));
639 frameBuffer.insert(
"Z",
643 sizeof(
float) * -
width));
646 file.setFrameBuffer(frameBuffer);
649 catch (
const std::exception &exc) {
650 printf(
"OpenEXR-save: ERROR: %s\n", exc.what());
721 struct MultiViewChannelName *
m;
756 data->multiView =
new StringVector();
766 if (
data ==
nullptr) {
787 for (StringVector::const_iterator i = views.begin();
count < views.size(); ++i) {
803 StringVector sv = multiView(
file.header(0));
804 for (
const std::string &view_name : sv) {
805 views.push_back(view_name);
811 for (
int p = 0; p <
file.parts(); p++) {
813 if (
file.header(p).hasView()) {
818 views.push_back(
view);
829 if (viewname ==
nullptr || viewname[0] ==
'\0') {
834 const char delims[] = {
'.',
'\0'};
851 const char *passname,
852 const char *viewname,
861 echan = MEM_cnew<ExrChannel>(
"exr channel");
862 echan->
m =
new MultiViewChannelName();
864 if (layname && layname[0] !=
'\0') {
865 echan->
m->name = layname;
866 echan->
m->name.append(
".");
867 echan->
m->name.append(passname);
870 echan->
m->name.assign(passname);
873 echan->
m->internal_name = echan->
m->name;
875 echan->
m->view.assign(viewname ? viewname :
"");
881 if (layname && layname[0] !=
'\0') {
884 else if (!
data->multiView->empty()) {
885 std::string raw_name = insertViewName(echan->
m->name, *
data->multiView, echan->
view_id);
898 data->num_half_channels++;
906 const char *filepath,
919 bool is_singlelayer, is_multilayer, is_multiview;
931 header.channels(), *
data->multiView, &is_singlelayer, &is_multilayer, &is_multiview);
934 header.insert(
"BlenderMultiChannel", StringAttribute(
"Blender V2.55.1 and newer"));
938 addMultiView(header, *
data->multiView);
945 data->ofile =
new OutputFile(*(
data->ofile_stream), header);
947 catch (
const std::exception &exc) {
948 std::cerr <<
"IMB_exr_begin_write: ERROR: " << exc.what() << std::endl;
951 delete data->ofile_stream;
953 data->ofile =
nullptr;
954 data->ofile_stream =
nullptr;
957 return (
data->ofile !=
nullptr);
961 void *handle,
const char *filepath,
int mipmap,
int width,
int height,
int tilex,
int tiley)
965 std::vector<Header> headers;
972 data->mipmap = mipmap;
974 header.setTileDescription(TileDescription(tilex, tiley, (mipmap) ? MIPMAP_LEVELS : ONE_LEVEL));
975 header.compression() = RLE_COMPRESSION;
976 header.setType(TILEDIMAGE);
978 header.insert(
"BlenderMultiChannel", StringAttribute(
"Blender V2.43"));
980 int numparts =
data->multiView->size();
984 for (
int i = 0; i < numparts; i++) {
985 headers.push_back(header);
986 headers[headers.size() - 1].setView((*(
data->multiView))[i]);
987 headers[headers.size() - 1].setName((*(
data->multiView))[i]);
991 exr_printf(
"%s %-6s %-22s \"%s\"\n",
"p",
"view",
"name",
"internal_name");
992 exr_printf(
"---------------------------------------------------------------\n");
999 echan->
m->internal_name = echan->
m->name;
1000 echan->
m->part_number = echan->
view_id;
1002 headers[echan->
view_id].channels().insert(echan->
m->internal_name, Channel(
Imf::FLOAT));
1004 echan->
m->part_number,
1005 echan->
m->view.c_str(),
1006 echan->
m->name.c_str(),
1007 echan->
m->internal_name.c_str());
1014 data->mpofile =
new MultiPartOutputFile(*(
data->ofile_stream), headers.data(), headers.size());
1016 catch (
const std::exception &) {
1017 delete data->mpofile;
1018 delete data->ofile_stream;
1020 data->mpofile =
nullptr;
1021 data->ofile_stream =
nullptr;
1039 data->ifile =
new MultiPartInputFile(*(
data->ifile_stream));
1041 catch (
const std::exception &) {
1043 delete data->ifile_stream;
1045 data->ifile =
nullptr;
1046 data->ifile_stream =
nullptr;
1053 Box2i dw =
data->ifile->header(0).dataWindow();
1054 data->width = *
width = dw.max.x - dw.min.x + 1;
1055 data->height = *
height = dw.max.y - dw.min.y + 1;
1067 std::vector<MultiViewChannelName>
channels;
1070 for (
const MultiViewChannelName &channel :
channels) {
1072 data,
nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0,
nullptr,
false);
1075 echan->
m->name = channel.name;
1076 echan->
m->view = channel.view;
1077 echan->
m->part_number = channel.part_number;
1078 echan->
m->internal_name = channel.internal_name;
1086 void *handle,
const char *layname,
const char *passname,
int xstride,
int ystride,
float *rect)
1092 if (layname && layname[0] !=
'\0') {
1111 printf(
"IMB_exr_set_channel error %s\n",
name);
1116 const char *layname,
1117 const char *passname,
1118 const char *viewname)
1136 if (layname && layname[0] !=
'\0') {
1141 else if (!
data->multiView->empty()) {
1143 std::string raw_name = insertViewName(
name, *
data->multiView, view_id);
1171 FrameBuffer frameBuffer;
1174 if (
data->channels.first) {
1176 half *rect_half =
nullptr, *current_rect_half =
nullptr;
1179 if (
data->num_half_channels != 0) {
1182 current_rect_half = rect_half;
1188 float *rect = echan->
rect;
1189 half *cur = current_rect_half;
1190 for (
size_t i = 0; i <
num_pixels; i++, cur++) {
1193 half *rect_to_write = current_rect_half + (
data->height - 1L) *
data->width;
1201 frameBuffer.insert(echan->
name,
1205 -echan->
ystride *
sizeof(
float)));
1209 data->ofile->setFrameBuffer(frameBuffer);
1211 data->ofile->writePixels(
data->height);
1213 catch (
const std::exception &exc) {
1214 std::cerr <<
"OpenEXR-writePixels: ERROR: " << exc.what() << std::endl;
1217 if (rect_half !=
nullptr) {
1222 printf(
"Error: attempt to save MultiLayer without layers.\n");
1227 void *handle,
int partx,
int party,
int level,
const char *viewname,
bool empty)
1231 FrameBuffer frameBuffer;
1232 std::string
view(viewname);
1235 exr_printf(
"\nIMB_exrtile_write_channels(view: %s)\n", viewname);
1236 exr_printf(
"%s %-6s %-22s \"%s\"\n",
"p",
"view",
"name",
"internal_name");
1237 exr_printf(
"---------------------------------------------------------------------\n");
1246 if (!
STREQ(viewname, echan->
m->view.c_str())) {
1251 echan->
m->part_number,
1252 echan->
m->view.c_str(),
1253 echan->
m->name.c_str(),
1254 echan->
m->internal_name.c_str());
1257 frameBuffer.insert(echan->
m->internal_name,
1260 echan->
xstride *
sizeof(
float),
1261 echan->
ystride *
sizeof(
float)));
1265 TiledOutputPart
out(*
data->mpofile, view_id);
1266 out.setFrameBuffer(frameBuffer);
1270 out.writeTile(partx /
data->tilex, party /
data->tiley, level);
1272 catch (
const std::exception &exc) {
1273 std::cerr <<
"OpenEXR-writeTile: ERROR: " << exc.what() << std::endl;
1280 int numparts =
data->ifile->parts();
1283 const StringAttribute *ta =
data->ifile->header(0).findTypedAttribute<StringAttribute>(
1284 "BlenderMultiChannel");
1287 short flip = (ta &&
STRPREFIX(ta->value().c_str(),
"Blender V2.43"));
1290 "\nIMB_exr_read_channels\n%s %-6s %-22s "
1291 "\"%s\"\n---------------------------------------------------------------------\n",
1297 for (
int i = 0; i < numparts; i++) {
1299 InputPart in(*
data->ifile, i);
1300 Header header = in.header();
1301 Box2i dw = header.dataWindow();
1304 FrameBuffer frameBuffer;
1308 if (echan->
m->part_number != i) {
1313 echan->
m->part_number,
1314 echan->
m->view.c_str(),
1315 echan->
m->name.c_str(),
1316 echan->
m->internal_name.c_str());
1319 float *rect = echan->
rect;
1325 rect -= echan->
xstride * (dw.min.x - dw.min.y *
data->width);
1332 rect -= echan->
xstride * (dw.min.x + dw.min.y *
data->width);
1335 frameBuffer.insert(echan->
m->internal_name,
1336 Slice(
Imf::FLOAT, (
char *)rect, xstride, ystride));
1339 printf(
"warning, channel with no rect set %s\n", echan->
m->internal_name.c_str());
1345 in.setFrameBuffer(frameBuffer);
1346 exr_printf(
"readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, dw.min.y, dw.max.y);
1347 in.readPixels(dw.min.y, dw.max.y);
1349 catch (
const std::exception &exc) {
1350 std::cerr <<
"OpenEXR-readPixels: ERROR: " << exc.what() << std::endl;
1358 void *(*addview)(
void *base,
const char *
str),
1359 void *(*addlayer)(
void *base,
const char *
str),
1360 void (*addpass)(
void *base,
1365 const char *chan_id,
1373 if (
data->multiView->empty()) {
1378 for (
const std::string &view_name : *
data->multiView) {
1379 addview(base, view_name.c_str());
1384 printf(
"cannot convert multilayer, no layers in handle\n");
1388 for (lay = (
ExrLayer *)
data->layers.first; lay; lay = lay->next) {
1389 void *laybase = addlayer(base, lay->name);
1391 for (pass = (
ExrPass *)lay->passes.first; pass; pass = pass->
next) {
1399 pass->
rect =
nullptr;
1413 delete data->ifile_stream;
1415 delete data->mpofile;
1416 delete data->ofile_stream;
1417 delete data->multiView;
1419 data->ifile =
nullptr;
1420 data->ifile_stream =
nullptr;
1421 data->ofile =
nullptr;
1422 data->mpofile =
nullptr;
1423 data->ofile_stream =
nullptr;
1449 const char delims[] = {
'.',
'\0'};
1458 return (
int)(end - *token);
1463 const char *channelname,
1464 const bool has_xyz_channels)
1471 else if (echan->
chan_id ==
'Y' && !has_xyz_channels) {
1472 BLI_strncpy(passname, channelname, passname_maxncpy);
1474 else if (
ELEM(echan->
chan_id,
'R',
'G',
'B',
'A',
'V',
'X',
'Y',
'Z')) {
1475 BLI_strncpy(passname,
"Combined", passname_maxncpy);
1478 BLI_strncpy(passname, channelname, passname_maxncpy);
1485 bool has_xyz_channels)
1488 const char *
name = echan->
m->name.c_str();
1489 const char *end =
name + strlen(
name);
1509 printf(
"multilayer read: bad channel name: %s\n",
name);
1530 if (
ELEM(chan_id,
'X',
'Y',
'Z',
'R',
'G',
'B',
'U',
'V',
'A')) {
1562 printf(
"multilayer read: bad channel name: %s\n",
name);
1588 if (lay ==
nullptr) {
1589 lay = MEM_cnew<ExrLayer>(
"exr layer");
1601 if (pass ==
nullptr) {
1602 pass = MEM_cnew<ExrPass>(
"exr pass");
1604 if (
STREQ(passname,
"Combined")) {
1619 bool x_found =
false;
1620 bool y_found =
false;
1621 bool z_found =
false;
1623 if (channel->m->name ==
"X" || channel->m->name ==
"x") {
1626 if (channel->m->name ==
"Y" || channel->m->name ==
"y") {
1629 if (channel->m->name ==
"Z" || channel->m->name ==
"z") {
1634 return x_found && y_found && z_found;
1640 const MultiPartInputFile &
file)
1642 std::vector<MultiViewChannelName>
channels;
1645 StringVector multiview;
1646 bool has_multiview =
false;
1647 if (
file.parts() == 1) {
1648 if (hasMultiView(
file.header(0))) {
1649 multiview = multiView(
file.header(0));
1650 has_multiview =
true;
1655 for (
int p = 0; p <
file.parts(); p++) {
1656 const ChannelList &
c =
file.header(p).channels();
1658 std::string part_view =
"";
1659 if (
file.header(p).hasView()) {
1660 part_view =
file.header(p).view();
1662 std::string part_name =
"";
1663 if (
file.header(p).hasName()) {
1664 part_name =
file.header(p).name();
1667 for (ChannelList::ConstIterator i =
c.begin(); i !=
c.end(); i++) {
1668 MultiViewChannelName m;
1669 m.name = std::string(i.name());
1670 m.internal_name = m.name;
1672 if (has_multiview) {
1673 m.view = viewFromChannelName(m.name, multiview);
1674 m.name = removeViewName(m.internal_name, m.view);
1681 if (!part_name.empty()) {
1682 m.name = part_name +
"." + m.name;
1699 for (
const MultiViewChannelName &channel :
channels) {
1701 data,
nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0,
nullptr,
false);
1704 echan->
m->name = channel.name;
1705 echan->
m->view = channel.view;
1706 echan->
m->part_number = channel.part_number;
1707 echan->
m->internal_name = channel.internal_name;
1715 for (; echan; echan = echan->
next) {
1718 const char *
view = echan->
m->view.c_str();
1723 if (
view[0] !=
'\0') {
1726 BLI_strncpy(passname, tmp_pass,
sizeof(passname));
1744 printf(
"error, too many channels in one pass: %s\n", echan->
m->name.c_str());
1751 if (pass->totchan) {
1753 data->width *
data->height * pass->totchan *
sizeof(
float),
"pass rect");
1754 if (pass->totchan == 1) {
1756 echan->
rect = pass->rect;
1759 pass->chan_id[0] = echan->
chan_id;
1767 if (
ELEM(pass->totchan, 3, 4)) {
1768 if (pass->chan[0]->chan_id ==
'B' || pass->chan[1]->chan_id ==
'B' ||
1769 pass->chan[2]->chan_id ==
'B') {
1770 lookup[(
unsigned int)
'R'] = 0;
1771 lookup[(
unsigned int)
'G'] = 1;
1772 lookup[(
unsigned int)
'B'] = 2;
1773 lookup[(
unsigned int)
'A'] = 3;
1775 else if (pass->chan[0]->chan_id ==
'Y' || pass->chan[1]->chan_id ==
'Y' ||
1776 pass->chan[2]->chan_id ==
'Y') {
1777 lookup[(
unsigned int)
'X'] = 0;
1778 lookup[(
unsigned int)
'Y'] = 1;
1779 lookup[(
unsigned int)
'Z'] = 2;
1780 lookup[(
unsigned int)
'W'] = 3;
1783 lookup[(
unsigned int)
'U'] = 0;
1784 lookup[(
unsigned int)
'V'] = 1;
1785 lookup[(
unsigned int)
'A'] = 2;
1787 for (
int a = 0;
a < pass->totchan;
a++) {
1788 echan = pass->chan[
a];
1790 echan->
xstride = pass->totchan;
1796 for (
int a = 0;
a < pass->totchan;
a++) {
1798 echan->
rect = pass->rect +
a;
1799 echan->
xstride = pass->totchan;
1814 MultiPartInputFile &
file,
1820 data->ifile_stream = &file_stream;
1842 va_start(args, fmt);
1843 std::vsprintf(
output, fmt, args);
1853 int numparts =
file.parts();
1854 if (numparts == 1 && hasMultiView(
file.header(0))) {
1855 const StringVector views = multiView(
file.header(0));
1856 printf(
"OpenEXR-load: MultiView file\n");
1857 printf(
"OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str());
1858 for (
const std::string &
view : views) {
1859 printf(
"OpenEXR-load: Found view %s\n",
view.c_str());
1862 else if (numparts > 1) {
1863 printf(
"OpenEXR-load: MultiPart file\n");
1864 for (
int i = 0; i < numparts; i++) {
1865 if (
file.header(i).hasView()) {
1866 printf(
"OpenEXR-load: Part %d: view = \"%s\"\n", i,
file.header(i).view().c_str());
1871 for (
int j = 0; j < numparts; j++) {
1872 const ChannelList &
channels =
file.header(j).channels();
1873 for (ChannelList::ConstIterator i =
channels.begin(); i !=
channels.end(); ++i) {
1874 const Channel &channel = i.channel();
1875 printf(
"OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
1883 const ChannelList &
channels =
file.header(0).channels();
1885 for (ChannelList::ConstIterator i =
channels.begin(); i !=
channels.end(); ++i) {
1887 const char *
str = i.name();
1902 static const char *channel_names[] = {
1903 "V",
"R",
"Red",
"G",
"Green",
"B",
"Blue",
"AR",
"RA",
"AG",
"GA",
"AB",
"BA",
nullptr};
1906 int num_channels = 0;
1908 for (
int i = 0; channel_names[i]; i++) {
1910 std::string lower_case_name = std::string(channel_names[i]);
1912 lower_case_name.end(),
1913 lower_case_name.begin(),
1914 [](
unsigned char c) { return std::tolower(c); });
1916 if (header.channels().findChannel(channel_names[i]) ||
1917 header.channels().findChannel(lower_case_name)) {
1918 rgb_channels[num_channels++] = channel_names[i];
1919 if (num_channels == 3) {
1925 return num_channels;
1934 return header.channels().findChannel(
"Y") !=
nullptr;
1940 return header.channels().findChannel(
"BY") !=
nullptr &&
1941 header.channels().findChannel(
"RY") !=
nullptr;
1947 return !(header.channels().findChannel(
"Z") ==
nullptr);
1953 return !(header.channels().findChannel(
"A") ==
nullptr);
1959 return (header.channels().findChannel(
"X") !=
nullptr ||
1960 header.channels().findChannel(
"x") !=
nullptr) &&
1961 (header.channels().findChannel(
"Y") !=
nullptr ||
1962 header.channels().findChannel(
"y") !=
nullptr) &&
1963 (header.channels().findChannel(
"Z") !=
nullptr ||
1964 header.channels().findChannel(
"z") !=
nullptr);
1969 const ChannelList &
channels =
file.header(0).channels();
1970 for (ChannelList::ConstIterator i =
channels.begin(); i !=
channels.end(); ++i) {
1971 const Channel &channel = i.channel();
1972 if (channel.type !=
HALF) {
1981 const ChannelList &
channels =
file.header(0).channels();
1982 std::set<std::string> layerNames;
1988 return (!layerNames.empty());
1992 StringVector &views,
1993 bool *r_singlelayer,
1997 std::set<std::string> layerNames;
1999 *r_singlelayer =
true;
2000 *r_multilayer = *r_multiview =
false;
2005 if (!views.empty() && !views[0].empty()) {
2006 *r_multiview =
true;
2009 *r_singlelayer =
false;
2010 *r_multilayer = (layerNames.size() > 1);
2011 *r_multiview =
false;
2015 if (!layerNames.empty()) {
2023 for (ChannelList::ConstIterator i =
channels.begin(); i !=
channels.end(); i++) {
2024 for (
const std::string &layer_name : layerNames) {
2027 std::string layerName = layer_name;
2028 size_t pos = layerName.rfind(
'.');
2030 if (
pos == std::string::npos) {
2031 *r_multilayer =
true;
2032 *r_singlelayer =
false;
2040 *r_singlelayer =
true;
2041 *r_multilayer =
false;
2049 for (
int p = 0; p <
file.parts(); p++) {
2050 if (hasMultiView(
file.header(p))) {
2060 return file.parts() > 1;
2094 struct ImBuf *ibuf =
nullptr;
2096 MultiPartInputFile *
file =
nullptr;
2108 file =
new MultiPartInputFile(*membuf);
2110 Box2i dw =
file->header(0).dataWindow();
2111 const size_t width = dw.max.x - dw.min.x + 1;
2112 const size_t height = dw.max.y - dw.min.y + 1;
2125 printf(
"Error: can't process EXR multilayer file\n");
2133 if (hasXDensity(
file->header(0))) {
2145 Header::ConstIterator iter;
2148 for (iter = header.begin(); iter != header.end(); iter++) {
2149 const StringAttribute *attr =
file->header(0).findTypedAttribute<StringAttribute>(
2170 const char *rgb_channels[3];
2174 FrameBuffer frameBuffer;
2176 size_t xstride =
sizeof(
float[4]);
2177 size_t ystride = -xstride *
width;
2187 if (num_rgb_channels > 0) {
2188 for (
int i = 0; i < num_rgb_channels; i++) {
2190 Slice(
Imf::FLOAT, (
char *)(first + i), xstride, ystride));
2195 Slice(
Imf::FLOAT, (
char *)first, xstride, ystride));
2197 Slice(
Imf::FLOAT, (
char *)(first + 1), xstride, ystride));
2199 Slice(
Imf::FLOAT, (
char *)(first + 2), xstride, ystride));
2201 else if (has_luma) {
2203 Slice(
Imf::FLOAT, (
char *)first, xstride, ystride));
2206 Slice(
Imf::FLOAT, (
char *)(first + 1), xstride, ystride, 1, 1, 0.5f));
2209 Slice(
Imf::FLOAT, (
char *)(first + 2), xstride, ystride, 1, 1, 0.5f));
2214 Slice(
Imf::FLOAT, (
char *)(first + 3), xstride, ystride, 1, 1, 1.0f));
2226 InputPart in(*
file, 0);
2227 in.setFrameBuffer(frameBuffer);
2228 in.readPixels(dw.min.y, dw.max.y);
2238 if (flag & IM_rect) {
2244 for (
size_t a = 0;
a < (size_t)ibuf->
x * ibuf->
y;
a++) {
2255 else if (!has_xyz && num_rgb_channels <= 1) {
2257 for (
size_t a = 0;
a < (size_t)ibuf->
x * ibuf->
y;
a++) {
2280 catch (
const std::exception &exc) {
2281 std::cerr << exc.what() << std::endl;
2294 const size_t max_thumb_size,
2299 IStream *stream =
nullptr;
2300 Imf::RgbaInputFile *
file =
nullptr;
2318 file =
new RgbaInputFile(*stream, 1);
2320 if (!
file->isComplete()) {
2324 Imath::Box2i dw =
file->dataWindow();
2325 int source_w = dw.max.x - dw.min.x + 1;
2326 int source_h = dw.max.y - dw.min.y + 1;
2327 *r_width = source_w;
2328 *r_height = source_h;
2331 if (
file->header().hasPreviewImage()) {
2343 if (colorspace && colorspace[0]) {
2347 float scale_factor =
MIN2((
float)max_thumb_size / (
float)source_w,
2348 (
float)max_thumb_size / (
float)source_h);
2349 int dest_w = (int)(source_w * scale_factor);
2350 int dest_h = (int)(source_h * scale_factor);
2355 Imf::Array<Imf::Rgba> pixels(source_w);
2358 for (
int h = 0; h < dest_h; h++) {
2361 int source_y = (int)((
float)h / scale_factor) + dw.min.y;
2362 file->setFrameBuffer(&pixels[0] - dw.min.x - source_y * source_w, 1, source_w);
2363 file->readPixels(source_y);
2365 for (
int w = 0;
w < dest_w;
w++) {
2367 int source_x = (int)(
MIN2((
w / scale_factor), dw.max.x - 1));
2368 float *dest_px = &ibuf->
rect_float[(h * dest_w +
w) * 4];
2369 dest_px[0] = pixels[source_x].r;
2370 dest_px[1] = pixels[source_x].g;
2371 dest_px[2] = pixels[source_x].b;
2372 dest_px[3] = pixels[source_x].a;
2376 if (
file->lineOrder() == INCREASING_Y) {
2386 catch (
const std::exception &exc) {
2387 std::cerr << exc.what() << std::endl;
2400 Imf::staticInitialize();
2407 Imf::setGlobalThreadCount(0);
typedef float(TangentPoint)[2]
void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip)
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_file_descriptor_size(int file) ATTR_WARN_UNUSED_RESULT
size_t BLI_file_size(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_kdtree_nd_() free(KDTree *tree)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_rfindstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float clamp_f(float value, float min, float max)
void ycc_to_rgb(float y, float cb, float cr, float *r_r, float *r_g, float *r_b, int colorspace)
float srgb_to_linearrgb(float c)
#define BLI_YCC_ITU_BT709
BLI_mmap_file * BLI_mmap_open(int fd) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1)
void * BLI_mmap_get_pointer(BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
char BLI_toupper_ascii(const char c)
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_str_partition_ex(const char *str, const char *end, const char delim[], const char **sep, const char **suf, bool from_right) ATTR_NONNULL(1
size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL()
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
int BLI_system_thread_count(void)
typedef double(DMatrix)[4][4]
struct PreviewImage PreviewImage
#define R_IMF_EXR_CODEC_PXR24
#define R_IMF_EXR_CODEC_NONE
#define R_IMF_EXR_CODEC_RLE
#define R_IMF_EXR_CODEC_ZIP
#define R_IMF_EXR_CODEC_DWAA
#define R_IMF_EXR_CODEC_ZIPS
#define R_IMF_EXR_CODEC_DWAB
#define R_IMF_EXR_CODEC_B44A
#define R_IMF_EXR_CODEC_B44
#define R_IMF_EXR_CODEC_PIZ
_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_FLOAT
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
bool imb_addrectfloatImBuf(struct ImBuf *ibuf, const unsigned int channels)
void IMB_rect_from_float(struct ImBuf *ibuf)
bool addzbuffloatImBuf(struct ImBuf *ibuf)
struct ImBuf * IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, unsigned int w, unsigned int h, unsigned int channels)
void IMB_flipy(struct ImBuf *ibuf)
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
void imb_mmap_unlock(void)
bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
bool imb_addencodedbufferImBuf(ImBuf *ibuf)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void seekg(exr_file_offset_t pos) override
bool read(char c[], int n) override
exr_file_offset_t tellg() override
IFileStream(const char *filepath)
void seekg(exr_file_offset_t pos) override
IMMapStream(const char *filepath)
exr_file_offset_t tellg() override
bool read(char c[], int n) override
void seekg(exr_file_offset_t pos) override
IMemStream(unsigned char *exrbuf, size_t exrsize)
bool read(char c[], int n) override
exr_file_offset_t tellg() override
OFileStream(const char *filepath)
exr_file_offset_t tellp() override
void seekp(exr_file_offset_t pos) override
void write(const char c[], int n) override
void write(const char c[], int n) override
void seekp(exr_file_offset_t pos) override
exr_file_offset_t tellp() override
void colorspace_set_default_role(char *colorspace, int size, int role)
SyclQueue void void size_t num_bytes void
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
ccl_gpu_kernel_postfix ccl_global float int num_pixels
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
static bool parse_channels(const ImageSpec &in_spec, vector< MergeImageLayer > &layers, string &error)
GAttributeReader lookup(const void *owner, const AttributeIDRef &attribute_id)
SymEdge< T > * prev(const SymEdge< T > *se)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static const pxr::TfToken preview("preview", pxr::TfToken::Immortal)
bool IMB_exr_begin_write(void *handle, const char *filepath, int width, int height, int compress, const StampData *stamp)
static const char * exr_rgba_channelname(MultiPartInputFile &file, const char *chan)
static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data)
static bool exr_has_multiview(MultiPartInputFile &file)
static void exr_printf(const char *__restrict fmt,...)
void IMB_exr_add_view(void *handle, const char *name)
static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *passname, bool has_xyz_channels)
static bool exr_has_xyz(MultiPartInputFile &file)
static void openexr_header_compression(Header *header, int compression)
static int imb_exr_get_multiView_id(StringVector &views, const std::string &name)
bool IMB_exr_has_multilayer(void *handle)
static ExrLayer * imb_exr_get_layer(ListBase *lb, char *layname)
struct ImBuf * imb_load_openexr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
void IMB_exr_close(void *handle)
void IMB_exrtile_begin_write(void *handle, const char *filepath, int mipmap, int width, int height, int tilex, int tiley)
void IMB_exr_clear_channels(void *handle)
static bool exr_is_half_float(MultiPartInputFile &file)
static void imb_exr_pass_name_from_channel(char *passname, const ExrChannel *echan, const char *channelname, const bool has_xyz_channels)
static bool imb_exr_is_multi(MultiPartInputFile &file)
static void openexr_header_metadata_callback(void *data, const char *propname, char *prop, int UNUSED(len))
static bool exr_has_luma(MultiPartInputFile &file)
static int exr_has_rgb(MultiPartInputFile &file, const char *rgb_channels[3])
void imb_initopenexr(void)
static struct ExrPass * imb_exr_get_pass(ListBase *lb, char *passname)
bool IMB_exr_begin_read(void *handle, const char *filepath, int *width, int *height, const bool parse_channels)
static int imb_exr_split_token(const char *str, const char *end, const char **token)
bool imb_is_a_openexr(const unsigned char *mem, const size_t size)
void * IMB_exr_get_handle_name(const char *name)
struct ImBuf * imb_load_filepath_thumbnail_openexr(const char *filepath, const int UNUSED(flags), const size_t max_thumb_size, char colorspace[], size_t *r_width, size_t *r_height)
#define exr_file_offset_t
void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, const char *viewname, int xstride, int ystride, float *rect, bool use_half_float)
void IMB_exr_write_channels(void *handle)
static bool exr_has_chroma(MultiPartInputFile &file)
static bool imb_exr_is_multilayer_file(MultiPartInputFile &file)
void IMB_exr_read_channels(void *handle)
static half float_to_half_safe(const float value)
static void openexr_header_metadata(Header *header, struct ImBuf *ibuf)
void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname, bool empty)
static void imb_exr_insert_view_name(char *name_full, const char *passname, const char *viewname)
static ListBase exrhandles
void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
void * IMB_exr_get_handle(void)
static bool exr_has_multipart_file(MultiPartInputFile &file)
static void exr_print_filecontents(MultiPartInputFile &file)
static void imb_exr_type_by_channels(ChannelList &channels, StringVector &views, bool *r_singlelayer, bool *r_multilayer, bool *r_multiview)
static bool exr_has_xyz_channels(ExrHandle *exr_handle)
static void imb_exr_get_views(MultiPartInputFile &file, StringVector &views)
static std::vector< MultiViewChannelName > exr_channels_in_multi_part_file(const MultiPartInputFile &file)
void IMB_exr_multilayer_convert(void *handle, void *base, void *(*addview)(void *base, const char *str), void *(*addlayer)(void *base, const char *str), void(*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view))
static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags)
float * IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname)
static bool exr_has_zbuffer(MultiPartInputFile &file)
static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flags)
static ExrHandle * imb_exr_begin_read_mem(IStream &file_stream, MultiPartInputFile &file, int width, int height)
bool imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags)
static bool exr_has_alpha(MultiPartInputFile &file)
void imb_exitopenexr(void)
char name[EXR_TOT_MAXNAME+1]
struct MultiViewChannelName * m
OFileStream * ofile_stream
MultiPartInputFile * ifile
MultiPartOutputFile * mpofile
char name[EXR_LAY_MAXNAME+1]
char chan_id[EXR_PASS_MAXCHAN]
char view[EXR_VIEW_MAXNAME]
char name[EXR_PASS_MAXNAME]
struct ExrChannel * chan[EXR_PASS_MAXCHAN]
char internal_name[EXR_PASS_MAXNAME]
struct IDProperty * metadata
ImbFormatOptions foptions
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)