#pragma once #include #include "jcmp_quantization.hpp" // joshua's compression :D namespace jcmp { typedef uint32_t uint; struct header { char signature[4]; uint width; uint height; uint length; quantization::parameters qp; header() = default; header(uint width_, uint height_, uint length_, quantization::parameters const & p) : signature{'J', 'C', 'M', 'P'} , width(width_) , height(height_) , length(length_) , qp(p) {} quantization::base get_quantization(quantization::type t){ return quantization::get(t, qp.f_max_abs, qp.f_min_abs, false); } }; struct __attribute__ ((__packed__)) coefficient { uint8_t c; uint x; uint y; }; struct image { header header; std::vector data; image() = default; image(uint width, uint height, quantization::parameters const & p, std::vector const & data_in) : header(width, height, data_in.size(), p) , data(data_in) {} void clear(){ header.length = header.height = header.width = 0; header.qp.f_max_abs = header.qp.f_min_abs = 0; data.clear(); } }; // Way of writing does not matter for performance // timings: http://i.imgur.com/cskC43O.png (300 points per method) // It's not surprising as filebuf is already a buffer inline void write_to_file(image const & image, std::string filename){ std::filebuf file; file.open(filename, std::ios_base::out|std::ios_base::trunc); file.sputn(reinterpret_cast(&image.header), sizeof(header)); file.sputn(reinterpret_cast(image.data.data()), image.data.size() * sizeof(coefficient)); } // Assumes Iterator points to a coefficient] // length in header is not used template inline void write_to_file(header h, Iterator begin, Iterator end, std::string filename){ h.length = 0; std::filebuf file; file.open(filename, std::ios_base::out|std::ios_base::trunc); file.sputn(reinterpret_cast(&h), sizeof(header)); while(begin != end){ file.sputn(reinterpret_cast(&*begin++), sizeof(coefficient)); h.length++; } // http://stackoverflow.com/questions/2530274/how-to-overwrite-only-part-of-a-file-in-c file.pubseekpos(0); file.sputn(reinterpret_cast(&h), sizeof(header)); } inline image read_from_file(std::string const& filename){ std::filebuf file; file.open(filename, std::ios_base::in); image image; file.sgetn(reinterpret_cast(&image.header), sizeof(header)); assert(strncmp("JCMP", image.header.signature, 4) == 0); image.data.resize(image.header.length); file.sgetn(reinterpret_cast(image.data.data()), image.data.size() * sizeof(coefficient)); return image; } static_assert(sizeof(header) == 32, "struct not propery packed"); static_assert(sizeof(coefficient) == 9, "struct not propery packed"); }