Change the translation of the "Help" menu item to "?", so that the menu can be displa...
[reactos.git] / rosapps / smartpdf / fitz / stream / filt_dcte.c
1 #include "fitz-base.h"
2 #include "fitz-stream.h"
3
4 #include "filt_dctc.h"
5
6 typedef struct fz_dcte_s fz_dcte;
7
8 struct mydstmgr
9 {
10 struct jpeg_destination_mgr super;
11 fz_buffer *buf;
12 };
13
14 struct fz_dcte_s
15 {
16 fz_filter super;
17
18 struct jpeg_compress_struct cinfo;
19 struct mydstmgr dst;
20 struct myerrmgr err;
21 int stage;
22
23 int columns;
24 int rows;
25 int colors;
26 };
27
28 static void myinitdest(j_compress_ptr cinfo) { /* empty */ }
29 static boolean myemptybuf(j_compress_ptr cinfo) { return FALSE; }
30 static void mytermdest(j_compress_ptr cinfo) { /* empty */ }
31
32 fz_error *
33 fz_newdcte(fz_filter **fp, fz_obj *params)
34 {
35 fz_error *err;
36 fz_obj *obj;
37 int i;
38
39 FZ_NEWFILTER(fz_dcte, e, dcte);
40
41 e->stage = 0;
42
43 obj = fz_dictgets(params, "Columns");
44 if (!obj) { fz_free(e); return fz_throw("ioerror in dcte: missing Columns parameter"); }
45 e->columns = fz_toint(obj);
46
47 obj = fz_dictgets(params, "Rows");
48 if (!obj) { fz_free(e); return fz_throw("ioerror in dcte: missing Rows parameter"); }
49 e->rows = fz_toint(obj);
50
51 obj = fz_dictgets(params, "Colors");
52 if (!obj) { fz_free(e); return fz_throw("ioerror in dcte: missing Colors parameter"); }
53 e->colors = fz_toint(obj);
54
55 /* setup error callback first thing */
56 myiniterr(&e->err);
57 e->cinfo.err = (struct jpeg_error_mgr*) &e->err;
58
59 if (setjmp(e->err.jb)) {
60 err = fz_throw("ioerror in dcte: %s", e->err.msg);
61 fz_free(e);
62 return err;
63 }
64
65 jpeg_create_compress(&e->cinfo);
66
67 /* prepare destination manager */
68 e->cinfo.dest = (struct jpeg_destination_mgr *) &e->dst;
69 e->dst.super.init_destination = myinitdest;
70 e->dst.super.empty_output_buffer = myemptybuf;
71 e->dst.super.term_destination = mytermdest;
72
73 e->dst.super.next_output_byte = nil;
74 e->dst.super.free_in_buffer = 0;
75
76 /* prepare required encoding options */
77 e->cinfo.image_width = e->columns;
78 e->cinfo.image_height = e->rows;
79 e->cinfo.input_components = e->colors;
80
81 switch (e->colors) {
82 case 1: e->cinfo.in_color_space = JCS_GRAYSCALE; break;
83 case 3: e->cinfo.in_color_space = JCS_RGB; break;
84 case 4: e->cinfo.in_color_space = JCS_CMYK; break;
85 default: e->cinfo.in_color_space = JCS_UNKNOWN; break;
86 }
87
88 jpeg_set_defaults(&e->cinfo);
89
90 /* FIXME check this */
91 obj = fz_dictgets(params, "ColorTransform");
92 if (obj) {
93 int colortransform = fz_toint(obj);
94 if (e->colors == 3 && !colortransform)
95 jpeg_set_colorspace(&e->cinfo, JCS_RGB);
96 if (e->colors == 4 && colortransform)
97 jpeg_set_colorspace(&e->cinfo, JCS_YCCK);
98 if (e->colors == 4 && !colortransform)
99 jpeg_set_colorspace(&e->cinfo, JCS_CMYK);
100 }
101
102 obj = fz_dictgets(params, "HSamples");
103 if (obj && fz_isarray(obj)) {
104 fz_obj *o;
105 for (i = 0; i < e->colors; i++) {
106 o = fz_arrayget(obj, i);
107 e->cinfo.comp_info[i].h_samp_factor = fz_toint(o);
108 }
109 }
110
111 obj = fz_dictgets(params, "VSamples");
112 if (obj && fz_isarray(obj)) {
113 fz_obj *o;
114 for (i = 0; i < e->colors; i++) {
115 o = fz_arrayget(obj, i);
116 e->cinfo.comp_info[i].v_samp_factor = fz_toint(o);
117 }
118 }
119
120 /* TODO: quant-tables and huffman-tables */
121
122 return nil;
123 }
124
125 void
126 fz_dropdcte(fz_filter *filter)
127 {
128 fz_dcte *e = (fz_dcte*)filter;
129
130 if (setjmp(e->err.jb)) {
131 fprintf(stderr, "ioerror in dcte: jpeg_destroy_compress: %s", e->err.msg);
132 return;
133 }
134
135 jpeg_destroy_compress(&e->cinfo);
136 }
137
138 /* Adobe says zigzag order. IJG > v6a says natural order. */
139 #if JPEG_LIB_VERSION >= 61
140 #define unzigzag(x) unzigzagorder[x]
141 /* zigzag array position of n'th element of natural array order */
142 static const unsigned char unzigzagorder[] =
143 {
144 0, 1, 5, 6, 14, 15, 27, 28,
145 2, 4, 7, 13, 16, 26, 29, 42,
146 3, 8, 12, 17, 25, 30, 41, 43,
147 9, 11, 18, 24, 31, 40, 44, 53,
148 10, 19, 23, 32, 39, 45, 52, 54,
149 20, 22, 33, 38, 46, 51, 55, 60,
150 21, 34, 37, 47, 50, 56, 59, 61,
151 35, 36, 48, 49, 57, 58, 62, 63
152 };
153 #else
154 #define unzigzag(x) (x)
155 #endif
156
157 fz_error *
158 fz_setquanttables(fz_dcte *e, unsigned int **qtables, int qfactor)
159 {
160 int i, j;
161 unsigned int table[64];
162
163 if (setjmp(e->err.jb)) {
164 return fz_throw("ioerror in dcte: %s", e->err.msg);
165 }
166
167 /* TODO: check for duplicate tables */
168
169 for (i = 0; i < e->colors; i++) {
170 for (j = 0; j < 64; j++) {
171 table[j] = unzigzag(qtables[i][j]);
172 }
173 jpeg_add_quant_table(&e->cinfo, i, table, qfactor, TRUE);
174 e->cinfo.comp_info[i].quant_tbl_no = i;
175 }
176
177 return nil;
178 }
179
180 fz_error *
181 fz_processdcte(fz_filter *filter, fz_buffer *in, fz_buffer *out)
182 {
183 fz_dcte *e = (fz_dcte*)filter;
184 JSAMPROW scanline[1];
185 int stride;
186 int i;
187
188 e->dst.buf = out;
189 e->dst.super.free_in_buffer = out->ep - out->wp;
190 e->dst.super.next_output_byte = out->wp;
191
192 if (setjmp(e->err.jb)) {
193 return fz_throw("ioerror in dcte: %s", e->err.msg);
194 }
195
196 switch (e->stage)
197 {
198 case 0:
199 /* must have enough space for markers, typically 600 bytes or so */
200 if (out->wp + 1024 > out->ep)
201 goto needoutput;
202
203 jpeg_start_compress(&e->cinfo, TRUE);
204
205 /* TODO: write Adobe ColorTransform marker */
206
207 /* fall through */
208 e->stage = 1;
209
210 case 1:
211 stride = e->columns * e->colors;
212
213 while (e->cinfo.next_scanline < e->cinfo.image_height)
214 {
215 if (in->rp + stride > in->wp)
216 goto needinput;
217
218 scanline[0] = in->rp;
219
220 i = jpeg_write_scanlines(&e->cinfo, scanline, 1);
221
222 if (i == 0)
223 goto needoutput;
224
225 in->rp += stride;
226 }
227
228 /* fall through */
229 e->stage = 2;
230
231 case 2:
232 /* must have enough space for end markers */
233 if (out->wp + 100 > out->ep)
234 goto needoutput;
235
236 /* finish compress cannot suspend! */
237 jpeg_finish_compress(&e->cinfo);
238
239 e->stage = 3;
240 out->eof = 1;
241 out->wp = out->ep - e->dst.super.free_in_buffer;
242 return fz_iodone;
243 }
244
245 needinput:
246 out->wp = out->ep - e->dst.super.free_in_buffer;
247 return fz_ioneedin;
248
249 needoutput:
250 out->wp = out->ep - e->dst.super.free_in_buffer;
251 return fz_ioneedout;
252 }
253