2 * graphics file reading for page
13 typedef struct Convert Convert;
14 typedef struct GfxInfo GfxInfo;
15 typedef struct Graphic Graphic;
20 char *truecmd; /* cmd for true color */
30 uchar *buf; /* if stdin */
51 * N.B. These commands need to read stdin if %a is replaced
52 * with an empty string.
55 [Ipic] { "plan9", "fb/3to1 rgbv %a |fb/pcp -tplan9" },
56 [Itiff] { "tiff", "fb/tiff2pic %a | fb/3to1 rgbv | fb/pcp -tplan9" },
57 [Iplan9bm] { "plan9bm", nil },
58 [Ijpeg] { "jpeg", "jpg -9 %a", "jpg -t9 %a" },
59 [Igif] { "gif", "gif -9 %a", "gif -t9 %a" },
60 [Iinferno] { "inferno", nil },
61 [Ifax] { "fax", "aux/g3p9bit -g %a" },
62 [Icvt2pic] { "unknown", "fb/cvt2pic %a |fb/3to1 rgbv" },
63 [Ippm] { "ppm", "ppm -9 %a", "ppm -t9 %a" },
64 /* ``temporary'' hack for hobby */
65 [Iccittg4] { "ccitt-g4", "cat %a|rx nslocum /usr/lib/ocr/bin/bcp -M|fb/pcp -tcompressed -l0" },
66 [Ipng] { "png", "png -9 %a", "png -t9 %a" },
67 [Iyuv] { "yuv", "yuv -9 %a", "yuv -t9 %a" },
68 [Ibmp] { "bmp", "bmp -9 %a", "bmp -t9 %a" }
71 static Image* convert(Graphic*);
72 static Image* gfxdrawpage(Document *d, int page);
73 static char* gfxpagename(Document*, int);
74 static int spawnrc(char*, uchar*, int);
75 static void waitrc(void);
76 static int spawnpost(int);
77 static int addpage(Document*, char*);
78 static int rmpage(Document*, int);
79 static int genaddpage(Document*, char*, uchar*, int);
82 gfxpagename(Document *doc, int page)
84 GfxInfo *gfx = doc->extra;
85 return gfx->g[page].name;
89 gfxdrawpage(Document *doc, int page)
91 GfxInfo *gfx = doc->extra;
92 return convert(gfx->g+page);
96 initgfx(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
104 doc = emalloc(sizeof(*doc));
105 gfx = emalloc(sizeof(*gfx));
109 doc->drawpage = gfxdrawpage;
110 doc->pagename = gfxpagename;
111 doc->addpage = addpage;
112 doc->rmpage = rmpage;
116 fprint(2, "reading through graphics...\n");
118 genaddpage(doc, nil, buf, nbuf);
120 for(i=0; i<argc; i++)
121 if(addpage(doc, argv[i]) < 0)
122 fprint(2, "warning: not including %s: %r\n", argv[i]);
129 genaddpage(Document *doc, char *name, uchar *buf, int nbuf)
140 assert((name == nil) ^ (buf == nil));
141 assert(name != nil || doc->npage == 0);
143 for(i=0; i<doc->npage; i++)
144 if(strcmp(gfx->g[i].name, name) == 0)
149 if((b = Bopen(name, OREAD)) == nil) {
150 werrstr("Bopen: %r");
154 if(Bread(b, xbuf, sizeof xbuf) != sizeof xbuf) {
155 werrstr("short read: %r");
164 gfx->g = erealloc(gfx->g, (doc->npage+1)*(sizeof(*gfx->g)));
165 g = &gfx->g[doc->npage];
167 memset(g, 0, sizeof *g);
168 if(memcmp(buf, "GIF", 3) == 0)
170 else if(memcmp(buf, "\111\111\052\000", 4) == 0)
172 else if(memcmp(buf, "\115\115\000\052", 4) == 0)
174 else if(memcmp(buf, "\377\330\377", 3) == 0)
176 else if(memcmp(buf, "\211PNG\r\n\032\n", 3) == 0)
178 else if(memcmp(buf, "compressed\n", 11) == 0)
180 else if(memcmp(buf, "\0PC Research, Inc", 17) == 0)
182 else if(memcmp(buf, "TYPE=ccitt-g31", 14) == 0)
184 else if(memcmp(buf, "II*", 3) == 0)
186 else if(memcmp(buf, "TYPE=ccitt-g4", 13) == 0)
188 else if(memcmp(buf, "TYPE=", 5) == 0)
190 else if(buf[0] == 'P' && '0' <= buf[1] && buf[1] <= '9')
192 else if(memcmp(buf, "BM", 2) == 0)
194 else if(memcmp(buf, " ", 10) == 0 &&
195 '0' <= buf[10] && buf[10] <= '9' &&
198 else if(strtochan((char*)buf) != 0)
200 else if (l > 4 && strcmp(name + l -4, ".yuv") == 0)
206 g->name = estrdup(name);
208 g->name = estrdup("stdin"); /* so it can be freed */
213 if(chatty) fprint(2, "classified \"%s\" as \"%s\"\n", g->name, cvt[g->type].name);
218 addpage(Document *doc, char *name)
220 return genaddpage(doc, name, nil, 0);
224 rmpage(Document *doc, int n)
229 if(n < 0 || n >= doc->npage)
234 free(gfx->g[n].name);
236 for(i=n; i<doc->npage; i++)
237 gfx->g[i] = gfx->g[i+1];
253 char *name, buf[1000];
260 if(chatty) fprint(2, "no conversion for bitmap \"%s\"...\n", g->name);
261 if(g->buf == nil){ /* not stdin */
262 fd = open(g->name, OREAD);
264 fprint(2, "cannot open file: %r\n");
268 fd = stdinpipe(g->buf, g->nbuf);
271 if(truecolor && c.truecmd)
274 if(g->buf != nil) /* is stdin */
278 if(strlen(cmd)+strlen(name) > sizeof buf) {
279 fprint(2, "command too long\n");
282 snprint(buf, sizeof buf, cmd, name);
283 if(chatty) fprint(2, "using \"%s\" to convert \"%s\"...\n", buf, g->name);
284 fd = spawnrc(buf, g->buf, g->nbuf);
287 fprint(2, "cannot spawn converter: %r\n");
292 im = readimage(display, fd, 0);
294 fprint(2, "warning: couldn't read image: %r\n");
298 /* for some reason rx doesn't work well with wait */
299 /* for some reason 3to1 exits on success with a non-null status of |3to1 */
300 if(rcspawned && g->type != Iccittg4) {
301 if((w=wait())!=nil && w->msg[0] && !strstr(w->msg, "3to1"))
302 fprint(2, "slave wait error: %s\n", w->msg);
309 spawnrc(char *cmd, uchar *stdinbuf, int nstdinbuf)
314 if(chatty) fprint(2, "spawning(%s)...", cmd);
318 if((pid = fork()) < 0)
324 dup(stdinpipe(stdinbuf, nstdinbuf), 0);
326 dup(open("/dev/null", OREAD), 0);
329 execl("/bin/rc", "rc", "-c", cmd, nil);