amiga_imgv
view tools/convhammer/main.c @ 7:4c36d0f44aa6
lbm loading
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 29 Oct 2017 13:21:11 +0200 |
parents | 663471a80c21 |
children |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <arpa/inet.h>
6 #include "image.h"
8 /* hammer dump format (input)
9 * byte order: little endian
10 *
11 * 4 bytes: palette changes per scanline (cps)
12 * 256 * cps * 2 bytes: [ idx | r | g | b ]
13 * 320 * 256 bytes: linear HAM pixels
14 */
16 /* interleaved ham format (output)
17 * byte order: big endian
18 *
19 * 4 bytes: magic: "HAAM"
20 * 2 bytes: width
21 * 2 bytes: height
22 * 1 byte: number of bitplanes
23 * 1 byte: padding
24 * 2 bytes: number of palette change descriptors (nchg)
25 * 16 * 2 bytes: initial palette [ x | r | g | b ]
26 * nchg * 4 bytes: [ scanline ] [ idx | r | g | b ]
27 * width * height / 8 * bitplanes bytes: pixels interleaved scanlines
28 * [ row0 bpl0 ] ... [ row0 bplN ] [ row1 bpl0 ] ... [ row1 bplN ] ...
29 */
31 struct ham_image *load_hammer(const char *fname);
32 int save_ham(struct ham_image *img, const char *fname);
33 int save_ppm(struct ham_image *img, const char *fname);
34 void free_image(struct ham_image *img);
36 int main(int argc, char **argv)
37 {
38 int i;
39 struct ham_image *img;
40 char *name, *dot;
42 for(i=1; i<argc; i++) {
43 if(!(img = load_hammer(argv[i]))) {
44 fprintf(stderr, "failed to load hammer dump: %s\n", argv[i]);
45 continue;
46 }
48 if(!(name = malloc(strlen(argv[i] + 8)))) {
49 perror("failed to allocate output name buffer");
50 abort();
51 }
52 strcpy(name, argv[i]);
54 if((dot = strrchr(name, '.'))) {
55 *dot = 0;
56 }
57 strcat(name, ".ham");
59 if(save_ham(img, name) == -1) {
60 fprintf(stderr, "failed to save ham image: %s\n", name);
61 free_image(img);
62 continue;
63 }
65 if((dot = strrchr(name, '.'))) {
66 *dot = 0;
67 }
68 strcat(name, ".ppm");
70 if(save_ppm(img, name) == -1) {
71 fprintf(stderr, "failed to save ppm image: %s\n", name);
72 free_image(img);
73 continue;
74 }
75 }
76 return 0;
77 }
79 static uint16_t nops(uint16_t x) { return x; }
80 static uint16_t swaps(uint16_t x) { return (x >> 8) | (x << 8); }
82 struct ham_image *load_hammer(const char *fname)
83 {
84 int i, x, y, pstart, numpix = 320 * 256;
85 FILE *fp = 0;
86 uint32_t cps, npalent;
87 struct ham_image *img = 0;
88 struct palchange *tail = 0;
89 unsigned char *inpixels = 0;
90 unsigned char *srcptr, *destptr;
91 uint16_t endtest = 0xaabb;
92 uint16_t (*letohs)(uint16_t);
94 letohs = (*(unsigned char*)&endtest == 0xaa) ? swaps : nops;
96 if(!(fp = fopen(fname, "rb"))) {
97 fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno));
98 return 0;
99 }
101 if(!(img = malloc(sizeof *img))) {
102 perror("failed to allocate image");
103 goto err;
104 }
105 img->width = 320;
106 img->height = 256;
107 img->nbitplanes = 6;
108 img->chglist = 0;
110 if(!(img->pixels = malloc(img->width * img->height / 8 * img->nbitplanes))) {
111 perror("failed to allocate pixels");
112 goto err;
113 }
115 if(fread(&cps, 4, 1, fp) < 1) goto err;
116 cps = letohs(cps);
117 if(cps <= 0 || cps > 16) {
118 fprintf(stderr, "invalid changes-per-line value: %u\n", (unsigned int)cps);
119 goto err;
120 }
121 printf(" image needs %d palette changes/line\n", (int)cps);
123 /* read palette changes and palette */
125 npalent = cps * 256;
126 pstart = npalent - 16;
128 for(i=0; i<npalent; i++) {
129 uint16_t palent;
130 struct palchange *chg;
132 if(fread(&palent, 2, 1, fp) < 1) {
133 perror("unexpected end of file");
134 goto err;
135 }
136 palent = letohs(palent);
138 if(!(chg = malloc(sizeof *chg))) {
139 perror("failed to allocate palchange node");
140 goto err;
141 }
142 chg->line = i / cps;
143 chg->entry = palent;
144 chg->next = 0;
145 if(tail) {
146 tail->next = chg;
147 tail = chg;
148 } else {
149 img->chglist = tail = chg;
150 }
152 if(i >= pstart) {
153 img->palette[i - pstart] = palent & 0xfff;
154 }
155 }
157 /* read pixels */
158 if(!(inpixels = malloc(numpix))) {
159 perror("failed to allocate pixel buffer");
160 goto err;
161 }
162 if(fread(inpixels, 1, numpix, fp) < numpix) {
163 perror("unexpected end of file while reading pixels");
164 goto err;
165 }
167 /* correct HAM codes */
168 srcptr = inpixels;
169 for(i=0; i<numpix; i++) {
170 unsigned char idx = *srcptr;
171 int ham = (idx >> 4) & 3;
173 switch(ham) {
174 case 1:
175 ham = 2;
176 break;
177 case 2:
178 ham = 3;
179 break;
180 case 3:
181 ham = 1;
182 default:
183 break;
184 }
186 *srcptr++ = (idx & 0xf) | (ham << 4);
187 }
189 for(i=0; i<img->nbitplanes; i++) {
190 srcptr = inpixels;
191 destptr = img->pixels + i * img->width / 8;
192 for(y=0; y<img->height; y++) {
193 unsigned char pixval = 0;
194 for(x=0; x<img->width; x++) {
195 pixval = (pixval << 1) | ((*srcptr++ >> i) & 1);
196 if((x & 7) == 7) {
197 *destptr++ = pixval;
198 pixval = 0;
199 }
200 }
201 destptr += img->width / 8 * (img->nbitplanes - 1);
202 }
203 }
205 free(inpixels);
206 fclose(fp);
207 return img;
209 err:
210 free(inpixels);
211 if(img) {
212 while(img->chglist) {
213 void *tmp = img->chglist;
214 img->chglist = img->chglist->next;
215 free(tmp);
216 }
217 free(img->pixels);
218 free(img);
219 }
220 if(fp) fclose(fp);
221 return 0;
222 }
224 int save_ham(struct ham_image *img, const char *fname)
225 {
226 int i, num;
227 unsigned char c, *pptr;
228 uint16_t val;
229 FILE *fp;
230 struct palchange *chg;
232 if(!(fp = fopen(fname, "wb"))) {
233 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
234 return -1;
235 }
236 fprintf(fp, "HAAM");
238 val = htons(img->width);
239 fwrite(&val, 2, 1, fp);
240 val = htons(img->height);
241 fwrite(&val, 2, 1, fp);
242 c = img->nbitplanes;
243 fwrite(&c, 1, 1, fp);
244 fwrite(&c, 1, 1, fp); /* padding */
246 num = 0;
247 chg = img->chglist;
248 while(chg) {
249 ++num;
250 chg = chg->next;
251 }
252 num = htons(num);
253 fwrite(&num, 2, 1, fp);
255 for(i=0; i<16; i++) {
256 val = htons(img->palette[i]);
257 fwrite(&val, 2, 1, fp);
258 }
260 chg = img->chglist;
261 while(chg) {
262 val = htons(chg->line);
263 fwrite(&val, 2, 1, fp);
264 val = htons(chg->entry);
265 fwrite(&val, 2, 1, fp);
266 chg = chg->next;
267 }
269 pptr = img->pixels;
270 num = img->width * img->height / 8 * img->nbitplanes;
271 for(i=0; i<num; i++) {
272 fwrite(pptr, 1, 1, fp);
273 ++pptr;
274 }
275 fclose(fp);
276 return 0;
277 }
279 #define ARED(x) ((((x) & 0xf00) >> 4) | (((x) & 0xf00) >> 8))
280 #define AGREEN(x) (((x) & 0xf0) | (((x) & 0xf0) >> 4))
281 #define ABLUE(x) ((((x) & 0xf) << 4) | ((x) & 0xf))
283 int save_ppm(struct ham_image *img, const char *fname)
284 {
285 int i, j, k;
286 unsigned char palette[16][3];
287 unsigned char color[3] = {0, 0, 0};
288 unsigned char *src;
289 FILE *fp;
290 struct palchange *chg = img->chglist;
292 if(!(fp = fopen(fname, "wb"))) {
293 fprintf(stderr, "failed to open: %s for writing: %s\n", fname, strerror(errno));
294 return -1;
295 }
296 fprintf(fp, "P6\n%d %d\n255\n", img->width, img->height);
298 for(i=0; i<16; i++) {
299 uint16_t pcol = img->palette[i];
300 palette[i][0] = ARED(pcol);
301 palette[i][1] = AGREEN(pcol);
302 palette[i][2] = ABLUE(pcol);
303 }
305 src = img->pixels;
306 for(i=0; i<img->height; i++) {
307 while(chg && chg->line <= i) {
308 int idx = (chg->entry & 0xf000) >> 12;
309 /*printf("line %d chg idx: %d -> %d %d %d\n", i, idx, ARED(chg->entry), AGREEN(chg->entry), ABLUE(chg->entry));*/
310 palette[idx][0] = ARED(chg->entry);
311 palette[idx][1] = AGREEN(chg->entry);
312 palette[idx][2] = ABLUE(chg->entry);
313 chg = chg->next;
314 }
316 for(j=0; j<img->width; j++) {
317 unsigned char idx = 0;
318 unsigned char ham;
319 int bit = 7 - (j & 7);
321 for(k=0; k<img->nbitplanes; k++) {
322 idx |= (((*(src + k * img->width / 8) >> bit) & 1) << k);
323 }
325 ham = (idx >> 4) & 3;
327 switch(ham) {
328 case 0:
329 color[0] = palette[idx][0];
330 color[1] = palette[idx][1];
331 color[2] = palette[idx][2];
332 break;
333 case 1:
334 color[2] = ABLUE(idx);
335 break;
336 case 2:
337 color[0] = ABLUE(idx);
338 break;
339 case 3:
340 color[1] = ABLUE(idx);
341 }
343 fputc(color[0], fp);
344 fputc(color[1], fp);
345 fputc(color[2], fp);
347 if(!bit) {
348 ++src;
349 }
350 }
351 src += img->width / 8 * (img->nbitplanes - 1);
352 }
354 fclose(fp);
355 return 0;
356 }
358 void free_image(struct ham_image *img)
359 {
360 if(img) {
361 free(img->pixels);
362 while(img->chglist) {
363 void *tmp = img->chglist;
364 img->chglist = img->chglist->next;
365 free(tmp);
366 }
367 free(img);
368 }
369 }