lbm2bin

view src/main.c @ 4:0b96363742d3

added palette export, and fixed a planar pixel output bug
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 16 Jul 2017 21:30:23 +0300
parents bfd8aa2ca393
children 89fd62196739
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <errno.h>
6 #include "image.h"
8 static int proc_image(const char *fname);
9 static const char *modestr(int cmode);
10 static void output_planar(FILE *fp, struct image *img);
11 static void output_linear(FILE *fp, struct image *img);
12 static void output_palette(FILE *fp, struct image *img, int pcol_bits);
14 static int planar = 0;
15 static int pcol_bits = 8;
16 static int verbose = 0;
18 int main(int argc, char **argv)
19 {
20 int i;
22 for(i=1; i<argc; i++) {
23 if(argv[i][0] == '-') {
24 if(argv[i][2] == 0) {
25 switch(argv[i][1]) {
26 case 'a':
27 planar = 1;
28 pcol_bits = 4;
29 break;
31 case 'p':
32 planar = 1;
33 break;
35 case 'l':
36 planar = 0;
37 break;
39 case 'v':
40 verbose = 1;
41 break;
43 case 'h':
44 printf("usage: %s [options] <file 1> <file 2> ... <file n>\n", argv[0]);
45 printf("Options:\n");
46 printf(" -a: amiga mode (4bit palette colors & planar format)\n");
47 printf(" -p: output image in planar format\n");
48 printf(" -c: output image in linear (chunky) format\n");
49 printf(" -v: verbose output\n");
50 printf(" -h: print usage and exit\n");
51 return 0;
53 default:
54 fprintf(stderr, "invalid option: %s\n", argv[i]);
55 return 1;
56 }
57 } else {
58 fprintf(stderr, "invalid option: %s\n", argv[i]);
59 }
60 } else {
61 if(proc_image(argv[i]) == -1) {
62 return 1;
63 }
64 }
65 }
66 return 0;
67 }
69 static int proc_image(const char *fname)
70 {
71 int i;
72 struct image img;
73 char *outfname, *suffix;
74 FILE *fp;
76 if(load_image(&img, fname) == -1) {
77 fprintf(stderr, "failed to load image: %s\n", fname);
78 return -1;
79 }
81 if(!(outfname = malloc(strlen(fname) + 4))) {
82 perror("failed to allocate output filename");
83 return -1;
84 }
85 strcpy(outfname, fname);
86 if(!(suffix = strrchr(outfname, '.'))) {
87 suffix = outfname + strlen(outfname);
88 }
89 strcpy(suffix, ".img");
91 if(verbose) {
92 printf("processing %s -> %s\n", fname, outfname);
93 }
95 if(!(fp = fopen(outfname, "wb"))) {
96 fprintf(stderr, "failed to open output file: %s: %s\n", outfname, strerror(errno));
97 destroy_image(&img);
98 free(outfname);
99 return -1;
100 }
102 if(verbose) {
103 printf(" bits per pixel: %d (%d colors)\n", img.bpp, 1 << img.bpp);
104 if(img.num_ranges) {
105 printf(" color ranges:\n");
106 for(i=0; i<img.num_ranges; i++) {
107 printf(" [%d]: %d - %d, rate: %u, mode: %s\n", i, img.range[i].low, img.range[i].high,
108 img.range[i].rate, modestr(img.range[i].cmode));
109 }
110 }
111 }
113 if(planar) {
114 if(verbose) printf(" writing planar pixels\n");
115 output_planar(fp, &img);
116 } else {
117 if(verbose) printf(" writing linear pixels\n");
118 output_linear(fp, &img);
119 }
120 fclose(fp);
122 /* open fname.pal */
123 strcpy(outfname, fname);
124 if(!(suffix = strrchr(outfname, '.'))) {
125 suffix = outfname + strlen(outfname);
126 }
127 strcpy(suffix, ".pal");
129 if(!(fp = fopen(outfname, "wb"))) {
130 fprintf(stderr, "failed to open palette file %s for writing: %s\n",
131 outfname, strerror(errno));
132 free(outfname);
133 destroy_image(&img);
134 return -1;
135 }
137 if(verbose) {
138 printf(" writing %d bit palette colors\n", pcol_bits);
139 output_palette(fp, &img, pcol_bits);
140 }
142 fclose(fp);
143 free(outfname);
144 destroy_image(&img);
145 return 0;
146 }
148 static void output_planar(FILE *fp, struct image *img)
149 {
150 int i, x, y;
151 unsigned char acc = 0;
152 int acc_bit = 7;
153 unsigned char *pptr = img->pixels;
155 for(i=0; i<img->bpp; i++) {
156 for(y=0; y<img->height; y++) {
157 for(x=0; x<img->width; x++) {
158 acc |= (((*pptr >> i) & 1) << acc_bit);
159 if(--acc_bit == 0) {
160 fputc(acc, fp);
161 acc_bit = 7;
162 acc = 0;
163 ++pptr;
164 }
165 }
166 }
167 }
168 }
170 static void output_linear(FILE *fp, struct image *img)
171 {
172 int i, j;
173 unsigned char *pptr = img->pixels;
175 for(i=0; i<img->height; i++) {
176 for(j=0; j<img->width; j++) {
177 fputc(*pptr++, fp);
178 }
179 }
180 }
182 static void output_palette(FILE *fp, struct image *img, int pcol_bits)
183 {
184 int i, num_colors;
186 num_colors = 1 << img->bpp;
188 assert(pcol_bits == 8 || pcol_bits == 4);
190 if(pcol_bits == 8) {
191 for(i=0; i<num_colors; i++) {
192 fputc(img->palette[i].r, fp);
193 fputc(img->palette[i].g, fp);
194 fputc(img->palette[i].b, fp);
195 }
196 } else {
197 /* nibble colors */
198 for(i=0; i<num_colors; i++) {
199 fputc(img->palette[i].b | (img->palette[i].g << 4), fp);
200 fputc(img->palette[i].r, fp);
201 }
202 }
203 }
205 static const char *modestr(int cmode)
206 {
207 switch(cmode) {
208 case CYCLE_NORMAL:
209 return "forward";
210 case CYCLE_REVERSE:
211 return "reverse";
212 case CYCLE_PINGPONG:
213 return "ping-pong";
214 case CYCLE_SINE_HALF:
215 return "half-sine";
216 case CYCLE_SINE:
217 return "sine";
218 default:
219 break;
220 }
221 return "unknown";
222 }