📄 jmemmgr.c
字号:
}
/* Allocate the in-memory buffers and initialize backing store as needed. */
for (sptr = big_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
unitheights = (sptr->rows_in_array + sptr->unitheight - 1L)
/ sptr->unitheight;
if (unitheights <= max_unitheights) {
/* This buffer fits in memory */
sptr->rows_in_mem = sptr->rows_in_array;
} else {
/* It doesn't fit in memory, create backing store. */
sptr->rows_in_mem = max_unitheights * sptr->unitheight;
jopen_backing_store(& sptr->b_s_info,
(long) (sptr->rows_in_array *
sptr->samplesperrow * SIZEOF(JSAMPLE)));
sptr->b_s_open = TRUE;
}
sptr->mem_buffer = alloc_small_sarray(sptr->samplesperrow,
sptr->rows_in_mem);
/* Reach into the small_sarray header and get the rowsperchunk field.
* Yes, I know, this is horrible coding practice.
*/
sptr->rowsperchunk =
((small_sarray_ptr) sptr->mem_buffer)[-1].rowsperchunk;
sptr->cur_start_row = 0;
sptr->dirty = FALSE;
}
}
for (bptr = big_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
unitheights = (bptr->rows_in_array + bptr->unitheight - 1L)
/ bptr->unitheight;
if (unitheights <= max_unitheights) {
/* This buffer fits in memory */
bptr->rows_in_mem = bptr->rows_in_array;
} else {
/* It doesn't fit in memory, create backing store. */
bptr->rows_in_mem = max_unitheights * bptr->unitheight;
jopen_backing_store(& bptr->b_s_info,
(long) (bptr->rows_in_array *
bptr->blocksperrow * SIZEOF(JBLOCK)));
bptr->b_s_open = TRUE;
}
bptr->mem_buffer = alloc_small_barray(bptr->blocksperrow,
bptr->rows_in_mem);
/* Reach into the small_barray header and get the rowsperchunk field. */
bptr->rowsperchunk =
((small_barray_ptr) bptr->mem_buffer)[-1].rowsperchunk;
bptr->cur_start_row = 0;
bptr->dirty = FALSE;
}
}
}
LOCAL void
do_sarray_io (big_sarray_ptr ptr, boolean writing)
/* Do backing store read or write of a "big" sample array */
{
long bytesperrow, file_offset, byte_count, rows, i;
bytesperrow = ptr->samplesperrow * SIZEOF(JSAMPLE);
file_offset = ptr->cur_start_row * bytesperrow;
/* Loop to read or write each allocation chunk in mem_buffer */
for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) {
/* One chunk, but check for short chunk at end of buffer */
rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i);
/* Transfer no more than fits in file */
rows = MIN(rows, ptr->rows_in_array - (ptr->cur_start_row + i));
if (rows <= 0) /* this chunk might be past end of file! */
break;
byte_count = rows * bytesperrow;
if (writing)
(*ptr->b_s_info.write_backing_store) (& ptr->b_s_info,
(void FAR *) ptr->mem_buffer[i],
file_offset, byte_count);
else
(*ptr->b_s_info.read_backing_store) (& ptr->b_s_info,
(void FAR *) ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
}
LOCAL void
do_barray_io (big_barray_ptr ptr, boolean writing)
/* Do backing store read or write of a "big" coefficient-block array */
{
long bytesperrow, file_offset, byte_count, rows, i;
bytesperrow = ptr->blocksperrow * SIZEOF(JBLOCK);
file_offset = ptr->cur_start_row * bytesperrow;
/* Loop to read or write each allocation chunk in mem_buffer */
for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) {
/* One chunk, but check for short chunk at end of buffer */
rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i);
/* Transfer no more than fits in file */
rows = MIN(rows, ptr->rows_in_array - (ptr->cur_start_row + i));
if (rows <= 0) /* this chunk might be past end of file! */
break;
byte_count = rows * bytesperrow;
if (writing)
(*ptr->b_s_info.write_backing_store) (& ptr->b_s_info,
(void FAR *) ptr->mem_buffer[i],
file_offset, byte_count);
else
(*ptr->b_s_info.read_backing_store) (& ptr->b_s_info,
(void FAR *) ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
}
METHODDEF JSAMPARRAY
access_big_sarray (big_sarray_ptr ptr, long start_row, boolean writable)
/* Access the part of a "big" sample array starting at start_row */
/* and extending for ptr->unitheight rows. writable is true if */
/* caller intends to modify the accessed area. */
{
/* debugging check */
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
start_row+ptr->unitheight > ptr->cur_start_row+ptr->rows_in_mem) {
/* ERREXIT(methods, "Virtual array controller messed up"); */
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
do_sarray_io(ptr, TRUE);
ptr->dirty = FALSE;
}
/* 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 address 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) {
ptr->cur_start_row = start_row;
} else {
ptr->cur_start_row = start_row + ptr->unitheight - ptr->rows_in_mem;
if (ptr->cur_start_row < 0)
ptr->cur_start_row = 0; /* don't fall off front end of file */
}
/* If reading, read in the selected part of the array.
* If we are writing, we need not pre-read the selected portion,
* since the access sequence constraints ensure it would be garbage.
*/
if (! writable) {
do_sarray_io(ptr, FALSE);
}
}
/* Flag the buffer dirty if caller will write in it */
if (writable)
ptr->dirty = TRUE;
/* Return address of proper part of the buffer */
return ptr->mem_buffer + (start_row - ptr->cur_start_row);
}
METHODDEF JBLOCKARRAY
access_big_barray (big_barray_ptr ptr, long start_row, boolean writable)
/* Access the part of a "big" coefficient-block array starting at start_row */
/* and extending for ptr->unitheight rows. writable is true if */
/* caller intends to modify the accessed area. */
{
/* debugging check */
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
start_row+ptr->unitheight > ptr->cur_start_row+ptr->rows_in_mem) {
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
do_barray_io(ptr, TRUE);
ptr->dirty = FALSE;
}
/* 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 address 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) {
ptr->cur_start_row = start_row;
} else {
ptr->cur_start_row = start_row + ptr->unitheight - ptr->rows_in_mem;
if (ptr->cur_start_row < 0)
ptr->cur_start_row = 0; /* don't fall off front end of file */
}
/* If reading, read in the selected part of the array.
* If we are writing, we need not pre-read the selected portion,
* since the access sequence constraints ensure it would be garbage.
*/
if (! writable) {
do_barray_io(ptr, FALSE);
}
}
/* Flag the buffer dirty if caller will write in it */
if (writable)
ptr->dirty = TRUE;
/* Return address of proper part of the buffer */
return ptr->mem_buffer + (start_row - ptr->cur_start_row);
}
METHODDEF void
free_big_sarray (big_sarray_ptr ptr)
/* Free a "big" (virtual-memory) 2-D sample array */
{
big_sarray_ptr * llink;
/* Remove item from list -- linear search is fast enough */
llink = &big_sarray_list;
while (*llink != ptr) {
llink = &( (*llink)->next );
}
*llink = ptr->next;
if (ptr->b_s_open) /* there may be no backing store */
(*ptr->b_s_info.close_backing_store) (& ptr->b_s_info);
if (ptr->mem_buffer != NULL) /* just in case never realized */
free_small_sarray(ptr->mem_buffer);
free_small((void *) ptr); /* free the control block too */
}
METHODDEF void
free_big_barray (big_barray_ptr ptr)
/* Free a "big" (virtual-memory) 2-D coefficient-block array */
{
big_barray_ptr * llink;
/* Remove item from list -- linear search is fast enough */
llink = &big_barray_list;
while (*llink != ptr) {
llink = &( (*llink)->next );
}
*llink = ptr->next;
if (ptr->b_s_open) /* there may be no backing store */
(*ptr->b_s_info.close_backing_store) (& ptr->b_s_info);
if (ptr->mem_buffer != NULL) /* just in case never realized */
free_small_barray(ptr->mem_buffer);
free_small((void *) ptr); /* free the control block too */
}
/*
* Cleanup: free anything that's been allocated since jselmemmgr().
*/
METHODDEF void
free_all (void)
{
/* First free any open "big" arrays -- these may release small arrays */
while (big_sarray_list != NULL)
free_big_sarray(big_sarray_list);
while (big_barray_list != NULL)
free_big_barray(big_barray_list);
/* Free any open small arrays -- these may release small objects */
/* +1's are because we must pass a pointer to the data, not the header */
while (small_sarray_list != NULL)
free_small_sarray((JSAMPARRAY) (small_sarray_list + 1));
while (small_barray_list != NULL)
free_small_barray((JBLOCKARRAY) (small_barray_list + 1));
/* Free any remaining small objects */
while (small_list != NULL)
free_small((void *) (small_list + 1));
#ifdef NEED_ALLOC_MEDIUM
while (medium_list != NULL)
free_medium((void FAR *) (medium_list + 1));
#endif
jmem_term(); /* system-dependent cleanup */
#ifdef MEM_STATS
if (methods->trace_level > 0)
print_mem_stats(); /* print optional memory usage statistics */
#endif
}
/*
* The method selection routine for virtual memory systems.
* The system-dependent setup routine should call this routine
* to install the necessary method pointers in the supplied struct.
*/
GLOBAL void
jselmemmgr (external_methods_ptr emethods)
{
methods = emethods; /* save struct addr for error exit access */
emethods->alloc_small = alloc_small;
emethods->free_small = free_small;
#ifdef NEED_ALLOC_MEDIUM
emethods->alloc_medium = alloc_medium;
emethods->free_medium = free_medium;
#else
emethods->alloc_medium = alloc_small;
emethods->free_medium = free_small;
#endif
emethods->alloc_small_sarray = alloc_small_sarray;
emethods->free_small_sarray = free_small_sarray;
emethods->alloc_small_barray = alloc_small_barray;
emethods->free_small_barray = free_small_barray;
emethods->request_big_sarray = request_big_sarray;
emethods->request_big_barray = request_big_barray;
emethods->alloc_big_arrays = alloc_big_arrays;
emethods->access_big_sarray = access_big_sarray;
emethods->access_big_barray = access_big_barray;
emethods->free_big_sarray = free_big_sarray;
emethods->free_big_barray = free_big_barray;
emethods->free_all = free_all;
/* Initialize list headers to empty */
small_list = NULL;
#ifdef NEED_ALLOC_MEDIUM
medium_list = NULL;
#endif
small_sarray_list = NULL;
small_barray_list = NULL;
big_sarray_list = NULL;
big_barray_list = NULL;
jmem_init(emethods); /* system-dependent initialization */
/* Check for an environment variable JPEGMEM; if found, override the
* default max_memory setting from jmem_init. Note that a command line
* -m argument may again override this value.
* If your system doesn't support getenv(), define NO_GETENV to disable
* this feature.
*/
#ifndef NO_GETENV
{ char * memenv;
if ((memenv = getenv("JPEGMEM")) != NULL) {
long lval;
char ch = 'x';
if (sscanf(memenv, "%ld%c", &lval, &ch) > 0) {
if (ch == 'm' || ch == 'M')
lval *= 1000L;
emethods->max_memory_to_use = lval * 1000L;
}
}
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -