/* +-------------------------------------------------------------------+ */ /* | Copyright 1993, David Koblas (koblas@netcom.com) | */ /* | | */ /* | Permission to use, copy, modify, and to distribute this software | */ /* | and its documentation for any purpose is hereby granted without | */ /* | fee, provided that the above copyright notice appear in all | */ /* | copies and that both that copyright notice and this permission | */ /* | notice appear in supporting documentation. There is no | */ /* | representations about the suitability of this software for | */ /* | any purpose. this software is provided "as is" without express | */ /* | or implied warranty. | */ /* | | */ /* +-------------------------------------------------------------------+ */ /* $Id: readWritePS.c,v 1.14 2005/03/20 20:15:34 demailly Exp $ */ /* default ghostcript resolution * replace by 72 if 180 is too much to wish for ... */ #define GS_COMMAND \ "gs -g2000x2000 -sDEVICE=ppmraw -r180 -q -dNOPAUSE -sOutputFile=" #include #include #include #include "image.h" #include "libpnmrw.h" #if defined(sco) || defined(__CYGWIN__) #include #else #include #include #endif #include typedef struct { float wpercent, hpercent; int wbbox, hbbox, width, height, rx, ry, wsubdiv, hsubdiv, orient; } PageInfo; extern void * xmalloc(size_t n); extern FILE * openTemp(char **np); extern void removeTemp(void); #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* static void writePreview(FILE * fd, Image * image) { } */ #if 0 static void writeCmap(FILE * fd, Image * image) { int runlen, maxCount; int col, used; int i, x, y; unsigned char *ucp; char buf[280]; short map[256]; int isRLE; /* ** Remap the colors to the number used */ for (i = 0; i < 256; i++) map[i] = -1; for (ucp = image->data, y = 0; y < image->width * image->height; y++, ucp++) map[*ucp] = 1; for (used = i = 0; i < 256; i++) if (map[i] != -1) map[i] = used++; /* ** If compression will help */ fprintf(fd, "/rgbmap %d string def\n", used * 3); fputs("% RLE drawing routine\n\ /buffer 2 string def \n\ /rgb (000) def \n\ /drawcolormappedimage { \n\ /buffer 1 string def \n\ /rgbval 3 string def \n\ /npixels 384 string def % 128 * 3 \n\ { currentfile buffer readhexstring pop % read run information \n\ /len exch 0 get store \n\ len 128 ge \n\ { 0 1 len 128 sub % this is a run of raw data \n\ { currentfile buffer readhexstring pop pop \n\ /rgbval rgbmap buffer 0 get 3 mul 3 getinterval store \n\ npixels exch 3 mul rgbval putinterval \n\ } for \n\ npixels 0 len 127 sub 3 mul getinterval \n\ } \n\ { % else it's run data \n\ currentfile buffer readhexstring pop pop \n\ /rgbval rgbmap buffer 0 get 3 mul 3 getinterval store \n\ 0 1 len { npixels exch 3 mul rgval putinterval } for \n\ npixels 0 len 1 add 3 mul getinterval \n\ } ifelse \n\ } \n\ false 3 colorimage \n\ } bind def\n", fd); fprintf(fd, "%%%% get the rgb map\n"); fprintf(fd, "currentfile rgbmap readhexstring\n"); ucp = image->cmapData; for (col = i = 0; i < image->cmapSize; i++, ucp += 3) { if (map[i] == -1) continue; fprintf(fd, "%02.2x%02.2x%02.2x ", ucp[0], ucp[1], ucp[2]); if (++col == 10) { putc('\n', fd); col = 0; } } if (col != 0) putc('\n', fd); fprintf(fd, "pop pop\n\n"); fprintf(fd, "%d %d 8\n", image->width, image->height); fprintf(fd, "[ %d 0 0 -%d 0 %d ]\n", image->width, image->height, image->height); fprintf(fd, "drawcolormappedimage\n"); ucp = image->data; maxCount = 0x7f; #define PUT(fd, val) do { \ fprintf(fd, "%02.2x", val); \ if (++col == 35) \ { col = 0; putc('\n', fd); } \ } while (0) #define WRITE(fd, flg, buf, len) do { int _i; \ PUT(fd, (len) + (flg ? 0 : 128)); \ if (flg) \ PUT(fd, map[buf[0]]); \ else \ for (_i = 0; _i < (len); _i++) \ PUT(fd, map[buf[_i]]); \ putc(' ', fd); \ } while (0) col = 0; for (y = 0; y < image->height; y++) { int prev; runlen = 0; for (x = 0; x < image->width; x++, ucp++) { int v = *ucp; if (runlen == 0) isRLE = TRUE; else if (runlen == maxCount) { WRITE(fd, isRLE, buf, runlen); runlen = 0; isRLE = TRUE; } else if (isRLE && v != prev) { if (runlen == 1) isRLE = FALSE; else { WRITE(fd, isRLE, buf, runlen); runlen = 0; } } else if (!isRLE && v == prev) { WRITE(fd, isRLE, buf, runlen); buf[0] = prev; runlen = 1; isRLE = TRUE; } buf[runlen++] = v; prev = v; } if (runlen != 0) WRITE(fd, isRLE, buf, runlen); col = 0; putc('\n', fd); } putc('\n', fd); #undef WRITE #undef PUT } #endif static void writeRGB(FILE * fd, Image * image, PageInfo *pinfo) { unsigned char *ucp, *vcp, *wcp, *tcp; unsigned char r, g, b, rp, gp, bp, wp, hp, i, j; int x, y, xp, yp; int col = 0; wp = (unsigned char) pinfo->wsubdiv; hp = (unsigned char) pinfo->hsubdiv; x = image->width * pinfo->wsubdiv; y = image->height * pinfo->hsubdiv; fprintf(fd, "/line %d string def\n", x * 3); fprintf(fd, "%d %d 8\n", x, y); fprintf(fd, "[ %d 0 0 -%d 0 %d ]\n", x, y, y); fprintf(fd, "{currentfile line readhexstring pop}\n"); fprintf(fd, "false 3 colorimage\n"); if (wp == 1 && hp == 1) for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) { ucp = ImagePixel(image, x, y); fprintf(fd, "%02x%02x%02x", ucp[0], ucp[1], ucp[2]); if (++col == 12) { putc('\n', fd); col = 0; } } else for (y = 0; y < image->height; y++) { if (y+1 < image->height) yp = y+1; else yp = y; for (j = 0; j < hp; j++) for (x = 0; x < image->width; x++) { ucp = ImagePixel(image, x, y); if (x+1 < image->width) xp = x+1; else xp = x; vcp = ImagePixel(image, xp, y); if (j==0) { r = ucp[0]; g = ucp[1]; b = ucp[2]; rp = vcp[0]; gp = vcp[1]; bp = vcp[2]; } else { wcp = ImagePixel(image, x, yp); tcp = ImagePixel(image, xp, yp); r = ((hp-j)*ucp[0] + j*wcp[0])/hp; g = ((hp-j)*ucp[1] + j*wcp[1])/hp; b = ((hp-j)*ucp[2] + j*wcp[2])/hp; rp = ((hp-j)*vcp[0] + j*tcp[0])/hp; gp = ((hp-j)*vcp[1] + j*tcp[1])/hp; bp = ((hp-j)*vcp[2] + j*tcp[2])/hp; } for (i = 0; i < wp; i++) { if (i==0) fprintf(fd, "%02x%02x%02x", r, g, b); else fprintf(fd, "%02x%02x%02x", ((wp-i)*r+i*rp)/wp, ((wp-i)*g+i*gp)/wp, ((wp-i)*b+i*bp)/wp); if (++col == 12) { putc('\n', fd); col = 0; } } } } if (col != 0) putc('\n', fd); } int WriteResizedPS(char *file, Image * image, void *data) { FILE *fd; PageInfo *pinfo = (PageInfo *)data; char *cp, buf[256]; time_t t; if ((fd = fopen(file, "w")) == NULL) return 1; if ((cp = strrchr(file, '/')) == NULL) cp = file; else cp++; strcpy(buf, cp); if ((cp = strrchr(buf, '.')) != NULL) *cp = '\0'; time(&t); fprintf(fd, "%%!PS-Adobe-2.0 EPSF-2.0\n"); fprintf(fd, "%%%%Creator: XPaint\n%%%%Title: %s\n%%%%Pages: 1\n", buf); fprintf(fd, "%%%%BoundingBox: %d %d %d %d\n", 0, 0, pinfo->wbbox, pinfo->hbbox); fprintf(fd, "%%%%CreationDate: %s", ctime(&t)); fprintf(fd, "%%%%EndComments\n"); /* ** Write a preview image */ /* Void routine. Don't know what other people had in mind for this... writePreview(fd, image); */ fprintf(fd, "%%%%EndProlog\n"); fprintf(fd, "%%%%Page: 1 1\n"); fprintf(fd, "\n\ngsave\n\n"); /* ** Write the actual image */ fprintf(fd, "/inch {72 mul} def\n"); if (pinfo->rx || pinfo->ry) fprintf(fd, "%d %d translate\n", pinfo->rx, pinfo->ry); if (pinfo->orient) fprintf(fd, "%d %d translate 90 rotate\n", (int)(0.01 * image->height * pinfo->hpercent), 0); fprintf(fd, "%g %g scale\n", 0.01 * image->width * pinfo->wpercent, 0.01 * image->height * pinfo->hpercent ); #if 0 if (image->cmapSize == 0 || image->cmapSize > 256) writeRGB(fd, image, pinfo); else writeCmap(fd, image); #else writeRGB(fd, image, pinfo); #endif fprintf(fd, "%%\n\ngrestore\nshowpage\n%%%%Trailer\n"); fclose(fd); return 0; } int TestPS(char *file) { char header[8]; FILE *fp = fopen(file, "rb"); /* libpng requires ANSI; so do we */ if (!fp) return 0; fread(header, 1, 8, fp); fclose(fp); if (!strncasecmp(header, "%!PS", 4)) return 1; if (!strncasecmp(header, "%PDF", 4)) return 2; if (!strncasecmp(header, "%TEX", 4)) return 3; if (!strncasecmp(header, "%LTX", 4)) return 4; return 0; } Image * ReadPS(char *file) { char *tmp; char rad[260]; char buf[2048]; FILE *fp; int format; int wth, hth, w, h, pnm_type, bytes_per_pixel, type_doc; int x, y, i, j; int top, bottom, left, right; int *lborder, *rborder; xel **els = NULL; xel *curel; xelval maxval; char filled, newchr; char *compil, *data, *dp; Image *image; fp = fopen(file, "rb"); if (!fp) return NULL; fclose(fp); fp = openTemp(&tmp); if (!fp) return NULL; fclose(fp); type_doc = TestPS(file); if (!type_doc) return; /* should not happen anyway ... */ strncpy(rad, file, 256), rad[256] = '\0'; if ((dp=rindex(rad, '.'))) *dp = '\0'; if (type_doc>=3) { if (type_doc==3) compil = "tex"; if (type_doc==4) compil = "latex"; sprintf(buf, "%s \"\\\\nonstopmode\\\\input\" %s ; dvips %s.dvi -o %s.ps ", compil, file, rad, rad); system(buf); strcat(rad, ".ps"); } else strcpy(rad, file); sprintf(buf, GS_COMMAND"%s -- %s", tmp, rad); system(buf); pnm_init2(tmp); if ((fp = fopen(tmp, "r")) == NULL) return NULL; if ((els = pnm_readpnm(fp, &wth, &hth, &maxval, &format)) == NULL) return NULL; pnm_type = PNM_FORMAT_TYPE(format); fclose(fp); removeTemp(); if (pnm_type == PPM_TYPE) bytes_per_pixel = 3; else bytes_per_pixel = 1; data = (char *)xmalloc(bytes_per_pixel*wth*hth); lborder = (int *)xmalloc(hth*sizeof(int)); rborder = (int *)xmalloc(hth*sizeof(int)); if (!data || !lborder || !rborder) return NULL; dp = data; for (y = 0; y < hth; y++) { lborder[y] = 0; rborder[y] = -1; for (curel = els[y], x = 0; x < wth; x++, curel++) { if (pnm_type == PPM_TYPE) { newchr = *dp++ = 255 * PPM_GETR(*curel) / maxval; filled = 255-newchr; newchr = *dp++ = 255 * PPM_GETG(*curel) / maxval; filled |= 255-newchr; newchr = *dp++ = 255 * PPM_GETB(*curel) / maxval; filled |= 255-newchr; } else if (pnm_type == PGM_TYPE) { newchr = *dp++ = 255 * PNM_GET1(*curel) / maxval; filled = 255-newchr; } else { newchr = *dp++ = (PNM_GET1(*curel) != PBM_WHITE) ? 1 : 0; filled = 1-newchr; } if (filled) rborder[y] = x; else { if (lborder[y] == x) ++lborder[y]; } } } top = 0; bottom = -1; left = wth-1; right = 0; for (y = 0; y < hth; y++) { if (rborder[y] == -1) { if (top == y) ++top; } else bottom = y; if (lborder[y]right) right = rborder[y]; } if (top>bottom || left>right) return NULL; w = right-left+1; h = bottom-top+1; if (pnm_type == PBM_TYPE) image = ImageNewBW(w, h); else if (pnm_type == PGM_TYPE) image = ImageNewGrey(w, h); else image = ImageNew(w, h); if (pnm_type == PPM_TYPE) { for (y = top; y <= bottom; y++) for (x = left; x <= right; x++) { i = 3*(y*wth + x); j = 3*((y-top)*w + x-left); memcpy(&image->data[j], &data[i], 3); } } else { for (y = top; y <= bottom; y++) for (x = left; x <= right; x++) { i = y*wth + x; j = (y-top)*w + x-left; image->data[j] = data[i]; } } free(data); free(lborder); free(rborder); pnm_freearray(els, hth); return image; } int WritePS(char *file, Image * image) { PageInfo pinfo; pinfo.wbbox = image->width; pinfo.hbbox = image->height; pinfo.width = image->width; pinfo.height = image->height; pinfo.rx = 0; pinfo.ry = 0; pinfo.wsubdiv = 1; pinfo.hsubdiv = 1; pinfo.orient = 0; pinfo.wpercent = 100.0; pinfo.hpercent = 100.0; return WriteResizedPS(file, image, &pinfo); } int WritePDF(char *file, Image * image) { char *tmp; char buf[512]; FILE *fp; fp = openTemp(&tmp); if (!fp) return 1; fclose(fp); if (WritePS(tmp, image)) return 1; fp = fopen(tmp, "rb"); if (!fp) return 1; fclose(fp); sprintf(buf, "gs -sDEVICE=pdfwrite -q -dNOPAUSE -sOutputFile=%s -- %s", file, tmp); system(buf); removeTemp(); return 0; }