// // jpg.hpp // ImageStreams // // Created by Joshua Moerman on 9/15/12. // Copyright (c) 2012 Vadovas. All rights reserved. // #ifndef ImageStreams_jpg_hpp #define ImageStreams_jpg_hpp #include #include #include #include #include "basics.hpp" /* JPEG only supports 8bits or 24bits per pixel (eg grayscale or full color). Top to bottom */ namespace jpg{ template J_COLOR_SPACE color_space(){ int num_colors = pixel_formats::traits

::num_colors; switch (num_colors) { case 1: return JCS_GRAYSCALE; case 3: return JCS_RGB; default: return JCS_UNKNOWN; } } template struct ostream{ typedef P pixel; ostream() = delete; ostream(ostream const &) = delete; ostream & operator=(ostream const &) = delete; ostream(uint32_t width, uint32_t height, std::string filename) : fp(0) , cinfo() , jerr() , row(width) , x(0) { fp = fopen(filename.c_str(), "wb"); if(!fp) throw std::runtime_error("Could not open file"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, fp); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = pixel_formats::traits::num_colors; cinfo.in_color_space = color_space(); jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 95, true); // quality in [0, 100], boolean indicates "force_baseline" (only matters when quality < 25) jpeg_start_compress(&cinfo, true); // true means we will write completely } ~ostream(){ jpeg_finish_compress(&cinfo); fclose(fp); jpeg_destroy_compress(&cinfo); } ostream& operator<<(pixel const & p){ row[x] = p; ++x; if(x >= row.size()){ // this will return the number of scanlines written unsigned char * ptr = reinterpret_cast(row.data()); jpeg_write_scanlines(&cinfo, &ptr, 1); x = 0; } return *this; } private: FILE* fp; jpeg_compress_struct cinfo; jpeg_error_mgr jerr; std::vector row; uint32_t x; }; typedef ostream<> colored_ostream; typedef ostream gray_ostream; } #endif