DEADSOFTWARE

hopefully no more windows
[d2df-editor.git] / src / lib / vampimg / JpegLib / imjcmainct.pas
1 unit imjcmainct;
3 { This file contains the main buffer controller for compression.
4 The main buffer lies between the pre-processor and the JPEG
5 compressor proper; it holds downsampled data in the JPEG colorspace. }
7 { Original : jcmainct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
9 interface
11 {$I imjconfig.inc}
13 { Note: currently, there is no operating mode in which a full-image buffer
14 is needed at this step. If there were, that mode could not be used with
15 "raw data" input, since this module is bypassed in that case. However,
16 we've left the code here for possible use in special applications. }
18 {$undef FULL_MAIN_BUFFER_SUPPORTED}
20 uses
21 imjmorecfg,
22 imjinclude,
23 imjdeferr,
24 imjerror,
25 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
26 imjutils,
27 {$endif}
28 imjpeglib;
30 { Initialize main buffer controller. }
32 {GLOBAL}
33 procedure jinit_c_main_controller (cinfo : j_compress_ptr;
34 need_full_buffer : boolean);
36 implementation
39 { Private buffer controller object }
41 type
42 my_main_ptr = ^my_main_controller;
43 my_main_controller = record
44 pub : jpeg_c_main_controller; { public fields }
46 cur_iMCU_row : JDIMENSION; { number of current iMCU row }
47 rowgroup_ctr : JDIMENSION; { counts row groups received in iMCU row }
48 suspended : boolean; { remember if we suspended output }
49 pass_mode : J_BUF_MODE; { current operating mode }
51 { If using just a strip buffer, this points to the entire set of buffers
52 (we allocate one for each component). In the full-image case, this
53 points to the currently accessible strips of the virtual arrays. }
55 buffer : array[0..MAX_COMPONENTS-1] of JSAMPARRAY;
57 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
58 { If using full-image storage, this array holds pointers to virtual-array
59 control blocks for each component. Unused if not full-image storage. }
61 whole_image : array[0..MAX_COMPONENTS-1] of jvirt_sarray_ptr;
62 {$endif}
63 end; {my_main_controller}
66 { Forward declarations }
67 {METHODDEF}
68 procedure process_data_simple_main(cinfo : j_compress_ptr;
69 input_buf : JSAMPARRAY;
70 var in_row_ctr: JDIMENSION;
71 in_rows_avail : JDIMENSION); forward;
73 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
74 {METHODDEF}
75 procedure process_data_buffer_main(cinfo : j_compress_ptr;
76 input_buf : JSAMPARRAY;
77 var in_row_ctr : JDIMENSION;
78 in_rows_avail : JDIMENSION); forward;
79 {$endif}
82 { Initialize for a processing pass. }
84 {METHODDEF}
85 procedure start_pass_main (cinfo : j_compress_ptr;
86 pass_mode : J_BUF_MODE);
87 var
88 main : my_main_ptr;
89 begin
90 main := my_main_ptr (cinfo^.main);
92 { Do nothing in raw-data mode. }
93 if (cinfo^.raw_data_in) then
94 exit;
96 main^.cur_iMCU_row := 0; { initialize counters }
97 main^.rowgroup_ctr := 0;
98 main^.suspended := FALSE;
99 main^.pass_mode := pass_mode; { save mode for use by process_data }
101 case (pass_mode) of
102 JBUF_PASS_THRU:
103 begin
104 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
105 if (main^.whole_image[0] <> NIL) then
106 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
107 {$endif}
108 main^.pub.process_data := process_data_simple_main;
109 end;
110 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
111 JBUF_SAVE_SOURCE,
112 JBUF_CRANK_DEST,
113 JBUF_SAVE_AND_PASS:
114 begin
115 if (main^.whole_image[0] = NIL) then
116 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
117 main^.pub.process_data := process_data_buffer_main;
118 end;
119 {$endif}
120 else
121 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
122 end;
123 end;
126 { Process some data.
127 This routine handles the simple pass-through mode,
128 where we have only a strip buffer. }
130 {METHODDEF}
131 procedure process_data_simple_main (cinfo : j_compress_ptr;
132 input_buf : JSAMPARRAY;
133 var in_row_ctr : JDIMENSION;
134 in_rows_avail : JDIMENSION);
135 var
136 main : my_main_ptr;
137 begin
138 main := my_main_ptr (cinfo^.main);
140 while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do
141 begin
142 { Read input data if we haven't filled the main buffer yet }
143 if (main^.rowgroup_ctr < DCTSIZE) then
144 cinfo^.prep^.pre_process_data (cinfo,
145 input_buf,
146 in_row_ctr,
147 in_rows_avail,
148 JSAMPIMAGE(@main^.buffer),
149 main^.rowgroup_ctr,
150 JDIMENSION(DCTSIZE));
152 { If we don't have a full iMCU row buffered, return to application for
153 more data. Note that preprocessor will always pad to fill the iMCU row
154 at the bottom of the image. }
155 if (main^.rowgroup_ctr <> DCTSIZE) then
156 exit;
158 { Send the completed row to the compressor }
159 if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(@main^.buffer))) then
160 begin
161 { If compressor did not consume the whole row, then we must need to
162 suspend processing and return to the application. In this situation
163 we pretend we didn't yet consume the last input row; otherwise, if
164 it happened to be the last row of the image, the application would
165 think we were done. }
167 if (not main^.suspended) then
168 begin
169 Dec(in_row_ctr);
170 main^.suspended := TRUE;
171 end;
172 exit;
173 end;
174 { We did finish the row. Undo our little suspension hack if a previous
175 call suspended; then mark the main buffer empty. }
177 if (main^.suspended) then
178 begin
179 Inc(in_row_ctr);
180 main^.suspended := FALSE;
181 end;
182 main^.rowgroup_ctr := 0;
183 Inc(main^.cur_iMCU_row);
184 end;
185 end;
188 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
190 { Process some data.
191 This routine handles all of the modes that use a full-size buffer. }
193 {METHODDEF}
194 procedure process_data_buffer_main (cinfo : j_compress_ptr;
195 input_buf : JSAMPARRAY;
196 var in_row_ctr : JDIMENSION;
197 in_rows_avail : JDIMENSION);
198 var
199 main : my_main_ptr;
200 ci : int;
201 compptr : jpeg_component_info_ptr;
202 writing : boolean;
203 begin
204 main := my_main_ptr (cinfo^.main);
205 writing := (main^.pass_mode <> JBUF_CRANK_DEST);
207 while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do
208 begin
209 { Realign the virtual buffers if at the start of an iMCU row. }
210 if (main^.rowgroup_ctr = 0) then
211 begin
212 compptr := cinfo^.comp_info;
213 for ci := 0 to pred(cinfo^.num_components) do
214 begin
215 main^.buffer[ci] := cinfo^.mem^.access_virt_sarray
216 (j_common_ptr (cinfo), main^.whole_image[ci],
217 main^.cur_iMCU_row * (compptr^.v_samp_factor * DCTSIZE),
218 JDIMENSION (compptr^.v_samp_factor * DCTSIZE), writing);
219 Inc(compptr);
220 end;
221 { In a read pass, pretend we just read some source data. }
222 if (not writing) then
223 begin
224 Inc(in_row_ctr, cinfo^.max_v_samp_factor * DCTSIZE);
225 main^.rowgroup_ctr := DCTSIZE;
226 end;
227 end;
229 { If a write pass, read input data until the current iMCU row is full. }
230 { Note: preprocessor will pad if necessary to fill the last iMCU row. }
231 if (writing) then
232 begin
233 cinfo^.prep^.pre_process_data (cinfo,
234 input_buf, in_row_ctr, in_rows_avail,
235 JSAMPIMAGE(@main^.buffer),
236 main^.rowgroup_ctr,
237 JDIMENSION (DCTSIZE));
239 { Return to application if we need more data to fill the iMCU row. }
240 if (main^.rowgroup_ctr < DCTSIZE) then
241 exit;
242 end;
244 { Emit data, unless this is a sink-only pass. }
245 if (main^.pass_mode <> JBUF_SAVE_SOURCE) then
246 begin
247 if (not cinfo^.coef^.compress_data (cinfo,
248 JSAMPIMAGE(@main^.buffer))) then
249 begin
250 { If compressor did not consume the whole row, then we must need to
251 suspend processing and return to the application. In this situation
252 we pretend we didn't yet consume the last input row; otherwise, if
253 it happened to be the last row of the image, the application would
254 think we were done. }
256 if (not main^.suspended) then
257 begin
258 Dec(in_row_ctr);
259 main^.suspended := TRUE;
260 end;
261 exit;
262 end;
263 { We did finish the row. Undo our little suspension hack if a previous
264 call suspended; then mark the main buffer empty. }
266 if (main^.suspended) then
267 begin
268 Inc(in_row_ctr);
269 main^.suspended := FALSE;
270 end;
271 end;
273 { If get here, we are done with this iMCU row. Mark buffer empty. }
274 main^.rowgroup_ctr := 0;
275 Inc(main^.cur_iMCU_row);
276 end;
277 end;
279 {$endif} { FULL_MAIN_BUFFER_SUPPORTED }
282 { Initialize main buffer controller. }
284 {GLOBAL}
285 procedure jinit_c_main_controller (cinfo : j_compress_ptr;
286 need_full_buffer : boolean);
287 var
288 main : my_main_ptr;
289 ci : int;
290 compptr : jpeg_component_info_ptr;
291 begin
292 main := my_main_ptr(
293 cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
294 SIZEOF(my_main_controller)) );
295 cinfo^.main := jpeg_c_main_controller_ptr(main);
296 main^.pub.start_pass := start_pass_main;
298 { We don't need to create a buffer in raw-data mode. }
299 if (cinfo^.raw_data_in) then
300 exit;
302 { Create the buffer. It holds downsampled data, so each component
303 may be of a different size. }
305 if (need_full_buffer) then
306 begin
307 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
308 { Allocate a full-image virtual array for each component }
309 { Note we pad the bottom to a multiple of the iMCU height }
310 compptr := cinfo^.comp_info;
311 for ci := 0 to pred(cinfo^.num_components) do
312 begin
313 main^.whole_image[ci] := cinfo^.mem^.request_virt_sarray
314 (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE,
315 compptr^.width_in_blocks * DCTSIZE,
316 JDIMENSION (jround_up( long (compptr^.height_in_blocks),
317 long (compptr^.v_samp_factor)) * DCTSIZE),
318 JDIMENSION (compptr^.v_samp_factor * DCTSIZE));
319 Inc(compptr);
320 end;
321 {$else}
322 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
323 {$endif}
324 end
325 else
326 begin
327 {$ifdef FULL_MAIN_BUFFER_SUPPORTED}
328 main^.whole_image[0] := NIL; { flag for no virtual arrays }
329 {$endif}
330 { Allocate a strip buffer for each component }
331 compptr := jpeg_component_info_ptr(cinfo^.comp_info);
332 for ci := 0 to pred(cinfo^.num_components) do
333 begin
334 main^.buffer[ci] := cinfo^.mem^.alloc_sarray
335 (j_common_ptr(cinfo), JPOOL_IMAGE,
336 compptr^.width_in_blocks * DCTSIZE,
337 JDIMENSION (compptr^.v_samp_factor * DCTSIZE));
338 Inc(compptr);
339 end;
340 end;
341 end;
343 end.