Skip to content

Commit 963b46a

Browse files
authored
iff: Temporarily address breakage with optional IOProxy revert (#3760)
When we recently added IOProxy support to the Maya iff file reader in PR 3647, something broke for certain (but not all) iff files, and I have productions stumbling over this. It's proving tricky to track down and I have shows needing a fix immediatly, so this change sets up a CMake variable ENABLE_RLA_IOPROXY, default to ON, but when set to OFF, it switches back to the old "no proxy" versions of the iff reader. Disabling this will get me out of my current emergency -- at the cost of not having IOProxy for iff, which I don't need at this moment anyway -- and give me some breathing room to fix the problem for real, at which point I will re-remove the old code.
1 parent e59397a commit 963b46a

File tree

7 files changed

+1734
-3
lines changed

7 files changed

+1734
-3
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
cmake_minimum_required (VERSION 3.12)
66

7-
set (OpenImageIO_VERSION "2.5.0.1")
7+
set (OpenImageIO_VERSION "2.5.0.2")
88
set (OpenImageIO_VERSION_OVERRIDE "" CACHE STRING
99
"Version override (use with caution)!")
1010
mark_as_advanced (OpenImageIO_VERSION_OVERRIDE)

src/iff.imageio/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@
22
# SPDX-License-Identifier: BSD-3-Clause
33
# https://github.com/OpenImageIO/oiio
44

5-
add_oiio_plugin (iffinput.cpp iffoutput.cpp)
5+
option (ENABLE_RLA_IOPROXY "(Temporarily) turn this off to switch back to the old pre-IOProxy RLA implementation to address a bug." ON)
6+
if (ENABLE_RLA_IOPROXY)
7+
add_oiio_plugin (iffinput.cpp iffoutput.cpp)
8+
else ()
9+
add_oiio_plugin (noproxy-iffinput.cpp noproxy-iffoutput.cpp noproxy-iff_pvt.cpp)
10+
endif ()

src/iff.imageio/iffinput.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ class IffInput final : public ImageInput {
8787
return read_type_len(name, len) && read_str(val, len);
8888
}
8989

90+
// Read a 4-byte type code (no endian swap), and if that succeeds (beware
91+
// of EOF or other errors), then also read a 32 bit size (subject to
92+
// endian swap).
9093
bool read_typesize(uint8_t type[4], uint32_t& size)
9194
{
9295
return ioread(type, 1, 4) && read(&size);
@@ -181,7 +184,7 @@ IffInput::open(const std::string& name, ImageSpec& spec)
181184
m_spec.full_height = m_iff_header.height;
182185

183186
// tiles
184-
if (m_iff_header.tile_width > 0 || m_iff_header.tile_height > 0) {
187+
if (m_iff_header.tile_width > 0 && m_iff_header.tile_height > 0) {
185188
m_spec.tile_width = m_iff_header.tile_width;
186189
m_spec.tile_height = m_iff_header.tile_height;
187190
// only 1 subimage for IFF

src/iff.imageio/noproxy-iff_pvt.cpp

Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
// Copyright 2008-present Contributors to the OpenImageIO project.
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
// https://github.com/OpenImageIO/oiio
4+
#include "noproxy-iff_pvt.h"
5+
#include <OpenImageIO/dassert.h>
6+
7+
OIIO_PLUGIN_NAMESPACE_BEGIN
8+
9+
using namespace iff_pvt;
10+
11+
#define STRINGIZE2(a) #a
12+
#define STRINGIZE(a) STRINGIZE2(a)
13+
14+
15+
16+
bool
17+
IffFileHeader::read_header(FILE* fd, std::string& err)
18+
{
19+
uint8_t type[4];
20+
uint32_t size;
21+
uint32_t chunksize;
22+
uint32_t tbhdsize;
23+
uint32_t flags;
24+
uint16_t bytes;
25+
uint16_t prnum;
26+
uint16_t prden;
27+
28+
// read FOR4 <size> CIMG.
29+
err.clear();
30+
for (;;) {
31+
// get type and length
32+
if (!read_typesize(fd, type, size)) {
33+
err = "could not read type/size @ L" STRINGIZE(__LINE__);
34+
return false;
35+
}
36+
37+
chunksize = align_size(size, 4);
38+
39+
if (type[0] == 'F' && type[1] == 'O' && type[2] == 'R'
40+
&& type[3] == '4') {
41+
// get type
42+
if (!fread(&type, 1, sizeof(type), fd)) {
43+
err = "could not read FDR4 type @ L" STRINGIZE(__LINE__);
44+
return false;
45+
}
46+
47+
// check if CIMG
48+
if (type[0] == 'C' && type[1] == 'I' && type[2] == 'M'
49+
&& type[3] == 'G') {
50+
// read TBHD.
51+
for (;;) {
52+
if (!read_typesize(fd, type, size)) {
53+
err = "could not read CIMG length @ L" STRINGIZE(
54+
__LINE__);
55+
return false;
56+
}
57+
58+
chunksize = align_size(size, 4);
59+
60+
if (type[0] == 'T' && type[1] == 'B' && type[2] == 'H'
61+
&& type[3] == 'D') {
62+
tbhdsize = size;
63+
64+
// test if table header size is correct
65+
if (tbhdsize != 24 && tbhdsize != 32) {
66+
err = "bad table header @ L" STRINGIZE(__LINE__);
67+
return false; // bad table header
68+
}
69+
70+
// get width and height
71+
if (!read(fd, width) || !read(fd, height)
72+
|| !read(fd, prnum) || !read(fd, prden)
73+
|| !read(fd, flags) || !read(fd, bytes)
74+
|| !read(fd, tiles) || !read(fd, compression)) {
75+
err = "@ L" STRINGIZE(__LINE__);
76+
return false;
77+
}
78+
79+
// get xy
80+
if (tbhdsize == 32) {
81+
if (!read(fd, x) || !read(fd, y)) {
82+
err = "could not get xy @ L" STRINGIZE(
83+
__LINE__);
84+
return false;
85+
}
86+
} else {
87+
x = 0;
88+
y = 0;
89+
}
90+
91+
// tiles
92+
if (tiles == 0) {
93+
err = "non-tiles not supported @ L" STRINGIZE(
94+
__LINE__);
95+
return false;
96+
} // non-tiles not supported
97+
98+
// 0 no compression
99+
// 1 RLE compression
100+
// 2 QRL (not supported)
101+
// 3 QR4 (not supported)
102+
if (compression > 1) {
103+
err = "only RLE compression is supported @ L" STRINGIZE(
104+
__LINE__);
105+
return false;
106+
}
107+
108+
// test format.
109+
if (flags & RGBA) {
110+
// test if black is set
111+
OIIO_DASSERT(!(flags & BLACK));
112+
113+
// test for RGB channels.
114+
if (flags & RGB)
115+
pixel_channels = 3;
116+
117+
// test for alpha channel
118+
if (flags & ALPHA)
119+
pixel_channels++;
120+
121+
// test pixel bits
122+
pixel_bits = bytes ? 16 : 8;
123+
}
124+
125+
// Z format.
126+
else if (flags & ZBUFFER) {
127+
pixel_channels = 1;
128+
pixel_bits = 32; // 32bit
129+
// NOTE: Z_F32 support - not supported
130+
OIIO_DASSERT(bytes == 0);
131+
}
132+
133+
// read AUTH, DATE or FOR4
134+
135+
for (;;) {
136+
// get type
137+
if (!read_typesize(fd, type, size)) {
138+
err = "could not read type/size @ L" STRINGIZE(
139+
__LINE__);
140+
return false;
141+
}
142+
143+
chunksize = align_size(size, 4);
144+
145+
if (type[0] == 'A' && type[1] == 'U'
146+
&& type[2] == 'T' && type[3] == 'H') {
147+
std::vector<char> str(chunksize);
148+
if (!fread(&str[0], 1, chunksize, fd)) {
149+
err = "could not read author @ L" STRINGIZE(
150+
__LINE__);
151+
return false;
152+
}
153+
author = std::string(&str[0], size);
154+
} else if (type[0] == 'D' && type[1] == 'A'
155+
&& type[2] == 'T' && type[3] == 'E') {
156+
std::vector<char> str(chunksize);
157+
if (!fread(&str[0], 1, chunksize, fd)) {
158+
err = "could not read date @ L" STRINGIZE(
159+
__LINE__);
160+
return false;
161+
}
162+
date = std::string(&str[0], size);
163+
} else if (type[0] == 'F' && type[1] == 'O'
164+
&& type[2] == 'R' && type[3] == '4') {
165+
if (!fread(&type, 1, sizeof(type), fd)) {
166+
err = "could not read FOR4 type @ L" STRINGIZE(
167+
__LINE__);
168+
return false;
169+
}
170+
171+
// check if CIMG
172+
if (type[0] == 'T' && type[1] == 'B'
173+
&& type[2] == 'M' && type[3] == 'P') {
174+
// tbmp position for later user in in
175+
// read_native_tile
176+
177+
tbmp_start = ftell(fd);
178+
179+
// read first RGBA block to detect tile size.
180+
181+
for (unsigned int t = 0; t < tiles; t++) {
182+
if (!read_typesize(fd, type, size)) {
183+
err = "xxx @ L" STRINGIZE(__LINE__);
184+
return false;
185+
}
186+
chunksize = align_size(size, 4);
187+
188+
// check if RGBA
189+
if (type[0] == 'R' && type[1] == 'G'
190+
&& type[2] == 'B'
191+
&& type[3] == 'A') {
192+
// get tile coordinates.
193+
uint16_t xmin, xmax, ymin, ymax;
194+
if (!read(fd, xmin)
195+
|| !read(fd, ymin)
196+
|| !read(fd, xmax)
197+
|| !read(fd, ymax)) {
198+
err = "xxx @ L" STRINGIZE(
199+
__LINE__);
200+
return false;
201+
}
202+
203+
// check tile
204+
if (xmin > xmax || ymin > ymax
205+
|| xmax >= width
206+
|| ymax >= height) {
207+
err = "tile min/max nonsensical @ L" STRINGIZE(
208+
__LINE__);
209+
return false;
210+
}
211+
212+
// set tile width and height
213+
tile_width = xmax - xmin + 1;
214+
tile_height = ymax - ymin + 1;
215+
216+
// done, return
217+
return true;
218+
}
219+
220+
// skip to the next block.
221+
if (fseek(fd, chunksize, SEEK_CUR)) {
222+
err = "could not fseek @ L" STRINGIZE(
223+
__LINE__);
224+
return false;
225+
}
226+
}
227+
} else {
228+
// skip to the next block.
229+
if (fseek(fd, chunksize, SEEK_CUR)) {
230+
err = "could not fseek @ L" STRINGIZE(
231+
__LINE__);
232+
return false;
233+
}
234+
}
235+
} else {
236+
// skip to the next block.
237+
if (fseek(fd, chunksize, SEEK_CUR)) {
238+
err = "could not fseek @ L" STRINGIZE(
239+
__LINE__);
240+
return false;
241+
}
242+
}
243+
}
244+
// TBHD done, break
245+
break;
246+
}
247+
248+
// skip to the next block.
249+
if (fseek(fd, chunksize, SEEK_CUR)) {
250+
err = "could not fseek @ L" STRINGIZE(__LINE__);
251+
return false;
252+
}
253+
}
254+
}
255+
}
256+
// skip to the next block.
257+
if (fseek(fd, chunksize, SEEK_CUR)) {
258+
err = "could not fseek @ L" STRINGIZE(__LINE__);
259+
return false;
260+
}
261+
}
262+
err = "unknown error, ended early @ L" STRINGIZE(__LINE__);
263+
return false;
264+
}
265+
266+
267+
268+
bool
269+
IffOutput::write_header(IffFileHeader& header)
270+
{
271+
// write 'FOR4' type, with 0 length for now (to reserve it)
272+
if (!(write_str("FOR4") && write_int(0)))
273+
return false;
274+
275+
// write 'CIMG' type
276+
if (!write_str("CIMG"))
277+
return false;
278+
279+
// write 'TBHD' type
280+
if (!write_str("TBHD"))
281+
return false;
282+
283+
// 'TBHD' length, 32 bytes
284+
if (!write_int(32))
285+
return false;
286+
287+
if (!write_int(header.width) || !write_int(header.height))
288+
return false;
289+
290+
// write prnum and prden (pixel aspect ratio? -- FIXME)
291+
if (!write_short(1) || !write_short(1)) //NOSONAR
292+
return false;
293+
294+
// write flags and channels
295+
if (!write_int(header.pixel_channels == 3 ? RGB : RGBA)
296+
|| !write_short(header.pixel_bits == 8 ? 0 : 1)
297+
|| !write_short(header.tiles))
298+
return false;
299+
300+
// write compression
301+
// 0 no compression
302+
// 1 RLE compression
303+
// 2 QRL (not supported)
304+
// 3 QR4 (not supported)
305+
if (!write_int(header.compression))
306+
return false;
307+
308+
// write x and y
309+
if (!write_int(header.x) || !write_int(header.y))
310+
return false;
311+
312+
// Write metadata
313+
write_meta_string("AUTH", header.author);
314+
write_meta_string("DATE", header.date);
315+
316+
// for4 position for later user in close
317+
header.for4_start = ftell(m_fd);
318+
319+
// write 'FOR4' type, with 0 length to reserve it for now
320+
if (!write_str("FOR4") || !write_int(0))
321+
return false;
322+
323+
// write 'TBMP' type
324+
if (!write_str("TBMP"))
325+
return false;
326+
327+
return true;
328+
}
329+
330+
331+
332+
OIIO_PLUGIN_NAMESPACE_END

0 commit comments

Comments
 (0)