JPEG and PNG code taken out of image.cpp
[wxWidgets.git] / src / common / imagjpeg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: imagjpeg.cpp
3 // Purpose: wxImage JPEG handler
4 // Author: Robert Roebling
5 // RCS-ID: $Id$
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "image.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/image.h"
22 #include "wx/bitmap.h"
23 #include "wx/debug.h"
24 #include "wx/log.h"
25 #include "wx/app.h"
26 #if wxUSE_LIBJPEG
27 extern "C" {
28 #include <jpeglib.h>
29 }
30 #endif
31 #include "wx/filefn.h"
32 #include "wx/wfstream.h"
33 #include "wx/intl.h"
34 #include "wx/module.h"
35
36 // For memcpy
37 #include <string.h>
38
39 #ifdef __SALFORDC__
40 #ifdef FAR
41 #undef FAR
42 #endif
43 #endif
44
45 #ifdef __WXMSW__
46 #include <windows.h>
47 #endif
48
49 //-----------------------------------------------------------------------------
50 // wxJPEGHandler
51 //-----------------------------------------------------------------------------
52
53 #if wxUSE_LIBJPEG
54
55 #if !USE_SHARED_LIBRARIES
56 IMPLEMENT_DYNAMIC_CLASS(wxJPEGHandler,wxImageHandler)
57 #endif
58
59 #if wxUSE_STREAMS
60
61
62 //------------- JPEG Data Source Manager
63
64 typedef struct {
65 struct jpeg_source_mgr pub; /* public fields */
66
67 JOCTET* buffer; /* start of buffer */
68 } my_source_mgr;
69
70 typedef my_source_mgr * my_src_ptr;
71
72 METHODDEF(void) my_init_source ( j_decompress_ptr cinfo )
73 {
74 }
75
76 METHODDEF(boolean) my_fill_input_buffer ( j_decompress_ptr cinfo )
77 {
78 return TRUE;
79 }
80
81 METHODDEF(void) my_skip_input_data ( j_decompress_ptr cinfo, long num_bytes )
82 {
83 my_src_ptr src = (my_src_ptr) cinfo->src;
84
85 src->pub.next_input_byte += (size_t) num_bytes;
86 src->pub.bytes_in_buffer -= (size_t) num_bytes;
87 }
88
89 METHODDEF(void) my_term_source ( j_decompress_ptr cinfo )
90 {
91 my_src_ptr src = (my_src_ptr) cinfo->src;
92
93 free (src->buffer);
94 }
95
96 void jpeg_wxio_src( j_decompress_ptr cinfo, wxInputStream& infile )
97 {
98 my_src_ptr src;
99
100 if (cinfo->src == NULL) { /* first time for this JPEG object? */
101 cinfo->src = (struct jpeg_source_mgr *)
102 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
103 sizeof(my_source_mgr));
104 src = (my_src_ptr) cinfo->src;
105 }
106 src = (my_src_ptr) cinfo->src;
107 src->pub.bytes_in_buffer = infile.StreamSize(); /* forces fill_input_buffer on first read */
108 src->buffer = (JOCTET *) malloc (infile.StreamSize());
109 src->pub.next_input_byte = src->buffer; /* until buffer loaded */
110 infile.Read(src->buffer, infile.StreamSize());
111
112 src->pub.init_source = my_init_source;
113 src->pub.fill_input_buffer = my_fill_input_buffer;
114 src->pub.skip_input_data = my_skip_input_data;
115 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
116 src->pub.term_source = my_term_source;
117 }
118
119
120
121 bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream )
122 {
123 struct jpeg_decompress_struct cinfo;
124 struct jpeg_error_mgr jerr;
125 JSAMPARRAY tempbuf;
126 unsigned char *ptr;
127 unsigned stride;
128
129 image->Destroy();
130 cinfo.err = jpeg_std_error( &jerr );
131 jpeg_create_decompress( &cinfo );
132 jpeg_wxio_src( &cinfo, stream );
133 jpeg_read_header( &cinfo, TRUE );
134 cinfo.out_color_space = JCS_RGB;
135 jpeg_start_decompress( &cinfo );
136
137 image->Create( cinfo.image_width, cinfo.image_height );
138 if (!image->Ok()) {
139 jpeg_finish_decompress( &cinfo );
140 jpeg_destroy_decompress( &cinfo );
141 return FALSE;
142 }
143 image->SetMask( FALSE );
144 ptr = image->GetData();
145 stride = cinfo.output_width * 3;
146 tempbuf = (*cinfo.mem->alloc_sarray)
147 ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 );
148
149 while ( cinfo.output_scanline < cinfo.output_height ) {
150 jpeg_read_scanlines( &cinfo, tempbuf, 1 );
151 memcpy( ptr, tempbuf[0], stride );
152 ptr += stride;
153 }
154 jpeg_finish_decompress( &cinfo );
155 jpeg_destroy_decompress( &cinfo );
156 return TRUE;
157 }
158
159
160
161
162
163 typedef struct {
164 struct jpeg_destination_mgr pub;
165
166 wxOutputStream *stream;
167 JOCTET * buffer;
168 } my_destination_mgr;
169
170 typedef my_destination_mgr * my_dest_ptr;
171
172 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
173
174 METHODDEF(void) init_destination (j_compress_ptr cinfo)
175 {
176 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
177
178 /* Allocate the output buffer --- it will be released when done with image */
179 dest->buffer = (JOCTET *)
180 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
181 OUTPUT_BUF_SIZE * sizeof(JOCTET));
182 dest->pub.next_output_byte = dest->buffer;
183 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
184 }
185
186 METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
187 {
188 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
189
190 dest->stream->Write(dest->buffer, OUTPUT_BUF_SIZE);
191 dest->pub.next_output_byte = dest->buffer;
192 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
193 return TRUE;
194 }
195
196 METHODDEF(void) term_destination (j_compress_ptr cinfo)
197 {
198 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
199 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
200 /* Write any data remaining in the buffer */
201 if (datacount > 0)
202 dest->stream->Write(dest->buffer, datacount);
203 }
204
205 GLOBAL(void) jpeg_wxio_dest (j_compress_ptr cinfo, wxOutputStream& outfile)
206 {
207 my_dest_ptr dest;
208
209 if (cinfo->dest == NULL) { /* first time for this JPEG object? */
210 cinfo->dest = (struct jpeg_destination_mgr *)
211 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
212 sizeof(my_destination_mgr));
213 }
214
215 dest = (my_dest_ptr) cinfo->dest;
216 dest->pub.init_destination = init_destination;
217 dest->pub.empty_output_buffer = empty_output_buffer;
218 dest->pub.term_destination = term_destination;
219 dest->stream = &outfile;
220 }
221
222 bool wxJPEGHandler::SaveFile( wxImage *image, wxOutputStream& stream )
223 {
224 struct jpeg_compress_struct cinfo;
225 struct jpeg_error_mgr jerr;
226 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
227 JSAMPLE *image_buffer;
228 int stride; /* physical row width in image buffer */
229
230 cinfo.err = jpeg_std_error(&jerr);
231 jpeg_create_compress(&cinfo);
232 jpeg_wxio_dest(&cinfo, stream);
233
234 cinfo.image_width = image->GetWidth();
235 cinfo.image_height = image->GetHeight();
236 cinfo.input_components = 3;
237 cinfo.in_color_space = JCS_RGB;
238 jpeg_set_defaults(&cinfo);
239 jpeg_start_compress(&cinfo, TRUE);
240
241 stride = cinfo.image_width * 3; /* JSAMPLEs per row in image_buffer */
242 image_buffer = image->GetData();
243 while (cinfo.next_scanline < cinfo.image_height) {
244 row_pointer[0] = &image_buffer[cinfo.next_scanline * stride];
245 jpeg_write_scanlines( &cinfo, row_pointer, 1 );
246 }
247 jpeg_finish_compress(&cinfo);
248 jpeg_destroy_compress(&cinfo);
249
250 return TRUE;
251 }
252 #endif // wxUSE_STREAMS
253
254 #endif
255
256 // wxUSE_LIBJPEG
257