2 #include "fitz-stream.h"
6 typedef struct fz_dcte_s fz_dcte
;
10 struct jpeg_destination_mgr super
;
18 struct jpeg_compress_struct cinfo
;
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 */ }
33 fz_newdcte(fz_filter
**fp
, fz_obj
*params
)
39 FZ_NEWFILTER(fz_dcte
, e
, dcte
);
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
);
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
);
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
);
55 /* setup error callback first thing */
57 e
->cinfo
.err
= (struct jpeg_error_mgr
*) &e
->err
;
59 if (setjmp(e
->err
.jb
)) {
60 err
= fz_throw("ioerror in dcte: %s", e
->err
.msg
);
65 jpeg_create_compress(&e
->cinfo
);
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
;
73 e
->dst
.super
.next_output_byte
= nil
;
74 e
->dst
.super
.free_in_buffer
= 0;
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
;
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;
88 jpeg_set_defaults(&e
->cinfo
);
90 /* FIXME check this */
91 obj
= fz_dictgets(params
, "ColorTransform");
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
);
102 obj
= fz_dictgets(params
, "HSamples");
103 if (obj
&& fz_isarray(obj
)) {
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
);
111 obj
= fz_dictgets(params
, "VSamples");
112 if (obj
&& fz_isarray(obj
)) {
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
);
120 /* TODO: quant-tables and huffman-tables */
126 fz_dropdcte(fz_filter
*filter
)
128 fz_dcte
*e
= (fz_dcte
*)filter
;
130 if (setjmp(e
->err
.jb
)) {
131 fprintf(stderr
, "ioerror in dcte: jpeg_destroy_compress: %s", e
->err
.msg
);
135 jpeg_destroy_compress(&e
->cinfo
);
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
[] =
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
154 #define unzigzag(x) (x)
158 fz_setquanttables(fz_dcte
*e
, unsigned int **qtables
, int qfactor
)
161 unsigned int table
[64];
163 if (setjmp(e
->err
.jb
)) {
164 return fz_throw("ioerror in dcte: %s", e
->err
.msg
);
167 /* TODO: check for duplicate tables */
169 for (i
= 0; i
< e
->colors
; i
++) {
170 for (j
= 0; j
< 64; j
++) {
171 table
[j
] = unzigzag(qtables
[i
][j
]);
173 jpeg_add_quant_table(&e
->cinfo
, i
, table
, qfactor
, TRUE
);
174 e
->cinfo
.comp_info
[i
].quant_tbl_no
= i
;
181 fz_processdcte(fz_filter
*filter
, fz_buffer
*in
, fz_buffer
*out
)
183 fz_dcte
*e
= (fz_dcte
*)filter
;
184 JSAMPROW scanline
[1];
189 e
->dst
.super
.free_in_buffer
= out
->ep
- out
->wp
;
190 e
->dst
.super
.next_output_byte
= out
->wp
;
192 if (setjmp(e
->err
.jb
)) {
193 return fz_throw("ioerror in dcte: %s", e
->err
.msg
);
199 /* must have enough space for markers, typically 600 bytes or so */
200 if (out
->wp
+ 1024 > out
->ep
)
203 jpeg_start_compress(&e
->cinfo
, TRUE
);
205 /* TODO: write Adobe ColorTransform marker */
211 stride
= e
->columns
* e
->colors
;
213 while (e
->cinfo
.next_scanline
< e
->cinfo
.image_height
)
215 if (in
->rp
+ stride
> in
->wp
)
218 scanline
[0] = in
->rp
;
220 i
= jpeg_write_scanlines(&e
->cinfo
, scanline
, 1);
232 /* must have enough space for end markers */
233 if (out
->wp
+ 100 > out
->ep
)
236 /* finish compress cannot suspend! */
237 jpeg_finish_compress(&e
->cinfo
);
241 out
->wp
= out
->ep
- e
->dst
.super
.free_in_buffer
;
246 out
->wp
= out
->ep
- e
->dst
.super
.free_in_buffer
;
250 out
->wp
= out
->ep
- e
->dst
.super
.free_in_buffer
;