bool ZfileInput::read_native_scanline(int subimage, int miplevel, int y, int z, void* data) { lock_guard lock(m_mutex); if (!seek_subimage(subimage, miplevel)) return false; if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: close the file and re-open. ImageSpec dummyspec; int subimage = current_subimage(); if (!close() || !open(m_filename, dummyspec) || !seek_subimage(subimage, miplevel)) return false; // Somehow, the re-open failed ASSERT(m_next_scanline == 0 && current_subimage() == subimage); } while (m_next_scanline <= y) { // Keep reading until we're read the scanline we really need gzread(m_gz, data, m_spec.width * sizeof(float)); ++m_next_scanline; } if (m_swab) swap_endian((float*)data, m_spec.width); return true; }
bool HdrInput::read_native_scanline(int subimage, int miplevel, int y, int z, void* data) { lock_guard lock(m_mutex); if (!seek_subimage(subimage, miplevel)) return false; if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: close the file and re-open. ImageSpec dummyspec; int subimage = current_subimage(); int miplevel = current_miplevel(); if (!close() || !open(m_filename, dummyspec) || !seek_subimage(subimage, miplevel)) return false; // Somehow, the re-open failed assert(m_next_scanline == 0 && current_subimage() == subimage && current_miplevel() == miplevel); } while (m_next_scanline <= y) { // Keep reading until we're read the scanline we really need int r = RGBE_ReadPixels_RLE(m_fd, (float*)data, m_spec.width, 1, rgbe_error); ++m_next_scanline; if (r != RGBE_RETURN_SUCCESS) { error("%s", rgbe_error); return false; } } return true; }
bool JpgInput::read_native_scanline(int subimage, int miplevel, int y, int z, void* data) { if (!seek_subimage(subimage, miplevel)) return false; if (m_raw) return false; if (y < 0 || y >= (int)m_cinfo.output_height) // out of range scanline return false; if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: close the file and re-open. ImageSpec dummyspec; int subimage = current_subimage(); if (!close() || !open(m_filename, dummyspec) || !seek_subimage(subimage, 0)) return false; // Somehow, the re-open failed assert(m_next_scanline == 0 && current_subimage() == subimage); } // Set up our custom error handler if (setjmp(m_jerr.setjmp_buffer)) { // Jump to here if there's a libjpeg internal error return false; } void* readdata = data; if (m_cmyk) { // If the file's data is CMYK, read into a 4-channel buffer, then // we'll have to convert. m_cmyk_buf.resize(m_spec.width * 4); readdata = &m_cmyk_buf[0]; ASSERT(m_spec.nchannels == 3); } for (; m_next_scanline <= y; ++m_next_scanline) { // Keep reading until we've read the scanline we really need if (jpeg_read_scanlines(&m_cinfo, (JSAMPLE**)&readdata, 1) != 1 || m_fatalerr) { error("JPEG failed scanline read (\"%s\")", filename().c_str()); return false; } } if (m_cmyk) cmyk_to_rgb(m_spec.width, (unsigned char*)readdata, 4, (unsigned char*)data, 3); return true; }
bool TIFFInput::open (const std::string &name, ImageSpec &newspec) { m_filename = name; m_subimage = -1; return seek_subimage (0, 0, newspec); }
bool GIFInput::open (const std::string &name, ImageSpec &newspec) { m_filename = name; m_subimage = -1; m_canvas.clear (); return seek_subimage (0, 0, newspec); }
OIIO_PLUGIN_EXPORTS_END bool HdrInput::open (const std::string &name, ImageSpec &newspec) { m_filename = name; return seek_subimage (0, 0, newspec); }
bool GIFInput::open (const std::string &name, ImageSpec &newspec) { m_filename = name; m_subimage = -1; m_next_scanline = -1; m_cached_data.clear (); return seek_subimage (0, 0, newspec); }
bool PNGInput::read_native_scanline (int y, int z, void *data) { y -= m_spec.y; if (y < 0 || y >= m_spec.height) // out of range scanline return false; if (m_interlace_type != 0) { // Interlaced. Punt and read the whole image if (m_buf.empty ()) readimg (); size_t size = spec().scanline_bytes(); memcpy (data, &m_buf[0] + y * size, size); } else { // Not an interlaced image -- read just one row if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: close the file and re-open. ImageSpec dummyspec; int subimage = current_subimage(); if (! close () || ! open (m_filename, dummyspec) || ! seek_subimage (subimage, dummyspec)) return false; // Somehow, the re-open failed assert (m_next_scanline == 0 && current_subimage() == subimage); } while (m_next_scanline <= y) { // Keep reading until we're read the scanline we really need // std::cerr << "reading scanline " << m_next_scanline << "\n"; std::string s = PNG_pvt::read_next_scanline (m_png, data); if (s.length ()) { close (); error ("%s", s.c_str ()); return false; } ++m_next_scanline; } } // PNG specifically dictates unassociated (un-"premultiplied") alpha. // Convert to associated unless we were requested not to do so. if (m_spec.alpha_channel != -1 && !m_keep_unassociated_alpha) { float gamma = m_spec.get_float_attribute ("oiio:Gamma", 1.0f); if (m_spec.format == TypeDesc::UINT16) associateAlpha ((unsigned short *)data, m_spec.width, m_spec.nchannels, m_spec.alpha_channel, gamma); else associateAlpha ((unsigned char *)data, m_spec.width, m_spec.nchannels, m_spec.alpha_channel, gamma); } return true; }
bool OpenEXRInput::open (const std::string &name, ImageSpec &newspec) { // Quick check to reject non-exr files if (! Filesystem::is_regular (name)) { error ("Could not open file \"%s\"", name.c_str()); return false; } bool tiled; if (! Imf::isOpenExrFile (name.c_str(), tiled)) { error ("\"%s\" is not an OpenEXR file", name.c_str()); return false; } pvt::set_exr_threads (); m_spec = ImageSpec(); // Clear everything with default constructor try { m_input_stream = new OpenEXRInputStream (name.c_str()); } catch (const std::exception &e) { m_input_stream = NULL; error ("OpenEXR exception: %s", e.what()); return false; } catch (...) { // catch-all for edge cases or compiler bugs m_input_stream = NULL; error ("OpenEXR exception: unknown"); return false; } try { m_input_multipart = new Imf::MultiPartInputFile (*m_input_stream); } catch (const std::exception &e) { delete m_input_stream; m_input_stream = NULL; error ("OpenEXR exception: %s", e.what()); return false; } catch (...) { // catch-all for edge cases or compiler bugs m_input_stream = NULL; error ("OpenEXR exception: unknown"); return false; } m_nsubimages = m_input_multipart->parts(); m_parts.resize (m_nsubimages); m_subimage = -1; m_miplevel = -1; bool ok = seek_subimage (0, 0, newspec); if (! ok) close (); return ok; }
OIIO_PLUGIN_EXPORTS_END bool HdrInput::open(const std::string& name, ImageSpec& newspec) { m_filename = name; bool ok = seek_subimage(0, 0); newspec = spec(); return ok; }
bool DPXInput::open (const std::string &name, ImageSpec &newspec) { // open the image m_stream = new InStream(); if (! m_stream->Open(name.c_str())) { error ("Could not open file \"%s\"", name.c_str()); return false; } m_dpx.SetInStream(m_stream); if (! m_dpx.ReadHeader()) { error ("Could not read header"); return false; } bool ok = seek_subimage (0, 0, newspec); newspec = spec (); return ok; }
bool NullInput::open(const std::string& name, ImageSpec& newspec, const ImageSpec& config) { m_filename = name; m_subimage = -1; m_miplevel = -1; m_mip = false; m_topspec = config; // std::vector<std::pair<string_view,string_view> > args; // string_view filename = deconstruct_uri (name, &args); std::map<std::string, std::string> args; std::string filename; if (!Strutil::get_rest_arguments(name, filename, args)) return false; if (filename.empty()) return false; // To keep the "null" input reader from reading from ANY name, only // succeed if it ends in ".null" or ".nul" --OR-- if the config has a // special override "null:force" set to nonzero (that lets the caller // guarantee a null input even if the name has no extension, say). if (!Strutil::ends_with(filename, ".null") && !Strutil::ends_with(filename, ".nul") && config.get_int_attribute("null:force") == 0) return false; // Override the config with default resolution if it was not set if (m_topspec.width <= 0) m_topspec.width = 1024; if (m_topspec.height <= 0) m_topspec.height = 1024; if (m_topspec.depth <= 0) m_topspec.depth = 1; if (m_topspec.full_width <= 0) m_topspec.full_width = m_topspec.width; if (m_topspec.full_height <= 0) m_topspec.full_height = m_topspec.height; if (m_topspec.full_depth <= 0) m_topspec.full_depth = m_topspec.depth; if (m_topspec.nchannels <= 0) m_topspec.nchannels = 4; if (m_topspec.format == TypeUnknown) m_topspec.format = TypeFloat; m_filename = filename; std::vector<float> fvalue; for (const auto& a : args) { if (a.first == "RES") { parse_res(a.second, m_topspec.width, m_topspec.height, m_topspec.depth); m_topspec.full_x = m_topspec.x; m_topspec.full_y = m_topspec.y; m_topspec.full_z = m_topspec.z; m_topspec.full_width = m_topspec.width; m_topspec.full_height = m_topspec.height; m_topspec.full_depth = m_topspec.depth; } else if (a.first == "TILE" || a.first == "TILES") { parse_res(a.second, m_topspec.tile_width, m_topspec.tile_height, m_topspec.tile_depth); } else if (a.first == "CHANNELS") { m_topspec.nchannels = Strutil::from_string<int>(a.second); m_topspec.default_channel_names(); } else if (a.first == "MIP") { m_mip = Strutil::from_string<int>(a.second); } else if (a.first == "TEX") { if (Strutil::from_string<int>(a.second)) { if (!m_spec.tile_width) { m_topspec.tile_width = 64; m_topspec.tile_height = 64; m_topspec.tile_depth = 1; } m_topspec.attribute("wrapmodes", "black,black"); m_topspec.attribute("textureformat", "Plain Texture"); m_mip = true; } } else if (a.first == "TYPE") { m_topspec.set_format(TypeDesc(a.second)); } else if (a.first == "PIXEL") { Strutil::extract_from_list_string(fvalue, a.second); fvalue.resize(m_topspec.nchannels); } else if (a.first.size() && a.second.size()) { parse_param(a.first, a.second, m_topspec); } } if (fvalue.size()) { // Convert float to the native type fvalue.resize(m_topspec.nchannels, 0.0f); m_value.resize(m_topspec.pixel_bytes()); convert_types(TypeFloat, fvalue.data(), m_topspec.format, m_value.data(), m_topspec.nchannels); } bool ok = seek_subimage(0, 0); newspec = spec(); return ok; }
bool OpenEXRInput::open (const std::string &name, ImageSpec &newspec) { // Quick check to reject non-exr files if (! Filesystem::is_regular (name)) { error ("Could not open file \"%s\"", name.c_str()); return false; } bool tiled; if (! Imf::isOpenExrFile (name.c_str(), tiled)) { error ("\"%s\" is not an OpenEXR file", name.c_str()); return false; } pvt::set_exr_threads (); m_spec = ImageSpec(); // Clear everything with default constructor try { m_input_stream = new OpenEXRInputStream (name.c_str()); } catch (const std::exception &e) { m_input_stream = NULL; error ("OpenEXR exception: %s", e.what()); return false; } #ifdef USE_OPENEXR_VERSION2 try { m_input_multipart = new Imf::MultiPartInputFile (*m_input_stream); } catch (const std::exception &e) { delete m_input_stream; m_input_stream = NULL; error ("OpenEXR exception: %s", e.what()); return false; } m_nsubimages = m_input_multipart->parts(); #else try { if (tiled) { m_input_tiled = new Imf::TiledInputFile (*m_input_stream); } else { m_input_scanline = new Imf::InputFile (*m_input_stream); } } catch (const std::exception &e) { delete m_input_stream; m_input_stream = NULL; error ("OpenEXR exception: %s", e.what()); return false; } if (! m_input_scanline && ! m_input_tiled) { error ("Unknown error opening EXR file"); return false; } m_nsubimages = 1; // OpenEXR 1.x did not have multipart #endif m_parts.resize (m_nsubimages); m_subimage = -1; m_miplevel = -1; bool ok = seek_subimage (0, 0, newspec); if (! ok) close (); return ok; }
bool GIFInput::read_native_scanline (int _y, int z, void *data) { if (_y < 0 || _y > m_spec.height) return false; bool interlacing = m_spec.get_int_attribute ("gif:Interlacing") != 0; // decode scanline index if image is interlaced int gif_y = interlacing ? decode_line_number (_y) : _y; if (interlacing) { // gif is interlaced so cache the scanlines int scanlines_cached = m_cached_data.size() / m_spec.width; if (gif_y >= scanlines_cached) { // scanline is not cached yet, read the scanline and preceding ones m_cached_data.resize (m_spec.width * (gif_y + 1)); int delta_size = m_spec.width * (gif_y - scanlines_cached + 1); if (DGifGetLine (m_gif_file, &m_cached_data[scanlines_cached * m_spec.width], delta_size) == GIF_ERROR) { report_last_error (); return false; } } translate_scanline (&m_cached_data[gif_y * m_spec.width], data); } else { // no interlacing, thus no scanlines caching if (m_next_scanline > gif_y) { // requested scanline is located before the one to read next // random access is not supported, so reopen the file, find // current subimage and skip preceding image data ImageSpec dummyspec; if (! close () || ! open (m_filename, dummyspec) || ! seek_subimage (m_subimage, 0, dummyspec)) { return false; } int remaining_size = m_spec.width * gif_y; boost::scoped_array<unsigned char> buffer (new unsigned char[remaining_size]); if (DGifGetLine (m_gif_file, buffer.get(), remaining_size) == GIF_ERROR) { report_last_error (); return false; } } else if (m_next_scanline < gif_y) { // requested scanline is located after the one to read next // skip the lines in between int delta_size = m_spec.width * (gif_y - m_next_scanline); boost::scoped_array<unsigned char> buffer (new unsigned char[delta_size]); if (DGifGetLine (m_gif_file, buffer.get(), delta_size) == GIF_ERROR) { report_last_error (); return false; } } // read the requested scanline boost::scoped_array<unsigned char> fscanline (new unsigned char[m_spec.width]); if (DGifGetLine (m_gif_file, fscanline.get(), m_spec.width) == GIF_ERROR) { report_last_error (); return false; } translate_scanline (fscanline.get(), data); } m_next_scanline = gif_y + 1; return true; }
bool TIFFInput::read_native_scanline (int y, int z, void *data) { y -= m_spec.y; // For compression modes that don't support random access to scanlines // (which I *think* is only LZW), we need to emulate random access by // re-seeking. if (m_no_random_access) { if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: start over. // FIXME: I'm too tired to look into it now, but I wonder if // it is able to randomly seek to the first line in any // "strip", in which case we don't need to start from 0, just // start from the beginning of the strip we need. ImageSpec dummyspec; int old_subimage = current_subimage(); int old_miplevel = current_miplevel(); if (! close () || ! open (m_filename, dummyspec) || ! seek_subimage (old_subimage, old_miplevel, dummyspec)) { return false; // Somehow, the re-open failed } ASSERT (m_next_scanline == 0 && current_subimage() == old_subimage && current_miplevel() == old_miplevel); } while (m_next_scanline < y) { // Keep reading until we're read the scanline we really need m_scratch.resize (m_spec.scanline_bytes()); if (TIFFReadScanline (m_tif, &m_scratch[0], m_next_scanline) < 0) { error ("%s", lasterr.c_str()); return false; } ++m_next_scanline; } } m_next_scanline = y+1; int nvals = m_spec.width * m_spec.nchannels; m_scratch.resize (m_spec.scanline_bytes()); bool no_bit_convert = (m_bitspersample == 8 || m_bitspersample == 16 || m_bitspersample == 32); if (m_photometric == PHOTOMETRIC_PALETTE) { // Convert from palette to RGB if (TIFFReadScanline (m_tif, &m_scratch[0], y) < 0) { error ("%s", lasterr.c_str()); return false; } palette_to_rgb (m_spec.width, &m_scratch[0], (unsigned char *)data); } else { // Not palette int plane_bytes = m_spec.width * m_spec.format.size(); int planes = m_separate ? m_spec.nchannels : 1; std::vector<unsigned char> scratch2 (m_separate ? m_spec.scanline_bytes() : 0); // Where to read? Directly into user data if no channel shuffling // or bit shifting is needed, otherwise into scratch space. unsigned char *readbuf = (no_bit_convert && !m_separate) ? (unsigned char *)data : &m_scratch[0]; // Perform the reads. Note that for contig, planes==1, so it will // only do one TIFFReadScanline. for (int c = 0; c < planes; ++c) /* planes==1 for contig */ if (TIFFReadScanline (m_tif, &readbuf[plane_bytes*c], y, c) < 0) { error ("%s", lasterr.c_str()); return false; } if (m_bitspersample < 8) { // m_scratch now holds nvals n-bit values, contig or separate std::swap (m_scratch, scratch2); for (int c = 0; c < planes; ++c) /* planes==1 for contig */ bit_convert (m_separate ? m_spec.width : nvals, &scratch2[plane_bytes*c], m_bitspersample, m_separate ? &m_scratch[plane_bytes*c] : (unsigned char *)data+plane_bytes*c, 8); } else if (m_bitspersample > 8 && m_bitspersample < 16) { // m_scratch now holds nvals n-bit values, contig or separate std::swap (m_scratch, scratch2); for (int c = 0; c < planes; ++c) /* planes==1 for contig */ bit_convert (m_separate ? m_spec.width : nvals, &scratch2[plane_bytes*c], m_bitspersample, m_separate ? &m_scratch[plane_bytes*c] : (unsigned char *)data+plane_bytes*c, 16); } if (m_separate) { // Convert from separate (RRRGGGBBB) to contiguous (RGBRGBRGB). // We know the data is in m_scratch at this point, so // contiguize it into the user data area. separate_to_contig (m_spec.width, &m_scratch[0], (unsigned char *)data); } } if (m_photometric == PHOTOMETRIC_MINISWHITE) invert_photometric (nvals, data); // If alpha is unassociated and we aren't requested to keep it that // way, multiply the colors by alpha per the usual OIIO conventions // to deliver associated color & alpha. if (m_convert_alpha) unassalpha_to_assocalpha (m_spec.width, data); return true; }
bool TIFFInput::read_native_scanline (int y, int z, void *data) { y -= m_spec.y; // For compression modes that don't support random access to scanlines // (which I *think* is only LZW), we need to emulate random access by // re-seeking. if (m_no_random_access) { if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: start over. // FIXME: I'm too tired to look into it now, but I wonder if // it is able to randomly seek to the first line in any // "strip", in which case we don't need to start from 0, just // start from the beginning of the strip we need. ImageSpec dummyspec; int old_subimage = current_subimage(); int old_miplevel = current_miplevel(); if (! close () || ! open (m_filename, dummyspec) || ! seek_subimage (old_subimage, old_miplevel, dummyspec)) { return false; // Somehow, the re-open failed } ASSERT (m_next_scanline == 0 && current_subimage() == old_subimage && current_miplevel() == old_miplevel); } while (m_next_scanline < y) { // Keep reading until we're read the scanline we really need m_scratch.resize (m_spec.scanline_bytes()); if (TIFFReadScanline (m_tif, &m_scratch[0], m_next_scanline) < 0) { error ("%s", lasterr.c_str()); return false; } ++m_next_scanline; } } m_next_scanline = y+1; if (m_photometric == PHOTOMETRIC_PALETTE) { // Convert from palette to RGB m_scratch.resize (m_spec.width); if (TIFFReadScanline (m_tif, &m_scratch[0], y) < 0) { error ("%s", lasterr.c_str()); return false; } palette_to_rgb (m_spec.width, &m_scratch[0], (unsigned char *)data); } else if (m_planarconfig == PLANARCONFIG_SEPARATE && m_spec.nchannels > 1) { // Convert from separate (RRRGGGBBB) to contiguous (RGBRGBRGB) m_scratch.resize (m_spec.scanline_bytes()); int plane_bytes = m_spec.width * m_spec.format.size(); for (int c = 0; c < m_spec.nchannels; ++c) if (TIFFReadScanline (m_tif, &m_scratch[plane_bytes*c], y, c) < 0) { error ("%s", lasterr.c_str()); return false; } separate_to_contig (m_spec.width, &m_scratch[0], (unsigned char *)data); } else if (m_bitspersample == 1 || m_bitspersample == 2 || m_bitspersample == 4) { // <8 bit images m_scratch.resize (m_spec.width); if (TIFFReadScanline (m_tif, &m_scratch[0], y) < 0) { error ("%s", lasterr.c_str()); return false; } nbit_to_8bit (m_spec.width, &m_scratch[0], (unsigned char *)data, m_bitspersample); } else { // Contiguous, >= 8 bit per sample -- the "usual" case if (TIFFReadScanline (m_tif, data, y) < 0) { error ("%s", lasterr.c_str()); return false; } } if (m_photometric == PHOTOMETRIC_MINISWHITE) invert_photometric (m_spec.width * m_spec.nchannels, data); // If alpha is unassociated and we aren't requested to keep it that // way, multiply the colors by alpha per the usual OIIO conventions // to deliver associated color & alpha. if (m_convert_alpha) unassalpha_to_assocalpha (m_spec.width, data); return true; }