some meshgen and map rendering updates
[voxelands-alt.git] / src / graphics / image_bmp.c
blob6646ba0d093016810bce3226d4571a68e5671748
1 /************************************************************************
2 * image_bmp.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 typedef struct bmp_file_header_s {
26 short int type;
27 unsigned int size;
28 short int reserved1;
29 short int reserved2;
30 unsigned int offset;
31 } __attribute__((packed)) bmp_file_header_t;
33 typedef struct bmp_info_header_s {
34 unsigned int size;
35 int width;
36 int height;
37 short int planes;
38 short int bpp;
39 unsigned int compression;
40 unsigned int img_size;
41 int hres;
42 int vres;
43 unsigned int palette_colors;
44 unsigned int important_colors;
45 } __attribute__((packed)) bmp_info_header_t;
47 /* is it a bmp image? */
48 int image_is_bmp(file_t *f)
50 bmp_file_header_t bmfh;
51 file_read(f,&bmfh,sizeof(bmp_file_header_t));
52 file_seek(f,0,SEEK_SET);
53 if (bmfh.type == 19778)
54 return 1;
55 return 0;
58 /* load a bitmap image to a texture */
59 int image_load_bmp(file_t *f, image_t *p)
61 int i;
62 int j;
63 unsigned char* p_data;
64 colour_t *colours;
65 bmp_info_header_t bmih;
66 bmp_file_header_t bmfh;
67 unsigned int size;
68 int offset;
69 int pad;
70 int x;
71 int y;
73 file_read(f,&bmfh,sizeof(bmp_file_header_t));
74 file_read(f,&bmih,sizeof(bmp_info_header_t));
76 p->w = bmih.width;
77 p->h = bmih.height;
79 size = (p->w*p->h*(unsigned int)(bmih.bpp/8.0));
81 /* unsupported format */
82 if (bmih.bpp < 8)
83 return 1;
85 /* get the colour index for 8bit images */
86 if (bmih.bpp == 8)
87 colours = file_get(f);
89 pad = (int)((float)p->w*(float)bmih.bpp/8.0);
90 offset = 0;
92 while (pad%4) {
93 pad++;
94 offset++;
97 p->pixels = malloc(sizeof(unsigned char)*(p->w*p->h*4));
99 if (!p->pixels)
100 return 1;
102 file_seek(f,bmfh.offset,SEEK_SET);
103 p_data = file_get(f);
105 /* convert whatever pixel format the image is in to 32 bit RGBA */
107 /* 8 bits per pixel */
108 if (bmih.bpp == 8) {
109 if (p->h>0) {
110 int t = size*8;
111 j=0;
112 for (i=0; i<t;i+=4) {
113 if ((i+1)%pad == 0)
114 i += offset;
115 p->pixels[i] = colours[p_data[j]].b;
116 p->pixels[i+1] = colours[p_data[j]].g;
117 p->pixels[i+2] = colours[p_data[j]].r;
118 p->pixels[i+3] = 255;
119 j++;
121 }else{
122 int t = size*8;
123 j = size-1;
124 for (i=0; i<t; i+=4) {
125 if ((i+1)%pad == 0)
126 i += offset;
127 p->pixels[i] = colours[p_data[j]].b;
128 p->pixels[i+1] = colours[p_data[j]].g;
129 p->pixels[i+2] = colours[p_data[j]].r;
130 p->pixels[i+3] = 255;
131 j--;
134 /* 24 bits per pixel */
135 }else if (bmih.bpp == 24) {
136 if (p->h>0) {
137 for (i=0, j=0; j<size; j+=3, i+=4) {
138 if ((j+1)%pad == 0)
139 j += offset;
140 p->pixels[i+3] = 255;
141 p->pixels[i+2] = p_data[j];
142 p->pixels[i+1] = p_data[j+1];
143 p->pixels[i] = p_data[j+2];
145 }else{
146 j = size-3;
147 for (i=0; i<size; i+=4) {
148 /* if ((i+1)%pad == 0)
149 i += offset; */
150 p->pixels[i+3] = 255;
151 p->pixels[j+2] = p_data[i];
152 p->pixels[j+1] = p_data[i+1];
153 p->pixels[j] = p_data[i+2];
154 j-=3;
157 /* 32 bits per pixel */
158 }else if (bmih.bpp == 32) {
159 if (p->h>0) {
160 i = 0;
161 for (y=p->h-1; y>-1; y--) {
162 for (x=0; x<p->w; x++) {
163 if ((i+1)%pad == 0)
164 i += offset;
165 j = ((y*p->w)+x)*4;
166 p->pixels[j] = p_data[i+2];
167 p->pixels[j+1] = p_data[i+1];
168 p->pixels[j+2] = p_data[i];
169 p->pixels[j+3] = p_data[i+3];
170 i += 4;
173 }else{
174 j = size-4;
175 for (i=0; i<size; i+=4) {
176 if ((i+1)%pad == 0)
177 i += offset;
178 p->pixels[j+3] = p_data[i+3];
179 p->pixels[j+2] = p_data[i];
180 p->pixels[j+1] = p_data[i+1];
181 p->pixels[j] = p_data[i+2];
182 j-=4;
185 /* unsupported bits per pixel */
186 }else{
187 return 1;
190 return 0;
193 /* write pixel data to a bmp image */
194 int image_save_bmp(image_t *p, char* file)
196 char buff[2048];
197 FILE *f;
198 int i;
199 bmp_file_header_t bmfh;
200 bmp_info_header_t bmih;
202 bmih.size = sizeof(bmp_info_header_t);
203 bmih.width = p->w;
204 bmih.height = p->h;
205 bmih.planes = 1;
206 bmih.bpp = 32;
207 bmih.compression = 0;
208 bmih.img_size = p->w*p->h*4;
209 bmih.hres = 0;
210 bmih.vres = 0;
211 bmih.palette_colors = 0;
212 bmih.important_colors = 0;
214 bmfh.type = 19778;
215 bmfh.size = sizeof(bmp_file_header_t)+sizeof(bmp_info_header_t)+bmih.img_size;
216 bmfh.reserved1 = 0;
217 bmfh.reserved2 = 0;
218 bmfh.offset = sizeof(bmp_file_header_t)+sizeof(bmp_info_header_t);
220 if (!path_get(NULL,file,0,buff,2048))
221 return 1;
222 f = fopen(buff,"wb");
223 if (!f)
224 return 1;
226 fwrite(&bmfh,sizeof(bmp_file_header_t),1,f);
227 fwrite(&bmih,sizeof(bmp_info_header_t),1,f);
229 /* bmp expects BGRA so change it from RGBA */
230 for (i=0; i<bmih.img_size; i+=4) {
231 fwrite(&p->pixels[i+2],1,1,f);
232 fwrite(&p->pixels[i+1],1,1,f);
233 fwrite(&p->pixels[i],1,1,f);
234 fwrite(&p->pixels[i+3],1,1,f);
237 fclose(f);
239 return 0;