1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "image/image.hh"
|
---|
10 | #include "file/file.hh"
|
---|
11 | #include "status/status.hh"
|
---|
12 | #include "loaders/jpg/jpeglib.h"
|
---|
13 |
|
---|
14 |
|
---|
15 | boolean i4_jpg_empty(j_compress_ptr cinfo);
|
---|
16 | void i4_jpg_null(j_compress_ptr cinfo) { }
|
---|
17 | void i4_jpg_fin(j_compress_ptr cinfo);
|
---|
18 |
|
---|
19 | enum { JPG_BUF_SIZE=10*1024 };
|
---|
20 |
|
---|
21 | struct i4_jpg_write_mgr : public jpeg_destination_mgr
|
---|
22 | {
|
---|
23 | w8 buf[JPG_BUF_SIZE];
|
---|
24 | int size;
|
---|
25 | i4_file_class *fp;
|
---|
26 |
|
---|
27 | i4_jpg_write_mgr(i4_file_class *fp) : fp(fp)
|
---|
28 | {
|
---|
29 | init_destination=i4_jpg_null;
|
---|
30 | empty_output_buffer=i4_jpg_empty;
|
---|
31 | term_destination=i4_jpg_fin;
|
---|
32 |
|
---|
33 | next_output_byte=(JOCTET *)buf;
|
---|
34 | free_in_buffer=JPG_BUF_SIZE;
|
---|
35 | }
|
---|
36 | } *i4_current_jpg_write_mgr;
|
---|
37 |
|
---|
38 | boolean i4_jpg_empty(j_compress_ptr cinfo)
|
---|
39 | {
|
---|
40 | i4_jpg_write_mgr *m=i4_current_jpg_write_mgr;
|
---|
41 |
|
---|
42 | int ws=JPG_BUF_SIZE;
|
---|
43 | i4_current_jpg_write_mgr->fp->write(m->buf, ws);
|
---|
44 |
|
---|
45 | m->size+=ws;
|
---|
46 | m->next_output_byte=(JOCTET *)i4_current_jpg_write_mgr->buf;
|
---|
47 | m->free_in_buffer=JPG_BUF_SIZE;
|
---|
48 |
|
---|
49 | return TRUE;
|
---|
50 | }
|
---|
51 |
|
---|
52 |
|
---|
53 | void i4_jpg_fin(j_compress_ptr cinfo)
|
---|
54 | {
|
---|
55 | i4_jpg_write_mgr *m=i4_current_jpg_write_mgr;
|
---|
56 | int ws=(w8 *)m->next_output_byte-m->buf;
|
---|
57 | i4_current_jpg_write_mgr->fp->write(m->buf, ws);
|
---|
58 | }
|
---|
59 |
|
---|
60 | // return size of jpeg written
|
---|
61 | int i4_write_jpeg(i4_image_class *im,
|
---|
62 | i4_file_class *fp,
|
---|
63 | int quality, // 0..100
|
---|
64 | i4_status_class *status)
|
---|
65 | {
|
---|
66 | if (im->width()>4096)
|
---|
67 | return 0;
|
---|
68 |
|
---|
69 | /* This struct contains the JPEG compression parameters and pointers to
|
---|
70 | * working space (which is allocated as needed by the JPEG library).
|
---|
71 | * It is possible to have several such structures, representing multiple
|
---|
72 | * compression/decompression processes, in existence at once. We refer
|
---|
73 | * to any one struct (and its associated working data) as a "JPEG object".
|
---|
74 | */
|
---|
75 | struct jpeg_compress_struct cinfo;
|
---|
76 | /* This struct represents a JPEG error handler. It is declared separately
|
---|
77 | * because applications often want to supply a specialized error handler
|
---|
78 | * (see the second half of this file for an example). But here we just
|
---|
79 | * take the easy way out and use the standard error handler, which will
|
---|
80 | * print a message on stderr and call exit() if compression fails.
|
---|
81 | * Note that this struct must live as long as the main JPEG parameter
|
---|
82 | * struct, to avoid dangling-pointer problems.
|
---|
83 | */
|
---|
84 | struct jpeg_error_mgr jerr;
|
---|
85 | /* More stuff */
|
---|
86 |
|
---|
87 | /* Step 1: allocate and initialize JPEG compression object */
|
---|
88 |
|
---|
89 | /* We have to set up the error handler first, in case the initialization
|
---|
90 | * step fails. (Unlikely, but it could happen if you are out of memory.)
|
---|
91 | * This routine fills in the contents of struct jerr, and returns jerr's
|
---|
92 | * address which we place into the link field in cinfo.
|
---|
93 | */
|
---|
94 | cinfo.err = jpeg_std_error(&jerr);
|
---|
95 | /* Now we can initialize the JPEG compression object. */
|
---|
96 | jpeg_create_compress(&cinfo);
|
---|
97 |
|
---|
98 | /* Step 2: specify data destination (eg, a file) */
|
---|
99 | /* Note: steps 2 and 3 can be done in either order. */
|
---|
100 |
|
---|
101 |
|
---|
102 | i4_jpg_write_mgr write_mgr(fp);
|
---|
103 | i4_current_jpg_write_mgr=&write_mgr;
|
---|
104 |
|
---|
105 | cinfo.dest = &write_mgr;
|
---|
106 |
|
---|
107 |
|
---|
108 | /* Step 3: set parameters for compression */
|
---|
109 | /* First we supply a description of the input image.
|
---|
110 | * Four fields of the cinfo struct must be filled in:
|
---|
111 | */
|
---|
112 | cinfo.image_width = im->width(); /* image width and height, in pixels */
|
---|
113 | cinfo.image_height = im->height();
|
---|
114 | cinfo.input_components = 3; /* # of color components per pixel */
|
---|
115 | cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
---|
116 | /* Now use the library's routine to set default compression parameters.
|
---|
117 | * (You must set at least cinfo.in_color_space before calling this,
|
---|
118 | * since the defaults depend on the source color space.)
|
---|
119 | */
|
---|
120 | jpeg_set_defaults(&cinfo);
|
---|
121 | /* Now you can set any non-default parameters you wish to.
|
---|
122 | * Here we just illustrate the use of quality (quantization table) scaling:
|
---|
123 | */
|
---|
124 | jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
|
---|
125 |
|
---|
126 | /* Step 4: Start compressor */
|
---|
127 |
|
---|
128 | /* TRUE ensures that we will write a complete interchange-JPEG file.
|
---|
129 | * Pass TRUE unless you are very sure of what you're doing.
|
---|
130 | */
|
---|
131 | jpeg_start_compress(&cinfo, TRUE);
|
---|
132 |
|
---|
133 | /* Step 5: while (scan lines remain to be written) */
|
---|
134 | /* jpeg_write_scanlines(...); */
|
---|
135 |
|
---|
136 |
|
---|
137 | w8 buf[4096*3];
|
---|
138 |
|
---|
139 | int im_w=im->width();
|
---|
140 |
|
---|
141 | while (cinfo.next_scanline < cinfo.image_height)
|
---|
142 | {
|
---|
143 | if (status)
|
---|
144 | status->update((float)cinfo.next_scanline/cinfo.image_height);
|
---|
145 |
|
---|
146 | JSAMPROW scanline[1]={buf};
|
---|
147 | w8 *c=buf;
|
---|
148 |
|
---|
149 | for (int x=0; x<im_w; x++)
|
---|
150 | {
|
---|
151 | i4_color color=im->get_pixel(x, cinfo.next_scanline);
|
---|
152 | c[0]=(color>>16)&0xff;
|
---|
153 | c[1]=(color>>8)&0xff;
|
---|
154 | c[2]=(color)&0xff;
|
---|
155 | c+=3;
|
---|
156 | }
|
---|
157 | jpeg_write_scanlines(&cinfo, scanline, 1);
|
---|
158 | }
|
---|
159 |
|
---|
160 | /* Step 6: Finish compression */
|
---|
161 |
|
---|
162 | jpeg_finish_compress(&cinfo);
|
---|
163 |
|
---|
164 | /* Step 7: release JPEG compression object */
|
---|
165 |
|
---|
166 | /* This is an important step since it will release a good deal of memory. */
|
---|
167 | jpeg_destroy_compress(&cinfo);
|
---|
168 |
|
---|
169 |
|
---|
170 | return write_mgr.size;
|
---|
171 | /* And we're done! */
|
---|
172 | }
|
---|