Canola
0.8.D001
|
00001 // 00002 // canola - canon canola 1614p emulator 00003 // Copyright (C) 2011 Peter Miller 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License, version 3, as 00007 // published by the Free Software Foundation. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License along 00015 // with this program. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include <lib/ac/stdio.h> 00019 #include <lib/ac/string.h> 00020 #include <libexplain/fclose.h> 00021 #include <libexplain/fopen.h> 00022 #include <jpeglib.h> 00023 00024 #include <lib/image/format/jpeg.h> 00025 00026 00027 image_format_jpeg::~image_format_jpeg() 00028 { 00029 } 00030 00031 00032 image_format_jpeg::image_format_jpeg(int a_width, int a_height) : 00033 image_format(a_width, a_height) 00034 { 00035 } 00036 00037 00038 image_format_jpeg::image_format_jpeg( 00039 int a_width, 00040 int a_height, 00041 data_t *a_data 00042 ) : 00043 image_format(a_width, a_height, a_data) 00044 { 00045 } 00046 00047 00048 const char * 00049 image_format_jpeg::type_name(void) 00050 const 00051 { 00052 return "JPEG"; 00053 } 00054 00055 00056 image::pointer 00057 image_format_jpeg::create(const std::string &filename) 00058 { 00059 jpeg_decompress_struct cinfo; 00060 jpeg_error_mgr jerr; 00061 cinfo.err = jpeg_std_error(&jerr); 00062 jpeg_create_decompress(&cinfo); 00063 00064 // 00065 // tell the jpeg library where to get its input from 00066 // 00067 FILE *fp = explain_fopen_or_die(filename.c_str(), "rb"); 00068 jpeg_stdio_src(&cinfo, fp); 00069 00070 // 00071 // read the file header 00072 // 00073 jpeg_read_header(&cinfo, TRUE); 00074 00075 // tell the decompress we want RGB data 00076 cinfo.out_color_space = JCS_RGB; 00077 cinfo.quantize_colors = false; 00078 00079 jpeg_start_decompress(&cinfo); 00080 int width = cinfo.output_width; 00081 int height = cinfo.output_height; 00082 00083 size_t rgba_row_stride = width * 4; 00084 size_t rgba_data_size = height * rgba_row_stride; 00085 data_t *rgba_data = new data_t [rgba_data_size]; 00086 00087 int row_stride = width * cinfo.output_components; 00088 JSAMPLE *buffer = new JSAMPLE [row_stride]; 00089 00090 for (int y = 0; y < height; ++y) 00091 { 00092 // 00093 // jpeg_read_scanlines expects an array of pointers to scanlines. 00094 // Here the array is only one element long, but you could ask for 00095 // more than one scanline at a time if that's more convenient. 00096 // 00097 jpeg_read_scanlines(&cinfo, &buffer, 1); 00098 00099 // 00100 // Transfer the RGB row into an RGBA row 00101 // 00102 JSAMPLE *ip = buffer; 00103 data_t *op = rgba_data + y * rgba_row_stride; 00104 for (int x = 0; x < width; ++x) 00105 { 00106 *op++ = *ip++; 00107 *op++ = *ip++; 00108 *op++ = *ip++; 00109 *op++ = 255; 00110 } 00111 } 00112 delete buffer; 00113 00114 // 00115 // All done, release the resources. 00116 // 00117 jpeg_finish_decompress(&cinfo); 00118 explain_fclose_or_die(fp); 00119 00120 // 00121 // Create the object. 00122 // 00123 return pointer(new image_format_jpeg(width, height, rgba_data)); 00124 } 00125 00126 00127 void 00128 image_format_jpeg::save_to_file(const std::string &filename) 00129 const 00130 { 00131 // 00132 // create file 00133 // 00134 FILE *fp = explain_fopen_or_die(filename.c_str(), "wb"); 00135 00136 jpeg_compress_struct cinfo; 00137 memset(&cinfo, 0, sizeof(cinfo)); 00138 jpeg_error_mgr jerr; 00139 memset(&jerr, 0, sizeof(jerr)); 00140 cinfo.err = jpeg_std_error(&jerr); 00141 jpeg_create_compress(&cinfo); 00142 jpeg_stdio_dest(&cinfo, fp); 00143 cinfo.image_width = get_width(); 00144 cinfo.image_height = get_height(); 00145 cinfo.input_components = 3; 00146 cinfo.in_color_space = JCS_RGB; 00147 jpeg_set_defaults(&cinfo); 00148 jpeg_set_quality(&cinfo, 100, 1); 00149 jpeg_start_compress(&cinfo, 1); 00150 00151 // 00152 // Write each scan line, one at a time 00153 JSAMPLE *rowbuf = new JSAMPLE [cinfo.image_width * 3]; 00154 while (cinfo.next_scanline < cinfo.image_height) 00155 { 00156 const data_t *ip = get_data(cinfo.next_scanline); 00157 JSAMPLE *op = rowbuf; 00158 for (size_t x = 0; x < cinfo.image_width; ++x) 00159 { 00160 // turn RGBA data into RGB data 00161 *op++ = *ip++; 00162 *op++ = *ip++; 00163 *op++ = *ip++; 00164 ++ip; 00165 } 00166 jpeg_write_scanlines(&cinfo, &rowbuf, 1); 00167 } 00168 delete rowbuf; 00169 jpeg_finish_compress(&cinfo); 00170 jpeg_destroy_compress(&cinfo); 00171 00172 explain_fclose_or_die(fp); 00173 } 00174 00175 00176 image::pointer 00177 image_format_jpeg::create_blank(int width, int height) 00178 { 00179 return pointer(new image_format_jpeg(width, height)); 00180 }