📄 jquant1.pas
字号:
input_buf : JSAMPARRAY;
output_buf : JSAMPARRAY;
num_rows : int); far;
{ Fast path for out_color_components=3, with ordered dithering }
var
cquantize : my_cquantize_ptr;
pixcode : int; {register}
input_ptr : JSAMPLE_PTR; {register}
output_ptr : JSAMPLE_PTR; {register}
colorindex0 : JSAMPROW;
colorindex1 : JSAMPROW;
colorindex2 : JSAMPROW;
dither0 : ^ODITHER_vector; { points to active row of dither matrix }
dither1 : ^ODITHER_vector;
dither2 : ^ODITHER_vector;
row_index, col_index : int; { current indexes into dither matrix }
row : int;
col : JDIMENSION;
width : JDIMENSION;
var
pad_offset : int;
begin
cquantize := my_cquantize_ptr (cinfo^.cquantize);
colorindex0 := (cquantize^.colorindex)^[0];
colorindex1 := (cquantize^.colorindex)^[1];
colorindex2 := (cquantize^.colorindex)^[2];
width := cinfo^.output_width;
{ Nomssi: work around negative offset }
if my_cquantize_ptr (cinfo^.cquantize)^.is_padded then
pad_offset := MAXJSAMPLE
else
pad_offset := 0;
Dec(JSAMPLE_PTR(colorindex0), pad_offset);
Dec(JSAMPLE_PTR(colorindex1), pad_offset);
Dec(JSAMPLE_PTR(colorindex2), pad_offset);
for row := 0 to pred(num_rows) do
begin
row_index := cquantize^.row_index;
input_ptr := JSAMPLE_PTR(input_buf^[row]);
output_ptr := JSAMPLE_PTR(output_buf^[row]);
dither0 := @(cquantize^.odither[0]^[row_index]);
dither1 := @(cquantize^.odither[1]^[row_index]);
dither2 := @(cquantize^.odither[2]^[row_index]);
col_index := 0;
for col := pred(width) downto 0 do
begin
pixcode := GETJSAMPLE(colorindex0^[GETJSAMPLE(input_ptr^) + pad_offset
+ dither0^[col_index]]);
Inc(input_ptr);
Inc(pixcode, GETJSAMPLE(colorindex1^[GETJSAMPLE(input_ptr^) + pad_offset
+ dither1^[col_index]]));
Inc(input_ptr);
Inc(pixcode, GETJSAMPLE(colorindex2^[GETJSAMPLE(input_ptr^) + pad_offset
+ dither2^[col_index]]));
Inc(input_ptr);
output_ptr^ := JSAMPLE (pixcode);
Inc(output_ptr);
col_index := (col_index + 1) and ODITHER_MASK;
end;
row_index := (row_index + 1) and ODITHER_MASK;
cquantize^.row_index := row_index;
end;
end;
{METHODDEF}
procedure quantize_fs_dither (cinfo : j_decompress_ptr;
input_buf : JSAMPARRAY;
output_buf : JSAMPARRAY;
num_rows : int); far;
{ General case, with Floyd-Steinberg dithering }
var
cquantize : my_cquantize_ptr;
cur : LOCFSERROR; {register} { current error or pixel value }
belowerr : LOCFSERROR; { error for pixel below cur }
bpreverr : LOCFSERROR; { error for below/prev col }
bnexterr : LOCFSERROR; { error for below/next col }
delta : LOCFSERROR;
prev_errorptr,
errorptr : FSERRORPTR; {register} { => fserrors[] at column before current }
input_ptr, {register}
output_ptr : JSAMPLE_PTR; {register}
colorindex_ci : JSAMPROW;
colormap_ci : JSAMPROW;
pixcode : int;
nc : int;
dir : int; { 1 for left-to-right, -1 for right-to-left }
dirnc : int; { dir * nc }
ci : int;
row : int;
col : JDIMENSION;
width : JDIMENSION;
range_limit : range_limit_table_ptr;
begin
cquantize := my_cquantize_ptr (cinfo^.cquantize);
nc := cinfo^.out_color_components;
width := cinfo^.output_width;
range_limit := cinfo^.sample_range_limit;
for row := 0 to pred(num_rows) do
begin
{ Initialize output values to 0 so can process components separately }
jzero_far( (output_buf)^[row],
size_t(width * SIZEOF(JSAMPLE)));
for ci := 0 to pred(nc) do
begin
input_ptr := JSAMPLE_PTR(@ input_buf^[row]^[ci]);
output_ptr := JSAMPLE_PTR(output_buf^[row]);
errorptr := FSERRORPTR(cquantize^.fserrors[ci]); { => entry before first column }
if (cquantize^.on_odd_row) then
begin
{ work right to left in this row }
Inc(input_ptr, (width-1) * nc); { so point to rightmost pixel }
Inc(output_ptr, width-1);
dir := -1;
dirnc := -nc;
Inc(errorptr, (width+1)); { => entry after last column }
end
else
begin
{ work left to right in this row }
dir := 1;
dirnc := nc;
{errorptr := cquantize^.fserrors[ci];}
end;
colorindex_ci := cquantize^.colorindex^[ci];
colormap_ci := (cquantize^.sv_colormap)^[ci];
{ Preset error values: no error propagated to first pixel from left }
cur := 0;
{ and no error propagated to row below yet }
belowerr := 0;
bpreverr := 0;
for col := pred(width) downto 0 do
begin
prev_errorptr := errorptr;
Inc(errorptr, dir); { advance errorptr to current column }
{ cur holds the error propagated from the previous pixel on the
current line. Add the error propagated from the previous line
to form the complete error correction term for this pixel, and
round the error term (which is expressed * 16) to an integer.
RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
for either sign of the error value.
Note: errorptr points to *previous* column's array entry. }
cur := (cur + errorptr^ + 8) div 16;
{ Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
The maximum error is +- MAXJSAMPLE; this sets the required size
of the range_limit array. }
Inc( cur, GETJSAMPLE(input_ptr^));
cur := GETJSAMPLE(range_limit^[cur]);
{ Select output value, accumulate into output code for this pixel }
pixcode := GETJSAMPLE(colorindex_ci^[cur]);
Inc(output_ptr^, JSAMPLE (pixcode));
{ Compute actual representation error at this pixel }
{ Note: we can do this even though we don't have the final }
{ pixel code, because the colormap is orthogonal. }
Dec(cur, GETJSAMPLE(colormap_ci^[pixcode]));
{ Compute error fractions to be propagated to adjacent pixels.
Add these into the running sums, and simultaneously shift the
next-line error sums left by 1 column. }
bnexterr := cur;
delta := cur * 2;
Inc(cur, delta); { form error * 3 }
prev_errorptr^ := FSERROR (bpreverr + cur);
Inc(cur, delta); { form error * 5 }
bpreverr := belowerr + cur;
belowerr := bnexterr;
Inc(cur, delta); { form error * 7 }
{ At this point cur contains the 7/16 error value to be propagated
to the next pixel on the current line, and all the errors for the
next line have been shifted over. We are therefore ready to move on. }
Inc(input_ptr, dirnc); { advance input ptr to next column }
Inc(output_ptr, dir); { advance output ptr to next column }
end;
{ Post-loop cleanup: we must unload the final error value into the
final fserrors[] entry. Note we need not unload belowerr because
it is for the dummy column before or after the actual array. }
errorptr^ := FSERROR (bpreverr); { unload prev err into array }
{ Nomssi : ?? }
end;
cquantize^.on_odd_row := not cquantize^.on_odd_row;
end;
end;
{ Allocate workspace for Floyd-Steinberg errors. }
{LOCAL}
procedure alloc_fs_workspace (cinfo : j_decompress_ptr);
var
cquantize : my_cquantize_ptr;
arraysize : size_t;
i : int;
begin
cquantize := my_cquantize_ptr (cinfo^.cquantize);
arraysize := size_t ((cinfo^.output_width + 2) * SIZEOF(FSERROR));
for i := 0 to pred(cinfo^.out_color_components) do
begin
cquantize^.fserrors[i] := FS_ERROR_FIELD_PTR(
cinfo^.mem^.alloc_large(j_common_ptr(cinfo), JPOOL_IMAGE, arraysize));
end;
end;
{ Initialize for one-pass color quantization. }
{METHODDEF}
procedure start_pass_1_quant (cinfo : j_decompress_ptr;
is_pre_scan : boolean); far;
var
cquantize : my_cquantize_ptr;
arraysize : size_t;
i : int;
begin
cquantize := my_cquantize_ptr (cinfo^.cquantize);
{ Install my colormap. }
cinfo^.colormap := cquantize^.sv_colormap;
cinfo^.actual_number_of_colors := cquantize^.sv_actual;
{ Initialize for desired dithering mode. }
case (cinfo^.dither_mode) of
JDITHER_NONE:
if (cinfo^.out_color_components = 3) then
cquantize^.pub.color_quantize := color_quantize3
else
cquantize^.pub.color_quantize := color_quantize;
JDITHER_ORDERED:
begin
if (cinfo^.out_color_components = 3) then
cquantize^.pub.color_quantize := quantize3_ord_dither
else
cquantize^.pub.color_quantize := quantize_ord_dither;
cquantize^.row_index := 0; { initialize state for ordered dither }
{ If user changed to ordered dither from another mode,
we must recreate the color index table with padding.
This will cost extra space, but probably isn't very likely. }
if (not cquantize^.is_padded) then
create_colorindex(cinfo);
{ Create ordered-dither tables if we didn't already. }
if (cquantize^.odither[0] = NIL) then
create_odither_tables(cinfo);
end;
JDITHER_FS:
begin
cquantize^.pub.color_quantize := quantize_fs_dither;
cquantize^.on_odd_row := FALSE; { initialize state for F-S dither }
{ Allocate Floyd-Steinberg workspace if didn't already. }
if (cquantize^.fserrors[0] = NIL) then
alloc_fs_workspace(cinfo);
{ Initialize the propagated errors to zero. }
arraysize := size_t ((cinfo^.output_width + 2) * SIZEOF(FSERROR));
for i := 0 to pred(cinfo^.out_color_components) do
jzero_far({far} pointer( cquantize^.fserrors[i] ), arraysize);
end;
else
ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
end;
end;
{ Finish up at the end of the pass. }
{METHODDEF}
procedure finish_pass_1_quant (cinfo : j_decompress_ptr); far;
begin
{ no work in 1-pass case }
end;
{ Switch to a new external colormap between output passes.
Shouldn't get to this module! }
{METHODDEF}
procedure new_color_map_1_quant (cinfo : j_decompress_ptr); far;
begin
ERREXIT(j_common_ptr(cinfo), JERR_MODE_CHANGE);
end;
{ Module initialization routine for 1-pass color quantization. }
{GLOBAL}
procedure jinit_1pass_quantizer (cinfo : j_decompress_ptr);
var
cquantize : my_cquantize_ptr;
begin
cquantize := my_cquantize_ptr(
cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
SIZEOF(my_cquantizer)));
cinfo^.cquantize := jpeg_color_quantizer_ptr(cquantize);
cquantize^.pub.start_pass := start_pass_1_quant;
cquantize^.pub.finish_pass := finish_pass_1_quant;
cquantize^.pub.new_color_map := new_color_map_1_quant;
cquantize^.fserrors[0] := NIL; { Flag FS workspace not allocated }
cquantize^.odither[0] := NIL; { Also flag odither arrays not allocated }
{ Make sure my internal arrays won't overflow }
if (cinfo^.out_color_components > MAX_Q_COMPS) then
ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
{ Make sure colormap indexes can be represented by JSAMPLEs }
if (cinfo^.desired_number_of_colors > (MAXJSAMPLE+1)) then
ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
{ Create the colormap and color index table. }
create_colormap(cinfo);
create_colorindex(cinfo);
{ Allocate Floyd-Steinberg workspace now if requested.
We do this now since it is FAR storage and may affect the memory
manager's space calculations. If the user changes to FS dither
mode in a later pass, we will allocate the space then, and will
possibly overrun the max_memory_to_use setting. }
if (cinfo^.dither_mode = JDITHER_FS) then
alloc_fs_workspace(cinfo);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -