void PixMap::read_direct_image(ReadSource in, unique_ptr<RasterImage>& image) const { if (pixel_type != RGB_DIRECT) { throw Exception("image is not direct"); } if (pack_type != 4) { throw Exception(format("unsupported pack_type {0}", pack_type)); } image.reset(new RasterImage(bounds)); if (row_bytes == 0) { return; } size_t bytes_read = 0; for (int y = 0; y < bounds.height(); ++y) { Bytes bytes; if (row_bytes <= 250) { bytes.resize(read<uint8_t>(in)); bytes_read += 1; } else { bytes.resize(read<uint16_t>(in)); bytes_read += 2; } in.shift(bytes.data(), bytes.size()); bytes_read += bytes.size(); BytesSlice remainder(bytes); Bytes components; while (!remainder.empty()) { uint8_t header = read<uint8_t>(remainder); if (header >= 0x80) { components.push(0x101 - header, read<uint8_t>(remainder)); } else { size_t size = header + 1; components.push(size, '\0'); uint8_t* data = components.data() + components.size() - size; remainder.shift(data, size); } } const int16_t w = bounds.width(); const BytesSlice red = components.slice((cmp_count - 3) * w, w); const BytesSlice green = components.slice((cmp_count - 2) * w, w); const BytesSlice blue = components.slice((cmp_count - 1) * w); for (int x = 0; x < w; ++x) { image->set(x, y, AlphaColor(red.at(x), green.at(x), blue.at(x))); } } if ((bytes_read % 2) != 0) { in.shift(1); } }
void read_from(ReadSource in, BitMap& out) { read(in, out.base_addr); read(in, out.row_bytes); read(in, out.bounds); if (out.base_addr != 0) { throw Exception("PixMap::base_addr must be 0"); } }
virtual void visit_object(const StringMap<Json>& value) const { if (_state == NEW) { _state = UNLOCKED_CHAPTERS; if (value.find("unlocked-levels") != value.end()) { value.find("unlocked-levels")->second.accept(*this); } _state = NEW; return; } throw Exception("invalid ledger content"); }
void PixMap::read_packed_image( sfz::ReadSource in, const ColorTable& clut, unique_ptr<RasterImage>& image) const { if (pixel_type != INDEXED) { throw Exception("image is not indexed"); } image.reset(new RasterImage(bounds)); if (row_bytes == 0) { return; } size_t bytes_read = 0; for (int y = 0; y < bounds.height(); ++y) { Bytes bytes; if (row_bytes <= 250) { bytes.resize(read<uint8_t>(in)); bytes_read += 1; } else { bytes.resize(read<uint16_t>(in)); bytes_read += 2; } in.shift(bytes.data(), bytes.size()); bytes_read += bytes.size(); int32_t x = 0; BytesSlice remainder = bytes; while (!remainder.empty()) { uint8_t header = read<uint8_t>(remainder); if (header >= 0x80) { uint8_t value = read<uint8_t>(remainder); uint8_t size = 0x101 - header; for (int j = 0; j < size; ++j) { if (x < bounds.width()) { image->set(x + bounds.left, y + bounds.top, lookup(clut, value)); } ++x; } } else { uint8_t size = header + 1; for (int j = 0; j < size; ++j) { if (x < bounds.width()) { uint8_t value = read<uint8_t>(remainder); image->set(x + bounds.left, y + bounds.top, lookup(clut, value)); } ++x; } } } } if ((bytes_read % 2 == 1)) { in.shift(1); } }
void BitsSlice::shift(uint8_t* data, size_t size) { if (size == 0) { return; } else if (size + _bit_index > 8) { throw Exception(format("unhandled case ({0} + {1})", size, _bit_index)); } uint8_t byte = _bytes.at(0); *data = bits(byte, _bit_index, _bit_index + size); _bit_index += size; if (_bit_index == 8) { _bytes.shift(1); _bit_index = 0; } }
void read_from(ReadSource in, PixMap& out) { read(in, out.row_bytes); out.row_bytes &= 0x3fff; read(in, out.bounds); read(in, out.pm_version); read(in, out.pack_type); read(in, out.pack_size); read(in, out.h_res); read(in, out.v_res); read(in, out.pixel_type); read(in, out.pixel_size); read(in, out.cmp_count); read(in, out.cmp_size); read(in, out.plane_bytes); read(in, out.pm_table); read(in, out.pm_reserved); if (out.plane_bytes != 0) { throw Exception("PixMap::plane_bytes must be 0"); } if (out.pm_reserved != 0) { throw Exception("PixMap::pm_reserved must be 0"); } switch (out.pixel_type) { case INDEXED: { switch (out.pixel_size) { case 1: case 2: case 4: case 8: break; default: throw Exception(format("indexed pixels may not have size {0}", out.pixel_size)); } if ((out.pack_type != 0) || (out.pack_size != 0)) { throw Exception("indexed pixels may not be packed"); } if ((out.cmp_count != 1) || (out.cmp_size != out.pixel_size)) { throw Exception("indexed pixels must have one component"); } break; } case RGB_DIRECT: { switch (out.pixel_size) { case 16: { throw Exception(format("unsupported pixel_size {0}", out.pixel_size)); break; } case 32: { if (out.cmp_size != 8) { throw Exception("32-bit direct pixels must have cmp_size 8"); } break; } default: { throw Exception(format("direct pixels may not have size {0}", out.pixel_size)); } } if ((out.cmp_count != 3) && (out.cmp_count != 4)) { throw Exception("direct pixels must have three or four components"); } break; } default: { throw Exception(format("illegal PixMap pixel_type {0}", out.pixel_type)); } } }