1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
/*
* pnmraw2cmyk.c -- converts RBG image from PNM raw
* to series of dithered CMY(K) PBMraw bitmaps
*
* (C) 1999 Henryk Paluch, released under GNU GPL license, version 2
*
* $Id: pnmraw2cmyk.c,v 1.3 1999/03/28 17:52:49 henryk Exp $
*/
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<unistd.h> /* getopt() */
#include<syslog.h>
#define DIV8(x) ( (x) >> 3 )
#define MOD8(x) ( (x) & 0x7 )
int height; /* height of PBM bitmap (lines e.g., pixels) */
int width; /* width of line bitmap in pixels) */
int bwidth; /* real bitmap width (bytes) */
int obwidth; /* output bitmap width (bytes) */
int obsize; /* output bitmap size (bytes) */
int plates; /* number of color plates (3 or 4) */
unsigned char *lines=NULL; /* this is pixel buffer for one line */
unsigned char *olines=NULL;
static char *fprefix=NULL;
static int mayeof=0;
static int genk=0;
/* parse_pnm_header() - decodes header of PNM bitmap
* sets global vars: height (pixels),
* bwidth (real bitamp width - bytes)
* width (memory bitmap width - bytes)
* PNMraw is simple RGB bitmap. It consists
* of text header and raw data bytes.
* Example: P6
* # comment lines
* width height
* 255
* raw bytes
*
* width & height is in pixels,
* every pixel is 3 byte value of RGB
*/
int parse_pnm_header(FILE *f)
{
char buf[1024];
int tmp;
if (fgets(buf,1023,f)==0 || strncmp(buf,"P6",2)!=0)
{
if (mayeof)
return 0;
else
{
fprintf(stderr,"Illegal pnmraw header");
exit(-1);
}
}
do{
fgets(buf,1023,f); /* skip comment line(s) */
}while(buf[0]=='#');
sscanf(buf,"%d %d\n",&width,&height);
if (width <=0 || height <=0)
{
fprintf(stderr,"Illegal width (%d) or height (%d)\n",width,height);
exit(-1);
}
fgets(buf,64,stdin); // scanf corrupts \n !!!
bwidth= width*3; /* round width to whole byte */
fprintf(stderr,"bwidth (bytes): %d (%d pixels), height (lines): %d\n",
bwidth,width, height);
return 1;
}
/* read_lines() -- read 'readcount' data lines from PBM bitmap
* to 'lines' -- bitmap in memory
*/
int read_line(FILE *f)
{
int i,c;
if (lines==NULL)
lines=(char*)malloc(bwidth);
/* zero the buffer */
/* memset(lines,(char)0,bwidth); */
c=fread(lines,1,bwidth,f);
if (c==-1)
{
perror("fread");
exit(-1);
}
return c;
}
static void write_pbm_bitmap(FILE *f,unsigned char *buf,char *filename,
int plate)
{
char *plnames[4]={"Cyan","Magenta","Yellow","Black"};
int i;
fprintf(f,"P4\n");
fprintf(f,"# dithered separation '%s', %s plate\n",
filename,plnames[plate]);
fprintf(f,"%d %d\n",width,height);
for(i=0;i<height;i++)
{
if (fwrite(buf+i*obwidth,1,obwidth,f)!=obwidth)
{
fprintf(stderr,"short write\n");
exit(-1);
}
}
}
static void usage(void)
{
int i;
fprintf(stderr,"pnmraw2cmyk PBMraw bitmap converter\n");
fprintf(stderr," convert PNMraw RGB bitmap into separate"
" CMY(K) dithered PBMraw bitmaps\n");
fprintf(stderr,"Usage: pnmraw2cmyk [ -h ] "
" < input.pnmraw > output.pbmraw (s)\n");
fprintf(stderr," -h\tthis help text\n");
fprintf(stderr," -o name\toutput to separate CMY(K) files"
" instead of stdout\n");
fprintf(stderr," -k generate full CMYK instead of CMY\n");
exit(-1);
}
int main(int argc, char *argv[])
{
int pagecount=0;
int c,i;
while( (c=getopt(argc, argv, ":o:hk"))!=-1 )
switch(c){
case 'h':
usage();
break;
case 'o':
fprefix=optarg;
break;
case 'k':
genk=1;
break;
default:
usage();
}
plates= (genk ? 4 : 3); /* number of color plates: 3 = CMY, 4 = CMYK */
/* process raw PBM bitmap(s) */
while(parse_pnm_header(stdin))
{
obwidth=(width+7)/8;
fprintf(stderr,"Output bitmap width (%d bytes)\n",obwidth);
obsize=obwidth*height;
fprintf(stderr,"Output bitmap size (%d bytes)\n",obsize);
olines=(unsigned char*)malloc(obsize*plates);
fprintf(stderr,"Allocated %d bytes for %d bitmaps\n",obsize*plates,
plates);
/* now it is time to dither */
for(i=0;i<height;i++)
{
if (read_line(stdin)!=bwidth)
{
fprintf(stderr,"short read\n");
exit(-1);
}
dither_cmyk(lines, /* input row */
i, /* row number */
width, /* width of source in pixels */
width, /* width of dest in pixels */
olines+0*obsize+obwidth*i, /* cyan outbuf */
olines+1*obsize+obwidth*i, /* magenta outbuf */
olines+2*obsize+obwidth*i, /* yellow outbuf */
(genk ? /* black outbuf */
olines+3*obsize+obwidth*i
: NULL ));
}
if (fprefix!=NULL)
{
char pnames[]="cmyk";
FILE *ff;
int y;
char buf[1024];
for(y=0;y<plates;y++)
{
snprintf(buf,1023,"%s%c-%03d.pbm",fprefix,pnames[y],pagecount);
if ( (ff=fopen(buf,"w+"))==NULL)
{
fprintf(stderr,"fopen '%s'",buf);
perror("");
exit(-1);
}
write_pbm_bitmap(ff,olines+y*obsize,buf,y);
fclose(ff);
}
}
else
{
int y;
for(y=0;y<plates;y++)
write_pbm_bitmap(stdout,olines+y*obsize,"(stdout)",y);
}
pagecount++;
mayeof=1;
if (lines!=NULL)
{
free(lines);
lines=NULL;
}
if (olines!=NULL)
{
free(olines);
olines=NULL;
}
}
return 0;
}
|