⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jmemmgr.pas

📁 DELPHI版的JPEG文件解码源程序
💻 PAS
📖 第 1 页 / 共 4 页
字号:
	break;
      slop := slop div 2;
      if (slop < MIN_SLOP) then   { give up when it gets real small }
	out_of_memory(cinfo, 2);  { jpeg_get_small failed }
    end;
    Inc(mem^.total_space_allocated, min_request + slop);
    { Success, initialize the new pool header and add to end of list }
    hdr_ptr^.hdr.next := NIL;
    hdr_ptr^.hdr.bytes_used := 0;
    hdr_ptr^.hdr.bytes_left := sizeofobject + slop;
    if (prev_hdr_ptr = NIL) then       { first pool in class? }
      mem^.small_list[pool_id] := hdr_ptr
    else
      prev_hdr_ptr^.hdr.next := hdr_ptr;
  end;

  { OK, allocate the object from the current pool }
  data_ptr := byteptr (hdr_ptr);
  Inc(small_pool_ptr(data_ptr));  { point to first data byte in pool }
  Inc(data_ptr, hdr_ptr^.hdr.bytes_used); { point to place for object }
  Inc(hdr_ptr^.hdr.bytes_used, sizeofobject);
  Dec(hdr_ptr^.hdr.bytes_left, sizeofobject);

  alloc_small := pointer(data_ptr);
end;


{ Allocation of "large" objects.

  The external semantics of these are the same as "small" objects,
  except that FAR pointers are used on 80x86.  However the pool
  management heuristics are quite different.  We assume that each
  request is large enough that it may as well be passed directly to
  jpeg_get_large; the pool management just links everything together
  so that we can free it all on demand.
  Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
  structures.  The routines that create these structures (see below)
  deliberately bunch rows together to ensure a large request size. }

{METHODDEF}
function alloc_large (cinfo : j_common_ptr;
                      pool_id : int;
                      sizeofobject : size_t) : pointer; FAR;
{ Allocate a "large" object }
var
  mem : my_mem_ptr;
  hdr_ptr : large_pool_ptr;
  odd_bytes : size_t;
var
  dest_ptr : large_pool_ptr;
begin
  mem := my_mem_ptr (cinfo^.mem);

  { Check for unsatisfiable request (do now to ensure no overflow below) }
  if (sizeofobject > size_t (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) then
    out_of_memory(cinfo, 3);	{ request exceeds malloc's ability }

  { Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) }
  odd_bytes := sizeofobject mod SIZEOF(ALIGN_TYPE);
  if (odd_bytes > 0) then
    Inc(sizeofobject, SIZEOF(ALIGN_TYPE) - odd_bytes);

  { Always make a new pool }
  if (pool_id < 0) or (pool_id >= JPOOL_NUMPOOLS) then
    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);	{ safety check }

  hdr_ptr := large_pool_ptr (jpeg_get_large(cinfo, sizeofobject +
					    SIZEOF(large_pool_hdr)));
  if (hdr_ptr = NIL) then
    out_of_memory(cinfo, 4);	{ jpeg_get_large failed }
  Inc(mem^.total_space_allocated, sizeofobject + SIZEOF(large_pool_hdr));

  { Success, initialize the new pool header and add to list }
  hdr_ptr^.hdr.next := mem^.large_list[pool_id];
  { We maintain space counts in each pool header for statistical purposes,
    even though they are not needed for allocation. }

  hdr_ptr^.hdr.bytes_used := sizeofobject;
  hdr_ptr^.hdr.bytes_left := 0;
  mem^.large_list[pool_id] := hdr_ptr;

  {alloc_large := pointerFAR (hdr_ptr + 1); - point to first data byte in pool }
  dest_ptr := hdr_ptr;
  Inc(large_pool_ptr(dest_ptr));
  alloc_large := dest_ptr;
end;


{ Creation of 2-D sample arrays.
  The pointers are in near heap, the samples themselves in FAR heap.

  To minimize allocation overhead and to allow I/O of large contiguous
  blocks, we allocate the sample rows in groups of as many rows as possible
  without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
  NB: the virtual array control routines, later in this file, know about
  this chunking of rows.  The rowsperchunk value is left in the mem manager
  object so that it can be saved away if this sarray is the workspace for
  a virtual array. }

{METHODDEF}
function alloc_sarray (cinfo : j_common_ptr;
                       pool_id : int;
	               samplesperrow : JDIMENSION;
                       numrows : JDIMENSION) : JSAMPARRAY; far;
{ Allocate a 2-D sample array }
var
  mem : my_mem_ptr;
  the_result : JSAMPARRAY;
  workspace : JSAMPROW;
  rowsperchunk, currow, i : JDIMENSION;
  ltemp : long;
begin
  mem := my_mem_ptr(cinfo^.mem);

  { Calculate max # of rows allowed in one allocation chunk }
  ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div
	  (long(samplesperrow) * SIZEOF(JSAMPLE));
  if (ltemp <= 0) then
    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
  if (ltemp < long(numrows)) then
    rowsperchunk := JDIMENSION (ltemp)
  else
    rowsperchunk := numrows;
  mem^.last_rowsperchunk := rowsperchunk;

  { Get space for row pointers (small object) }
  the_result := JSAMPARRAY (alloc_small(cinfo, pool_id,
				    size_t (numrows * SIZEOF(JSAMPROW))));

  { Get the rows themselves (large objects) }
  currow := 0;
  while (currow < numrows) do
  begin
    {rowsperchunk := MIN(rowsperchunk, numrows - currow);}
    if rowsperchunk > numrows - currow then
      rowsperchunk := numrows - currow;

    workspace := JSAMPROW (alloc_large(cinfo, pool_id,
	size_t (size_t(rowsperchunk) * size_t(samplesperrow)
		  * SIZEOF(JSAMPLE))) );
    for i := pred(rowsperchunk) downto 0 do
    begin
      the_result^[currow] := workspace;
      Inc(currow);
      Inc(JSAMPLE_PTR(workspace), samplesperrow);
    end;
  end;

  alloc_sarray := the_result;
end;


{ Creation of 2-D coefficient-block arrays.
  This is essentially the same as the code for sample arrays, above. }

{METHODDEF}
function alloc_barray (cinfo : j_common_ptr;
                       pool_id : int;
	               blocksperrow : JDIMENSION;
                       numrows : JDIMENSION) : JBLOCKARRAY; far;
{ Allocate a 2-D coefficient-block array }
var
  mem : my_mem_ptr;
  the_result : JBLOCKARRAY;
  workspace : JBLOCKROW;
  rowsperchunk, currow, i : JDIMENSION;
  ltemp : long;
begin
  mem := my_mem_ptr(cinfo^.mem);

  { Calculate max # of rows allowed in one allocation chunk }
  ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div
	  (long(blocksperrow) * SIZEOF(JBLOCK));
  if (ltemp <= 0) then
    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
  if (ltemp < long(numrows)) then
    rowsperchunk := JDIMENSION (ltemp)
  else
    rowsperchunk := numrows;
  mem^.last_rowsperchunk := rowsperchunk;

  { Get space for row pointers (small object) }
  the_result := JBLOCKARRAY (alloc_small(cinfo, pool_id,
				     size_t (numrows * SIZEOF(JBLOCKROW))) );

  { Get the rows themselves (large objects) }
  currow := 0;
  while (currow < numrows) do
  begin
    {rowsperchunk := MIN(rowsperchunk, numrows - currow);}
    if rowsperchunk > numrows - currow then
      rowsperchunk := numrows - currow;

    workspace := JBLOCKROW (alloc_large(cinfo, pool_id,
	size_t (size_t(rowsperchunk) * size_t(blocksperrow)
		  * SIZEOF(JBLOCK))) );
    for i := rowsperchunk downto 1 do
    begin
      the_result^[currow] := workspace;
      Inc(currow);
      Inc(JBLOCK_PTR(workspace), blocksperrow);
    end;
  end;

  alloc_barray := the_result;
end;


{ About virtual array management:

  The above "normal" array routines are only used to allocate strip buffers
  (as wide as the image, but just a few rows high).  Full-image-sized buffers
  are handled as "virtual" arrays.  The array is still accessed a strip at a
  time, but the memory manager must save the whole array for repeated
  accesses.  The intended implementation is that there is a strip buffer in
  memory (as high as is possible given the desired memory limit), plus a
  backing file that holds the rest of the array.

  The request_virt_array routines are told the total size of the image and
  the maximum number of rows that will be accessed at once.  The in-memory
  buffer must be at least as large as the maxaccess value.

  The request routines create control blocks but not the in-memory buffers.
  That is postponed until realize_virt_arrays is called.  At that time the
  total amount of space needed is known (approximately, anyway), so free
  memory can be divided up fairly.

  The access_virt_array routines are responsible for making a specific strip
  area accessible (after reading or writing the backing file, if necessary).
  Note that the access routines are told whether the caller intends to modify
  the accessed strip; during a read-only pass this saves having to rewrite
  data to disk.  The access routines are also responsible for pre-zeroing
  any newly accessed rows, if pre-zeroing was requested.

  In current usage, the access requests are usually for nonoverlapping
  strips; that is, successive access start_row numbers differ by exactly
  num_rows := maxaccess.  This means we can get good performance with simple
  buffer dump/reload logic, by making the in-memory buffer be a multiple
  of the access height; then there will never be accesses across bufferload
  boundaries.  The code will still work with overlapping access requests,
  but it doesn't handle bufferload overlaps very efficiently. }


{METHODDEF}
function request_virt_sarray (cinfo : j_common_ptr;
                              pool_id : int;
                              pre_zero : boolean;
		              samplesperrow : JDIMENSION;
                              numrows : JDIMENSION;
		              maxaccess : JDIMENSION) : jvirt_sarray_ptr; far;
{ Request a virtual 2-D sample array }
var
  mem : my_mem_ptr;
  the_result : jvirt_sarray_ptr;
begin
  mem := my_mem_ptr (cinfo^.mem);

  { Only IMAGE-lifetime virtual arrays are currently supported }
  if (pool_id <> JPOOL_IMAGE) then
    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);	{ safety check }

  { get control block }
  the_result := jvirt_sarray_ptr (alloc_small(cinfo, pool_id,
				  SIZEOF(jvirt_sarray_control)) );

  the_result^.mem_buffer := NIL;	{ marks array not yet realized }
  the_result^.rows_in_array := numrows;
  the_result^.samplesperrow := samplesperrow;
  the_result^.maxaccess := maxaccess;
  the_result^.pre_zero := pre_zero;
  the_result^.b_s_open := FALSE;	{ no associated backing-store object }
  the_result^.next := mem^.virt_sarray_list; { add to list of virtual arrays }
  mem^.virt_sarray_list := the_result;

  request_virt_sarray := the_result;
end;


{METHODDEF}
function request_virt_barray (cinfo : j_common_ptr;
                              pool_id : int;
                              pre_zero : boolean;
		              blocksperrow : JDIMENSION;
                              numrows : JDIMENSION;
		              maxaccess : JDIMENSION) : jvirt_barray_ptr; far;
{ Request a virtual 2-D coefficient-block array }
var
  mem : my_mem_ptr;
  the_result : jvirt_barray_ptr;
begin
  mem := my_mem_ptr(cinfo^.mem);

  { Only IMAGE-lifetime virtual arrays are currently supported }
  if (pool_id <> JPOOL_IMAGE) then
    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);	{ safety check }

  { get control block }
  the_result := jvirt_barray_ptr(alloc_small(cinfo, pool_id,
				  SIZEOF(jvirt_barray_control)) );

  the_result^.mem_buffer := NIL;	{ marks array not yet realized }
  the_result^.rows_in_array := numrows;
  the_result^.blocksperrow := blocksperrow;
  the_result^.maxaccess := maxaccess;
  the_result^.pre_zero := pre_zero;
  the_result^.b_s_open := FALSE;	{ no associated backing-store object }
  the_result^.next := mem^.virt_barray_list; { add to list of virtual arrays }
  mem^.virt_barray_list := the_result;

  request_virt_barray := the_result;
end;


{METHODDEF}
procedure realize_virt_arrays (cinfo : j_common_ptr); far;
{ Allocate the in-memory buffers for any unrealized virtual arrays }
var
  mem : my_mem_ptr;
  space_per_minheight, maximum_space, avail_mem : long;
  minheights, max_minheights : long;
  sptr : jvirt_sarray_ptr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -