amiga_imgv
changeset 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 |
files | src/image.h tools/convhammer/main.c |
diffstat | 2 files changed, 156 insertions(+), 5 deletions(-) [+] |
line diff
1.1 --- a/src/image.h Wed Oct 25 21:05:24 2017 +0300 1.2 +++ b/src/image.h Thu Oct 26 10:04:29 2017 +0300 1.3 @@ -4,7 +4,7 @@ 1.4 #include "inttypes.h" 1.5 1.6 struct palchange { 1.7 - int line; 1.8 + uint16_t line; 1.9 uint16_t entry; /* [ idx | r | g | b ] */ 1.10 struct palchange *next; 1.11 };
2.1 --- a/tools/convhammer/main.c Wed Oct 25 21:05:24 2017 +0300 2.2 +++ b/tools/convhammer/main.c Thu Oct 26 10:04:29 2017 +0300 2.3 @@ -1,6 +1,7 @@ 2.4 #include <stdio.h> 2.5 #include <stdlib.h> 2.6 #include <string.h> 2.7 +#include <errno.h> 2.8 #include <arpa/inet.h> 2.9 #include "image.h" 2.10 2.11 @@ -54,7 +55,7 @@ 2.12 } 2.13 strcat(name, ".ham"); 2.14 2.15 - if(save_ham(name, img) == -1) { 2.16 + if(save_ham(img, name) == -1) { 2.17 fprintf(stderr, "failed to save ham image: %s\n", name); 2.18 free_image(img); 2.19 continue; 2.20 @@ -63,14 +64,133 @@ 2.21 return 0; 2.22 } 2.23 2.24 +static uint16_t nops(uint16_t x) { return x; } 2.25 +static uint16_t swaps(uint16_t x) { return (x >> 8) | (x << 8); } 2.26 + 2.27 struct ham_image *load_hammer(const char *fname) 2.28 { 2.29 + int i, x, y, pstart, numpix = 320 * 256; 2.30 + FILE *fp = 0; 2.31 + uint32_t cps, npalent; 2.32 + struct ham_image *img = 0; 2.33 + struct palchange *tail = 0; 2.34 + unsigned char *inpixels = 0; 2.35 + unsigned char *srcptr, *destptr; 2.36 + uint16_t endtest = 0xaabb; 2.37 + uint16_t (*letohs)(uint16_t); 2.38 + 2.39 + letohs = (*(unsigned char*)&endtest == 0xaa) ? swaps : nops; 2.40 + 2.41 + if(!(fp = fopen(fname, "rb"))) { 2.42 + fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); 2.43 + return 0; 2.44 + } 2.45 + 2.46 + if(!(img = malloc(sizeof *img))) { 2.47 + perror("failed to allocate image"); 2.48 + goto err; 2.49 + } 2.50 + img->width = 320; 2.51 + img->height = 256; 2.52 + img->nbitplanes = 6; 2.53 + img->chglist = 0; 2.54 + 2.55 + if(!(img->pixels = malloc(img->width * img->height / 8 * img->nbitplanes))) { 2.56 + perror("failed to allocate pixels"); 2.57 + goto err; 2.58 + } 2.59 + 2.60 + if(fread(&cps, 4, 1, fp) < 1) goto err; 2.61 + cps = letohs(cps); 2.62 + if(cps <= 0 || cps > 16) { 2.63 + fprintf(stderr, "invalid changes-per-line value: %u\n", (unsigned int)cps); 2.64 + goto err; 2.65 + } 2.66 + 2.67 + /* read palette changes and palette */ 2.68 + 2.69 + npalent = cps * 256; 2.70 + pstart = npalent - 16; 2.71 + 2.72 + for(i=0; i<npalent; i++) { 2.73 + uint16_t palent; 2.74 + struct palchange *chg; 2.75 + 2.76 + if(fread(&palent, 2, 1, fp) < 1) { 2.77 + perror("unexpected end of file"); 2.78 + goto err; 2.79 + } 2.80 + palent = letohs(palent); 2.81 + 2.82 + if(!(chg = malloc(sizeof *chg))) { 2.83 + perror("failed to allocate palchange node"); 2.84 + goto err; 2.85 + } 2.86 + chg->line = i / cps; 2.87 + chg->entry = palent; 2.88 + chg->next = 0; 2.89 + if(tail) { 2.90 + tail->next = chg; 2.91 + tail = chg; 2.92 + } else { 2.93 + img->chglist = tail = chg; 2.94 + } 2.95 + 2.96 + if(i >= pstart) { 2.97 + img->palette[i - pstart] = palent & 0xfff; 2.98 + } 2.99 + } 2.100 + 2.101 + /* read pixels */ 2.102 + if(!(inpixels = malloc(numpix))) { 2.103 + perror("failed to allocate pixel buffer"); 2.104 + goto err; 2.105 + } 2.106 + if(fread(inpixels, 1, numpix, fp) < numpix) { 2.107 + perror("unexpected end of file while reading pixels"); 2.108 + goto err; 2.109 + } 2.110 + 2.111 + for(i=0; i<img->nbitplanes; i++) { 2.112 + srcptr = inpixels; 2.113 + destptr = img->pixels + i * img->width / 8; 2.114 + for(y=0; y<img->height; y++) { 2.115 + unsigned char pixval = 0; 2.116 + for(x=0; x<img->width; x++) { 2.117 + pixval = (pixval << 1) | ((*srcptr++ >> i) & 1); 2.118 + if((x & 7) == 7) { 2.119 + *destptr++ = pixval; 2.120 + pixval = 0; 2.121 + } 2.122 + } 2.123 + destptr += img->width / 8 * (img->nbitplanes - 1); 2.124 + } 2.125 + } 2.126 + 2.127 + return img; 2.128 + 2.129 +err: 2.130 + free(inpixels); 2.131 + if(img) { 2.132 + while(img->chglist) { 2.133 + void *tmp = img->chglist; 2.134 + img->chglist = img->chglist->next; 2.135 + free(tmp); 2.136 + } 2.137 + free(img->pixels); 2.138 + free(img); 2.139 + } 2.140 + if(fp) fclose(fp); 2.141 + return 0; 2.142 } 2.143 2.144 int save_ham(struct ham_image *img, const char *fname) 2.145 { 2.146 + int i, num; 2.147 + unsigned char c, *pptr; 2.148 uint16_t val; 2.149 FILE *fp; 2.150 + struct palchange *chg; 2.151 2.152 if(!(fp = fopen(fname, "wb"))) { 2.153 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno)); 2.154 @@ -79,10 +199,41 @@ 2.155 fprintf(fp, "HAAM"); 2.156 2.157 val = htons(img->width); 2.158 - fwrite(fp, 2, 1, &val); 2.159 + fwrite(&val, 2, 1, fp); 2.160 val = htons(img->height); 2.161 - fwrite(fp, 2, 1, &val); 2.162 - /* TODO: continue */ 2.163 + fwrite(&val, 2, 1, fp); 2.164 + c = img->nbitplanes; 2.165 + fwrite(&c, 1, 1, fp); 2.166 + fwrite(&c, 1, 1, fp); /* padding */ 2.167 + 2.168 + num = 0; 2.169 + chg = img->chglist; 2.170 + while(chg) { 2.171 + ++num; 2.172 + chg = chg->next; 2.173 + } 2.174 + num = htons(num); 2.175 + fwrite(&num, 2, 1, fp); 2.176 + 2.177 + chg = img->chglist; 2.178 + while(chg) { 2.179 + val = htons(chg->line); 2.180 + fwrite(&val, 2, 1, fp); 2.181 + val = htons(chg->entry); 2.182 + fwrite(&val, 2, 1, fp); 2.183 + chg = chg->next; 2.184 + } 2.185 + 2.186 + pptr = img->pixels; 2.187 + num = img->width * img->height / 8 * img->nbitplanes; 2.188 + for(i=0; i<num; i++) { 2.189 + val = htons(*pptr); 2.190 + ++pptr; 2.191 + 2.192 + fwrite(&val, 2, 1, fp); 2.193 + } 2.194 + fclose(fp); 2.195 + return 0; 2.196 } 2.197 2.198 void free_image(struct ham_image *img)