rev |
line source |
nuclear@4
|
1 #include <stdio.h>
|
nuclear@4
|
2 #include <stdlib.h>
|
nuclear@4
|
3 #include <string.h>
|
nuclear@4
|
4 #include <errno.h>
|
nuclear@4
|
5 #include "image.h"
|
nuclear@4
|
6
|
nuclear@4
|
7 #define LOADFAIL(f, m) fprintf(stderr, "failed to load image: %s: %s\n", f, m)
|
nuclear@4
|
8
|
nuclear@4
|
9 int load_image(struct image *img, const char *fname)
|
nuclear@4
|
10 {
|
nuclear@4
|
11 static const char *magic = "TILEIMAG";
|
nuclear@4
|
12 FILE *fp;
|
nuclear@4
|
13 char sig[8];
|
nuclear@4
|
14
|
nuclear@4
|
15 if(!(fp = fopen(fname, "rb"))) {
|
nuclear@4
|
16 LOADFAIL(fname, strerror(errno));
|
nuclear@4
|
17 return -1;
|
nuclear@4
|
18 }
|
nuclear@4
|
19 if(fread(sig, sizeof sig, 1, fp) <= 0 || memcmp(sig, magic, 8) != 0) {
|
nuclear@4
|
20 LOADFAIL(fname, "corrupted or empty file");
|
nuclear@4
|
21 fclose(fp);
|
nuclear@4
|
22 return -1;
|
nuclear@4
|
23 }
|
nuclear@4
|
24 if(fread(&img->xsz, 4, 1, fp) <= 0 || fread(&img->ysz, 4, 1, fp) <= 0) {
|
nuclear@4
|
25 LOADFAIL(fname, "failed to read file header");
|
nuclear@4
|
26 fclose(fp);
|
nuclear@4
|
27 return -1;
|
nuclear@4
|
28 }
|
nuclear@4
|
29
|
nuclear@4
|
30 if(!(img->pixels = malloc(img->xsz * img->ysz))) {
|
nuclear@4
|
31 LOADFAIL(fname, "failed to allocate pixel buffer");
|
nuclear@4
|
32 fclose(fp);
|
nuclear@4
|
33 return -1;
|
nuclear@4
|
34 }
|
nuclear@4
|
35 if(fread(img->pixels, 1, img->xsz * img->ysz, fp) < img->xsz * img->ysz) {
|
nuclear@4
|
36 LOADFAIL(fname, "unexpected end of file while reading pixels");
|
nuclear@4
|
37 fclose(fp);
|
nuclear@4
|
38 return -1;
|
nuclear@4
|
39 }
|
nuclear@4
|
40 fclose(fp);
|
nuclear@4
|
41 return 0;
|
nuclear@4
|
42 }
|
nuclear@4
|
43
|
nuclear@4
|
44 void destroy_image(struct image *img)
|
nuclear@4
|
45 {
|
nuclear@4
|
46 if(img) {
|
nuclear@4
|
47 free(img->pixels);
|
nuclear@4
|
48 img->pixels = 0;
|
nuclear@4
|
49 }
|
nuclear@4
|
50 }
|
nuclear@4
|
51
|
nuclear@4
|
52 int load_palette(struct color *col, const char *fname)
|
nuclear@4
|
53 {
|
nuclear@4
|
54 FILE *fp;
|
nuclear@4
|
55 char buf[128];
|
nuclear@4
|
56 int nent = 0;
|
nuclear@4
|
57
|
nuclear@4
|
58 if(!(fp = fopen(fname, "r"))) {
|
nuclear@4
|
59 fprintf(stderr, "failed to open palette file: %s: %s\n", fname, strerror(errno));
|
nuclear@4
|
60 return -1;
|
nuclear@4
|
61 }
|
nuclear@4
|
62
|
nuclear@4
|
63 while(fgets(buf, sizeof buf, fp)) {
|
nuclear@4
|
64 char *endp, *line = buf;
|
nuclear@4
|
65 int r, g, b;
|
nuclear@4
|
66
|
nuclear@4
|
67 if(!line || !*line) continue;
|
nuclear@4
|
68
|
nuclear@4
|
69 if(*line == '#') { /* hex html-like values */
|
nuclear@4
|
70 unsigned int val = strtol(line + 1, &endp, 16);
|
nuclear@4
|
71 if(endp == line) {
|
nuclear@4
|
72 fprintf(stderr, "unrecognized line \"%s\" in palette file: %s\n", line, fname);
|
nuclear@4
|
73 fclose(fp);
|
nuclear@4
|
74 return -1;
|
nuclear@4
|
75 }
|
nuclear@4
|
76
|
nuclear@4
|
77 r = (val >> 16) & 0xff;
|
nuclear@4
|
78 g = (val >> 8) & 0xff;
|
nuclear@4
|
79 b = val & 0xff;
|
nuclear@4
|
80 } else {
|
nuclear@4
|
81 fprintf(stderr, "unrecognized line \"%s\" in palette file: %s\n", line, fname);
|
nuclear@4
|
82 fclose(fp);
|
nuclear@4
|
83 return -1;
|
nuclear@4
|
84 }
|
nuclear@4
|
85
|
nuclear@4
|
86 if(nent >= 256) {
|
nuclear@4
|
87 fprintf(stderr, "palette file %s contains more than 256 entries ... skipping the rest\n", fname);
|
nuclear@4
|
88 break;
|
nuclear@4
|
89 }
|
nuclear@4
|
90
|
nuclear@4
|
91 col[nent].r = r;
|
nuclear@4
|
92 col[nent].g = g;
|
nuclear@4
|
93 col[nent].b = b;
|
nuclear@4
|
94 nent++;
|
nuclear@4
|
95 }
|
nuclear@4
|
96
|
nuclear@4
|
97 printf("loaded palette: %s (%d colors)\n", fname, nent);
|
nuclear@4
|
98
|
nuclear@4
|
99 fclose(fp);
|
nuclear@4
|
100 return nent;
|
nuclear@4
|
101 }
|
nuclear@4
|
102
|
nuclear@4
|
103 #define MIN(a, b) ((a) < (b) ? (a) : (b))
|
nuclear@4
|
104 #define MAX(a, b) ((a) > (b) ? (a) : (b))
|
nuclear@4
|
105
|
nuclear@4
|
106 void blitkey(struct image *destimg, int dstx, int dsty, struct image *srcimg, int key)
|
nuclear@4
|
107 {
|
nuclear@4
|
108 int srcx = 0, srcy = 0;
|
nuclear@4
|
109 int i, j, width, height;
|
nuclear@4
|
110 unsigned char *src, *dst;
|
nuclear@4
|
111
|
nuclear@4
|
112 if(dstx < 0) {
|
nuclear@4
|
113 srcx += -dstx;
|
nuclear@4
|
114 dstx = 0;
|
nuclear@4
|
115 }
|
nuclear@4
|
116 if(dsty < 0) {
|
nuclear@4
|
117 srcy += -dsty;
|
nuclear@4
|
118 dsty = 0;
|
nuclear@4
|
119 }
|
nuclear@4
|
120
|
nuclear@4
|
121 width = MIN(destimg->xsz - dstx, srcimg->xsz - srcx);
|
nuclear@4
|
122 height = MIN(destimg->ysz - dsty, srcimg->ysz - srcy);
|
nuclear@4
|
123
|
nuclear@4
|
124 if(width <= 0 || height <= 0) return; /* ended up with a zero-area blit */
|
nuclear@4
|
125
|
nuclear@4
|
126 src = srcimg->pixels + srcy * srcimg->xsz + srcx;
|
nuclear@4
|
127 dst = destimg->pixels + dsty * destimg->xsz + dstx;
|
nuclear@4
|
128
|
nuclear@4
|
129 for(i=0; i<height; i++) {
|
nuclear@4
|
130 for(j=0; j<width; j++) {
|
nuclear@4
|
131 if(src[j] != key) {
|
nuclear@4
|
132 dst[j] = src[j];
|
nuclear@4
|
133 }
|
nuclear@4
|
134 }
|
nuclear@4
|
135 src += srcimg->xsz;
|
nuclear@4
|
136 dst += destimg->xsz;
|
nuclear@4
|
137 }
|
nuclear@4
|
138 }
|