This commit is contained in:
Ivan
2022-04-05 11:42:28 +03:00
commit 6dc0eb0fcf
5565 changed files with 1200500 additions and 0 deletions

View File

@@ -0,0 +1,177 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <pangolin/image/image_io.h>
#include <fstream>
namespace pangolin {
// PNG
TypedImage LoadPng(std::istream& in);
void SavePng(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, bool top_line_first, int zlib_compression_level );
// JPG
TypedImage LoadJpg(std::istream& in);
void SaveJpg(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, float quality);
// PPM
TypedImage LoadPpm(std::istream& in);
void SavePpm(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, bool top_line_first);
// TGA
TypedImage LoadTga(std::istream& in);
// Pango
TypedImage LoadPango(const std::string& filename);
void SavePango(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first);
// EXR
TypedImage LoadExr(std::istream& source);
void SaveExr(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first);
// ZSTD (https://github.com/facebook/zstd)
TypedImage LoadZstd(std::istream& in);
void SaveZstd(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level);
// https://github.com/lz4/lz4
TypedImage LoadLz4(std::istream& in);
void SaveLz4(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level);
// packed 12 bit image (obtained from unpacked 16bit)
TypedImage LoadPacked12bit(std::istream& in);
void SavePacked12bit(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level);
TypedImage LoadImage(std::istream& in, ImageFileType file_type)
{
switch (file_type) {
case ImageFileTypePng:
return LoadPng(in);
case ImageFileTypeJpg:
return LoadJpg(in);
case ImageFileTypePpm:
return LoadPpm(in);
case ImageFileTypeTga:
return LoadTga(in);
case ImageFileTypeZstd:
return LoadZstd(in);
case ImageFileTypeLz4:
return LoadLz4(in);
case ImageFileTypeP12b:
return LoadPacked12bit(in);
case ImageFileTypeExr:
return LoadExr(in);
default:
throw std::runtime_error("Unable to load image file-type through std::istream");
}
}
TypedImage LoadImage(const std::string& filename, ImageFileType file_type)
{
switch (file_type) {
case ImageFileTypePng:
case ImageFileTypeJpg:
case ImageFileTypePpm:
case ImageFileTypeTga:
case ImageFileTypeZstd:
case ImageFileTypeLz4:
case ImageFileTypeP12b:
case ImageFileTypeExr:
{
std::ifstream ifs(filename, std::ios_base::in|std::ios_base::binary);
return LoadImage(ifs, file_type);
}
case ImageFileTypePango:
return LoadPango(filename);
default:
throw std::runtime_error("Unsupported image file type, '" + filename + "'");
}
}
TypedImage LoadImage(const std::string& filename)
{
ImageFileType file_type = FileType(filename);
return LoadImage( filename, file_type );
}
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, ImageFileType file_type, bool top_line_first, float quality)
{
switch (file_type) {
case ImageFileTypePng:
// map quality [0..100] to PNG compression levels [0..9]
return SavePng(image, fmt, out, top_line_first, int(quality*0.09));
case ImageFileTypeJpg:
return SaveJpg(image, fmt, out, quality);
case ImageFileTypePpm:
return SavePpm(image,fmt,out,top_line_first);
case ImageFileTypeZstd:
return SaveZstd(image,fmt,out, quality);
case ImageFileTypeLz4:
return SaveLz4(image,fmt,out, quality);
case ImageFileTypeP12b:
return SavePacked12bit(image,fmt,out, quality);
default:
throw std::runtime_error("Unable to save image file-type through std::istream");
}
}
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, ImageFileType file_type, bool top_line_first, float quality)
{
switch (file_type) {
case ImageFileTypePng:
case ImageFileTypeJpg:
case ImageFileTypePpm:
case ImageFileTypeZstd:
case ImageFileTypeLz4:
case ImageFileTypeP12b:
{
std::ofstream ofs(filename, std::ios_base::binary);
return SaveImage(image, fmt, ofs, file_type, top_line_first, quality);
}
case ImageFileTypeExr:
return SaveExr(image, fmt, filename, top_line_first);
case ImageFileTypePango:
return SavePango(image, fmt, filename, top_line_first);
default:
throw std::runtime_error("Unsupported image file type, '" + filename + "'");
}
}
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first, float quality)
{
const std::string ext = FileLowercaseExtention(filename);
const ImageFileType file_type = FileTypeExtension(ext);
SaveImage(image, fmt, filename,file_type, top_line_first, quality);
}
void SaveImage(const TypedImage& image, const std::string& filename, bool top_line_first, float quality)
{
SaveImage(image, image.fmt, filename, top_line_first, quality);
}
}

View File

@@ -0,0 +1,188 @@
#include <pangolin/platform.h>
#include <fstream>
#include <pangolin/image/typed_image.h>
#ifdef HAVE_OPENEXR
#include <ImfChannelList.h>
#include <ImfInputFile.h>
#include <ImfOutputFile.h>
#include <ImfIO.h>
#endif // HAVE_OPENEXR
namespace pangolin {
#ifdef HAVE_OPENEXR
Imf::PixelType OpenEXRPixelType(int channel_bits)
{
if( channel_bits == 16 ) {
return Imf::PixelType::HALF;
}else if( channel_bits == 32 ) {
return Imf::PixelType::FLOAT;
}else{
throw std::runtime_error("Unsupported OpenEXR Pixel Type.");
}
}
void SetOpenEXRChannels(Imf::ChannelList& ch, const pangolin::PixelFormat& fmt)
{
const char* CHANNEL_NAMES[] = {"R","G","B","A"};
for(size_t c=0; c < fmt.channels; ++c) {
ch.insert( CHANNEL_NAMES[c], Imf::Channel(OpenEXRPixelType(fmt.channel_bits[c])) );
}
}
class StdIStream: public Imf::IStream
{
public:
StdIStream (std::istream &is):
Imf::IStream ("stream"),
_is (&is)
{
}
virtual bool read (char c[/*n*/], int n)
{
if (!*_is)
throw std::runtime_error("Unexpected end of file.");
_is->read (c, n);
if (_is->gcount() < n)
{
throw std::runtime_error("Early end of file");
return false;
}
return true;
}
virtual Imf::Int64 tellg ()
{
return std::streamoff (_is->tellg());
}
virtual void seekg (Imf::Int64 pos)
{
_is->seekg (pos);
}
virtual void clear ()
{
_is->clear();
}
private:
std::istream * _is;
};
PixelFormat GetPixelFormat(const Imf::Header& header)
{
const Imf::ChannelList &channels = header.channels();
size_t count = 0;
for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i){
const Imf::Channel& channel = i.channel();
if (channel.type != Imf::FLOAT){
throw std::invalid_argument("Currently, only 32-bit float OpenEXR files are supported.");
}
count += 1;
}
switch (count) {
case 1: return PixelFormatFromString("GRAY32F");
case 3: return PixelFormatFromString("RGB96F");
case 4: return PixelFormatFromString("RGBA128F");
default: throw std::invalid_argument("Currently, only 1, 3 or 4-channel OpenEXR files are supported.");
}
}
#endif //HAVE_OPENEXR
TypedImage LoadExr(std::istream& source)
{
#ifdef HAVE_OPENEXR
StdIStream istream(source);
Imf::InputFile file(istream);
PANGO_ENSURE(file.isComplete());
Imath::Box2i dw = file.header().dataWindow();
int width = dw.max.x - dw.min.x + 1;
int height = dw.max.y - dw.min.y + 1;
PixelFormat format = GetPixelFormat(file.header());
TypedImage img(width, height, format);
char *imgBase = (char *) img.ptr - (dw.min.x + dw.min.y * width) * sizeof(float) * format.channels;
Imf::FrameBuffer fb;
const Imf::ChannelList &channels = file.header().channels();
size_t c = 0;
for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i){
fb.insert(i.name(), Imf::Slice(
Imf::FLOAT, imgBase + sizeof(float) * c++,
sizeof(float) * format.channels,
sizeof(float) * format.channels * size_t(width),
1, 1,
0.0));
}
file.setFrameBuffer(fb);
file.readPixels(dw.min.y, dw.max.y);
return img;
#else
PANGOLIN_UNUSED(source);
throw std::runtime_error("Rebuild Pangolin for EXR support.");
#endif //HAVE_OPENEXR
}
void SaveExr(const Image<unsigned char>& image_in, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first)
{
#ifdef HAVE_OPENEXR
ManagedImage<unsigned char> flip_image;
Image<unsigned char> image;
if(top_line_first) {
image = image_in;
}else{
flip_image.Reinitialise(image_in.pitch,image_in.h);
for(size_t y=0; y<image_in.h; ++y) {
std::memcpy(flip_image.RowPtr(y), image_in.RowPtr(y), image_in.pitch);
}
image = flip_image;
}
Imf::Header header (image.w, image.h);
SetOpenEXRChannels(header.channels(), fmt);
Imf::OutputFile file (filename.c_str(), header);
Imf::FrameBuffer frameBuffer;
int ch=0;
size_t ch_bits = 0;
for(Imf::ChannelList::Iterator it = header.channels().begin(); it != header.channels().end(); ++it)
{
frameBuffer.insert(
it.name(),
Imf::Slice(
it.channel().type,
(char*)image.ptr + ch_bits/8,
fmt.channel_bits[ch]/8,
image.pitch
)
);
ch_bits += fmt.channel_bits[ch++];
}
file.setFrameBuffer(frameBuffer);
file.writePixels(image.h);
#else
PANGOLIN_UNUSED(image_in);
PANGOLIN_UNUSED(fmt);
PANGOLIN_UNUSED(filename);
PANGOLIN_UNUSED(top_line_first);
throw std::runtime_error("EXR Support not enabled. Please rebuild Pangolin.");
#endif // HAVE_OPENEXR
}
}

View File

@@ -0,0 +1,263 @@
#include <algorithm>
#include <fstream>
#include <pangolin/platform.h>
#include <pangolin/image/typed_image.h>
#ifdef HAVE_JPEG
# include <jpeglib.h>
# ifdef _WIN_
// Undef windows Macro polution from jpeglib.h
# undef LoadImage
# endif
#endif // HAVE_JPEG
// Inspired by https://cs.stanford.edu/~acoates/jpegAndIOS.txt
namespace pangolin {
#ifdef HAVE_JPEG
void error_handler(j_common_ptr cinfo) {
char msg[JMSG_LENGTH_MAX];
(*(cinfo->err->format_message)) (cinfo, msg);
throw std::runtime_error(msg);
}
const static size_t PANGO_JPEG_BUF_SIZE = 16384;
struct pango_jpeg_source_mgr {
struct jpeg_source_mgr pub;
std::istream* is;
JOCTET* buffer;
};
static void pango_jpeg_init_source(j_decompress_ptr /*cinfo*/) {
}
static boolean pango_jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
pango_jpeg_source_mgr* src = (pango_jpeg_source_mgr*)cinfo->src;
src->is->read((char*)src->buffer, PANGO_JPEG_BUF_SIZE);
size_t bytes = src->is->gcount();
if (bytes == 0) {
/* Insert a fake EOI marker */
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
bytes = 2;
}
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = bytes;
return TRUE;
}
static void pango_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
pango_jpeg_source_mgr* src = (pango_jpeg_source_mgr*)cinfo->src;
if (num_bytes > 0) {
while (num_bytes > (long)src->pub.bytes_in_buffer) {
num_bytes -= (long)src->pub.bytes_in_buffer;
pango_jpeg_fill_input_buffer(cinfo);
}
src->pub.next_input_byte += num_bytes;
src->pub.bytes_in_buffer -= num_bytes;
}
}
static void pango_jpeg_term_source(j_decompress_ptr cinfo) {
// must seek backward so that future reads will start at correct place.
pango_jpeg_source_mgr* src = (pango_jpeg_source_mgr*)cinfo->src;
src->is->clear();
src->is->seekg( src->is->tellg() - (std::streampos)src->pub.bytes_in_buffer );
}
static void pango_jpeg_set_source_mgr(j_decompress_ptr cinfo, std::istream& is) {
pango_jpeg_source_mgr* src = nullptr;
if (cinfo->src == 0)
{
cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(pango_jpeg_source_mgr));
src = (pango_jpeg_source_mgr*) cinfo->src;
src->buffer = (JOCTET *)(*cinfo->mem->alloc_small)
((j_common_ptr) cinfo, JPOOL_PERMANENT, PANGO_JPEG_BUF_SIZE*sizeof(JOCTET));
}else{
src = (pango_jpeg_source_mgr*) cinfo->src;
}
src->is = &is;
src->pub.init_source = pango_jpeg_init_source;
src->pub.fill_input_buffer = pango_jpeg_fill_input_buffer;
src->pub.skip_input_data = pango_jpeg_skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = pango_jpeg_term_source;
src->pub.bytes_in_buffer = 0;
src->pub.next_input_byte = 0;
}
struct pango_jpeg_destination_mgr {
struct jpeg_destination_mgr pub; /* public fields */
std::ostream* os; /* target stream */
JOCTET * buffer; /* start of buffer */
};
void pango_jpeg_init_destination (j_compress_ptr cinfo) {
pango_jpeg_destination_mgr* dest = (pango_jpeg_destination_mgr*) cinfo->dest;
dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
PANGO_JPEG_BUF_SIZE * sizeof(JOCTET));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = PANGO_JPEG_BUF_SIZE;
}
boolean pango_jpeg_empty_output_buffer(j_compress_ptr cinfo) {
pango_jpeg_destination_mgr* dest = (pango_jpeg_destination_mgr*)cinfo->dest;
dest->os->write((const char*)dest->buffer, PANGO_JPEG_BUF_SIZE);
if (dest->os->fail()) {
throw std::runtime_error("Couldn't write entire jpeg buffer to stream.");
}
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = PANGO_JPEG_BUF_SIZE;
return TRUE;
}
void pango_jpeg_term_destination (j_compress_ptr cinfo) {
pango_jpeg_destination_mgr* dest = (pango_jpeg_destination_mgr*) cinfo->dest;
size_t datacount = PANGO_JPEG_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
if (datacount > 0) {
dest->os->write((const char*)dest->buffer, datacount);
if (dest->os->fail()) {
throw std::runtime_error("Couldn't write remaining jpeg data to stream.");
}
}
dest->os->flush();
}
void pango_jpeg_set_dest_mgr(j_compress_ptr cinfo, std::ostream& os) {
pango_jpeg_destination_mgr* dest;
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof(pango_jpeg_destination_mgr));
}
dest = (pango_jpeg_destination_mgr*)cinfo->dest;
dest->pub.init_destination = pango_jpeg_init_destination;
dest->pub.empty_output_buffer = pango_jpeg_empty_output_buffer;
dest->pub.term_destination = pango_jpeg_term_destination;
dest->os = &os;
}
#endif // HAVE_JPEG
TypedImage LoadJpg(std::istream& is) {
#ifdef HAVE_JPEG
TypedImage image;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
// Setup decompression structure
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = error_handler;
jpeg_create_decompress(&cinfo);
pango_jpeg_set_source_mgr(&cinfo, is);
// read info from header.
int r = jpeg_read_header(&cinfo, TRUE);
if (r != JPEG_HEADER_OK) {
throw std::runtime_error("Failed to read JPEG header.");
} else if (cinfo.num_components != 3 && cinfo.num_components != 1) {
throw std::runtime_error("Unsupported number of color components");
} else {
jpeg_start_decompress(&cinfo);
// resize storage if necessary
PixelFormat fmt = PixelFormatFromString(cinfo.output_components == 3 ? "RGB24" : "GRAY8");
image.Reinitialise(cinfo.output_width, cinfo.output_height, fmt);
JSAMPARRAY imageBuffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE,
cinfo.output_width*cinfo.output_components, 1);
for (size_t y = 0; y < cinfo.output_height; y++) {
jpeg_read_scanlines(&cinfo, imageBuffer, 1);
uint8_t* dstRow = (uint8_t*)image.RowPtr(y);
memcpy(dstRow, imageBuffer[0], cinfo.output_width*cinfo.output_components);
}
jpeg_finish_decompress(&cinfo);
}
// clean up.
jpeg_destroy_decompress(&cinfo);
return image;
#else
PANGOLIN_UNUSED(is);
throw std::runtime_error("Rebuild Pangolin for JPEG support.");
#endif // HAVE_JPEG
}
TypedImage LoadJpg(const std::string& filename) {
std::ifstream f(filename);
return LoadJpg(f);
}
void SaveJpg(const Image<unsigned char>& img, const PixelFormat& fmt, std::ostream& os, float quality) {
#ifdef HAVE_JPEG
const int iquality = (int)std::max(std::min(quality, 100.0f),0.0f);
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
if (fmt.channels != 1 && fmt.channels != 3) {
throw std::runtime_error("Unsupported number of image channels.");
}
if (fmt.bpp != 8 && fmt.bpp != 24) {
throw std::runtime_error("Unsupported image depth.");
}
// set up compression structure
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
pango_jpeg_set_dest_mgr(&cinfo, os);
cinfo.image_width = img.w;
cinfo.image_height = img.h;
cinfo.input_components = fmt.channels;
if (fmt.channels == 3) {
cinfo.in_color_space = JCS_RGB;
} else {
cinfo.in_color_space = JCS_GRAYSCALE;
}
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, iquality, (boolean)true);
jpeg_start_compress(&cinfo, (boolean)true);
JSAMPROW row;
while (cinfo.next_scanline < cinfo.image_height) {
row = (JSAMPROW)((char*)img.RowPtr(cinfo.next_scanline));
jpeg_write_scanlines(&cinfo, &row, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
#else
PANGOLIN_UNUSED(img);
PANGOLIN_UNUSED(fmt);
PANGOLIN_UNUSED(os);
PANGOLIN_UNUSED(quality);
throw std::runtime_error("Rebuild Pangolin for JPEG support.");
#endif // HAVE_JPEG
}
void SaveJpg(const Image<unsigned char>& img, const PixelFormat& fmt, const std::string& filename, float quality) {
std::ofstream f(filename);
SaveJpg(img, fmt, f, quality);
}
}

View File

@@ -0,0 +1,86 @@
#include <fstream>
#include <memory>
#include <pangolin/image/typed_image.h>
#ifdef HAVE_LZ4
# include <lz4.h>
#endif
namespace pangolin {
#pragma pack(push, 1)
struct lz4_image_header
{
char magic[3];
char fmt[16];
size_t w, h;
int64_t compressed_size;
};
#pragma pack(pop)
void SaveLz4(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level)
{
#ifdef HAVE_LZ4
const int64_t src_size = image.SizeBytes();
const int64_t max_dst_size = LZ4_compressBound(src_size);
std::unique_ptr<char[]> output_buffer(new char[max_dst_size]);
// Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
// The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
// It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
// An acceleration value of "1" is the same as regular LZ4_compress_default()
// Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
const int64_t compressed_data_size = LZ4_compress_fast((char*)image.ptr, output_buffer.get(), src_size, max_dst_size, compression_level);
if (compressed_data_size < 0)
throw std::runtime_error("A negative result from LZ4_compress_default indicates a failure trying to compress the data.");
if (compressed_data_size == 0)
throw std::runtime_error("A result of 0 for LZ4 means compression worked, but was stopped because the destination buffer couldn't hold all the information.");
lz4_image_header header;
strncpy(header.magic,"LZ4",3);
strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
header.w = image.w;
header.h = image.h;
header.compressed_size = compressed_data_size;
out.write((char*)&header, sizeof(header));
out.write(output_buffer.get(), compressed_data_size);
#else
PANGOLIN_UNUSED(image);
PANGOLIN_UNUSED(fmt);
PANGOLIN_UNUSED(out);
PANGOLIN_UNUSED(compression_level);
throw std::runtime_error("Rebuild Pangolin for LZ4 support.");
#endif // HAVE_LZ4
}
TypedImage LoadLz4(std::istream& in)
{
#ifdef HAVE_LZ4
// Read in header, uncompressed
lz4_image_header header;
in.read( (char*)&header, sizeof(header));
TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));
std::unique_ptr<char[]> input_buffer(new char[header.compressed_size]);
in.read(input_buffer.get(), header.compressed_size);
const int decompressed_size = LZ4_decompress_safe(input_buffer.get(), (char*)img.ptr, header.compressed_size, img.SizeBytes());
if (decompressed_size < 0)
throw std::runtime_error(FormatString("A negative result from LZ4_decompress_safe indicates a failure trying to decompress the data. See exit code (%) for value returned.", decompressed_size));
if (decompressed_size == 0)
throw std::runtime_error("I'm not sure this function can ever return 0. Documentation in lz4.h doesn't indicate so.");
if (decompressed_size != (int)img.SizeBytes())
throw std::runtime_error(FormatString("decompressed size % is not equal to predicted size %", decompressed_size, img.SizeBytes()));
return img;
#else
PANGOLIN_UNUSED(in);
throw std::runtime_error("Rebuild Pangolin for LZ4 support.");
#endif // HAVE_LZ4
}
}

View File

@@ -0,0 +1,85 @@
#include <fstream>
#include <memory>
#include <pangolin/image/typed_image.h>
namespace pangolin {
#pragma pack(push, 1)
struct packed12bit_image_header
{
char magic[4];
char fmt[16];
size_t w, h;
};
#pragma pack(pop)
void SavePacked12bit(const Image<uint8_t>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int /*compression_level*/)
{
if (fmt.bpp != 16) {
throw std::runtime_error("packed12bit currently only supported with 16bit input image");
}
const size_t dest_pitch = (image.w*12)/ 8 + ((image.w*12) % 8 > 0? 1 : 0);
const size_t dest_size = image.h*dest_pitch;
std::unique_ptr<uint8_t[]> output_buffer(new uint8_t[dest_size]);
for(size_t r=0; r<image.h; ++r) {
uint8_t* pout = output_buffer.get() + r*dest_pitch;
uint16_t* pin = (uint16_t*)(image.ptr + r*image.pitch);
const uint16_t* pin_end = (uint16_t*)(image.ptr + (r+1)*image.pitch);
while(pin < pin_end) {
uint32_t val = (*(pin++) & 0x00000FFF);
val |= uint32_t(*(pin++) & 0x00000FFF) << 12;
*(pout++) = uint8_t( val & 0x000000FF);
*(pout++) = uint8_t((val & 0x0000FF00) >> 8);
*(pout++) = uint8_t((val & 0x00FF0000) >> 16);
}
}
packed12bit_image_header header;
strncpy(header.magic,"P12B",4);
strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
header.w = image.w;
header.h = image.h;
out.write((char*)&header, sizeof(header));
out.write((char*)output_buffer.get(), dest_size);
}
TypedImage LoadPacked12bit(std::istream& in)
{
// Read in header, uncompressed
packed12bit_image_header header;
in.read((char*)&header, sizeof(header));
TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));
if (img.fmt.bpp != 16) {
throw std::runtime_error("packed12bit currently only supported with 16bit input image");
}
const size_t input_pitch = (img.w*12)/ 8 + ((img.w*12) % 8 > 0? 1 : 0);
const size_t input_size = img.h*input_pitch;
std::unique_ptr<uint8_t[]> input_buffer(new uint8_t[input_size]);
in.read((char*)input_buffer.get(), input_size);
for(size_t r=0; r<img.h; ++r) {
uint16_t* pout = (uint16_t*)(img.ptr + r*img.pitch);
uint8_t* pin = input_buffer.get() + r*input_pitch;
const uint8_t* pin_end = input_buffer.get() + (r+1)*input_pitch;
while(pin < pin_end) {
uint32_t val = *(pin++);
val |= uint32_t(*(pin++)) << 8;
val |= uint32_t(*(pin++)) << 16;
*(pout++) = uint16_t( val & 0x000FFF);
*(pout++) = uint16_t((val & 0xFFF000) >> 12);
}
}
return img;
}
}

View File

@@ -0,0 +1,62 @@
#include <pangolin/platform.h>
#include <pangolin/image/typed_image.h>
#ifdef BUILD_PANGOLIN_VIDEO
# include <pangolin/video/drivers/pango.h>
# include <pangolin/video/drivers/pango_video_output.h>
#endif
namespace pangolin {
TypedImage LoadPango(const std::string& uri)
{
PANGOLIN_UNUSED(uri);
#ifdef BUILD_PANGOLIN_VIDEO
std::unique_ptr<VideoInterface> video = OpenVideo(uri);
if(!video || video->Streams().size() != 1) {
throw pangolin::VideoException("Wrong number of streams: exactly one expected.");
}
std::unique_ptr<uint8_t[]> buffer( new uint8_t[video->SizeBytes()] );
const StreamInfo& stream_info = video->Streams()[0];
// Grab first image from video
if(!video->GrabNext(buffer.get(), true)) {
throw pangolin::VideoException("Failed to grab image from stream");
}
// Allocate storage for user image to return
TypedImage image(stream_info.Width(), stream_info.Height(), stream_info.PixFormat());
// Copy image data into user buffer.
const Image<unsigned char> img = stream_info.StreamImage(buffer.get());
PANGO_ENSURE(image.pitch <= img.pitch);
for(size_t y=0; y < image.h; ++y) {
std::memcpy(image.RowPtr(y), img.RowPtr(y), image.pitch);
}
return image;
#else
throw std::runtime_error("Video Support not enabled. Please rebuild Pangolin.");
#endif
}
void SavePango(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& uri, bool /*top_line_first*/)
{
PANGOLIN_UNUSED(image);
PANGOLIN_UNUSED(fmt);
PANGOLIN_UNUSED(uri);
#ifdef BUILD_PANGOLIN_VIDEO
std::unique_ptr<VideoOutputInterface> video = OpenVideoOutput(uri);
StreamInfo stream(fmt, image.w, image.h, image.pitch);
video->SetStreams({stream});
video->WriteStreams(image.ptr);
#else
throw std::runtime_error("Video Support not enabled. Please rebuild Pangolin.");
#endif
}
}

View File

@@ -0,0 +1,234 @@
#include <pangolin/platform.h>
#include <fstream>
#include <pangolin/image/image_io.h>
#include <vector>
#ifdef HAVE_PNG
# include <png.h>
#endif // HAVE_PNG
namespace pangolin {
#ifdef HAVE_PNG
PixelFormat PngFormat(png_structp png_ptr, png_infop info_ptr )
{
const png_byte colour = png_get_color_type(png_ptr, info_ptr);
const png_byte depth = png_get_bit_depth(png_ptr, info_ptr);
if( depth == 8 ) {
if( colour == PNG_COLOR_MASK_COLOR ) {
return PixelFormatFromString("RGB24");
} else if( colour == (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) ) {
return PixelFormatFromString("RGBA32");
} else if( colour == PNG_COLOR_MASK_ALPHA ) {
return PixelFormatFromString("Y400A");
} else {
return PixelFormatFromString("GRAY8");
}
}else if( depth == 16 ) {
if( colour == 0 ) {
return PixelFormatFromString("GRAY16LE");
}
}
throw std::runtime_error("Unsupported PNG format");
}
void PNGAPI PngWarningsCallback(png_structp /*png_ptr*/, png_const_charp /*warning_message*/)
{
// Override default behaviour - don't do anything.
}
#define PNGSIGSIZE 8
bool pango_png_validate(std::istream& source)
{
png_byte pngsig[PNGSIGSIZE];
source.read((char*)pngsig, PNGSIGSIZE);
return source.good() && png_sig_cmp(pngsig, 0, PNGSIGSIZE) == 0;
}
void pango_png_stream_read(png_structp pngPtr, png_bytep data, png_size_t length) {
std::istream* s = (std::istream*)png_get_io_ptr(pngPtr);
PANGO_ASSERT(s);
s->read((char*)data, length);
}
void pango_png_stream_write(png_structp pngPtr, png_bytep data, png_size_t length) {
std::ostream* s = (std::ostream*)png_get_io_ptr(pngPtr);
PANGO_ASSERT(s);
s->write((char*)data, length);
}
void pango_png_stream_write_flush(png_structp pngPtr)
{
std::ostream* s = (std::ostream*)png_get_io_ptr(pngPtr);
PANGO_ASSERT(s);
s->flush();
}
#endif // HAVE_PNG
TypedImage LoadPng(std::istream& source)
{
#ifdef HAVE_PNG
//so First, we validate our stream with the validate function I just mentioned
if (!pango_png_validate(source)) {
throw std::runtime_error("Not valid PNG header");
}
//set up initial png structs
png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, &PngWarningsCallback);
if (!png_ptr) {
throw std::runtime_error( "PNG Init error 1" );
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
throw std::runtime_error( "PNG Init error 2" );
}
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
throw std::runtime_error( "PNG Init error 3" );
}
png_set_read_fn(png_ptr,(png_voidp)&source, pango_png_stream_read);
png_set_sig_bytes(png_ptr, PNGSIGSIZE);
// Setup transformation options
if( png_get_bit_depth(png_ptr, info_ptr) == 1) {
//Unpack bools to bytes to ease loading.
png_set_packing(png_ptr);
} else if( png_get_bit_depth(png_ptr, info_ptr) < 8) {
//Expand nonbool colour depths up to 8bpp
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
//Get rid of palette, by transforming it to RGB
if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
//read the file
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, NULL);
if( png_get_interlace_type(png_ptr,info_ptr) != PNG_INTERLACE_NONE) {
throw std::runtime_error( "Interlace not yet supported" );
}
const size_t w = png_get_image_width(png_ptr,info_ptr);
const size_t h = png_get_image_height(png_ptr,info_ptr);
const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
TypedImage img(w, h, PngFormat(png_ptr, info_ptr), pitch);
png_bytepp rows = png_get_rows(png_ptr, info_ptr);
for( unsigned int r = 0; r < h; r++) {
memcpy( img.ptr + pitch*r, rows[r], pitch );
}
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
return img;
#else
PANGOLIN_UNUSED(source);
throw std::runtime_error("Rebuild Pangolin for PNG support.");
#endif // HAVE_PNG
}
TypedImage LoadPng(const std::string& filename)
{
std::ifstream f(filename);
return LoadPng(f);
}
void SavePng(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& stream, bool top_line_first, int zlib_compression_level)
{
#ifdef HAVE_PNG
// Check image has supported bit depth
for(unsigned int i=1; i < fmt.channels; ++i) {
if( fmt.channel_bits[i] != fmt.channel_bits[0] ) {
throw std::runtime_error("PNG Saving only supported for images where each channel has the same bit depth.");
}
}
png_structp png_ptr;
png_infop info_ptr;
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
throw std::runtime_error( "PNG Error: Could not allocate write struct." );
}
// Initialize info structure
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
throw std::runtime_error( "PNG Error: Could not allocate info struct." );
}
// Setup Exception handling
if (setjmp(png_jmpbuf(png_ptr))) {
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
throw std::runtime_error( "PNG Error: Error during png creation." );
}
png_set_compression_level(png_ptr, zlib_compression_level);
png_set_write_fn(png_ptr,(png_voidp)&stream, pango_png_stream_write, pango_png_stream_write_flush);
const int bit_depth = fmt.channel_bits[0];
int colour_type;
switch (fmt.channels) {
case 1: colour_type = PNG_COLOR_TYPE_GRAY; break;
case 2: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
case 3: colour_type = PNG_COLOR_TYPE_RGB; break;
case 4: colour_type = PNG_COLOR_TYPE_RGBA; break;
default:
throw std::runtime_error( "PNG Error: unexpected image channel number");
}
// Write header
png_set_IHDR(
png_ptr, info_ptr, (png_uint_32)image.w, (png_uint_32)image.h, bit_depth, colour_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
);
// Setup rows to write:
std::vector<png_bytep> rows(image.h);
if(top_line_first) {
for (unsigned int y = 0; y< image.h; y++) {
rows[y] = image.ptr + y*image.pitch;
}
}else{
for (unsigned int y = 0; y< image.h; y++) {
rows[y] = image.ptr + (image.h-1-y)*image.pitch;
}
}
png_set_rows(png_ptr,info_ptr, &rows[0]);
// Write image data: switch to little-endian byte order, to match host.
png_write_png(png_ptr,info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, 0);
// Free resources
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
#else
PANGOLIN_UNUSED(image);
PANGOLIN_UNUSED(fmt);
PANGOLIN_UNUSED(stream);
PANGOLIN_UNUSED(top_line_first);
PANGOLIN_UNUSED(zlib_compression_level);
throw std::runtime_error("Rebuild Pangolin for PNG support.");
#endif // HAVE_PNG
}
}

View File

@@ -0,0 +1,104 @@
#include <fstream>
#include <pangolin/image/typed_image.h>
namespace pangolin {
PixelFormat PpmFormat(const std::string& strType, int num_colours)
{
if(strType == "P5") {
if(num_colours < 256) {
return PixelFormatFromString("GRAY8");
} else {
return PixelFormatFromString("GRAY16LE");
}
}else if(strType == "P6") {
return PixelFormatFromString("RGB24");
}else{
throw std::runtime_error("Unsupported PPM/PGM format");
}
}
void PpmConsumeWhitespaceAndComments(std::istream& in)
{
// TODO: Make a little more general / more efficient
while( in.peek() == ' ' ) in.get();
while( in.peek() == '\n' ) in.get();
while( in.peek() == '#' ) in.ignore(4096, '\n');
}
TypedImage LoadPpm(std::istream& in)
{
// Parse header
std::string ppm_type = "";
int num_colors = 0;
int w = 0;
int h = 0;
in >> ppm_type;
PpmConsumeWhitespaceAndComments(in);
in >> w;
PpmConsumeWhitespaceAndComments(in);
in >> h;
PpmConsumeWhitespaceAndComments(in);
in >> num_colors;
in.ignore(1,'\n');
if(!in.fail() && w > 0 && h > 0) {
TypedImage img(w, h, PpmFormat(ppm_type, num_colors) );
// Read in data
for(size_t r=0; r<img.h; ++r) {
in.read( (char*)img.ptr + r*img.pitch, img.pitch );
}
if(!in.fail()) {
return img;
}
}
throw std::runtime_error("Unable to load PPM file.");
}
void SavePpm(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, bool top_line_first)
{
// Setup header variables
std::string ppm_type = "";
int num_colors = 0;
int w = (int)image.w;
int h = (int)image.h;
if(fmt.format == "GRAY8") {
ppm_type = "P5";
num_colors = 255;
}else if(fmt.format == "GRAY16LE") {
ppm_type = "P5";
num_colors = 65535;
}else if(fmt.format == "RGB24") {
ppm_type = "P6";
num_colors = 255;
}else{
throw std::runtime_error("Unsupported pixel format");
}
// Write header
out << ppm_type;
out << " ";
out << w;
out << " ";
out << h;
out << " ";
out << num_colors;
out << "\n";
// Write out data
if(top_line_first) {
for(size_t r=0; r<image.h; ++r) {
out.write( (char*)image.ptr + r*image.pitch, image.pitch );
}
}else{
for(size_t r=0; r<image.h; ++r) {
out.write( (char*)image.ptr + (image.h-1-r)*image.pitch, image.pitch );
}
}
}
}

View File

@@ -0,0 +1,25 @@
#include <fstream>
#include <pangolin/image/typed_image.h>
namespace pangolin {
TypedImage LoadImage(
const std::string& filename,
const PixelFormat& raw_fmt,
size_t raw_width, size_t raw_height, size_t raw_pitch
) {
TypedImage img(raw_width, raw_height, raw_fmt, raw_pitch);
// Read from file, row at a time.
std::ifstream bFile( filename.c_str(), std::ios::in | std::ios::binary );
for(size_t r=0; r<img.h; ++r) {
bFile.read( (char*)img.ptr + r*img.pitch, img.pitch );
if(bFile.fail()) {
pango_print_warn("Unable to read raw image file to completion.");
break;
}
}
return img;
}
}

View File

@@ -0,0 +1,53 @@
#include <pangolin/platform.h>
#include <pangolin/image/image_io.h>
namespace pangolin {
PixelFormat TgaFormat(int depth, int color_type, int color_map)
{
if(color_map == 0) {
if(color_type == 2) {
// Colour
if(depth == 24) {
return PixelFormatFromString("RGB24");
}else if(depth == 32) {
return PixelFormatFromString("RGBA32");
}
}else if(color_type == 3){
// Greyscale
if(depth == 8) {
return PixelFormatFromString("GRAY8");
}else if(depth == 16) {
return PixelFormatFromString("Y400A");
}
}
}
throw std::runtime_error("Unsupported TGA format");
}
TypedImage LoadTga(std::istream& in)
{
unsigned char type[4];
unsigned char info[6];
in.read((char*)type, 3*sizeof(char));
in.seekg(12);
in.read((char*)info,6*sizeof(char));
const int width = info[0] + (info[1] * 256);
const int height = info[2] + (info[3] * 256);
if(in.good()) {
TypedImage img(width, height, TgaFormat(info[4], type[2], type[1]) );
//read in image data
const size_t data_size = img.h * img.pitch;
in.read((char*)img.ptr, sizeof(char)*data_size);
return img;
}
throw std::runtime_error("Unable to load TGA file");
}
}

View File

@@ -0,0 +1,125 @@
#include <fstream>
#include <memory>
#include <pangolin/image/typed_image.h>
#ifdef HAVE_ZSTD
# include <zstd.h>
#endif
namespace pangolin {
#pragma pack(push, 1)
struct zstd_image_header
{
char magic[4];
char fmt[16];
size_t w, h;
};
#pragma pack(pop)
void SaveZstd(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level)
{
#ifdef HAVE_ZSTD
// Write out header, uncompressed
zstd_image_header header;
strncpy(header.magic,"ZSTD",4);
strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
header.w = image.w;
header.h = image.h;
out.write((char*)&header, sizeof(header));
// Write out image data
const size_t output_buffer_size = ZSTD_CStreamOutSize();
std::unique_ptr<char[]> output_buffer(new char[output_buffer_size]);
ZSTD_CStream* const cstream = ZSTD_createCStream();
if (cstream==nullptr) {
throw std::runtime_error("ZSTD_createCStream() error");
}
size_t const initResult = ZSTD_initCStream(cstream, compression_level);
if (ZSTD_isError(initResult)) {
throw std::runtime_error(FormatString("ZSTD_initCStream() error : %", ZSTD_getErrorName(initResult)));
}
const size_t row_size_bytes = (fmt.bpp * image.w)/8;
for(size_t y=0; y < image.h; ++y) {
ZSTD_inBuffer input = { image.RowPtr(y), row_size_bytes, 0 };
while (input.pos < input.size) {
ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
size_t left_to_read = ZSTD_compressStream(cstream, &output , &input);
if (ZSTD_isError(left_to_read)) {
throw std::runtime_error(FormatString("ZSTD_compressStream() error : %", ZSTD_getErrorName(left_to_read)));
}
out.write(output_buffer.get(), output.pos);
}
}
ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
size_t const remainingToFlush = ZSTD_endStream(cstream, &output); /* close frame */
if (remainingToFlush) {
throw std::runtime_error("not fully flushed");
}
out.write(output_buffer.get(), output.pos);
ZSTD_freeCStream(cstream);
#else
PANGOLIN_UNUSED(image);
PANGOLIN_UNUSED(fmt);
PANGOLIN_UNUSED(out);
PANGOLIN_UNUSED(compression_level);
throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
#endif // HAVE_ZSTD
}
TypedImage LoadZstd(std::istream& in)
{
#ifdef HAVE_ZSTD
// Read in header, uncompressed
zstd_image_header header;
in.read( (char*)&header, sizeof(header));
TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));
const size_t input_buffer_size = ZSTD_DStreamInSize();
std::unique_ptr<char[]> input_buffer(new char[input_buffer_size]);
ZSTD_DStream* dstream = ZSTD_createDStream();
if(!dstream) {
throw std::runtime_error("ZSTD_createDStream() error");
}
size_t read_size_hint = ZSTD_initDStream(dstream);
if (ZSTD_isError(read_size_hint)) {
throw std::runtime_error(FormatString("ZSTD_initDStream() error : % \n", ZSTD_getErrorName(read_size_hint)));
}
// Image represents our fixed buffer.
ZSTD_outBuffer output = { img.ptr, img.SizeBytes(), 0 };
while(read_size_hint)
{
const size_t read = in.readsome(input_buffer.get(), read_size_hint);
ZSTD_inBuffer input = { input_buffer.get(), read, 0 };
while (input.pos < input.size) {
read_size_hint = ZSTD_decompressStream(dstream, &output , &input);
if (ZSTD_isError(read_size_hint)) {
throw std::runtime_error(FormatString("ZSTD_decompressStream() error : %", ZSTD_getErrorName(read_size_hint)));
}
}
}
ZSTD_freeDStream(dstream);
return img;
#else
PANGOLIN_UNUSED(in);
throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
#endif // HAVE_ZSTD
}
}

View File

@@ -0,0 +1,70 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <pangolin/image/pixel_format.h>
#include <stdexcept>
#include <vector>
namespace pangolin
{
// Not to exceed 8 byte Format code.
const PixelFormat SupportedPixelFormats[] =
{
{"GRAY8", 1, {8}, 8, 8, false},
{"GRAY10", 1, {10}, 10, 10, false},
{"GRAY12", 1, {12}, 12, 12, false},
{"GRAY16LE", 1, {16}, 16, 16, false},
{"GRAY32", 1, {32}, 32, 32, false},
{"Y400A", 2, {8,8}, 16, 8, false},
{"RGB24", 3, {8,8,8}, 24, 8, false},
{"BGR24", 3, {8,8,8}, 24, 8, false},
{"RGB48", 3, {16,16,16}, 48, 16, false},
{"BGR48", 3, {16,16,16}, 48, 16, false},
{"YUYV422", 3, {4,2,2}, 16, 8, false},
{"UYVY422", 3, {4,2,2}, 16, 8, false},
{"RGBA32", 4, {8,8,8,8}, 32, 8, false},
{"BGRA32", 4, {8,8,8,8}, 32, 8, false},
{"RGBA64", 4, {16,16,16,16}, 64, 16, false},
{"BGRA64", 4, {16,16,16,16}, 64, 16, false},
{"GRAY32F", 1, {32}, 32, 32, false},
{"GRAY64F", 1, {64}, 64, 64, false},
{"RGB96F", 3, {32,32,32}, 96, 32, false},
{"RGBA128F", 4, {32,32,32,32}, 128, 32, false},
{"",0,{0,0,0,0},0,0,0}
};
PixelFormat PixelFormatFromString(const std::string& format)
{
for(int i=0; !SupportedPixelFormats[i].format.empty(); ++i)
if(!format.compare(SupportedPixelFormats[i].format))
return SupportedPixelFormats[i];
throw std::runtime_error( std::string("Unknown Format: ") + format);
}
}