4 #include "jpegloader.h"
10 struct ErrorManager: jpeg_error_mgr
16 void error_exit(j_common_ptr jpeg)
18 ErrorManager *err = reinterpret_cast<ErrorManager *>(jpeg->err);
19 char buf[JMSG_LENGTH_MAX];
20 err->format_message(jpeg, buf);
25 void emit_message(j_common_ptr, int)
30 struct SourceManager: jpeg_source_mgr
32 Msp::IO::Seekable *io;
36 void init_source(j_decompress_ptr jpeg)
38 SourceManager *src = reinterpret_cast<SourceManager *>(jpeg->src);
39 src->next_input_byte = src->buffer;
40 src->bytes_in_buffer = 0;
43 boolean fill_input_buffer(j_decompress_ptr jpeg)
45 SourceManager *src = reinterpret_cast<SourceManager *>(jpeg->src);
46 src->next_input_byte = src->buffer;
47 src->bytes_in_buffer = src->io->read(reinterpret_cast<char *>(src->buffer), sizeof(src->buffer));
51 void skip_input_data(j_decompress_ptr jpeg, long count)
56 SourceManager *src = reinterpret_cast<SourceManager *>(jpeg->src);
57 if(static_cast<unsigned long>(count)<src->bytes_in_buffer)
59 src->next_input_byte += count;
60 src->bytes_in_buffer -= count;
64 src->io->seek(count-src->bytes_in_buffer, Msp::IO::S_CUR);
65 src->bytes_in_buffer = 0;
69 void term_source(j_decompress_ptr)
79 struct JpegLoader::Private
81 jpeg_decompress_struct jpeg;
83 SourceManager src_mgr;
87 JpegLoader::JpegLoader(IO::Seekable &io):
90 priv->jpeg.err = jpeg_std_error(&priv->err_mgr);
91 priv->err_mgr.error_exit = &error_exit;
92 priv->err_mgr.emit_message = &emit_message;
94 if(setjmp(priv->err_mgr.jmp))
95 throw runtime_error("error creating jpeg decompressor: "+priv->err_mgr.message);
97 jpeg_create_decompress(&priv->jpeg);
99 priv->jpeg.src = &priv->src_mgr;
100 priv->src_mgr.init_source = &init_source;
101 priv->src_mgr.fill_input_buffer = &fill_input_buffer;
102 priv->src_mgr.skip_input_data = &skip_input_data;
103 priv->src_mgr.resync_to_restart = &jpeg_resync_to_restart;
104 priv->src_mgr.term_source = &term_source;
105 priv->src_mgr.io = &io;
108 JpegLoader::~JpegLoader()
110 jpeg_destroy_decompress(&priv->jpeg);
114 bool JpegLoader::detect(const string &sig)
116 static const char jpeg_sig[] = { '\xFF', '\xD8', '\xFF' };
117 if(sig.size()<sizeof(jpeg_sig))
119 return !sig.compare(0, sizeof(jpeg_sig), jpeg_sig, sizeof(jpeg_sig));
122 void JpegLoader::load(Image::Data &data)
124 if(setjmp(priv->err_mgr.jmp))
125 throw bad_image_data(priv->err_mgr.message);
127 jpeg_read_header(&priv->jpeg, TRUE);
128 priv->jpeg.out_color_space = JCS_RGB;
129 jpeg_start_decompress(&priv->jpeg);
131 data.width = priv->jpeg.output_width;
132 data.height = priv->jpeg.output_height;
133 data.stride = priv->jpeg.output_width*priv->jpeg.output_components;
136 data.pixels = new char[data.stride*data.height];
138 while(priv->jpeg.output_scanline<data.height)
140 unsigned y = data.height-priv->jpeg.output_scanline;
141 unsigned count = min(y, 8U);
142 for(unsigned i=0; i<count; ++i)
143 rows[i] = reinterpret_cast<JSAMPROW>(data.pixels+(y-i-1)*data.stride);
144 jpeg_read_scanlines(&priv->jpeg, rows, count);
147 jpeg_finish_decompress(&priv->jpeg);
150 } // namespace Graphics