📄 jmemmgr.c
字号:
hdr = (small_sarray_ptr) alloc_small((size_t) (numrows * SIZEOF(JSAMPROW)
+ SIZEOF(small_sarray_hdr)));
result = (JSAMPARRAY) (hdr+1); /* advance past header */
/* Insert into list now so free_all does right thing if I fail */
/* after allocating only some of the rows... */
hdr->next = small_sarray_list;
hdr->numrows = 0;
hdr->rowsperchunk = rowsperchunk;
small_sarray_list = hdr;
/* Get the rows themselves; on 80x86 these are "far" */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
#ifdef MEM_STATS
total_bytes_sarray += rowsperchunk * samplesperrow * SIZEOF(JSAMPLE)
+ MALLOC_FAR_OVERHEAD;
#endif
workspace = (JSAMPROW) jget_large((size_t) (rowsperchunk * samplesperrow
* SIZEOF(JSAMPLE)));
if (workspace == NULL)
out_of_memory(3);
for (i = rowsperchunk; i > 0; i--) {
result[currow++] = workspace;
workspace += samplesperrow;
}
hdr->numrows = currow;
}
return result;
}
METHODDEF void
free_small_sarray (JSAMPARRAY ptr)
/* Free a "small" (all-in-memory) 2-D sample array */
{
small_sarray_ptr hdr;
small_sarray_ptr * llink;
long i;
hdr = (small_sarray_ptr) ptr;
hdr--; /* point back to header */
/* Remove item from list -- linear search is fast enough */
llink = &small_sarray_list;
while (*llink != hdr) {
llink = &( (*llink)->next );
}
*llink = hdr->next;
/* Free the rows themselves; on 80x86 these are "far" */
/* Note we only free the row-group headers! */
for (i = 0; i < hdr->numrows; i += hdr->rowsperchunk) {
jfree_large((void FAR *) ptr[i]);
}
/* Free header and row pointers */
free_small((void *) hdr);
#ifdef MEM_STATS
cur_num_sarray--;
#endif
}
/*
* Management of "small" (all-in-memory) 2-D coefficient-block arrays.
* This is essentially the same as the code for sample arrays, above.
*/
typedef struct small_barray_struct * small_barray_ptr;
typedef struct small_barray_struct {
small_barray_ptr next; /* next in list of allocated barrays */
long numrows; /* # of rows in this array */
long rowsperchunk; /* max # of rows per allocation chunk */
JBLOCKROW dummy; /* ensures alignment of following storage */
} small_barray_hdr;
static small_barray_ptr small_barray_list; /* head of list */
METHODDEF JBLOCKARRAY
alloc_small_barray (long blocksperrow, long numrows)
/* Allocate a "small" (all-in-memory) 2-D coefficient-block array */
{
small_barray_ptr hdr;
JBLOCKARRAY result;
JBLOCKROW workspace;
long rowsperchunk, currow, i;
#ifdef MEM_STATS
total_num_barray++;
cur_num_barray++;
if (cur_num_barray > max_num_barray) max_num_barray = cur_num_barray;
#endif
/* Calculate max # of rows allowed in one allocation chunk */
rowsperchunk = MAX_ALLOC_CHUNK / (blocksperrow * SIZEOF(JBLOCK));
/* Get space for header and row pointers; this is always "near" on 80x86 */
hdr = (small_barray_ptr) alloc_small((size_t) (numrows * SIZEOF(JBLOCKROW)
+ SIZEOF(small_barray_hdr)));
result = (JBLOCKARRAY) (hdr+1); /* advance past header */
/* Insert into list now so free_all does right thing if I fail */
/* after allocating only some of the rows... */
hdr->next = small_barray_list;
hdr->numrows = 0;
hdr->rowsperchunk = rowsperchunk;
small_barray_list = hdr;
/* Get the rows themselves; on 80x86 these are "far" */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
#ifdef MEM_STATS
total_bytes_barray += rowsperchunk * blocksperrow * SIZEOF(JBLOCK)
+ MALLOC_FAR_OVERHEAD;
#endif
workspace = (JBLOCKROW) jget_large((size_t) (rowsperchunk * blocksperrow
* SIZEOF(JBLOCK)));
if (workspace == NULL)
out_of_memory(4);
for (i = rowsperchunk; i > 0; i--) {
result[currow++] = workspace;
workspace += blocksperrow;
}
hdr->numrows = currow;
}
return result;
}
METHODDEF void
free_small_barray (JBLOCKARRAY ptr)
/* Free a "small" (all-in-memory) 2-D coefficient-block array */
{
small_barray_ptr hdr;
small_barray_ptr * llink;
long i;
hdr = (small_barray_ptr) ptr;
hdr--; /* point back to header */
/* Remove item from list -- linear search is fast enough */
llink = &small_barray_list;
while (*llink != hdr) {
llink = &( (*llink)->next );
}
*llink = hdr->next;
/* Free the rows themselves; on 80x86 these are "far" */
/* Note we only free the row-group headers! */
for (i = 0; i < hdr->numrows; i += hdr->rowsperchunk) {
jfree_large((void FAR *) ptr[i]);
}
/* Free header and row pointers */
free_small((void *) hdr);
#ifdef MEM_STATS
cur_num_barray--;
#endif
}
/*
* About "big" array management:
*
* To allow machines with limited memory to handle large images,
* all processing in the JPEG system is done a few pixel or block rows
* at a time. The above "small" array routines are only used to allocate
* strip buffers (as wide as the image, but just a few rows high).
* In some cases multiple passes must be made over the data. In these
* cases the "big" array routines are used. 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_big_array routines are told the total size of the image (in case
* it is useful to know the total file size that will be needed). They are
* also given the unit height, which is the number of rows that will be
* accessed at once; the in-memory buffer should be made a multiple of
* this height for best efficiency.
*
* The request routines create control blocks (and may open backing files),
* but they don't create the in-memory buffers. This is postponed until
* alloc_big_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_big_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 typical access pattern is one top-to-bottom pass to write the data,
* followed by one or more read-only top-to-bottom passes. However, other
* access patterns may occur while reading. For example, translation of image
* formats that use bottom-to-top scan order will require bottom-to-top read
* passes. The memory manager need not support multiple write passes nor
* funny write orders (meaning that rearranging rows must be handled while
* reading data out of the big array, not while putting it in).
*
* In current usage, the access requests are always for nonoverlapping strips;
* that is, successive access start_row numbers always differ by exactly the
* unitheight. This allows fairly simple buffer dump/reload logic if the
* in-memory buffer is made a multiple of the unitheight. It would be
* possible to keep downsampled rather than fullsize data in the "big" arrays,
* thus reducing temp file size, if we supported overlapping strip access
* (access requests differing by less than the unitheight). At the moment
* I don't believe this is worth the extra complexity.
*/
/* The control blocks for virtual arrays.
* System-dependent info for the associated backing store is hidden inside
* the backing_store_info struct.
*/
struct big_sarray_control {
long rows_in_array; /* total virtual array height */
long samplesperrow; /* width of array (and of memory buffer) */
long unitheight; /* # of rows accessed by access_big_sarray() */
JSAMPARRAY mem_buffer; /* the in-memory buffer */
long rows_in_mem; /* height of memory buffer */
long rowsperchunk; /* allocation chunk size in mem_buffer */
long cur_start_row; /* first logical row # in the buffer */
boolean dirty; /* do current buffer contents need written? */
boolean b_s_open; /* is backing-store data valid? */
big_sarray_ptr next; /* link to next big sarray control block */
backing_store_info b_s_info; /* System-dependent control info */
};
static big_sarray_ptr big_sarray_list; /* head of list */
struct big_barray_control {
long rows_in_array; /* total virtual array height */
long blocksperrow; /* width of array (and of memory buffer) */
long unitheight; /* # of rows accessed by access_big_barray() */
JBLOCKARRAY mem_buffer; /* the in-memory buffer */
long rows_in_mem; /* height of memory buffer */
long rowsperchunk; /* allocation chunk size in mem_buffer */
long cur_start_row; /* first logical row # in the buffer */
boolean dirty; /* do current buffer contents need written? */
boolean b_s_open; /* is backing-store data valid? */
big_barray_ptr next; /* link to next big barray control block */
backing_store_info b_s_info; /* System-dependent control info */
};
static big_barray_ptr big_barray_list; /* head of list */
METHODDEF big_sarray_ptr
request_big_sarray (long samplesperrow, long numrows, long unitheight)
/* Request a "big" (virtual-memory) 2-D sample array */
{
big_sarray_ptr result;
/* get control block */
result = (big_sarray_ptr) alloc_small(SIZEOF(struct big_sarray_control));
result->rows_in_array = numrows;
result->samplesperrow = samplesperrow;
result->unitheight = unitheight;
result->mem_buffer = NULL; /* marks array not yet realized */
result->b_s_open = FALSE; /* no associated backing-store object */
result->next = big_sarray_list; /* add to list of big arrays */
big_sarray_list = result;
return result;
}
METHODDEF big_barray_ptr
request_big_barray (long blocksperrow, long numrows, long unitheight)
/* Request a "big" (virtual-memory) 2-D coefficient-block array */
{
big_barray_ptr result;
/* get control block */
result = (big_barray_ptr) alloc_small(SIZEOF(struct big_barray_control));
result->rows_in_array = numrows;
result->blocksperrow = blocksperrow;
result->unitheight = unitheight;
result->mem_buffer = NULL; /* marks array not yet realized */
result->b_s_open = FALSE; /* no associated backing-store object */
result->next = big_barray_list; /* add to list of big arrays */
big_barray_list = result;
return result;
}
METHODDEF void
alloc_big_arrays (long extra_small_samples, long extra_small_blocks,
long extra_medium_space)
/* Allocate the in-memory buffers for any unrealized "big" arrays */
/* 'extra' values are upper bounds for total future small-array requests */
/* and far-heap requests */
{
long total_extra_space = extra_small_samples * SIZEOF(JSAMPLE)
+ extra_small_blocks * SIZEOF(JBLOCK)
+ extra_medium_space;
long space_per_unitheight, maximum_space, avail_mem;
long unitheights, max_unitheights;
big_sarray_ptr sptr;
big_barray_ptr bptr;
/* Compute the minimum space needed (unitheight rows in each buffer)
* and the maximum space needed (full image height in each buffer).
* These may be of use to the system-dependent jmem_available routine.
*/
space_per_unitheight = 0;
maximum_space = total_extra_space;
for (sptr = big_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
space_per_unitheight += sptr->unitheight *
sptr->samplesperrow * SIZEOF(JSAMPLE);
maximum_space += sptr->rows_in_array *
sptr->samplesperrow * SIZEOF(JSAMPLE);
}
}
for (bptr = big_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
space_per_unitheight += bptr->unitheight *
bptr->blocksperrow * SIZEOF(JBLOCK);
maximum_space += bptr->rows_in_array *
bptr->blocksperrow * SIZEOF(JBLOCK);
}
}
if (space_per_unitheight <= 0)
return; /* no unrealized arrays, no work */
/* Determine amount of memory to actually use; this is system-dependent. */
avail_mem = jmem_available(space_per_unitheight + total_extra_space,
maximum_space);
/* If the maximum space needed is available, make all the buffers full
* height; otherwise parcel it out with the same number of unitheights
* in each buffer.
*/
if (avail_mem >= maximum_space)
max_unitheights = 1000000000L;
else {
max_unitheights = (avail_mem - total_extra_space) / space_per_unitheight;
/* If there doesn't seem to be enough space, try to get the minimum
* anyway. This allows a "stub" implementation of jmem_available().
*/
if (max_unitheights <= 0)
max_unitheights = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -