bool TIFFInput::read_native_tile (int x, int y, int z, void *data) { x -= m_spec.x; y -= m_spec.y; int tile_pixels = m_spec.tile_width * m_spec.tile_height * std::max (m_spec.tile_depth, 1); if (m_photometric == PHOTOMETRIC_PALETTE) { // Convert from palette to RGB m_scratch.resize (tile_pixels); if (TIFFReadTile (m_tif, &m_scratch[0], x, y, z, 0) < 0) { error ("%s", lasterr.c_str()); return false; } palette_to_rgb (tile_pixels, &m_scratch[0], (unsigned char *)data); } else if (m_planarconfig == PLANARCONFIG_SEPARATE && m_spec.nchannels > 1) { // Convert from separate (RRRGGGBBB) to contiguous (RGBRGBRGB) int plane_bytes = tile_pixels * m_spec.format.size(); DASSERT ((size_t)plane_bytes*m_spec.nchannels == m_spec.tile_bytes()); m_scratch.resize (m_spec.tile_bytes()); for (int c = 0; c < m_spec.nchannels; ++c) if (TIFFReadTile (m_tif, &m_scratch[plane_bytes*c], x, y, z, c) < 0) { error ("%s (errno '%s')", lasterr.c_str(), errno ? strerror(errno) : "unknown"); return false; } separate_to_contig (tile_pixels, &m_scratch[0], (unsigned char *)data); } else { // Contiguous, >= 8 bit per sample -- the "usual" case if (TIFFReadTile (m_tif, data, x, y, z, 0) < 0) { error ("%s (errno '%s')", lasterr.c_str(), errno ? strerror(errno) : "unknown"); return false; } } if (m_photometric == PHOTOMETRIC_MINISWHITE) invert_photometric (tile_pixels, 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 (tile_pixels, 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; 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_tile (int x, int y, int z, void *data) { x -= m_spec.x; y -= m_spec.y; imagesize_t tile_pixels = m_spec.tile_pixels(); imagesize_t nvals = tile_pixels * m_spec.nchannels; m_scratch.resize (m_spec.tile_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 (TIFFReadTile (m_tif, &m_scratch[0], x, y, z, 0) < 0) { error ("%s", lasterr.c_str()); return false; } palette_to_rgb (tile_pixels, &m_scratch[0], (unsigned char *)data); } else { // Not palette imagesize_t plane_bytes = m_spec.tile_pixels() * m_spec.format.size(); int planes = m_separate ? m_spec.nchannels : 1; std::vector<unsigned char> scratch2 (m_separate ? m_spec.tile_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 TIFFReadTile. for (int c = 0; c < planes; ++c) /* planes==1 for contig */ if (TIFFReadTile (m_tif, &readbuf[plane_bytes*c], x, y, z, 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 ? tile_pixels : 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 ? tile_pixels : 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 (tile_pixels, &m_scratch[0], (unsigned char *)data); } } if (m_photometric == PHOTOMETRIC_MINISWHITE) invert_photometric (tile_pixels, 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 (tile_pixels, 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; }