bmp_cut tests
[my-code/api.git] / bmp / bmp.c
1 /* bmp.c -- bmp write/read api
2  *
3  * author: hackbard@hackdaworld.dyndns.org
4  *
5  */
6
7 #include "bmp.h"
8
9 int bmp_init(t_bmp *bmp,int outfd) {
10
11   dprintf(outfd,"[bmp] initializing bmp api ...\n");
12
13   memset(bmp,0,sizeof(t_bmp));
14   bmp->outfd=outfd;
15
16   return B_SUCCESS;
17 }
18
19 int bmp_shutdown(t_bmp *bmp) {
20
21   if(bmp->map!=NULL) {
22     dprintf(bmp->outfd,"[bmp] free pixmap memory\n");
23     free(bmp->map);
24   }
25
26   dprintf(bmp->outfd,"[bmp] shutdown\n");
27
28   return B_SUCCESS;
29 }
30
31 int bmp_check_header_and_info(t_bmp *bmp) {
32
33   dprintf(bmp->outfd,"[bmp] magic identifier: %c%c\n",
34           bmp->hdr.identifier&0xff,bmp->hdr.identifier>>8);
35
36   if(bmp->info.compression!=0) {
37     dprintf(bmp->outfd,"[bmp] compression not supported\n");
38     return B_NO_SUPPORT;
39   }
40   
41   if(bmp->info.bpp!=24) {
42     dprintf(bmp->outfd,"[bmp] only true color (24bpp) supported\n");
43     return B_NO_SUPPORT;
44   }
45     
46   if(bmp->hdr.offset!=BMP_H_SIZE+BMP_I_SIZE) {
47     dprintf(bmp->outfd,"[bmp] files with %d bytes offset not supported\n",
48             bmp->hdr.offset);
49     return B_NO_SUPPORT;
50   }
51
52   if(bmp->info.size!=BMP_I_SIZE) {
53     dprintf(bmp->outfd,"[bmp] files with %d bytes info size not supported\n",
54             bmp->info.size);
55     return B_NO_SUPPORT;
56   }
57     
58   return B_SUCCESS;
59 }
60
61 int bmp_alloc_map(t_bmp *bmp) {
62
63   int size;
64
65   size=bmp->width*bmp->height*3;
66
67   dprintf(bmp->outfd,"[bmp] alloc map memory (%d bytes)\n",size);
68
69   if((bmp->map=(t_pixel *)malloc(size))==NULL) {
70     dprintf(bmp->outfd,"[bmp] memory map alloc failed\n");
71     return B_E_MEM;
72   }
73
74   return B_SUCCESS;
75 }
76
77 int bmp_write_file(t_bmp *bmp) {
78  
79   int fill,xsize,size;
80   int y;
81   unsigned char buf[3];
82
83   memset(buf,0,3);
84
85   if(!(bmp->mode&WRITE)) {
86     dprintf(bmp->outfd,"[bmp] write mode not specified\n");
87     return B_WRONG_MODE;
88   }
89
90   xsize=bmp->width*3;
91   fill=(4-(xsize%4))%4;
92   size=(xsize+fill)*bmp->height;
93
94   /* construct it */
95   bmp->hdr.identifier='B'|('M'<<8);
96   bmp->hdr.size=size+BMP_H_SIZE+BMP_I_SIZE;
97   bmp->hdr.offset=BMP_H_SIZE+BMP_I_SIZE;
98   bmp->info.size=BMP_I_SIZE;
99   bmp->info.width=bmp->width;
100   bmp->info.height=bmp->height;
101   bmp->info.planes=1;
102   bmp->info.bpp=24;
103   bmp->info.imagesize=size;
104   if(bmp->info.xres==0) bmp->info.xres=2048;
105   if(bmp->info.yres==0) bmp->info.yres=2048;
106   bmp->info.noc=0;
107   bmp->info.ic=0;
108
109   /* write it */
110   if((bmp->fd=open(bmp->file,O_WRONLY|O_CREAT))<0) {
111     dprintf(bmp->outfd,"[bmp] unable to open file %s\n",bmp->file);
112     return B_NO_FILE;
113   }
114
115   if(write(bmp->fd,&(bmp->hdr),BMP_H_SIZE)<BMP_H_SIZE) {
116     dprintf(bmp->outfd,"[bmp] unable to write bmp header\n");
117     return B_E_WRITE_DATA;
118   }
119
120   if(write(bmp->fd,&(bmp->info),BMP_I_SIZE)<BMP_I_SIZE) {
121     dprintf(bmp->outfd,"[bmp] unable to write bmp info\n");
122     return B_E_WRITE_DATA;
123   }
124
125   for(y=0;y<bmp->height;y++) {
126     if(write(bmp->fd,bmp->map+y*bmp->width,xsize)<xsize) {
127       dprintf(bmp->outfd,"[bmp] unable to write image data line %d\n",y);
128       return B_E_WRITE_DATA;
129     }
130     if(write(bmp->fd,buf,fill)<fill) {
131       dprintf(bmp->outfd,"[bmp] unable to write fill bytes\n");
132       return B_E_WRITE_DATA;
133     }
134   }
135
136   close(bmp->fd);
137
138   return B_SUCCESS;
139 }
140
141 int bmp_cut_bottom(t_bmp *dst,t_bmp *src,int dz) {
142
143   dst->width=src->width;
144   dst->height=dz;
145
146   if(dz>src->height) {
147     dprintf(src->outfd,"[bmp] cut region greater than image height\n");
148     return B_E_GEOMETRY;
149   }
150
151   /* obsolete - we point to wanted memory instead
152   if(bmp_alloc_map(dst)!=B_SUCCESS) {
153     dprintf(dst->outfd,"[bmp] no map memory\n");
154     return B_E_MEM;
155   }
156   */
157
158   /* obsolete - we point to wanted memory instead
159   memcpy(dst->map,src->map+(src->height-dz)*src->width,
160          dz*src->width*sizeof(t_pixel));
161   */
162   dst->map=src->map+(src->height-dz)*src->width;
163
164   return B_SUCCESS;
165 }
166
167 int bmp_read_file(t_bmp *bmp) {
168
169   unsigned char buf[BMP_H_SIZE+BMP_I_SIZE];
170   int y,xsize;
171   int crop;
172
173   if(!(bmp->mode&READ)) {
174     dprintf(bmp->outfd,"[bmp] read mode not specified\n");
175     return B_WRONG_MODE;
176   }
177
178   if((bmp->fd=open(bmp->file,O_RDONLY))<0) {
179     dprintf(bmp->outfd,"[bmp] unable to open file %s\n",bmp->file);
180     return B_NO_FILE;
181   }
182
183   if(read(bmp->fd,buf,BMP_H_SIZE+BMP_I_SIZE)<BMP_H_SIZE+BMP_I_SIZE) {
184     dprintf(bmp->outfd,"[bmp] error reading bmp header & info\n");
185     return B_NO_HI;
186   }
187
188   memcpy(&(bmp->hdr),buf,BMP_H_SIZE);
189   memcpy(&(bmp->info),buf+BMP_H_SIZE,BMP_I_SIZE);
190
191   if(bmp_check_header_and_info(bmp)!=B_SUCCESS) {
192     dprintf(bmp->outfd,"[bmp] header/info check failed\n");
193     return B_HI_FAIL;
194   }
195
196   bmp->width=bmp->info.width;
197   bmp->height=bmp->info.height;
198
199   bmp->map=(t_pixel *)malloc(bmp->width*bmp->height*sizeof(t_pixel));
200   if(bmp->map==NULL) {
201     dprintf(bmp->outfd,"[bmp] malloc of map memory failed\n");
202     return B_E_MEM;
203   }
204
205   crop=bmp->info.imagesize/bmp->height-bmp->width*(bmp->info.bpp/8);
206   xsize=(bmp->info.bpp/8)*bmp->width;
207
208   for(y=0;y<bmp->height;y++) {
209     if(read(bmp->fd,bmp->map+y*bmp->width,xsize)<xsize) {
210       dprintf(bmp->outfd,"[bmp] reading image data of line %d failed\n",y);
211       return B_E_READ_DATA;
212     }
213     if(read(bmp->fd,buf,crop)<crop) {
214       dprintf(bmp->outfd,"[bmp] failed reading rest of line\n");
215       return B_E_READ_DATA;
216     }
217   }
218     
219   close(bmp->fd);
220
221   return B_SUCCESS;
222 }