Image ImageFormat_JPEG::decode(IReader& reader) const { const int64 size = reader.size(); uint8* buffer = static_cast<uint8*>(::malloc(static_cast<size_t>(size))); reader.read(buffer, size); int width, height; tjhandle tj = ::tjInitDecompress(); ::tjDecompressHeader(tj, buffer, static_cast<unsigned long>(size), &width, &height); Image image(width, height); ::tjDecompress( tj, buffer, static_cast<unsigned long>(size), image.dataAsUint8(), image.width(), image.stride(), image.height(), sizeof(Color), 0); ::tjDestroy(tj); ::free(buffer); return image; }
Size ImageFormat_JPEG::getSize(const IReader& reader) const { uint8 buf[24]; if (!reader.lookahead(buf)) { return{ 0, 0 }; } const auto len = reader.size(); // // http://www.wischik.com/lu/programmer/get-image-size.html // if ((buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF && buf[3] == 0xE0 && buf[6] == 'J' && buf[7] == 'F' && buf[8] == 'I' && buf[9] == 'F') || (buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF && buf[3] == 0xE1 && buf[6] == 'E' && buf[7] == 'x' && buf[8] == 'i' && buf[9] == 'f')) { int64 pos = 2; while (buf[2] == 0xFF) { if (buf[3] == 0xC0 || buf[3] == 0xC1 || buf[3] == 0xC2 || buf[3] == 0xC3 || buf[3] == 0xC5 || buf[3] == 0xC6 || buf[3] == 0xC7 || buf[3] == 0xC9 || buf[3] == 0xCA || buf[3] == 0xCB || buf[3] == 0xCD || buf[3] == 0xCE || buf[3] == 0xCF) { break; } pos += 2 + (buf[4] << 8) + buf[5]; if (pos + 12 > len) { break; } reader.lookahead(buf + 2, pos, 12); } } // JPEG: (first two bytes of buf are first two bytes of the jpeg file; rest of buf is the DCT frame if (buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF) { const int32 width = (buf[9] << 8) + buf[10]; const int32 height = (buf[7] << 8) + buf[8]; return{ width, height }; } return{ 0, 0 }; }
TemporaryFile(const IReader& reader) : m_path(FileSystem::UniqueFilePath()) { WritableMemoryMapping file(m_path); const size_t size = static_cast<size_t>(reader.size()); file.map(0, size); reader.lookahead(file.data(), size); file.unmap(); }