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