1 /*
2  * xvpictoppm.c - reads XV 'thumbnail' files from stdin, writes standard PPM
3  *   files to stdout
4  */
5 
6 /*
7  *  THUMBNAIL FILE FORMAT:
8  *
9  * <magic number 'P7 332' >
10  * <comment identifying version of XV that wrote this file>
11  * <comment identifying type & size of the full-size image>
12  * <OPTIONAL comment identifying this as a BUILT-IN icon, in which case
13  *    there is no width,height,maxval info, nor any 8-bit data>
14  * <comment signifying end of comments>
15  * <width, height, and maxval of this file >
16  * <raw binary 8-bit data, in 3/3/2 Truecolor format>
17  *
18  * Example:
19  *    P7 332
20  *    #XVVERSION:Version 2.28  Rev: 9/26/92
21  *    #IMGINFO:512x440 Color JPEG
22  *    #END_OF_COMMENTS
23  *    48 40 255
24  *    <binary data>
25  *
26  * alternately:
27  *    P7 332
28  *    #XVVERSION:Version 2.28 Rev: 9/26/92
29  *    #BUILTIN:UNKNOWN
30  *    #IMGINFO:
31  *    #END_OF_COMMENTS
32  */
33 
34 
35 #include "xv.h"
36 #include "copyright.h"
37 
38 
39 
40 /*************** Function Declarations *************/
41        int   main          PARM((int, char **));
42 static void  errexit       PARM((void));
43 static byte *loadThumbFile PARM((int *, int *));
44 static void  writePPM      PARM((byte *, int, int));
45 
46 
47 
48 /****************************/
main(argc,argv)49 int main(argc, argv)
50      int    argc;
51      char **argv;
52 {
53   byte *pic;
54   int   w,h;
55 
56   pic = loadThumbFile(&w, &h);
57   writePPM(pic, w, h);
58 
59   return 0;
60 }
61 
62 
63 /****************************/
errexit()64 static void errexit()
65 {
66   perror("Unable to convert thumbnail file");
67   exit(-1);
68 }
69 
70 
71 /****************************/
loadThumbFile(wptr,hptr)72 static byte *loadThumbFile(wptr, hptr)
73      int  *wptr, *hptr;
74 {
75   /* read a thumbnail file from stdin */
76 
77   FILE *fp;
78   byte  *icon8, *pic24, *ip, *pp;
79   char  buf[256];
80   int   i, builtin, w, h, maxval, npixels, p24sz;
81 
82   fp = stdin;
83   builtin = 0;
84 
85   if (!fgets(buf, 256, fp))               errexit();
86   if (strncmp(buf, "P7 332", (size_t) 6)) errexit();
87 
88   /* read comments until we see '#END_OF_COMMENTS', or hit EOF */
89   while (1) {
90     if (!fgets(buf, 256, fp)) errexit();
91 
92     if (!strncmp(buf, "#END_OF_COMMENTS", (size_t) 16)) break;
93 
94     else if (!strncmp(buf, "#BUILTIN:",   (size_t)  9)) {
95       builtin = 1;
96       fprintf(stderr, "Built-in icon:  no image to convert\n");
97       exit(1);
98     }
99   }
100 
101 
102   /* read width, height, maxval */
103   if (!fgets(buf, 256, fp) || sscanf(buf, "%d %d %d", &w, &h, &maxval) != 3)
104     errexit();
105 
106   npixels = w * h;
107   p24sz = 3 * npixels;
108 
109   if (w <= 0 || h <= 0 || maxval != 255 || npixels/w != h || p24sz/3 != npixels)
110   {
111     fprintf(stderr, "Thumbnail dimensions out of range\n");
112     exit(1);
113   }
114 
115 
116   /* read binary data */
117   icon8 = (byte *) malloc((size_t) npixels);
118   if (!icon8) errexit();
119 
120   i = fread(icon8, (size_t) 1, (size_t) npixels, fp);
121   if (i != npixels) errexit();
122 
123 
124   /* make 24-bit version of icon */
125   pic24 = (byte *) malloc((size_t) p24sz);
126   if (!pic24) errexit();
127 
128   /* convert icon from 332 to 24-bit image */
129   for (i=0, ip=icon8, pp=pic24;  i<npixels;  i++, ip++, pp+=3) {
130     pp[0] = ( ((int) ((*ip >> 5) & 0x07)) * 255) / 7;
131     pp[1] = ( ((int) ((*ip >> 2) & 0x07)) * 255) / 7;
132     pp[2] = ( ((int) ((*ip >> 0) & 0x03)) * 255) / 3;
133   }
134 
135   free(icon8);
136 
137   *wptr = w;  *hptr = h;
138   return pic24;
139 }
140 
141 
142 /*******************************************/
writePPM(pic,w,h)143 static void writePPM(pic, w, h)
144      byte *pic;
145      int   w,h;
146 {
147   FILE *fp;
148   byte *pix;
149   int   i,j,len;
150 
151   fp = stdout;
152 
153   fprintf(fp,"P6\n");
154   fprintf(fp,"%d %d %d\n", w, h, 255);
155 
156   if (ferror(fp)) errexit();
157 
158   for (i=0, pix=pic, len=0; i<h; i++) {
159     for (j=0; j<w; j++, pix+=3) {
160       putc(pix[0],fp);  putc(pix[1],fp);  putc(pix[2],fp);
161     }
162   }
163 
164   if (ferror(fp)) errexit();
165 }
166