Skip to content

Commit 74ba55a

Browse files
committed
read pixels in exr_in::open(), copy to line buffers in exr_in::read()
1 parent 17c4b4a commit 74ba55a

File tree

3 files changed

+190
-16
lines changed

3 files changed

+190
-16
lines changed

src/apps/common/ojph_img_io.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@
5050
#endif /* OJPH_ENABLE_TIFF_SUPPORT */
5151

5252
#ifdef OJPH_ENABLE_OPENEXR_SUPPORT
53+
#define IMATH_HALF_NO_LOOKUP_TABLE
5354
#include <ImfRgbaFile.h>
5455
#include <ImfInputFile.h>
5556
#include <ImfChannelList.h>
5657
#include <ImfArray.h>
58+
#include <ImfTestFile.h>
5759
#include <iostream>
5860
#endif
5961

@@ -521,7 +523,8 @@ namespace ojph {
521523
public:
522524
exr_in()
523525
{
524-
//tiff_handle = NULL;
526+
pixels.resizeErase(1, 1);
527+
525528
fname = NULL;
526529
line_buffer = NULL;
527530
line_buffer_for_planar_support_uint8 = NULL;
@@ -543,6 +546,7 @@ namespace ojph {
543546
virtual ~exr_in()
544547
{
545548
close();
549+
546550
if (line_buffer)
547551
free(line_buffer);
548552
if (line_buffer_for_planar_support_uint8)
@@ -580,7 +584,6 @@ namespace ojph {
580584
}
581585

582586
private:
583-
//TIFF* tiff_handle;
584587
size_t bytes_per_line;
585588
ui16 planar_configuration;
586589

@@ -595,6 +598,8 @@ namespace ojph {
595598
ui32 bit_depth[4];
596599
bool is_signed[4];
597600
point subsampling[4];
601+
602+
Imf::Array2D<Imf::Rgba> pixels;
598603
};
599604
#endif
600605

src/apps/ojph_compress/ojph_compress.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,57 @@ int main(int argc, char * argv[]) {
11101110
else if (is_matching(".exr", v))
11111111
{
11121112
exr.open(input_filename);
1113+
1114+
ojph::param_siz siz = codestream.access_siz();
1115+
siz.set_image_extent(ojph::point(image_offset.x + exr.get_size().w,
1116+
image_offset.y + exr.get_size().h));
1117+
ojph::ui32 num_comps = exr.get_num_components();
1118+
siz.set_num_components(num_comps);
1119+
1120+
for (ojph::ui32 c = 0; c < num_comps; ++c)
1121+
siz.set_component(c, exr.get_comp_subsampling(c),
1122+
exr.get_bit_depth(c), exr.get_is_signed(c));
1123+
siz.set_image_offset(image_offset);
1124+
siz.set_tile_size(tile_size);
1125+
siz.set_tile_offset(tile_offset);
1126+
1127+
ojph::param_cod cod = codestream.access_cod();
1128+
cod.set_num_decomposition(num_decompositions);
1129+
cod.set_block_dims(block_size.w, block_size.h);
1130+
if (num_precincts != -1)
1131+
cod.set_precinct_size(num_precincts, precinct_size);
1132+
cod.set_progression_order(prog_order);
1133+
if (employ_color_transform == -1 && num_comps >= 3)
1134+
cod.set_color_transform(true);
1135+
else
1136+
cod.set_color_transform(employ_color_transform == 1);
1137+
cod.set_reversible(reversible);
1138+
if (!reversible && quantization_step != -1)
1139+
codestream.access_qcd().set_irrev_quant(quantization_step);
1140+
codestream.set_planar(false);
1141+
if (profile_string[0] != '\0')
1142+
codestream.set_profile(profile_string);
1143+
codestream.set_tilepart_divisions(tileparts_at_resolutions,
1144+
tileparts_at_components);
1145+
codestream.request_tlm_marker(tlm_marker);
1146+
1147+
ojph::param_nlt nlt = codestream.access_nlt();
1148+
nlt.set_type3_transformation(65535, true);
1149+
1150+
if (dims.w != 0 || dims.h != 0)
1151+
OJPH_WARN(0x01000071,
1152+
"-dims option is not needed and was not used\n");
1153+
if (num_components != 0)
1154+
OJPH_WARN(0x01000072,
1155+
"-num_comps is not needed and was not used\n");
1156+
if (is_signed[0] != -1)
1157+
OJPH_WARN(0x01000073,
1158+
"-signed is not needed and was not used\n");
1159+
if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
1160+
OJPH_WARN(0x01000075,
1161+
"-downsamp is not needed and was not used\n");
1162+
1163+
base = &exr;
11131164
}
11141165
#endif // !OJPH_ENABLE_OPENEXR_SUPPORT
11151166
else

src/apps/others/ojph_img_io.cpp

Lines changed: 132 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,18 +2051,54 @@ namespace ojph {
20512051
/////////////////////////////////////////////////////////////////////////////
20522052
void exr_in::open(const char* filename)
20532053
{
2054+
// check if this is a valid OpenEXR file
2055+
bool is_tiled_openexr_file = false;
2056+
bool is_deep_openexr_file = false;
2057+
bool is_mulitpart_openexr_file = false;
2058+
bool is_valid_openexr_file = Imf::isOpenExrFile(filename,
2059+
is_tiled_openexr_file, is_deep_openexr_file, is_mulitpart_openexr_file);
2060+
2061+
if (false == is_valid_openexr_file)
2062+
{
2063+
fprintf(stderr, "ERROR on line %d of file %s in function %s():\n the input file %s is not a valid OpenEXR file\n",
2064+
__LINE__, __FILE__, __FUNCTION__, filename);
2065+
return;
2066+
}
2067+
2068+
if (true == is_tiled_openexr_file || true == is_deep_openexr_file || true == is_mulitpart_openexr_file)
2069+
{
2070+
fprintf(stderr, "ERROR on line %d of file %s in function %s():\n the input file %s is a valid OpenEXR file but is not yet supported by this software.\n",
2071+
__LINE__, __FILE__, __FUNCTION__, filename);
2072+
if (true == is_tiled_openexr_file)
2073+
{
2074+
fprintf(stderr, " the input file %s is tiled.\n", filename);
2075+
}
2076+
if (true == is_deep_openexr_file)
2077+
{
2078+
fprintf(stderr, " the input file %s is deep.\n", filename);
2079+
}
2080+
if (true == is_mulitpart_openexr_file)
2081+
{
2082+
fprintf(stderr, " the input file %s is multi-part.\n", filename);
2083+
}
2084+
return;
2085+
}
2086+
2087+
bool has_RGB = false;
2088+
bool has_alpha = false;
2089+
2090+
// first open with most generic interface to see if the file can be supported by the easier RGBA interface
20542091
try {
20552092
Imf::InputFile file(filename);
20562093
Imath::Box2i dw = file.header().dataWindow();
20572094
int width = dw.max.x - dw.min.x + 1;
20582095
int height = dw.max.y - dw.min.y + 1;
20592096

2060-
bool has_alpha = file.header().channels().findChannel("A");
2061-
2062-
if (file.header().channels().begin().channel().type == Imf::HALF)
2063-
this->bit_depth[0] = 16;
2064-
else
2065-
this->bit_depth[0] = 32;
2097+
has_alpha = file.header().channels().findChannel("A");
2098+
bool has_R = file.header().channels().findChannel("R");
2099+
bool has_G = file.header().channels().findChannel("G");
2100+
bool has_B = file.header().channels().findChannel("B");
2101+
has_RGB = has_R ? has_G ? has_B : false : false;
20662102

20672103
this->width = width;
20682104
this->height = height;
@@ -2079,45 +2115,127 @@ namespace ojph {
20792115
{
20802116
case Imf::PixelType::UINT:
20812117
fprintf(stderr, "channel %d type = UINT\n", channel_index);
2118+
this->bit_depth[channel_index] = 32;
20822119
break;
20832120
case Imf::PixelType::HALF:
20842121
fprintf(stderr, "channel %d type = HALF\n", channel_index);
2122+
this->bit_depth[channel_index] = 16;
20852123
break;
20862124
case Imf::PixelType::FLOAT:
20872125
fprintf(stderr, "channel %d type = FLOAT\n", channel_index);
2126+
this->bit_depth[channel_index] = 32;
20882127
break;
20892128
default:
20902129
fprintf(stderr, "ERROR on line %d of file %s in function %s():\n channel %d PixelType = %d, this should be UINT=0, HALF=1 or FLOAT=2\n",
20912130
__LINE__, __FILE__, __FUNCTION__, channel_index, channel.type);
2131+
return;
20922132
break;
20932133
}
20942134

20952135
fprintf(stderr, "channel %d xSampling = %d\n", channel_index, channel.xSampling);
20962136
fprintf(stderr, "channel %d ySampling = %d\n", channel_index, channel.ySampling);
2097-
20982137
fprintf(stderr, "channel %d pLinear = %s\n", channel_index, channel.pLinear ? "true" : "false");
20992138

21002139
channel_index++;
21012140
}
21022141

2103-
this->num_comps = 3; // descriptor field can indicate 1, 3, or 4 comps
2104-
2105-
Imf::Array2D<Imf::Rgba> pixels(width, height);
2106-
2107-
//file.setFrameBuffer(&pixels[0][0], 1, width);
2108-
//file.readPixels(dw.min.y, dw.max.y);
2142+
this->num_comps = channel_index;
21092143

2144+
// check if this is a complete OpenEXR file
2145+
if (false == file.isComplete())
2146+
{
2147+
fprintf(stderr, "ERROR on line %d of file %s in function %s():\n the input file %s is not complete and therefore not yet supported by this software.\n",
2148+
__LINE__, __FILE__, __FUNCTION__, filename);
2149+
return;
2150+
}
21102151
}
21112152
catch (const std::exception& e) {
21122153
std::cerr << "error reading image file " << filename << ": " << e.what() << std::endl;
21132154
return;
21142155
}
2156+
2157+
// if the channels are RGB or RGBA then use the simple RGBA interface to read the pixel data
2158+
if ((3 == this->num_comps && true == has_RGB && false == has_alpha && bit_depth[0] == 16 && bit_depth[1] == 16 && bit_depth[2] == 16) ||
2159+
(4 == this->num_comps && true == has_RGB && true == has_alpha && bit_depth[0] == 16 && bit_depth[1] == 16 && bit_depth[2] == 16))
2160+
{
2161+
try {
2162+
//Imf::RgbaInputFile file(filename);
2163+
Imf::RgbaInputFile rgba_input_file(filename);
2164+
Imath::Box2i dw = rgba_input_file.dataWindow();
2165+
int width = dw.max.x - dw.min.x + 1;
2166+
int height = dw.max.y - dw.min.y + 1;
2167+
2168+
pixels.resizeErase(height, width);
2169+
rgba_input_file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
2170+
rgba_input_file.readPixels(dw.min.y, dw.max.y);
2171+
2172+
}
2173+
catch (const std::exception& e) {
2174+
std::cerr << "error reading image file " << filename << ": " << e.what() << std::endl;
2175+
return;
2176+
}
2177+
}
2178+
else
2179+
{
2180+
fprintf(stderr, "ERROR in file %s on line %d in function %s:\n Unable to use RGBA interface because this->num_comps = %d and has_RGB = false\n",
2181+
__FILE__, __LINE__, __FUNCTION__, this->num_comps);
2182+
}
2183+
21152184
}
21162185

21172186
ui32 exr_in::read(const line_buf* line, ui32 comp_num)
21182187
{
2188+
assert(comp_num < num_comps);
2189+
assert((ui32)line->size >= width);
21192190

2120-
return 0;
2191+
if (bit_depth[comp_num] != 16)
2192+
{
2193+
fprintf(stderr, "ERROR in file %s on line %d in function %s:\n bit_depth[%d] = %d, this software currently only supports reading 16-bit files\n",
2194+
__FILE__, __LINE__, __FUNCTION__, comp_num, bit_depth[comp_num]);
2195+
return 0;
2196+
}
2197+
2198+
if(cur_line < height)
2199+
{
2200+
switch (comp_num)
2201+
{
2202+
case 0:
2203+
for (ui32 i = 0; i < width; i++)
2204+
{
2205+
line->i32[i] = (si32)(pixels[cur_line][i].r);
2206+
}
2207+
break;
2208+
case 1:
2209+
for (ui32 i = 0; i < width; i++)
2210+
{
2211+
line->i32[i] = (si32)(pixels[cur_line][i].g);
2212+
}
2213+
break;
2214+
case 2:
2215+
for (ui32 i = 0; i < width; i++)
2216+
{
2217+
line->i32[i] = (si32)(pixels[cur_line][i].b);
2218+
}
2219+
break;
2220+
case 3:
2221+
for (ui32 i = 0; i < width; i++)
2222+
{
2223+
line->i32[i] = (si32)(pixels[cur_line][i].a);
2224+
}
2225+
break;
2226+
}
2227+
2228+
}
2229+
2230+
if (comp_num == 0)
2231+
{
2232+
cur_line++;
2233+
}
2234+
2235+
2236+
2237+
2238+
return width;
21212239
}
21222240
#endif
21232241
}

0 commit comments

Comments
 (0)