std::unique_ptr<uint8_t[]> DecodeTga(array_view<uint8_t> data) { if (data.size() < sizeof(TgaHeader)) { throw TempleException("Not enough data for TGA header"); } auto header = reinterpret_cast<const TgaHeader*>(data.data()); if (header->colorMapType != TgaColorMapType::TrueColor) { throw TempleException("Only true color TGA images are supported."); } if (header->dataType != TgaDataType::UncompressedRgb) { throw TempleException("Only uncompressed RGB TGA images are supported."); } if (header->bpp != 24 && header->bpp != 32) { throw TempleException("Only uncompressed RGB 24-bpp or 32-bpp TGA images are supported."); } auto result(std::make_unique<uint8_t[]>(header->width * header->height * 4)); auto dest = result.get(); // Points to the start of the TGA image data auto srcStart = data.data() + sizeof(TgaHeader) + header->imageIdLength; auto srcSize = data.size() - sizeof(TgaHeader) - header->imageIdLength; if (header->bpp == 24) { auto srcPitch = header->width * 3; Expects((int) srcSize >= header->height * srcPitch); for (int y = 0; y < header->height; ++y) { auto src = srcStart + (header->height - y - 1) * srcPitch; for (int x = 0; x < header->width; ++x) { *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = 0xFF; // Fixed alpha } } } else { auto srcPitch = header->width * 4; Expects((int) srcSize >= header->height * srcPitch); for (int y = 0; y < header->height; ++y) { auto src = srcStart + (header->height - y - 1) * srcPitch; for (int x = 0; x < header->width; ++x) { *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; } } } return result; }
bool DetectTga(array_view<uint8_t> data, ImageFileInfo& info) { if (data.size() < sizeof(TgaHeader)) { return false; } auto header = reinterpret_cast<const TgaHeader*>(data.data()); if (header->colorMapType != TgaColorMapType::TrueColor) { return false; // We don't supported index TGA } if (header->dataType != TgaDataType::UncompressedRgb) { return false; // We only support uncompressed RGB } if (header->bpp != 24 && header->bpp != 32) { return false; // We only support 24 or 32 bit TGAs } info.width = header->width; info.height = header->height; info.hasAlpha = (header->bpp == 32); info.format = ImageFileFormat::TGA; return true; }
bool operator == (const array_view & other) const noexcept { // Pointers to same memory (or both null). if (data() == other.data()) { return true; } // Different sizes, whole sequence can't be identical. if (size() != other.size()) { return false; } // Compare each element: return std::equal(begin(), end(), other.begin()); }
wal_bitmap xtk::wal_decode (const array_view<std::uint8_t>& data, const array_view<bitmap::value_type>& colormap) { const auto& header = *(const wal_header*)data.data (); auto _bitmap = wal_bitmap { make_bitmap_level (data, colormap, 0, header), make_bitmap_level (data, colormap, 1, header), make_bitmap_level (data, colormap, 2, header), make_bitmap_level (data, colormap, 3, header), std::string (header.name, strnlen (header.name, sizeof (header.name))), std::string (header.next_name, strnlen (header.next_name, sizeof (header.next_name))) }; return std::move (_bitmap); }
array_view(array_view<value_type, OtherLength> other) : Length(other.length()) , m_data(other.data()) { }
bool operator > (const array_view & other) const noexcept { return data() > other.data(); }
array_view(array_view<ConvertibleType> other) noexcept : m_pointer{ other.data() } , m_size_in_items{ other.size() } { }
bitmap xtk::pcx_decode (const array_view<std::uint8_t>& data) { static_assert (sizeof (pcx_header) == 128, "Header length incorrect"); const auto& header = *(const pcx_header*)data.data(); auto width = header.xmax - header.xmin + 1; auto height = header.ymax - header.ymin + 1; __xtk_assert (std::invalid_argument, header.vendor_id == 0x0A && header.version >= 5); xtk::Debug::log( "load_pcx: \n" "\tversion = %d\n" "\tbits_per_pixel = %d\n" "\tcolor_planes = %d\n" "\twidth = %u\n" "\theight = %u\n" , header.version, header.bits_per_pixel, header.color_planes, width, height ); __xtk_assert(std::invalid_argument, header.bits_per_pixel == 8 && header.color_planes == 0); auto buffer = std::make_unique<bitmap::value_type []> (width*height); auto stream = array_view<const std::uint8_t> {data.begin() + sizeof (header), data.end()}; auto next_pixel = 0u; auto next_sbyte = stream.begin (); auto palette = xtk::array_view<glm::tvec3<std::uint8_t>> { (const glm::tvec3<std::uint8_t> *)data.end () - 256, (const glm::tvec3<std::uint8_t> *)data.end () }; while (next_sbyte < stream.end ()) { auto rle = *next_sbyte; ++next_sbyte; if (rle >= 0xc0) { rle &= 0x3f; auto pixel = bitmap::value_type (palette [*next_sbyte], 255); ++next_sbyte; for (auto j = 0; j < rle; ++j) { buffer [next_pixel] = pixel; ++next_pixel; __xtk_assert (std::overflow_error, next_pixel <= width*height); } } else { buffer [next_pixel] = bitmap::value_type (palette [rle], 255); ++next_pixel; __xtk_assert (std::overflow_error, next_pixel <= width*height); } if (next_pixel >= width*height) { break; } } __xtk_assert (std::invalid_argument, next_pixel == width*height); return bitmap (std::move (buffer), width, height); }
void DeepData::init (int npix, int nchan, array_view<const TypeDesc> channeltypes, array_view<const std::string> channelnames) { clear (); m_npixels = npix; m_nchannels = nchan; ASSERT (channeltypes.size() >= 1); if (! m_impl) m_impl = new Impl; if (int(channeltypes.size()) >= nchan) { m_impl->m_channeltypes.assign (channeltypes.data(), channeltypes.data()+nchan); } else { m_impl->m_channeltypes.clear (); m_impl->m_channeltypes.resize (m_nchannels, channeltypes[0]); } m_impl->m_channelsizes.resize (m_nchannels); m_impl->m_channeloffsets.resize (m_nchannels); m_impl->m_channelnames.resize (m_nchannels); m_impl->m_myalphachannel.resize (m_nchannels, -1); m_impl->m_samplesize = 0; m_impl->m_nsamples.resize (m_npixels, 0); m_impl->m_capacity.resize (m_npixels, 0); m_impl->m_cumcapacity.resize (m_npixels, 0); // Channel name hunt // First, find Z, Zback, A for (int c = 0; c < m_nchannels; ++c) { size_t size = m_impl->m_channeltypes[c].size(); m_impl->m_channelsizes[c] = size; m_impl->m_channeloffsets[c] = m_impl->m_samplesize; m_impl->m_samplesize += size; m_impl->m_channelnames[c] = channelnames[c]; if (m_impl->m_z_channel < 0 && is_or_endswithdot (channelnames[c], "Z")) m_impl->m_z_channel = c; else if (m_impl->m_zback_channel < 0 && is_or_endswithdot (channelnames[c], "Zback")) m_impl->m_zback_channel = c; else if (m_impl->m_alpha_channel < 0 && is_or_endswithdot (channelnames[c], "A")) m_impl->m_alpha_channel = c; else if (m_impl->m_alpha_channel < 0 && is_or_endswithdot (channelnames[c], "Alpha")) m_impl->m_alpha_channel = c; else if (m_impl->m_AR_channel < 0 && is_or_endswithdot (channelnames[c], "AR")) m_impl->m_AR_channel = c; else if (m_impl->m_AG_channel < 0 && is_or_endswithdot (channelnames[c], "AG")) m_impl->m_AG_channel = c; else if (m_impl->m_AB_channel < 0 && is_or_endswithdot (channelnames[c], "AB")) m_impl->m_AB_channel = c; } // Now try to find which alpha corresponds to each channel for (int c = 0; c < m_nchannels; ++c) { // Skip non-color channels if (c == m_impl->m_z_channel || c == m_impl->m_zback_channel || m_impl->m_channeltypes[c] == TypeDesc::UINT32) continue; string_view name (channelnames[c]); // Alpha channels are their own alpha if (is_or_endswithdot (name, "A") || is_or_endswithdot (name, "AR") || is_or_endswithdot (name, "AG") || is_or_endswithdot (name, "AB") || is_or_endswithdot (name, "Alpha")) { m_impl->m_myalphachannel[c] = c; continue; } // For anything else, try to find its channel string_view prefix = name, suffix = name; size_t dot = name.find_last_of ('.'); if (dot == string_view::npos) { // No dot prefix.clear (); } else { // dot prefix = prefix.substr (0, dot+1); suffix = suffix.substr (dot+1); } std::string targetalpha = std::string(prefix) + "A" + std::string(suffix); for (int i = 0; i < m_nchannels; ++i) { if (Strutil::iequals (m_impl->m_channelnames[i], targetalpha)) { m_impl->m_myalphachannel[c] = i; break; } } if (m_impl->m_myalphachannel[c] < 0) m_impl->m_myalphachannel[c] = m_impl->m_alpha_channel; } }