00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 extern "C"
00026 {
00027 #include <jpeglib.h>
00028 }
00029
00030 namespace mapnik {
00031
00032 #define BUFFER_SIZE 4096
00033
00034 typedef struct
00035 {
00036 struct jpeg_destination_mgr pub;
00037 std::ostream * out;
00038 JOCTET * buffer;
00039 } dest_mgr;
00040
00041 inline void init_destination( j_compress_ptr cinfo)
00042 {
00043 dest_mgr * dest = reinterpret_cast<dest_mgr*>(cinfo->dest);
00044 dest->buffer = (JOCTET*) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00045 BUFFER_SIZE * sizeof(JOCTET));
00046 dest->pub.next_output_byte = dest->buffer;
00047 dest->pub.free_in_buffer = BUFFER_SIZE;
00048 }
00049
00050 inline boolean empty_output_buffer (j_compress_ptr cinfo)
00051 {
00052 dest_mgr * dest = reinterpret_cast<dest_mgr*>(cinfo->dest);
00053 dest->out->write((char*)dest->buffer, BUFFER_SIZE);
00054 if (!*(dest->out)) return false;
00055 dest->pub.next_output_byte = dest->buffer;
00056 dest->pub.free_in_buffer = BUFFER_SIZE;
00057 return true;
00058 }
00059
00060 inline void term_destination( j_compress_ptr cinfo)
00061 {
00062 dest_mgr * dest = reinterpret_cast<dest_mgr*>(cinfo->dest);
00063 size_t size = BUFFER_SIZE - dest->pub.free_in_buffer;
00064 if (size > 0)
00065 {
00066 dest->out->write((char*)dest->buffer, size);
00067 }
00068 dest->out->flush();
00069 }
00070
00071 template <typename T1, typename T2>
00072 void save_as_jpeg(T1 & file,int quality, T2 const& image)
00073 {
00074 struct jpeg_compress_struct cinfo;
00075 struct jpeg_error_mgr jerr;
00076
00077 int width=image.width();
00078 int height=image.height();
00079
00080 cinfo.err = jpeg_std_error(&jerr);
00081 jpeg_create_compress(&cinfo);
00082
00083 cinfo.dest = (struct jpeg_destination_mgr *)(*cinfo.mem->alloc_small)
00084 ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof(dest_mgr));
00085 dest_mgr * dest = (dest_mgr*) cinfo.dest;
00086 dest->pub.init_destination = init_destination;
00087 dest->pub.empty_output_buffer = empty_output_buffer;
00088 dest->pub.term_destination = term_destination;
00089 dest->out = &file;
00090
00091
00092 cinfo.image_width = width;
00093 cinfo.image_height = height;
00094 cinfo.input_components = 3;
00095 cinfo.in_color_space = JCS_RGB;
00096 jpeg_set_defaults(&cinfo);
00097 jpeg_set_quality(&cinfo, quality,1);
00098 jpeg_start_compress(&cinfo, 1);
00099 JSAMPROW row_pointer[1];
00100 JSAMPLE* row=reinterpret_cast<JSAMPLE*>( ::operator new (sizeof(JSAMPLE) * width*3));
00101 while (cinfo.next_scanline < cinfo.image_height)
00102 {
00103 const unsigned* imageRow=image.getRow(cinfo.next_scanline);
00104 int index=0;
00105 for (int i=0;i<width;++i)
00106 {
00107 row[index++]=(imageRow[i])&0xff;
00108 row[index++]=(imageRow[i]>>8)&0xff;
00109 row[index++]=(imageRow[i]>>16)&0xff;
00110 }
00111 row_pointer[0] = &row[0];
00112 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
00113 }
00114 ::operator delete(row);
00115
00116 jpeg_finish_compress(&cinfo);
00117 jpeg_destroy_compress(&cinfo);
00118 }
00119 }