…aaand add PREFIX to the freebsd makefile too
[voxelands-alt.git] / src / graphics / image_tga.c
blob9f0556570f4f26ace4e7a412428c4cb1baf21b72
1 /************************************************************************
2 * image_tga.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "graphics.h"
22 #include "file.h"
23 #include "path.h"
25 #include <string.h>
27 static unsigned char tga_uncompressed[12] = {0,0,2,0,0,0,0,0,0,0,0,0};
28 static unsigned char tga_compressed[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
30 /* is it a tga image? */
31 int image_is_tga(file_t *f)
33 if (!memcmp(f->data,tga_compressed,12))
34 return 1;
35 if (!memcmp(f->data,tga_uncompressed,12))
36 return 1;
37 return 0;
40 /* load a tga image to pixel data */
41 int image_load_tga(file_t *f, image_t *p)
43 int compressed = 0;
44 int bpp;
45 int size;
46 register int i;
47 int k;
48 unsigned char header[18];
50 file_read(f,header,18);
52 if (!memcmp(header,tga_compressed,12)) {
53 compressed = 1;
54 }else if (memcmp(header,tga_uncompressed,12)) {
55 return 1;
58 p->w = (header[13]*256)+header[12];
59 p->h = (header[15]*256)+header[14];
60 bpp = header[16]/8;
61 if (bpp < 3 || bpp > 4)
62 return 1;
64 size = p->w*p->h*bpp;
66 p->pixels = malloc(p->w*p->h*4);
68 if (compressed) {
69 unsigned int pixelcount = p->w*p->h;
70 unsigned int currentpixel = 0;
71 unsigned char chunkheader;
72 unsigned char colour[4];
73 k = 0;
74 do {
75 file_read(f,&chunkheader,1);
77 if(chunkheader < 128) {
78 chunkheader++;
80 for (i=0; i<chunkheader; i++) {
81 file_read(f,colour,bpp);
83 /* BGR -> RGB */
84 p->pixels[k] = colour[2];
85 p->pixels[k+1] = colour[1];
86 p->pixels[k+2] = colour[0];
88 /* ensure there's an alpha value */
89 if (bpp == 4) {
90 p->pixels[k + 3] = colour[3];
91 }else{
92 p->pixels[k + 3] = 255;
95 k += 4;
96 currentpixel++;
98 if (currentpixel > pixelcount) {
99 free(p->pixels);
100 return 1;
103 }else{
104 chunkheader -= 127;
106 file_read(f,colour,bpp);
108 for (i=0; i<chunkheader; i++) {
109 /* BGR -> RGB */
110 p->pixels[k] = colour[2];
111 p->pixels[k+1] = colour[1];
112 p->pixels[k+2] = colour[0];
114 /* ensure there's an alpha value */
115 if (bpp == 4) {
116 p->pixels[k + 3] = colour[3];
117 }else{
118 p->pixels[k + 3] = 255;
121 k += 4;
122 currentpixel++;
124 if (currentpixel > pixelcount) {
125 free(p->pixels);
126 return 1;
130 } while (currentpixel < pixelcount);
131 }else{
132 file_read(f,p->pixels,size);
134 if (bpp == 3) {
135 /* BGR -> RGBA */
136 unsigned char* data = malloc(p->w*p->h*4);
137 for (i=0,k=0; i<size; i+=3,k+=4) {
138 data[k] = p->pixels[i+2];
139 data[k+1] = p->pixels[i+1];
140 data[k+2] = p->pixels[i];
141 data[k+3] = 255;
143 free(p->pixels);
144 p->pixels = data;
145 }else{
146 /* BGRA -> RGBA */
147 for (i=0; i<size; i+=bpp) {
148 p->pixels[i] ^= p->pixels[i+2];
149 p->pixels[i+2] ^= p->pixels[i];
150 p->pixels[i] ^= p->pixels[i+2];
155 return 0;
158 /* write pixel data to a tga image */
159 int image_save_tga(image_t *p, char* file)
161 char buff[2048];
162 unsigned char header[18] = {0,0,2,0,0,0,0,0,0,0,0,0, 0,0,0,0,32,0};
163 FILE *f;
164 int i;
165 int sz = p->w*p->h*4;
167 header[13] = (p->w&0xFF00)>>8;
168 header[12] = p->w&0x00FF;
169 header[15] = (p->h&0xFF00)>>8;
170 header[14] = p->h&0x00FF;
172 if (!path_get(NULL,file,0,buff,2048))
173 return 1;
174 f = fopen(buff,"wb");
175 if (!f)
176 return 1;
178 fwrite(header,18,1,f);
180 /* tga expects BGRA so change it from RGBA */
181 for (i=0; i<sz; i+=4) {
182 fwrite(&p->pixels[i+2],1,1,f);
183 fwrite(&p->pixels[i+1],1,1,f);
184 fwrite(&p->pixels[i],1,1,f);
185 fwrite(&p->pixels[i+3],1,1,f);
188 fclose(f);
190 return 0;