1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
Unit jutils;
{ This file contains tables and miscellaneous utility routines needed
for both compression and decompression.
Note we prefix all global names with "j" to minimize conflicts with
a surrounding application. }
{ Source: jutils.c; Copyright (C) 1991-1996, Thomas G. Lane. }
interface
{$I jconfig.inc}
uses
jmorecfg,
jinclude,
jpeglib;
{ jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
of a DCT block read in natural order (left to right, top to bottom). }
{$ifdef FALSE} { This table is not actually needed in v6a }
const
jpeg_zigzag_order : array[0..DCTSIZE2] of int =
(0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63);
{$endif}
{ jpeg_natural_order[i] is the natural-order position of the i'th element
of zigzag order.
When reading corrupted data, the Huffman decoders could attempt
to reference an entry beyond the end of this array (if the decoded
zero run length reaches past the end of the block). To prevent
wild stores without adding an inner-loop test, we put some extra
"63"s after the real entries. This will cause the extra coefficient
to be stored in location 63 of the block, not somewhere random.
The worst case would be a run-length of 15, which means we need 16
fake entries. }
const
jpeg_natural_order : array[0..DCTSIZE2+16-1] of int =
(0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63,
63, 63, 63, 63, 63, 63, 63, 63, { extra entries for safety in decoder }
63, 63, 63, 63, 63, 63, 63, 63);
{ Arithmetic utilities }
{GLOBAL}
function jdiv_round_up (a : long; b : long) : long;
{GLOBAL}
function jround_up (a : long; b : long) : long;
{GLOBAL}
procedure jcopy_sample_rows (input_array : JSAMPARRAY;
source_row : int;
output_array : JSAMPARRAY; dest_row : int;
num_rows : int; num_cols : JDIMENSION);
{GLOBAL}
procedure jcopy_block_row (input_row : JBLOCKROW;
output_row : JBLOCKROW;
num_blocks : JDIMENSION);
{GLOBAL}
procedure jzero_far (target : pointer;{far} bytestozero : size_t);
procedure FMEMZERO(target : pointer; size : size_t);
procedure FMEMCOPY(dest,src : pointer; size : size_t);
implementation
{GLOBAL}
function jdiv_round_up (a : long; b : long) : long;
{ Compute a/b rounded up to next integer, ie, ceil(a/b) }
{ Assumes a >= 0, b > 0 }
begin
jdiv_round_up := (a + b - long(1)) div b;
end;
{GLOBAL}
function jround_up (a : long; b : long) : long;
{ Compute a rounded up to next multiple of b, ie, ceil(a/b)*b }
{ Assumes a >= 0, b > 0 }
begin
Inc(a, b - long(1));
jround_up := a - (a mod b);
end;
{ On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
and coefficient-block arrays. This won't work on 80x86 because the arrays
are FAR and we're assuming a small-pointer memory model. However, some
DOS compilers provide far-pointer versions of memcpy() and memset() even
in the small-model libraries. These will be used if USE_FMEM is defined.
Otherwise, the routines below do it the hard way. (The performance cost
is not all that great, because these routines aren't very heavily used.) }
{$ifndef NEED_FAR_POINTERS} { normal case, same as regular macros }
procedure FMEMZERO(target : pointer; size : size_t);
begin
FillChar(target^, size, 0);
end;
procedure FMEMCOPY(dest,src : pointer; size : size_t);
begin
Move(src^, dest^, size);
end;
{$else} { 80x86 case, define if we can }
{$ifdef USE_FMEM}
FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
{$endif}
{$endif}
{GLOBAL}
procedure jcopy_sample_rows (input_array : JSAMPARRAY; source_row : int;
output_array : JSAMPARRAY; dest_row : int;
num_rows : int; num_cols : JDIMENSION);
{ Copy some rows of samples from one place to another.
num_rows rows are copied from input_array[source_row++]
to output_array[dest_row++]; these areas may overlap for duplication.
The source and destination arrays must be at least as wide as num_cols. }
var
inptr, outptr : JSAMPLE_PTR; {register}
{$ifdef FMEMCOPY}
count : size_t; {register}
{$else}
count : JDIMENSION; {register}
{$endif}
row : int; {register}
begin
{$ifdef FMEMCOPY}
count := size_t(num_cols * SIZEOF(JSAMPLE));
{$endif}
Inc(JSAMPROW_PTR(input_array), source_row);
Inc(JSAMPROW_PTR(output_array), dest_row);
for row := pred(num_rows) downto 0 do
begin
inptr := JSAMPLE_PTR(input_array^[0]);
Inc(JSAMPROW_PTR(input_array));
outptr := JSAMPLE_PTR(output_array^[0]);
Inc(JSAMPROW_PTR(output_array));
{$ifdef FMEMCOPY}
FMEMCOPY(outptr, inptr, count);
{$else}
for count := pred(num_cols) downto 0 do
begin
outptr^ := inptr^; { needn't bother with GETJSAMPLE() here }
Inc(inptr);
Inc(outptr);
end;
{$endif}
end;
end;
{GLOBAL}
procedure jcopy_block_row (input_row : JBLOCKROW;
output_row : JBLOCKROW;
num_blocks : JDIMENSION);
{ Copy a row of coefficient blocks from one place to another. }
{$ifdef FMEMCOPY}
begin
FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
{$else}
var
inptr, outptr : JCOEFPTR; {register}
count : long; {register}
begin
inptr := JCOEFPTR (input_row);
outptr := JCOEFPTR (output_row);
for count := long(num_blocks) * DCTSIZE2 -1 downto 0 do
begin
outptr^ := inptr^;
Inc(outptr);
Inc(inptr);
end;
{$endif}
end;
{GLOBAL}
procedure jzero_far (target : pointer;{far} bytestozero : size_t);
{ Zero out a chunk of FAR memory. }
{ This might be sample-array data, block-array data, or alloc_large data. }
{$ifdef FMEMZERO}
begin
FMEMZERO(target, bytestozero);
{$else}
var
ptr : byteptr;
count : size_t; {register}
begin
ptr := target;
for count := bytestozero-1 downto 0 do
begin
ptr^ := 0;
Inc(ptr);
end;
{$endif}
end;
end.
|