home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 5
/
FreshFish_July-August1994.bin
/
bbs
/
gnu
/
gs-2.6.1.4-src.lha
/
src
/
amiga
/
gs-2.6.1.4
/
gsimage1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-27
|
16KB
|
543 lines
/* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
This file is part of Ghostscript.
Ghostscript is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the Ghostscript General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
General Public License. A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies. */
/* gsimage1.c */
/* Image procedures for Ghostscript library */
/* This file is logically part of gsimage.c; we have split it out */
/* to reduce the code working set. */
#include "gx.h"
#include "memory_.h"
#include "gpcheck.h"
#include "gserrors.h"
#include "gxfixed.h"
#include "gxarith.h"
#include "gxmatrix.h"
#include "gscspace.h"
#include "gspaint.h"
#include "gzstate.h"
#include "gzdevice.h" /* requires gsstate.h */
#include "gzcolor.h" /* requires gxdevice.h */
#include "gzpath.h"
#include "gxcolor.h"
#include "gxcpath.h"
#include "gxdevmem.h"
#include "gximage.h"
/* Process the next piece of an image */
int
gs_image_next(register gs_image_enum *penum, byte *dbytes, uint dsize)
{ uint rsize = penum->bytes_per_row;
uint pos = penum->byte_in_row;
int width = penum->width;
uint dleft = dsize;
uint dpos = 0;
gs_state *pgs = penum->pgs;
gx_device *save_dev = 0;
fixed xcur_save, ycur_save;
int y_save;
int code;
/* Accumulate separated colors, if needed */
if ( penum->plane_index == 0 )
penum->plane_size = dsize;
else if ( dsize != penum->plane_size )
return_error(gs_error_undefinedresult);
penum->planes[penum->plane_index] = dbytes;
if ( ++(penum->plane_index) != penum->spread )
return 0;
penum->plane_index = 0;
/* Save the dynamic state components in case of an error. */
xcur_save = penum->xcur;
ycur_save = penum->ycur;
y_save = penum->y;
/* We've accumulated an entire set of planes. */
if ( !penum->never_clip )
{ /* Install the clipping device if needed. */
gx_device *dev = (gx_device *)&penum->clip_dev;
save_dev = gs_currentdevice(pgs);
penum->clip_dev.target = save_dev;
gx_set_device_only(pgs, dev);
}
while ( dleft )
{ /* Fill up a row, then display it. */
uint bcount = min(dleft, rsize - pos);
byte *bptr =
penum->buffer + (pos << 3) / penum->bps * penum->spread;
int px;
for ( px = 0; px < penum->spread; px++ )
(*penum->unpack)(penum, &penum->map[px], bptr + px, penum->planes[px] + dpos, bcount, pos);
pos += bcount;
dpos += bcount;
dleft -= bcount;
if ( pos == rsize ) /* filled an entire row */
{
#ifdef DEBUG
if ( gs_debug['B'] )
{ int i, n = width * penum->spp;
dputs("[B]row:");
for ( i = 0; i < n; i++ )
dprintf1(" %02x", penum->buffer[i]);
dputs("\n");
}
#endif
if ( !penum->skewed )
{ /* Precompute integer y and height, */
/* and check for clipping. */
fixed yc = penum->ycur, yn;
fixed dyy = penum->fyy;
fixed adjust = penum->adjust;
if ( dyy > 0 )
dyy += adjust << 1,
yc -= adjust;
else
dyy = (adjust << 1) - dyy,
yc -= dyy - adjust;
if ( yc >= penum->clip_box.q.y ) goto mt;
yn = yc + dyy;
if ( yn <= penum->clip_box.p.y ) goto mt;
penum->yci = fixed2int_var_rounded(yc);
penum->hci =
fixed2int_var_rounded(yn) - penum->yci;
if ( penum->hci == 0 ) goto mt;
}
code = (*penum->render)(penum, penum->buffer, width * penum->spp, 1);
if ( code < 0 ) goto err;
mt: if ( ++(penum->y) == penum->height ) goto end;
pos = 0;
penum->xcur += penum->fyx;
penum->ycur += penum->fyy;
}
}
penum->byte_in_row = pos;
code = 0;
goto out;
end: /* End of data */
code = 1;
goto out;
err: /* Error or interrupt, restore original state. */
penum->plane_index = penum->spread - 1;
penum->xcur = xcur_save;
penum->ycur = ycur_save;
penum->y = y_save;
/* Note that caller must call gs_image_cleanup */
/* for both error and normal termination. */
out: if ( save_dev != 0 ) gx_set_device_only(pgs, save_dev);
return code;
}
/* Clean up by releasing the buffers. */
void
gs_image_cleanup(register gs_image_enum *penum)
{ if ( penum->buffer )
{ gs_free((char *)penum->buffer, 1, penum->buffer_size,
"image buffer");
penum->buffer = 0;
}
if ( penum->line )
{ gs_free((char *)penum->line, 1, penum->line_size,
"image line");
penum->line = 0;
}
}
/* ------ Unpacking procedures ------ */
void
image_unpack_1(const gs_image_enum *penum, const sample_map *pmap,
byte *bptr, register const byte *data, uint dsize, uint inpos)
{ register ulong *bufp = (unsigned long *)bptr;
int left = dsize;
register const ulong *map = &pmap->table.lookup4x1to32[0];
register uint b;
if ( left & 1 )
{ b = data[0];
bufp[0] = map[b >> 4];
bufp[1] = map[b & 0xf];
data++, bufp += 2;
}
left >>= 1;
while ( left-- )
{ b = data[0];
bufp[0] = map[b >> 4];
bufp[1] = map[b & 0xf];
b = data[1];
bufp[2] = map[b >> 4];
bufp[3] = map[b & 0xf];
data += 2, bufp += 4;
}
}
void
image_unpack_2(const gs_image_enum *penum, const sample_map *pmap,
byte *bptr, register const byte *data, uint dsize, uint inpos)
{ register ushort *bufp = (unsigned short *)bptr;
int left = dsize;
register const ushort *map = &pmap->table.lookup2x2to16[0];
while ( left-- )
{ register unsigned b = *data++;
*bufp++ = map[b >> 4];
*bufp++ = map[b & 0xf];
}
}
void
image_unpack_4(const gs_image_enum *penum, const sample_map *pmap,
register byte *bufp, register const byte *data, uint dsize, uint inpos)
{ register int spread = penum->spread;
int left = dsize;
register const byte *map = &pmap->table.lookup8[0];
while ( left-- )
{ register unsigned b = *data++;
*bufp = map[b >> 4]; bufp += spread;
*bufp = map[b & 0xf]; bufp += spread;
}
}
void
image_unpack_8(const gs_image_enum *penum, const sample_map *ignore_pmap,
byte *bufp, const byte *data, uint dsize, uint inpos)
{ if ( data != bufp ) memcpy(bufp, data, dsize);
}
/* ------ Rendering procedures ------ */
/* Rendering procedure for ignoring an image. We still need to iterate */
/* over the samples, because the procedure might have side effects. */
int
image_render_skip(gs_image_enum *penum, byte *data, uint w, int h)
{ return h;
}
/* Rendering procedure for a monobit image with no */
/* skew or rotation and pure colors. */
int
image_render_simple(gs_image_enum *penum, byte *buffer, uint w, int h)
{ byte *line = penum->line;
uint line_size, line_width;
gx_device *dev = penum->pgs->device->info;
dev_proc_copy_mono((*copy_mono)) = dev->procs->copy_mono;
int ix = fixed2int_rounded(penum->xcur);
const int iy = penum->yci, ih = penum->hci;
gx_color_index
zero = penum->icolor0.color1,
one = penum->icolor1.color1;
int dy;
if ( penum->map[0].table.lookup4x1to32[0] != 0 )
zero = penum->icolor1.color1,
one = penum->icolor0.color1;
if ( line == 0 )
{ /* A direct BitBlt is possible. */
line = buffer;
line_size = (w + 7) >> 3;
line_width = w;
}
else
{ fixed xl = penum->xcur + fixed_half - int2fixed(ix);
const fixed dxx = penum->fxx;
const fixed dxx_4 = dxx << 2;
const fixed dxx_8 = dxx_4 << 1;
register const byte *psrc = buffer;
byte sbit = 0x80;
byte *endp = buffer + (w >> 3);
const byte endbit = 1 << (~w & 7);
byte data;
line_size = penum->line_size;
line_width = penum->line_width;
if ( dxx < 0 )
ix -= line_width,
xl += int2fixed(line_width);
/* Invert the bit following the last valid data bit. */
if ( endbit == 0x80 ) *endp = ~endp[-1] << 7;
else if ( *endp & (endbit << 1) ) *endp &= ~endbit;
else *endp |= endbit;
data = *psrc;
memset(line, 0, line_size);
/*
* Loop invariants:
* data = *psrc;
* sb