some improvements to bmp_write_file function (still untested!)
[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   if(bmp->info.compression!=0) {
34     dprintf(bmp->outfd,"[bmp] compression not supported\n");
35     return B_NO_SUPPORT;
36   }
37   
38   if(bmp->info.bpp!=24) {
39     dprintf(bmp->outfd,"[bmp] only true color (24bpp) supported\n");
40     return B_NO_SUPPORT;
41   }
42     
43   if(bmp->hdr.offset!=B_H_SIZE+B_I_SIZE) {
44     dprintf(bmp->outfd,"[bmp] files with %d bytes offset not supported\n",
45             bmp->hdr-offset);
46     return B_NO_SUPPORT;
47   }
48
49   if(bmp->info.size!=BMP_I_SIZE) {
50     dprintf(bmp->outfd,"[bmp] files with %d bytes info size not supported\n",
51             bmp->info.size);
52     return B_NO_SUPPORT;
53   }
54     
55   return B_SUCCESS;
56 }
57
58 int bmp_write_file(t_bmp *bmp) {
59  
60   int fill,xsize,size;
61
62   if(!(bmp->mode&WRITE)) {
63     dprintf(bmp->outfd,"[bmp] write mode not specified\n");
64     return B_WRONG_MODE;
65   }
66
67   xsize=bmp->width*3;
68   fill=(4-(xsize%4))%4;
69   size=(xsize+fill)*bmp->height;
70
71   /* construct it */
72   bmp->hdr.identifier='B'|('M'<<8);
73   bmp->hdr.size=size+BMP_H_SIZE+BMP_I_SIZE;
74   bmp->hdr.offset=BMP_H_SIZE+BMP_I_SIZE;
75   bmp->info.size=BMP_I_SIZE;
76   bmp->info.width=bmp->width;
77   bmp->info.height=bmp->height;
78   bmp->info.planes=1;
79   bmp->info.bpp=24;
80   bmp->info.imagesize=size;
81   if(bmp->info.xres==0) bmp->info.xres=2048;
82   if(bmp->info.yres==0) bmp->info.yres=2048;
83   bmp->info.noc=0;
84   bmp->info.ic=0;
85
86   /* write it */
87   if((bmp->fd=open(bmp->file,O_WRONLY)<0) {
88     dprintf(bmp->outfd,"[bmp] unable to open file %s\n",bmp->file);
89     return B_NO_FILE;
90   }
91
92   if(write(bmp->fd,&(bmp->hdr),BMP_H_SIZE)<BMP_H_SIZE) {
93     dprintf(bmp->outfd,"[bmp] unable to write bmp header\n");
94     return B_E_WRITE_DATA;
95   }
96
97   if(write(bmp->fd,&(bmp->info),BMP_I_SIZE)<BMP_I_SIZE) {
98     dprintf(bmp->outfd,"[bmp] unable to write bmp info\n");
99     return B_E_WRITE_DATA;
100   }
101
102
103   return B_SUCCESS;
104 }
105
106 int bmp_read_file(t_bmp *bmp) {
107
108   unsigned char buf[BMP_HI_SIZE];
109   int y,xsize;
110   int crop;
111   unsigned char *data;
112
113   if(!(bmp->mode&READ)) {
114     dprintf(bmp->outfd,"[bmp] read mode not specified");
115     return B_WRONG_MODE;
116   }
117
118   if((bmp->fd=open(bmp->file,O_RDONLY))<0) {
119     dprintf(bmp->outfd,"[bmp] unable to open file %s\n",bmp->file);
120     return B_NO_FILE;
121   }
122
123   if(read(bmp->fd,buf,BMP_H_SIZE+BMP_I_SIZE)<BMP_H_SIZE+BMP_I_SIZE) {
124     dprintf(bmp->outfd,"[bmp] error reading bmp header & info\n");
125     return B_NO_HI;
126   }
127
128   memcpy(&(bmp->hdr),buf,BMP_H_SIZE);
129   memcpy(&(bmp->info),buf+BMP_H_SIZE,BMP_I_SIZE);
130
131   if(bmp_check_header_and_info(bmp)!=B_SUCCESS) {
132     dprintf(bmp->outfd,"[bmp] header/info check failed\n");
133     return B_HI_FAIL;
134   }
135
136   bmp->map=(t_pixel *)malloc(bmp->info.width*bmp->info.height*sizeof(t_pixel));
137   if(bmp->map==NULL) {
138     dprintf(bmp->outfd,"[bmp] malloc of map memory failed\n");
139     return B_E_MEM;
140   }
141
142   crop=(bmp->info.imagesize/bmp->info.height)%4;
143   xsize=(bmp->info.bpp/8)*bmp->info.width;
144
145   for(y=0;y<bmp->info.height;y++) {
146     if(read(bmp->fd,bmp->map+y*bmp->info.width,xsize)<xsize) {
147       dprintf(bmp->outfd,"[bmp] reading image data of line %d failed\n",y);
148       return B_E_READ_DATA;
149     }
150     if(read(bmp->fd,buf,crop)<crop) {
151       dprintf(bmp->outfd,"[bmp] failed reading rest of line\n");
152       return B_E_READ_DATA;
153     }
154   }
155     
156   close(bmp->fd);
157
158   return B_SUCCESS;
159 }