📄 jmemmgr.pas
字号:
bptr : jvirt_barray_ptr;
begin
mem := my_mem_ptr (cinfo^.mem);
{ Compute the minimum space needed (maxaccess rows in each buffer)
and the maximum space needed (full image height in each buffer).
These may be of use to the system-dependent jpeg_mem_available routine. }
space_per_minheight := 0;
maximum_space := 0;
sptr := mem^.virt_sarray_list;
while (sptr <> NIL) do
begin
if (sptr^.mem_buffer = NIL) then
begin { if not realized yet }
Inc(space_per_minheight, long(sptr^.maxaccess) *
long(sptr^.samplesperrow) * SIZEOF(JSAMPLE));
Inc(maximum_space, long(sptr^.rows_in_array) *
long(sptr^.samplesperrow) * SIZEOF(JSAMPLE));
end;
sptr := sptr^.next;
end;
bptr := mem^.virt_barray_list;
while (bptr <> NIL) do
begin
if (bptr^.mem_buffer = NIL) then
begin { if not realized yet }
Inc(space_per_minheight, long(bptr^.maxaccess) *
long(bptr^.blocksperrow) * SIZEOF(JBLOCK));
Inc(maximum_space, long(bptr^.rows_in_array) *
long(bptr^.blocksperrow) * SIZEOF(JBLOCK));
end;
bptr := bptr^.next;
end;
if (space_per_minheight <= 0) then
exit; { no unrealized arrays, no work }
{ Determine amount of memory to actually use; this is system-dependent. }
avail_mem := jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
mem^.total_space_allocated);
{ If the maximum space needed is available, make all the buffers full
height; otherwise parcel it out with the same number of minheights
in each buffer. }
if (avail_mem >= maximum_space) then
max_minheights := long(1000000000)
else
begin
max_minheights := avail_mem div space_per_minheight;
{ If there doesn't seem to be enough space, try to get the minimum
anyway. This allows a "stub" implementation of jpeg_mem_available(). }
if (max_minheights <= 0) then
max_minheights := 1;
end;
{ Allocate the in-memory buffers and initialize backing store as needed. }
sptr := mem^.virt_sarray_list;
while (sptr <> NIL) do
begin
if (sptr^.mem_buffer = NIL) then
begin { if not realized yet }
minheights := (long(sptr^.rows_in_array) - long(1)) div sptr^.maxaccess + long(1);
if (minheights <= max_minheights) then
begin
{ This buffer fits in memory }
sptr^.rows_in_mem := sptr^.rows_in_array;
end
else
begin
{ It doesn't fit in memory, create backing store. }
sptr^.rows_in_mem := JDIMENSION (max_minheights * sptr^.maxaccess);
jpeg_open_backing_store(cinfo,
@sptr^.b_s_info,
long(sptr^.rows_in_array) *
long(sptr^.samplesperrow) *
long(SIZEOF(JSAMPLE)));
sptr^.b_s_open := TRUE;
end;
sptr^.mem_buffer := alloc_sarray(cinfo, JPOOL_IMAGE,
sptr^.samplesperrow, sptr^.rows_in_mem);
sptr^.rowsperchunk := mem^.last_rowsperchunk;
sptr^.cur_start_row := 0;
sptr^.first_undef_row := 0;
sptr^.dirty := FALSE;
end;
sptr := sptr^.next;
end;
bptr := mem^.virt_barray_list;
while (bptr <> NIL) do
begin
if (bptr^.mem_buffer = NIL) then
begin { if not realized yet }
minheights := (long(bptr^.rows_in_array) - long(1)) div bptr^.maxaccess + long(1);
if (minheights <= max_minheights) then
begin
{ This buffer fits in memory }
bptr^.rows_in_mem := bptr^.rows_in_array;
end
else
begin
{ It doesn't fit in memory, create backing store. }
bptr^.rows_in_mem := JDIMENSION (max_minheights * bptr^.maxaccess);
jpeg_open_backing_store(cinfo,
@bptr^.b_s_info,
long(bptr^.rows_in_array) *
long(bptr^.blocksperrow) *
long(SIZEOF(JBLOCK)));
bptr^.b_s_open := TRUE;
end;
bptr^.mem_buffer := alloc_barray(cinfo, JPOOL_IMAGE,
bptr^.blocksperrow, bptr^.rows_in_mem);
bptr^.rowsperchunk := mem^.last_rowsperchunk;
bptr^.cur_start_row := 0;
bptr^.first_undef_row := 0;
bptr^.dirty := FALSE;
end;
bptr := bptr^.next;
end;
end;
{LOCAL}
procedure do_sarray_io (cinfo : j_common_ptr;
ptr : jvirt_sarray_ptr;
writing : boolean);
{ Do backing store read or write of a virtual sample array }
var
bytesperrow, file_offset, byte_count, rows, thisrow, i : long;
begin
bytesperrow := long(ptr^.samplesperrow * SIZEOF(JSAMPLE));
file_offset := ptr^.cur_start_row * bytesperrow;
{ Loop to read or write each allocation chunk in mem_buffer }
i := 0;
while i < long(ptr^.rows_in_mem) do
begin
{ One chunk, but check for short chunk at end of buffer }
{rows := MIN(long(ptr^.rowsperchunk), long(ptr^.rows_in_mem - i));}
rows := long(ptr^.rowsperchunk);
if rows > long(ptr^.rows_in_mem - i) then
rows := long(ptr^.rows_in_mem - i);
{ Transfer no more than is currently defined }
thisrow := long (ptr^.cur_start_row) + i;
{rows := MIN(rows, long(ptr^.first_undef_row) - thisrow);}
if (rows > long(ptr^.first_undef_row) - thisrow) then
rows := long(ptr^.first_undef_row) - thisrow;
{ Transfer no more than fits in file }
{rows := MIN(rows, long(ptr^.rows_in_array) - thisrow);}
if (rows > long(ptr^.rows_in_array) - thisrow) then
rows := long(ptr^.rows_in_array) - thisrow;
if (rows <= 0) then { this chunk might be past end of file! }
break;
byte_count := rows * bytesperrow;
if (writing) then
ptr^.b_s_info.write_backing_store (cinfo,
@ptr^.b_s_info,
pointer {FAR} (ptr^.mem_buffer^[i]),
file_offset, byte_count)
else
ptr^.b_s_info.read_backing_store (cinfo,
@ptr^.b_s_info,
pointer {FAR} (ptr^.mem_buffer^[i]),
file_offset, byte_count);
Inc(file_offset, byte_count);
Inc(i, ptr^.rowsperchunk);
end;
end;
{LOCAL}
procedure do_barray_io (cinfo : j_common_ptr;
ptr : jvirt_barray_ptr;
writing : boolean);
{ Do backing store read or write of a virtual coefficient-block array }
var
bytesperrow, file_offset, byte_count, rows, thisrow, i : long;
begin
bytesperrow := long (ptr^.blocksperrow) * SIZEOF(JBLOCK);
file_offset := ptr^.cur_start_row * bytesperrow;
{ Loop to read or write each allocation chunk in mem_buffer }
i := 0;
while (i < long(ptr^.rows_in_mem)) do
begin
{ One chunk, but check for short chunk at end of buffer }
{rows := MIN(long(ptr^.rowsperchunk), long(ptr^.rows_in_mem - i));}
rows := long(ptr^.rowsperchunk);
if rows >long(ptr^.rows_in_mem - i) then
rows := long(ptr^.rows_in_mem - i);
{ Transfer no more than is currently defined }
thisrow := long (ptr^.cur_start_row) + i;
{rows := MIN(rows, long(ptr^.first_undef_row - thisrow));}
if rows > long(ptr^.first_undef_row - thisrow) then
rows := long(ptr^.first_undef_row - thisrow);
{ Transfer no more than fits in file }
{rows := MIN(rows, long (ptr^.rows_in_array - thisrow));}
if (rows > long (ptr^.rows_in_array - thisrow)) then
rows := long (ptr^.rows_in_array - thisrow);
if (rows <= 0) then { this chunk might be past end of file! }
break;
byte_count := rows * bytesperrow;
if (writing) then
ptr^.b_s_info.write_backing_store (cinfo,
@ptr^.b_s_info,
{FAR} pointer(ptr^.mem_buffer^[i]),
file_offset, byte_count)
else
ptr^.b_s_info.read_backing_store (cinfo,
@ptr^.b_s_info,
{FAR} pointer(ptr^.mem_buffer^[i]),
file_offset, byte_count);
Inc(file_offset, byte_count);
Inc(i, ptr^.rowsperchunk);
end;
end;
{METHODDEF}
function access_virt_sarray (cinfo : j_common_ptr;
ptr : jvirt_sarray_ptr;
start_row : JDIMENSION;
num_rows : JDIMENSION;
writable : boolean ) : JSAMPARRAY; far;
{ Access the part of a virtual sample array starting at start_row }
{ and extending for num_rows rows. writable is true if }
{ caller intends to modify the accessed area. }
var
end_row : JDIMENSION;
undef_row : JDIMENSION;
var
bytesperrow : size_t;
var
ltemp : long;
begin
end_row := start_row + num_rows;
{ debugging check }
if (end_row > ptr^.rows_in_array) or (num_rows > ptr^.maxaccess) or
(ptr^.mem_buffer = NIL) then
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
{ Make the desired part of the virtual array accessible }
if (start_row < ptr^.cur_start_row) or
(end_row > ptr^.cur_start_row+ptr^.rows_in_mem) then
begin
if (not ptr^.b_s_open) then
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
{ Flush old buffer contents if necessary }
if (ptr^.dirty) then
begin
do_sarray_io(cinfo, ptr, TRUE);
ptr^.dirty := FALSE;
end;
{ Decide what part of virtual array to access.
Algorithm: if target address > current window, assume forward scan,
load starting at target address. If target address < current window,
assume backward scan, load so that target area is top of window.
Note that when switching from forward write to forward read, will have
start_row := 0, so the limiting case applies and we load from 0 anyway. }
if (start_row > ptr^.cur_start_row) then
begin
ptr^.cur_start_row := start_row;
end
else
begin
{ use long arithmetic here to avoid overflow & unsigned problems }
ltemp := long(end_row) - long(ptr^.rows_in_mem);
if (ltemp < 0) then
ltemp := 0; { don't fall off front end of file }
ptr^.cur_start_row := JDIMENSION(ltemp);
end;
{ Read in the selected part of the array.
During the initial write pass, we will do no actual read
because the selected part is all undefined. }
do_sarray_io(cinfo, ptr, FALSE);
end;
{ Ensure the accessed part of the array is defined; prezero if needed.
To improve locality of access, we only prezero the part of the array
that the caller is about to access, not the entire in-memory array. }
if (ptr^.first_undef_row < end_row) then
begin
if (ptr^.first_undef_row < start_row) then
begin
if (writable) then { writer skipped over a section of array }
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
undef_row := start_row; { but reader is allowed to read ahead }
end
else
begin
undef_row := ptr^.first_undef_row;
end;
if (writable) then
ptr^.first_undef_row := end_row;
if (ptr^.pre_zero) then
begin
bytesperrow := size_t(ptr^.samplesperrow) * SIZEOF(JSAMPLE);
Dec(undef_row, ptr^.cur_start_row); { make indexes relative to buffer }
Dec(end_row, ptr^.cur_start_row);
while (undef_row < end_row) do
begin
jzero_far({FAR} pointer(ptr^.mem_buffer^[undef_row]), bytesperrow);
Inc(undef_row);
end;
end
else
begin
if (not writable) then { reader looking at undefined data }
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
end;
end;
{ Flag the buffer dirty if caller will write in it }
if (writable) then
ptr^.dirty := TRUE;
{ Return address of proper part of the buffer }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -