lbm2bin

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