home *** CD-ROM | disk | FTP | other *** search
- /*
- * JET PAK - HP DeskJet and LaserJet series printer utilities
- *
- * JETBMP module - bitmap utility functions
- *
- * Version 1.1 (Public Domain)
- */
-
- /* system include files */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- /* application include files */
- #include "jetfont.h"
- #include "jetutil.h"
-
- /*
- * MODULE GLOBAL DATA
- */
-
- /* bitmap outline edge information, including slope type */
- #define SLOPE_NONE 0
- #define SLOPE_NE 1
- #define SLOPE_SE 2
- #define SLOPE_SW 3
- #define SLOPE_NW 4
- typedef struct edge {
- struct edge *nextedge;
- UNSIGNEDINT sx;
- UNSIGNEDINT sy;
- SIGNEDINT dx;
- SIGNEDINT dy;
- UNSIGNEDBYTE slope;
- } EDGE;
-
- /* bitmap outline polygon - series of edges forming closed polygon */
- typedef struct poly {
- struct poly *nextpoly;
- struct edge *firstedge;
- } POLY;
-
- /* lists of edges collected in first phase (four types) */
- static EDGE *top_edges[MAX_CELL_HEIGHT] = { 0 };
- static EDGE *right_edges[MAX_CELL_WIDTH] = { 0 };
- static EDGE *bottom_edges[MAX_CELL_HEIGHT] = { 0 };
- static EDGE *left_edges[MAX_CELL_WIDTH] = { 0 };
-
- static UNSIGNEDBYTE bits[8] =
- {
- 0x80, 0x40, 0x20, 0x10,
- 0x08, 0x04, 0x02, 0x01,
- };
-
- /*
- * BITMAP SMOOTHING MACROS AND FUNCTIONS
- */
-
- /* set a single bit */
- #define bitset(p,w,h,x,y) \
- { \
- if ((x) < (w) && (y) < (h)) \
- *((p) + (y)*(((w) + 7)/8) + (x)/8) |= bits[(x)%8]; \
- }
-
- /* clear a single bit */
- #define bitclear(p,w,h,x,y) \
- { \
- if ((x) < (w) && (y) < (h)) \
- *((p) + (y)*(((w) + 7)/8) + (x)/8) &= ~bits[(x)%8]; \
- }
-
- /* test a single bit */
- #define bitat(p,w,h,x,y) \
- ( (x) < (w) \
- && (y) < (h) \
- && (*((p) + (y)*(((w) + 7)/8) + (x)/8) & bits[(x)%8]) != 0 \
- )
-
- static void bitmapclear(p,w,h)
- UNSIGNEDBYTE *p; /* pointer to LJ format bitmap to be cleared */
- UNSIGNEDINT w, h; /* dimensions of bitmap */
- {
- /*
- * Clear the w by h bit bitmap at *p
- */
- UNSIGNEDINT wb = (w + 7)/8;
-
- while (h-- > 0)
- for (w = 0; w < wb; w++)
- *p++ = 0;
- }
-
- static void edge_smooth(p, w, h, ep, slope, cut)
- UNSIGNEDBYTE *p; /* pointer to LJ format bitmap */
- UNSIGNEDINT w, h; /* dimensions of LJ bitmap in dots */
- EDGE *ep; /* pointer to edge position and direction */
- UNSIGNEDBYTE slope; /* type of slope to be applied to edge */
- SIGNEDINT cut; /* where to start cutting into the edge */
- {
- /*
- * Smooth a single edge within bitmap.
- */
- UNSIGNEDINT x, y;
-
- switch(slope)
- {
- case SLOPE_NE:
- if (cut >= 0)
- return;
- if (cut < ep->dy)
- cut = ep->dy;
- x = ep->sx;
- for (y = ep->sy + ep->dy - cut; y > ep->sy + ep->dy; y--)
- bitset(p, w, h, x, y-1);
- break;
- case SLOPE_SE:
- if (cut <= 0)
- return;
- if (cut > ep->dy)
- cut = ep->dy;
- x = ep->sx - 1;
- for (y = ep->sy + cut; y < ep->sy + ep->dy; y++)
- bitset(p, w, h, x, y);
- break;
- case SLOPE_SW:
- if (cut <= 0)
- return;
- if (cut > ep->dy)
- cut = ep->dy;
- x = ep->sx - 1;
- for (y = ep->sy; y < ep->sy + ep->dy - cut; y++)
- bitset(p, w, h, x, y);
- break;
- case SLOPE_NW:
- if (cut >= 0)
- return;
- if (cut < ep->dy)
- cut = ep->dy;
- x = ep->sx;
- for (y = ep->sy; y > ep->sy + cut; y--)
- bitset(p, w, h, x, y-1);
- break;
- }
- }
-
- static void bitmap_free_all(firstpoly, cw, ch)
- POLY *firstpoly; /* handle to bitmap outline tree data */
- UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
- {
- /*
- * Free up all the heap storage allocated during the bitmap
- * smoothing process.
- */
- POLY *pp;
- EDGE *ep;
- UNSIGNEDINT x, y;
-
- /* free edge lists */
- for (x = 0; x < cw; x++)
- {
- while ((ep = left_edges[x]) != NULL)
- {
- left_edges[x] = ep->nextedge;
- free(ep);
- }
-
- while ((ep = right_edges[x]) != NULL)
- {
- right_edges[x] = ep->nextedge;
- free(ep);
- }
- }
- for (y = 0; y < ch; y++)
- {
- while ((ep = top_edges[y]) != NULL)
- {
- top_edges[y] = ep->nextedge;
- free(ep);
- }
-
- while ((ep = bottom_edges[y]) != NULL)
- {
- bottom_edges[y] = ep->nextedge;
- free(ep);
- }
- }
-
- /* free outline trees */
- while ((pp = firstpoly) != NULL)
- {
- while ((ep = pp->firstedge) != NULL)
- {
- pp->firstedge = ep->nextedge;
- free(ep);
- }
-
- firstpoly = pp->nextpoly;
- free(pp);
- }
- }
-
- static int bitmap_trace(sbp, bmp, cw, ch)
- UNSIGNEDBYTE *sbp; /* pointer to source (LJ) bitmap */
- UNSIGNEDBYTE *bmp; /* pointer to smoothed bitmap mask */
- UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
- {
- /*
- * Find the edges within a bitmap, by scanning adjacent rows and
- * columns. Four types of edges are identified - top, bottom, right
- * and left.
- *
- * The boundary cases where a row or column being examined lies
- * outside the regular bitmap are handled by pointing to the
- * smoothed bitmap mask (known to be all zero at this point).
- *
- * The meaning of the variables is as follows:
- *
- * x, y: tracks the dot being examined
- * bp1: points to the byte containing the first row/column
- * bp2: points to the byte containing the second row/column
- * mask1: mask for the first row/column (used with bp1)
- * mask2: mask for the second row/column (used with bp2)
- * offset: byte offset between bitmap rows
- */
- EDGE **epp, *ep;
- UNSIGNEDINT x, y, mask1, mask2, offset;
- UNSIGNEDBYTE *bp1, *bp2;
-
- /* get bitmap derived data used in subsequent calculations */
- offset = (cw + 7)/8;
-
- /* collect top edges */
- bp1 = bmp; /* first row lies above real bitmap */
- bp2 = sbp;
- for (y = 0; y < ch; y++)
- {
- epp = &top_edges[y];
-
- for (x = 0, mask1 = 0x80; x < cw; )
- {
- if ( ((*bp1 & mask1) == 0)
- && ((*bp2 & mask1) != 0) )
- {
- *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
- if (ep == NULL)
- {
- bitmap_free_all(NULL, cw, ch);
- return(ERROR);
- }
- ep->sx = x;
- ep->sy = y;
-
- do {
- ep->dx++;
- x++;
- if ((mask1 >>= 1) == 0)
- {
- mask1 = 0x80;
- bp1++;
- bp2++;
- }
- } while ( (x < cw)
- && ((*bp1 & mask1) == 0)
- && ((*bp2 & mask1) != 0) );
-
- epp = &ep->nextedge;
- }
- else
- {
- x++;
- if ((mask1 >>= 1) == 0)
- {
- mask1 = 0x80;
- bp1++;
- bp2++;
- }
- }
- }
-
- if (mask1 != 0x80)
- {
- /* bitmap width not an exact multiple of 8 */
- bp1++;
- bp2++;
- }
-
- if (y == 0)
- bp1 = sbp;
-
- }
-
- /* collect bottom edges */
- bp1 = sbp;
- bp2 = sbp + offset;
- for (y = 0; y < ch; y++)
- {
- if (y == (ch - 1))
- bp2 = bmp; /* second row lies below real bitmap */
-
- epp = &bottom_edges[y];
-
- for (x = 0, mask1 = 0x80; x < cw; )
- {
- if ( ((*bp1 & mask1) != 0)
- && ((*bp2 & mask1) == 0) )
- {
- *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
- if (ep == NULL)
- {
- bitmap_free_all(NULL, cw, ch);
- return(ERROR);
- }
- do {
- ep->dx--;
- x++;
- if ((mask1 >>= 1) == 0)
- {
- mask1 = 0x80;
- bp1++;
- bp2++;
- }
- } while ( (x < cw)
- && ((*bp1 & mask1) != 0)
- && ((*bp2 & mask1) == 0) );
-
- ep->sx = x;
- ep->sy = y + 1;
-
- epp = &ep->nextedge;
- }
- else
- {
- x++;
- if ((mask1 >>= 1) == 0)
- {
- mask1 = 0x80;
- bp1++;
- bp2++;
- }
- }
- }
-
- if (mask1 != 0x80)
- {
- /* bitmap width not an exact multiple of 8 */
- bp1++;
- bp2++;
- }
- }
-
- /* collect right edges */
- mask1 = 0x80;
- mask2 = 0x40;
- for (x = 0; x < cw; x++)
- {
- bp1 = sbp + x/8;
- if (x == (cw - 1))
- bp2 = bmp; /* second row lies to the right of real bitmap */
- else
- bp2 = sbp + (x + 1)/8;
-
- epp = &right_edges[x];
-
- for (y = 0; y < ch; )
- {
- if ( ((*bp1 & mask1) != 0)
- && ((*bp2 & mask2) == 0) )
- {
- *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
- if (ep == NULL)
- {
- bitmap_free_all(NULL, cw, ch);
- return(ERROR);
- }
- ep->sx = x + 1;
- ep->sy = y;
-
- do {
- ep->dy++;
- y++;
- bp1 += offset;
- bp2 += offset;
- } while ( (y < ch)
- && ((*bp1 & mask1) != 0)
- && ((*bp2 & mask2) == 0) );
-
- epp = &ep->nextedge;
- }
- else
- {
- y++;
- bp1 += offset;
- bp2 += offset;
- }
- }
-
- mask1 = mask2;
- if ((mask2 >>= 1) == 0)
- mask2 = 0x80;
- }
-
- /* collect left edges */
- mask1 = 0x01;
- mask2 = 0x80;
- for (x = 0; x < cw; x++)
- {
- if (x == 0)
- bp1 = bmp; /* first row lies to the left of real bitmap */
- else
- bp1 = sbp + (x - 1)/8;
- bp2 = sbp + x/8;
-
- epp = &left_edges[x];
-
- for (y = 0; y < ch; )
- {
- if ( ((*bp1 & mask1) == 0)
- && ((*bp2 & mask2) != 0) )
- {
- *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
- if (ep == NULL)
- {
- bitmap_free_all(NULL, cw, ch);
- return(ERROR);
- }
-
- do {
- ep->dy--;
- y++;
- bp1 += offset;
- bp2 += offset;
- } while ( (y < ch)
- && ((*bp1 & mask1) == 0)
- && ((*bp2 & mask2) != 0) );
-
- ep->sx = x;
- ep->sy = y;
-
- epp = &ep->nextedge;
- }
- else
- {
- y++;
- bp1 += offset;
- bp2 += offset;
- }
- }
-
- mask1 = mask2;
- if ((mask2 >>= 1) == 0)
- mask2 = 0x80;
- }
-
- return(OK);
- }
-
- int bitmap_smooth(sbp, bmp, cw, ch)
- UNSIGNEDBYTE *sbp; /* pointer to source (LJ) bitmap */
- UNSIGNEDBYTE *bmp; /* pointer to smoothed bitmap mask */
- UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
- {
- /*
- * Create smoothing data for a LaserJet bitmap. This is done
- * by filling in a mask bitmap of the same dimensions as the
- * source bitmap.
- *
- * A clear bit in the mask indicates the LaserJet bit should be
- * to the left in the DeskJet bitmap; a set bit in the mask indicates
- * the LaserJet bit should be to the right in the DeskJet bitmap.
- *
- * The LaserJet bitmap may itself be modified: it is sometimes
- * necessary to clear two adjacent bits within the body of a
- * character.
- *
- * The procedure for creating the smoothed bitmap mask is as
- * follows:
- *
- * 1. The LJ bitmap is examined (by bitmap_trace()) to find the
- * edge information. This is saved in four arrays (indexed by
- * row or column) of pointers to linked lists of edges:
- *
- * EDGE top_edges[]
- * EDGE right_edges[]
- * EDGE bottom_edges[]
- * EDGE left_edges[]
- *
- * EDGEs are expressed as a start position and an offset, with
- * the convention that top edges point to the right, right edges
- * point downwards, bottom edges point to the left and left
- * edges point upwards, thus:
- *
- * ^---->
- * |@@@@|
- * |@@@@|
- * |@@@@|
- * <----V
- *
- * 2. The edges are then joined up, in sequence, into polygons.
- * A linked list of POLYGON structures is constructed; each
- * POLYGON points to a ring of EDGE structures (the first EDGE
- * is pointed at by the POLYGON and also by the last EDGE in
- * the ring).
- *
- * As EDGEs are assigned to a place in a POLYGON they are
- * removed from the EDGE array linked lists, so that eventually,
- * the EDGE array linked lists should be left empty.
- *
- * 3. A pass is made round the EDGES of each POLYGON to determine
- * the type of slope associated with left and right edges that
- * are separated by two 1 bit wide edges of the same type (the
- * only edges of concern during the smoothing process)
- *
- * |@@@ @@@| @| |@
- * |@@@ @@@| @| |@
- * |@@@ @@@| @| |@
- * <^@@ @@<V @V> ^>@
- * |@@ @@| @@| |@@
- * |@@ @@| @@| |@@
- * <^@ @<V @@V> ^>@@
- * |@ @| @@@| |@@@
- * |@ @| @@@| |@@@
- * |@ @| @@@| |@@@
- *
- * NW SW SE NE
- *
- * The type of slope is recorded in the EDGE structure.
- *
- * 4. Another pass is made round the EDGES of each POLYGON to
- * actually apply the slope and create the smoothed bitmap mask.
- * This involves not only applying the slope identified in step
- * 3, but also extending that slope to adjacent left and
- * right edges that don't have a slope identified.
- *
- * edge_smooth() is called to apply smoothing to a single
- * edge at a defined position. This sets bits in the smoothed
- * bitmap mask when the ideal position of a bit at the edge
- * of the character lies to the right, rather than the left.
- *
- * 5. The smoothed bitmap mask is now completed by scanning
- * each row of the bitmap. The source bitmap and the smoothed
- * mask bitmap are considered together to envisage what the
- * output DeskJet bitmap will look like.
- *
- * Adjacent set bits in the DeskJet bitmap are not allowed.
- * So if a bit at a left edge needs to be to the right, bits
- * in the body of a character are flipped over to the right,
- * one by one.
- *
- * If adjacent set bits wind up at the right edge, and the
- * right edge bit ideally should be on the left, two adjacent
- * clear bits are created in the body of the character to
- * allow this.
- *
- * As a special case of the above: if the character has no body
- * (i.e. the bit on the left edge is adjacent to the bit on the
- * right edge), the bit on the left edge is shifted back to the
- * left. This is the only case where a bit cannot be placed at
- * its "ideal" position in the output DeskJet bitmap.
- */
- EDGE **pepp, **epp, *ep, *epm2, *epm1, *epp1, *epp2, *sep;
- POLY **ppp, *pp, *firstpoly = NULL;
- UNSIGNEDINT x, y;
- struct edge *null_nep = NULL;
-
- /* clear the mask bitmap */
- bitmapclear(bmp, cw, ch);
-
- /* 1. trace the edges of the shapes in the bitmap */
- if (bitmap_trace(sbp, bmp, cw, ch) == ERROR)
- return(ERROR);
-
- /* 2. join edges into polygons */
- ppp = &firstpoly;
- for (x = 0; x < cw; x++)
- {
- while (*(epp = &left_edges[x]) != NULL)
- {
- /* unused edge - make first of polygon */
- *ppp = (POLY *)zalloc(sizeof(POLY));
- if (*ppp == NULL)
- {
- bitmap_free_all(firstpoly, cw, ch);
- return(ERROR);
- }
-
- pepp = &(*ppp)->firstedge;
- do {
- /* move found edge from line list to polygon list */
- *pepp = *epp;
- *epp = (*epp)->nextedge;
-
- /* search for next edge in polygon */
- if ((*pepp)->dx == 0)
- {
- /* search top and bottom lists */
- if (((*pepp)->sy+(*pepp)->dy) < ch)
- {
- epp = &top_edges[(*pepp)->sy+(*pepp)->dy];
-
- while (*epp != NULL && (*epp)->sx != (*pepp)->sx)
- epp = &(*epp)->nextedge;
- }
- else
- {
- epp = &null_nep;
- }
-
- if (*epp == NULL && ((*pepp)->sy+(*pepp)->dy) != 0)
- {
- epp = &bottom_edges[(*pepp)->sy+(*pepp)->dy-1];
- while (*epp != NULL && (*epp)->sx != (*pepp)->sx)
- epp = &(*epp)->nextedge;
- }
- }
- else
- {
- /* search left and right lists */
- if (((*pepp)->sx+(*pepp)->dx) < cw)
- {
- epp = &left_edges[(*pepp)->sx+(*pepp)->dx];
-
- while (*epp != NULL && (*epp)->sy != (*pepp)->sy)
- epp = &(*epp)->nextedge;
- }
- else
- {
- epp = &null_nep;
- }
-
- if (*epp == NULL && ((*pepp)->sx+(*pepp)->dx) != 0)
- {
- epp = &right_edges[(*pepp)->sx+(*pepp)->dx-1];
- while (*epp != NULL && (*epp)->sy != (*pepp)->sy)
- epp = &(*epp)->nextedge;
- }
- }
-
- pepp = &(*pepp)->nextedge;
- } while (*epp != NULL);
-
- ppp = &(*ppp)->nextpoly;
- *pepp = NULL;
- }
- }
-
- /* 3. fill in the slope fields */
- for (pp = firstpoly; pp != NULL; pp = pp->nextpoly)
- {
- epm2 = pp->firstedge;
- epm1 = epm2->nextedge;
- sep = ep = epm1->nextedge;
- epp1 = ep->nextedge;
- epp2 = epp1->nextedge;
- do
- {
- if (epp2 == NULL)
- epp2 = pp->firstedge;
-
- if ( (epm1->dx == 1 && epp1->dx == 1)
- || (epm1->dx == -1 && epp1->dx == -1) )
- {
- if ( (ep->dy < 0 && epm2->dy < 0 && epp2->dy < 0)
- || (ep->dy > 0 && epm2->dy > 0 && epp2->dy > 0) )
- {
- if (epm1->dx == 1)
- {
- if (ep->dy < 0)
- ep->slope = SLOPE_NE;
- else
- ep->slope = SLOPE_SE;
- }
- else
- {
- if (ep->dy < 0)
- ep->slope = SLOPE_NW;
- else
- ep->slope = SLOPE_SW;
- }
- }
- }
-
- epm2 = epm1;
- epm1 = ep;
- ep = epp1;
- epp1 = epp2;
- epp2 = epp2->nextedge;
- } while (ep != sep);
- }
-
- /* 4. apply slope where necessary */
- for (pp = firstpoly; pp != NULL; pp = pp->nextpoly)
- {
- epm2 = pp->firstedge;
- epm1 = epm2->nextedge;
- sep = ep = epm1->nextedge;
- epp1 = ep->nextedge;
- epp2 = epp1->nextedge;
- do
- {
- if (epp2 == NULL)
- epp2 = pp->firstedge;
-
- if (ep->dy != 0)
- {
- if (ep->slope != SLOPE_NONE)
- {
- /* edge has a slope that can be applied */
- edge_smooth(bmp, cw, ch, ep, ep->slope, ep->dy/2);
- }
- else if (epm2->slope == SLOPE_NONE && epp2->slope != SLOPE_NONE)
- {
- /* apply slope of next edge along */
- switch(epp2->slope)
- {
- case SLOPE_NE:
- case SLOPE_SW:
- edge_smooth(bmp, cw, ch, ep, epp2->slope, epp2->dy/2);
- break;
- case SLOPE_NW:
- case SLOPE_SE:
- edge_smooth(bmp, cw, ch, ep, epp2->slope, ep->dy - (epp2->dy - epp2->dy/2));
- break;
- }
- }
- else if (epm2->slope != SLOPE_NONE && epp2->slope == SLOPE_NONE)
- {
- /* apply slope of previous edge */
- switch(epm2->slope)
- {
- case SLOPE_NW:
- case SLOPE_SE:
- edge_smooth(bmp, cw, ch, ep, epm2->slope, epm2->dy/2);
- break;
- case SLOPE_NE:
- case SLOPE_SW:
- edge_smooth(bmp, cw, ch, ep, epm2->slope, ep->dy - (epm2->dy - epm2->dy/2));
- break;
- }
- }
- else if (epm2->slope == SLOPE_SW && epp2->slope == SLOPE_SE)
- {
- /* concave right edge - apply next and previous edge
- slopes */
- edge_smooth(bmp, cw, ch, ep, epm2->slope, ep->dy - (epm2->dy - epm2->dy/2));
- edge_smooth(bmp, cw, ch, ep, epp2->slope, ep->dy - (epp2->dy - epp2->dy/2));
- }
- else if (epm2->slope == SLOPE_NW && epp2->slope == SLOPE_NE)
- {
- /* convex left edge - apply next and previous edge
- slopes */
- edge_smooth(bmp, cw, ch, ep, epm2->slope, epm2->dy/2);
- edge_smooth(bmp, cw, ch, ep, epp2->slope, epp2->dy/2);
- }
- }
-
- epm2 = epm1;
- epm1 = ep;
- ep = epp1;
- epp1 = epp2;
- epp2 = epp2->nextedge;
- } while (ep != sep);
- }
-
- /* 5. sort out adjacent set bits */
- for (y = 0; y < ch; y++)
- {
- for (x = 0; x < cw; x++)
- {
- if ( bitat(sbp, cw, ch, x , y)
- && bitat(sbp, cw, ch, x+1, y)
- && bitat(bmp, cw, ch, x , y) )
- {
- /* adjacent pair of bits found */
- if (bitat(sbp, cw, ch, x+2, y))
- {
- /* pair is not at the right edge of character - flip
- right bit of pair to the right */
- bitset(bmp, cw, ch, x+1, y);
- }
- else if (!bitat(bmp, cw, ch, x+1, y))
- {
- /* pair is at the right edge of character */
- if (bitat(sbp, cw, ch, x-1, y))
- {
- /* create two adjacent clear bits in the body
- of the character */
- bitclear(sbp, cw, ch, x, y);
- bitclear(bmp, cw, ch, x, y);
- }
- else
- {
- /* character is too thin to clear adjacent bits:
- flip left bit of pair back to the left */
- bitclear(bmp, cw, ch, x, y);
- }
- }
- }
- }
- }
-
- bitmap_free_all(firstpoly, cw, ch);
-
- return(OK);
- }
-
- /*
- * BITMAP CONVERSION FUNCTIONS
- */
-
- int bitmap_compress(sbp, cw, ch, dbp, dsize)
- UNSIGNEDBYTE *sbp; /* pointer to source (normal) bitmap */
- UNSIGNEDINT cw, ch; /* dimensions of bitmap in dots */
- UNSIGNEDBYTE *dbp; /* pointer to destination (compressed) bitmap */
- UNSIGNEDINT dsize; /* maximum available space for destination bitmap */
- {
- /*
- * Compress a DJ bitmap from normal bitmap format to zero byte
- * compression format. The conversion is done by columns from
- * left to right; within that, by rows from top to bottom. The
- * meaning of the variables is as follows:
- *
- * x, y: tracks the dot being converted
- * sbp2: points to the source byte containing the dot being converted
- * smask: source mask for the dot being converted (used with sbp2)
- * soffset: byte offset between rows of the source bitmap
- * dbp2: points to the destination data byte containing the dot being converted
- * dmask1: mask for the destination flag byte (used with dbp)
- * dmask2: mask for the destination data byte (used with dbp2)
- *
- * The total number of bytes required to encode the output bitmap
- * is returned.
- */
- UNSIGNEDINT x, y, smask;
- UNSIGNEDBYTE *sbp2;
- UNSIGNEDINT dmask1, dmask2, soffset;
- register UNSIGNEDBYTE *dbp2;
-
- /* check sufficient space is available */
- if ((cw + cw*((ch + 7)/8)) > dsize)
- return(ERROR);
-
- dbp2 = dbp + cw;
-
- /* get the byte offset between rows of the source bitmap */
- soffset = (cw + 7)/8;
-
- for (x = 0; x < cw; x++)
- {
- sbp2 = sbp + x/8;
- smask = bits[x%8];
-
- *dbp = 0;
- for (y = 0, dmask1 = 0x01; y < ch; dmask1 <<= 1)
- {
- *dbp2 = 0;
- for (dmask2 = 0x80; y < ch && dmask2 != 0; y++, dmask2 >>= 1)
- {
-
- if (*sbp2 & smask)
- *dbp2 |= dmask2;
-
- sbp2 += soffset;
- }
-
- if (*dbp2 != 0)
- {
- *dbp |= dmask1;
- dbp2++;
- }
- }
-
- dbp++;
- }
-
- return((int)(cw + (dbp2 - dbp)));
- }
-
- int bitmap_decompress(sbp, cw, ch, dbp, dsize)
- UNSIGNEDBYTE *sbp; /* pointer to source (compressed) bitmap */
- UNSIGNEDINT cw, ch; /* dimensions of bitmap in dots */
- UNSIGNEDBYTE *dbp; /* pointer to destination (normal) bitmap */
- UNSIGNEDINT dsize; /* maximum available space for destination bitmap */
- {
- /*
- * Decompress a DJ bitmap from zero byte compression format to
- * normal bitmap format. This function is the exact reverse of
- * bitmap_compress(). The conversion is done by columns from
- * left to right; within that, by rows from top to bottom. The
- * meaning of the variables is as follows:
- *
- * x, y: tracks the dot being converted
- * sbp2: points to the source data byte containing the dot being converted
- * smask1: mask for the source flag byte (used with sbp)
- * smask2: mask for the source data byte (used with sbp2)
- * dbp2: points to the destination byte containing the dot being converted
- * dmask: destination mask for the dot being converted (used with dbp2)
- * doffset: byte offset between rows of the destination bitmap
- */
- UNSIGNEDINT x, y, smask1, smask2;
- UNSIGNEDBYTE *sbp2 = sbp + cw;
- UNSIGNEDINT dmask, doffset;
- register UNSIGNEDBYTE *dbp2;
-
- /* get the byte offset between rows of the destination bitmap */
- doffset = (cw + 7)/8;
-
- /* check sufficient space is available */
- if ((doffset*ch) > dsize)
- return(ERROR);
-
- for (x = 0; x < cw; x++)
- {
- dbp2 = dbp + x/8;
- dmask = bits[x%8];
-
- for (y = 0, smask1 = 0x01; y < ch; smask1 <<= 1)
- {
- if (smask1 == 0x100)
- {
- smask1 = 0x01;
- sbp++;
- }
-
- for (smask2 = 0x80; y < ch && smask2 != 0; y++, smask2 >>= 1)
- {
- if ((*sbp & smask1) && (*sbp2 & smask2))
- *dbp2 |= dmask;
- else
- *dbp2 &= ~dmask;
-
- dbp2 += doffset;
- }
-
- if (*sbp & smask1)
- sbp2++;
- }
-
- sbp++;
- }
-
- return(OK);
- }
-
- int bitmap_lj_to_dj(sbp, bmp, cw, ch, nl, pl, pr, dbp, dsize)
- UNSIGNEDBYTE *sbp; /* pointer to source (LJ) bitmap */
- UNSIGNEDBYTE *bmp; /* pointer to smoothed bitmap mask */
- UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
- UNSIGNEDINT nl; /* number of leading blank lines */
- UNSIGNEDINT pl; /* number of pad columns on left */
- UNSIGNEDINT pr; /* number of pad columns on right */
- UNSIGNEDBYTE *dbp; /* pointer to destination (DJ compressed) bitmap */
- UNSIGNEDINT dsize; /* maximum available space for destination bitmap */
- {
- /*
- * Convert a bitmap from LJ format to DJ format. This function
- * is similar to bitmap_compress() but does two extra things:
- *
- * It converts the bitmap from 300x300 resolution to 600x300
- * resolution by inserting blank bits under the control of the
- * 'bmp' bitmap mask which contains smoothing data.
- *
- * It adds 'nl' blank lines at the start of the destination
- * bitmap before moving in the source bitmap. This is useful
- * because the LJ bitmaps often need to be shifted down in the
- * DJ bitmap.
- *
- * This routine assumes that ch will less than 64; fortunately this
- * should always be the case since the DJ series cannot handle more
- * than a 50 bit high stripe in a single pass.
- *
- * The meaning of the variables is as follows:
- *
- * x, y: tracks the dot being converted
- * sbp2: points to the source byte containing the dot being converted
- * smask: source mask for the dot being converted (used with sbp2)
- * soffset: byte offset between rows of the source bitmap
- * dbp2: points to the destination data byte containing the dot being converted
- * dmask1: mask for the destination flag byte (used with dbp)
- * dmask2: mask for the destination data byte (used with dbp2)
- *
- * The total number of bytes required to encode the output bitmap
- * is returned.
- */
- UNSIGNEDINT x, y, smask;
- UNSIGNEDBYTE *sbp2;
- UNSIGNEDBYTE *bmp2;
- UNSIGNEDINT dmask1, dmask2, soffset;
- register UNSIGNEDBYTE *dbp2;
-
- /* check sufficient space is available */
- if ((cw*2 + pl + pr + cw*((ch + 7)/8)) > dsize)
- return(ERROR);
-
- dbp2 = dbp + cw*2 + pl + pr;
-
- ch += nl;
- soffset = (cw + 7)/8;
-
- /* add in blank columns to left of bitmap */
- for (x = 0; x < pl; x++)
- *dbp++ = 0;
-
- for (x = 0; x < cw; x++)
- {
- /* do the left hand column */
- sbp2 = sbp + x/8;
- bmp2 = bmp + x/8;
- smask = bits[x%8];
-
- *dbp = 0;
- for (y = 0, dmask1 = 0x01; y < ch; dmask1 <<= 1)
- {
- *dbp2 = 0;
- for (dmask2 = 0x80; y < ch && dmask2 != 0; y++, dmask2 >>= 1)
- {
- if (y >= nl)
- {
- if ((*sbp2 ^ *bmp2) & smask)
- *dbp2 |= dmask2;
-
- sbp2 += soffset;
- bmp2 += soffset;
- }
- }
-
- if (*dbp2 != 0)
- {
- *dbp |= dmask1;
- dbp2++;
- }
- }
- dbp++;
-
- /* do the right hand column */
- sbp2 = sbp + x/8;
- bmp2 = bmp + x/8;
- smask = bits[x%8];
-
- *dbp = 0;
- for (y = 0, dmask1 = 0x01; y < ch; dmask1 <<= 1)
- {
- *dbp2 = 0;
- for (dmask2 = 0x80; y < ch && dmask2 != 0; y++, dmask2 >>= 1)
- {
- if (y >= nl)
- {
- if ((*sbp2 & *bmp2) & smask)
- *dbp2 |= dmask2;
-
- sbp2 += soffset;
- bmp2 += soffset;
- }
- }
-
- if (*dbp2 != 0)
- {
- *dbp |= dmask1;
- dbp2++;
- }
- }
- dbp++;
- }
-
- /* add in blank columns to right of bitmap */
- for (x = 0; x < pr; x++)
- *dbp++ = 0;
-
- return((int)(cw*2 + pl + pr + (dbp2 - dbp)));
- }
-
- int bitmap_dj_to_lj(sbp, cw, ch, nl, dbp, dsize)
- UNSIGNEDBYTE *sbp; /* pointer to source (compressed) bitmap */
- UNSIGNEDINT cw, ch; /* dimensions of bitmap in dots */
- UNSIGNEDINT nl; /* number of skipped lines */
- UNSIGNEDBYTE *dbp; /* pointer to destination (normal) bitmap */
- UNSIGNEDINT dsize; /* maximum available space for destination bitmap */
- {
- /*
- * Convert a bitmap from DJ format to LJ format. This function
- * is similar to bitmap_decompress() but in addition:
- *
- * It converts the bitmap from 600x300 resolution to 300x300
- * resolution by ORing together adjacent columns in the DJ
- * bitmap.
- *
- * It skips 'nl' blank lines in the destination bitmap before
- * starting the conversion.
- *
- * x, y: tracks the dot being converted
- * sbp2: points to the source data byte containing the dot being converted
- * smask1: mask for the source flag byte (used with sbp)
- * smask2: mask for the source data byte (used with sbp2)
- * dbp2: points to the destination byte containing the dot being converted
- * dmask: destination mask for the dot being converted (used with dbp2)
- * doffset: byte offset between rows of the destination bitmap
- */
- UNSIGNEDINT x, y, smask1, smask2;
- UNSIGNEDBYTE *sbp2 = sbp + cw;
- UNSIGNEDINT dmask, doffset;
- register UNSIGNEDBYTE *dbp2;
-
- /* get the byte offset between rows of the destination bitmap */
- doffset = (cw/2 + 7)/8;
-
- /* check sufficient space is available */
- if ((doffset*(ch + nl)) > dsize)
- return(ERROR);
-
- for (x = 0; x < cw; x++)
- {
- dbp2 = dbp + nl*doffset + (x/2)/8;
- dmask = bits[(x/2)%8];
-
- for (y = 0, smask1 = 0x01; y < ch; smask1 <<= 1)
- {
- if (smask1 == 0x100)
- {
- smask1 = 0x01;
- sbp++;
- }
-
- for (smask2 = 0x80; y < ch && smask2 != 0; y++, smask2 >>= 1)
- {
- if ((*sbp & smask1) && (*sbp2 & smask2))
- *dbp2 |= dmask;
-
- dbp2 += doffset;
- }
-
- if (*sbp & smask1)
- sbp2++;
- }
-
- sbp++;
- }
-
- return(OK);
- }
-