amiga_imgv

view tools/convhammer/main.c @ 2:f75893a33234

hammer -> ham image converter
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Oct 2017 10:04:29 +0300
parents 6320a20f17c5
children 663471a80c21
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 void free_image(struct ham_image *img);
35 int main(int argc, char **argv)
36 {
37 int i;
38 struct ham_image *img;
39 char *name, *dot;
41 for(i=1; i<argc; i++) {
42 if(!(img = load_hammer(argv[i]))) {
43 fprintf(stderr, "failed to load hammer dump: %s\n", argv[i]);
44 continue;
45 }
47 if(!(name = malloc(strlen(argv[i] + 8)))) {
48 perror("failed to allocate output name buffer");
49 abort();
50 }
51 strcpy(name, argv[i]);
53 if((dot = strrchr(name, '.'))) {
54 *dot = 0;
55 }
56 strcat(name, ".ham");
58 if(save_ham(img, name) == -1) {
59 fprintf(stderr, "failed to save ham image: %s\n", name);
60 free_image(img);
61 continue;
62 }
63 }
64 return 0;
65 }
67 static uint16_t nops(uint16_t x) { return x; }
68 static uint16_t swaps(uint16_t x) { return (x >> 8) | (x << 8); }
70 struct ham_image *load_hammer(const char *fname)
71 {
72 int i, x, y, pstart, numpix = 320 * 256;
73 FILE *fp = 0;
74 uint32_t cps, npalent;
75 struct ham_image *img = 0;
76 struct palchange *tail = 0;
77 unsigned char *inpixels = 0;
78 unsigned char *srcptr, *destptr;
79 uint16_t endtest = 0xaabb;
80 uint16_t (*letohs)(uint16_t);
82 letohs = (*(unsigned char*)&endtest == 0xaa) ? swaps : nops;
84 if(!(fp = fopen(fname, "rb"))) {
85 fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno));
86 return 0;
87 }
89 if(!(img = malloc(sizeof *img))) {
90 perror("failed to allocate image");
91 goto err;
92 }
93 img->width = 320;
94 img->height = 256;
95 img->nbitplanes = 6;
96 img->chglist = 0;
98 if(!(img->pixels = malloc(img->width * img->height / 8 * img->nbitplanes))) {
99 perror("failed to allocate pixels");
100 goto err;
101 }
103 if(fread(&cps, 4, 1, fp) < 1) goto err;
104 cps = letohs(cps);
105 if(cps <= 0 || cps > 16) {
106 fprintf(stderr, "invalid changes-per-line value: %u\n", (unsigned int)cps);
107 goto err;
108 }
110 /* read palette changes and palette */
112 npalent = cps * 256;
113 pstart = npalent - 16;
115 for(i=0; i<npalent; i++) {
116 uint16_t palent;
117 struct palchange *chg;
119 if(fread(&palent, 2, 1, fp) < 1) {
120 perror("unexpected end of file");
121 goto err;
122 }
123 palent = letohs(palent);
125 if(!(chg = malloc(sizeof *chg))) {
126 perror("failed to allocate palchange node");
127 goto err;
128 }
129 chg->line = i / cps;
130 chg->entry = palent;
131 chg->next = 0;
132 if(tail) {
133 tail->next = chg;
134 tail = chg;
135 } else {
136 img->chglist = tail = chg;
137 }
139 if(i >= pstart) {
140 img->palette[i - pstart] = palent & 0xfff;
141 }
142 }
144 /* read pixels */
145 if(!(inpixels = malloc(numpix))) {
146 perror("failed to allocate pixel buffer");
147 goto err;
148 }
149 if(fread(inpixels, 1, numpix, fp) < numpix) {
150 perror("unexpected end of file while reading pixels");
151 goto err;
152 }
154 for(i=0; i<img->nbitplanes; i++) {
155 srcptr = inpixels;
156 destptr = img->pixels + i * img->width / 8;
157 for(y=0; y<img->height; y++) {
158 unsigned char pixval = 0;
159 for(x=0; x<img->width; x++) {
160 pixval = (pixval << 1) | ((*srcptr++ >> i) & 1);
161 if((x & 7) == 7) {
162 *destptr++ = pixval;
163 pixval = 0;
164 }
165 }
166 destptr += img->width / 8 * (img->nbitplanes - 1);
167 }
168 }
170 return img;
172 err:
173 free(inpixels);
174 if(img) {
175 while(img->chglist) {
176 void *tmp = img->chglist;
177 img->chglist = img->chglist->next;
178 free(tmp);
179 }
180 free(img->pixels);
181 free(img);
182 }
183 if(fp) fclose(fp);
184 return 0;
185 }
187 int save_ham(struct ham_image *img, const char *fname)
188 {
189 int i, num;
190 unsigned char c, *pptr;
191 uint16_t val;
192 FILE *fp;
193 struct palchange *chg;
195 if(!(fp = fopen(fname, "wb"))) {
196 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
197 return -1;
198 }
199 fprintf(fp, "HAAM");
201 val = htons(img->width);
202 fwrite(&val, 2, 1, fp);
203 val = htons(img->height);
204 fwrite(&val, 2, 1, fp);
205 c = img->nbitplanes;
206 fwrite(&c, 1, 1, fp);
207 fwrite(&c, 1, 1, fp); /* padding */
209 num = 0;
210 chg = img->chglist;
211 while(chg) {
212 ++num;
213 chg = chg->next;
214 }
215 num = htons(num);
216 fwrite(&num, 2, 1, fp);
218 chg = img->chglist;
219 while(chg) {
220 val = htons(chg->line);
221 fwrite(&val, 2, 1, fp);
222 val = htons(chg->entry);
223 fwrite(&val, 2, 1, fp);
224 chg = chg->next;
225 }
227 pptr = img->pixels;
228 num = img->width * img->height / 8 * img->nbitplanes;
229 for(i=0; i<num; i++) {
230 val = htons(*pptr);
231 ++pptr;
233 fwrite(&val, 2, 1, fp);
234 }
235 fclose(fp);
236 return 0;
237 }
239 void free_image(struct ham_image *img)
240 {
241 if(img) {
242 free(img->pixels);
243 while(img->chglist) {
244 void *tmp = img->chglist;
245 img->chglist = img->chglist->next;
246 free(tmp);
247 }
248 free(img);
249 }
250 }