home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
netpbma.zip
/
ppm
/
ppmtopict.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-04
|
11KB
|
483 lines
/*
** ppmtopict.c - read a portable pixmap and produce a Macintosh PICT2 file.
**
** Copyright (C) 1990 by Ken Yap <ken@cs.rochester.edu>.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
#include "ppm.h"
#include "ppmcmap.h"
#define HEADER_SIZE 512
#define RUN_THRESH 3
#define MAX_RUN 128 /* 0xff = 2, 0xfe = 3, etc */
#define MAX_COUNT 128 /* 0x00 = 1, 0x01 = 2, etc */
/* Opcodes */
#define PICT_NOP 0x00
#define PICT_clipRgn 0x01
#define PICT_bkPat 0x02
#define PICT_txFont 0x03
#define PICT_txFace 0x04
#define PICT_txMode 0x05
#define PICT_spExtra 0x06
#define PICT_pnSize 0x07
#define PICT_pnMode 0x08
#define PICT_pnPat 0x09
#define PICT_thePat 0x0A
#define PICT_ovSize 0x0B
#define PICT_origin 0x0C
#define PICT_txSize 0x0D
#define PICT_fgColor 0x0E
#define PICT_bkColor 0x0F
#define PICT_txRatio 0x10
#define PICT_picVersion 0x11
#define PICT_blPixPat 0x12
#define PICT_pnPixPat 0x13
#define PICT_fillPixPat 0x14
#define PICT_pnLocHFrac 0x15
#define PICT_chExtra 0x16
#define PICT_rgbFgCol 0x1A
#define PICT_rgbBkCol 0x1B
#define PICT_hiliteMode 0x1C
#define PICT_hiliteColor 0x1D
#define PICT_defHilite 0x1E
#define PICT_opColor 0x1F
#define PICT_line 0x20
#define PICT_line_from 0x21
#define PICT_short_line 0x22
#define PICT_short_line_from 0x23
#define PICT_long_text 0x28
#define PICT_DH_text 0x29
#define PICT_DV_text 0x2A
#define PICT_DHDV_text 0x2B
#define PICT_frameRect 0x30
#define PICT_paintRect 0x31
#define PICT_eraseRect 0x32
#define PICT_invertRect 0x33
#define PICT_fillRect 0x34
#define PICT_frameSameRect 0x38
#define PICT_paintSameRect 0x39
#define PICT_eraseSameRect 0x3A
#define PICT_invertSameRect 0x3B
#define PICT_fillSameRect 0x3C
#define PICT_frameRRect 0x40
#define PICT_paintRRect 0x41
#define PICT_eraseRRect 0x42
#define PICT_invertRRect 0x43
#define PICT_fillRRect 0x44
#define PICT_frameSameRRect 0x48
#define PICT_paintSameRRect 0x49
#define PICT_eraseSameRRect 0x4A
#define PICT_invertSameRRect 0x4B
#define PICT_fillSameRRect 0x4C
#define PICT_frameOval 0x50
#define PICT_paintOval 0x51
#define PICT_eraseOval 0x52
#define PICT_invertOval 0x53
#define PICT_fillOval 0x54
#define PICT_frameSameOval 0x58
#define PICT_paintSameOval 0x59
#define PICT_eraseSameOval 0x5A
#define PICT_invertSameOval 0x5B
#define PICT_fillSameOval 0x5C
#define PICT_frameArc 0x60
#define PICT_paintArc 0x61
#define PICT_eraseArc 0x62
#define PICT_invertArc 0x63
#define PICT_fillArc 0x64
#define PICT_frameSameArc 0x68
#define PICT_paintSameArc 0x69
#define PICT_eraseSameArc 0x6A
#define PICT_invertSameArc 0x6B
#define PICT_fillSameArc 0x6C
#define PICT_framePoly 0x70
#define PICT_paintPoly 0x71
#define PICT_erasePoly 0x72
#define PICT_invertPoly 0x73
#define PICT_fillPoly 0x74
#define PICT_frameSamePoly 0x78
#define PICT_paintSamePoly 0x79
#define PICT_eraseSamePoly 0x7A
#define PICT_invertSamePoly 0x7B
#define PICT_fillSamePoly 0x7C
#define PICT_frameRgn 0x80
#define PICT_paintRgn 0x81
#define PICT_eraseRgn 0x82
#define PICT_invertRgn 0x83
#define PICT_fillRgn 0x84
#define PICT_frameSameRgn 0x88
#define PICT_paintSameRgn 0x89
#define PICT_eraseSameRgn 0x8A
#define PICT_invertSameRgn 0x8B
#define PICT_fillSameRgn 0x8C
#define PICT_BitsRect 0x90
#define PICT_BitsRgn 0x91
#define PICT_PackBitsRect 0x98
#define PICT_PackBitsRgn 0x99
#define PICT_shortComment 0xA0
#define PICT_longComment 0xA1
#define PICT_EndOfPicture 0xFF
#define PICT_headerOp 0x0C00
static void putFill ARGS(( FILE *fd, int n ));
static void putShort ARGS(( FILE *fd, int i ));
static void putLong ARGS(( FILE *fd, long i ));
static void putFixed ARGS(( FILE *fd, int in, int frac ));
static void putRect ARGS(( FILE *fd, int x1, int x2, int y1, int y2 ));
static int putRow ARGS(( FILE *fd, int row, int cols, pixel *rowpixels, char *packed ));
#define MAXCOLORS 256
static colorhash_table cht;
int
main(argc, argv)
int argc;
char *argv[];
{
FILE *ifp;
int argn, rows, cols, colors, i, row, oc;
register pixel **pixels;
char *packed;
pixval maxval;
long lmaxval, rval, gval, bval;
colorhist_vector chv;
ppm_init( &argc, argv );
argn = 1;
if (argn < argc)
{
ifp = pm_openr(argv[1]);
argn++;
}
else
ifp = stdin;
if (argn != argc)
pm_usage("[ppmfile]");
pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
if (cols < 8)
pm_error("ppm input too narrow, must be >= 8 pixels wide" );
lmaxval = (long)maxval;
pm_close(ifp);
/* Figure out the colormap. */
pm_message("computing colormap..." );
chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
if (chv == (colorhist_vector) 0)
pm_error("too many colors - try doing a 'ppmquant %d'", MAXCOLORS);
pm_message("%d colors found", colors );
/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash(chv, colors);
/* write the header */
putFill(stdout, HEADER_SIZE);
/* write picSize and picFrame */
putShort(stdout, 0);
putRect(stdout, 0, 0, rows, cols);
/* write version op and version */
putShort(stdout, PICT_picVersion);
putShort(stdout, 0x02FF);
putShort(stdout, PICT_headerOp);
putLong(stdout, -1L);
putFixed(stdout, 0, 0);
putFixed(stdout, 0, 0);
putFixed(stdout, cols, 0);
putFixed(stdout, rows, 0);
putFill(stdout, 4);
/* seems to be needed by many PICT2 programs */
putShort(stdout, PICT_clipRgn);
putShort(stdout, 10);
putRect(stdout, 0, 0, rows, cols);
/* write picture */
putShort(stdout, PICT_PackBitsRect);
putShort(stdout, cols | 0x8000);
putRect(stdout, 0, 0, rows, cols);
putShort(stdout, 0); /* pmVersion */
putShort(stdout, 0); /* packType */
putLong(stdout, 0L); /* packSize */
putFixed(stdout, 72, 0); /* hRes */
putFixed(stdout, 72, 0); /* vRes */
putShort(stdout, 0); /* pixelType */
putShort(stdout, 8); /* pixelSize */
putShort(stdout, 1); /* cmpCount */
putShort(stdout, 8); /* cmpSize */
putLong(stdout, 0L); /* planeBytes */
putLong(stdout, 0L); /* pmTable */
putLong(stdout, 0L); /* pmReserved */
putLong(stdout, 0L); /* ctSeed */
putShort(stdout, 0); /* ctFlags */
putShort(stdout, colors-1); /* ctSize */
/* Write out the colormap. */
for (i = 0; i < colors; i++)
{
putShort(stdout, i);
rval = PPM_GETR(chv[i].color);
gval = PPM_GETG(chv[i].color);
bval = PPM_GETB(chv[i].color);
if (lmaxval != 65535L)
{
rval = rval * 65535L / lmaxval;
gval = gval * 65535L / lmaxval;
bval = bval * 65535L / lmaxval;
}
putShort(stdout, (short)rval);
putShort(stdout, (short)gval);
putShort(stdout, (short)bval);
}
putRect(stdout, 0, 0, rows, cols); /* srcRect */
putRect(stdout, 0, 0, rows, cols); /* dstRect */
putShort(stdout, 0); /* mode */
/* Finally, write out the data. */
packed = (char*) malloc((unsigned)(cols+cols/MAX_COUNT+1));
oc = 0;
for (row = 0; row < rows; row++)
oc += putRow(stdout, row, cols, pixels[row], packed);
/* if we wrote an odd number of pixdata bytes, pad */
if (oc & 1)
(void) putc(0, stdout);
putShort(stdout, PICT_EndOfPicture);
lmaxval = ftell(stdout) - HEADER_SIZE;
if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0)
putShort(stdout, (short)(lmaxval & 0xffff));
exit(0);
}
static void
putFill(fd, n)
FILE *fd;
int n;
{
register int i;
for (i = 0; i < n; i++)
(void) putc(0, fd);
}
static void
putShort(fd, i)
FILE *fd;
int i;
{
(void) putc((i >> 8) & 0xff, fd);
(void) putc(i & 0xff, fd);
}
#if __STDC__
static void
putLong( FILE *fd, long i )
#else /*__STDC__*/
static void
putLong(fd, i)
FILE *fd;
long i;
#endif /*__STDC__*/
{
(void) putc((int)((i >> 24) & 0xff), fd);
(void) putc(((int)(i >> 16) & 0xff), fd);
(void) putc(((int)(i >> 8) & 0xff), fd);
(void) putc((int)(i & 0xff), fd);
}
static void
putFixed(fd, in, frac)
FILE *fd;
int in, frac;
{
putShort(fd, in);
putShort(fd, frac);
}
static void
putRect(fd, x1, x2, y1, y2)
FILE *fd;
int x1, x2, y1, y2;
{
putShort(fd, x1);
putShort(fd, x2);
putShort(fd, y1);
putShort(fd, y2);
}
#define RUNLENGTH
#ifdef RUNLENGTH
#define runtochar(c) (257-(c))
#define counttochar(c) ((c)-1)
static int
putRow(fd, row, cols, rowpixels, packed)
FILE *fd;
int row, cols;
pixel *rowpixels;
char *packed;
{
register int i;
int packcols, count, run, rep, oc;
register pixel *pP;
pixel lastp;
register char *p;
run = count = 0;
for (cols--, i = cols, pP = rowpixels + cols, p = packed, lastp = *pP;
i >= 0; i--, lastp = *pP, pP--)
{
if (PPM_EQUAL(lastp, *pP))
run++;
else if (run < RUN_THRESH)
{
while (run > 0)
{
*p++ = ppm_lookupcolor(cht, &lastp);
run--;
count++;
if (count == MAX_COUNT)
{
*p++ = counttochar(MAX_COUNT);
count -= MAX_COUNT;
}
}
run = 1;
}
else
{
if (count > 0)
*p++ = counttochar(count);
count = 0;
while (run > 0)
{
rep = run > MAX_RUN ? MAX_RUN : run;
*p++ = ppm_lookupcolor(cht, &lastp);
*p++ = runtochar(rep);
run -= rep;
}
run = 1;
}
}
if (run < RUN_THRESH)
{
while (run > 0)
{
*p++ = ppm_lookupcolor(cht, &lastp);
run--;
count++;
if (count == MAX_COUNT)
{
*p++ = counttochar(MAX_COUNT);
count -= MAX_COUNT;
}
}
}
else
{
if (count > 0)
*p++ = counttochar(count);
count = 0;
while (run > 0)
{
rep = run > MAX_RUN ? MAX_RUN : run;
*p++ = ppm_lookupcolor(cht, &lastp);
*p++ = runtochar(rep);
run -= rep;
}
run = 1;
}
if (count > 0)
*p++ = counttochar(count);
packcols = p - packed; /* how many did we write? */
if (cols > 250)
{
putShort(fd, packcols);
oc = packcols + 2;
}
else
{
(void) putc(packcols, fd);
oc = packcols + 1;
}
/* now write out the packed row */
while(p != packed)
{
--p;
(void) putc(*p, fd);
}
return (oc);
}
#else /* RUNLENGTH */
/* real dumb putRow with no compression */
static int
putRow(fd, row, cols, rowpixels, packed)
FILE *fd;
int row, cols;
pixel *rowpixels;
char *packed;
{
register int i, j, bc, oc;
register pixel *pP;
#if notdef
bzero(aux, cols); /* aux?? */
#endif /*notdef*/
bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
if (bc > 250)
{
putShort(fd, bc);
oc = bc + 2;
}
else
{
(void) putc(bc, fd);
oc = bc + 1;
}
for (i = 0, pP = rowpixels; i < cols;)
{
if (cols - i > MAX_COUNT)
{
(void) putc(MAX_COUNT - 1, fd);
for (j = 0; j < MAX_COUNT; j++)
{
(void) putc(ppm_lookupcolor(cht, pP), fd);
pP++;
}
i += MAX_COUNT;
}
else
{
(void) putc(cols - i - 1, fd);
for (j = 0; j < cols - i; j++)
{
(void) putc(ppm_lookupcolor(cht, pP), fd);
pP++;
}
i = cols;
}
}
return (oc);
}
#endif /* RUNLENGTH */