Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "gimage.h"
28 : #include "gimagebmpP.h"
29 :
30 0 : static void myputs(short s, FILE *file) {
31 0 : putc(s&0xff,file);
32 0 : putc(s>>8,file);
33 0 : }
34 :
35 0 : static void putl(short s, FILE *file) {
36 0 : putc(s&0xff,file);
37 0 : putc((s>>8)&0xff,file);
38 0 : putc((s>>16)&0xff,file);
39 0 : putc((s>>24)&0xff,file);
40 0 : }
41 :
42 0 : int GImageWrite_Bmp(GImage *gi, FILE *file) {
43 0 : struct _GImage *base = gi->list_len==0?gi->u.image:gi->u.images[0];
44 0 : int headersize=40, preheadersize=14;
45 : int filesize, offset, imagesize;
46 : int bitsperpixel, clutsize, ncol;
47 : int row, col, i;
48 :
49 0 : if ( base->image_type == it_mono ) {
50 0 : ncol = 2;
51 0 : bitsperpixel = 1;
52 0 : clutsize = ncol*4;
53 0 : } else if ( base->image_type == it_index ) {
54 0 : ncol = base->clut->clut_len;
55 0 : if ( ncol<=16 )
56 0 : bitsperpixel = 4;
57 : else
58 0 : bitsperpixel = 8;
59 0 : clutsize = ncol*4;
60 : } else {
61 0 : bitsperpixel = 24;
62 0 : clutsize = 0;
63 0 : ncol = 0;
64 : }
65 0 : imagesize = ((base->bytes_per_line + 3) & ~3U) * base->height;
66 0 : offset = preheadersize + headersize + clutsize;
67 0 : filesize = offset + imagesize;
68 :
69 0 : putc('B',file);
70 0 : putc('M',file);
71 0 : putl(filesize,file); /* filesize */
72 0 : myputs(0,file); /* mbz1 */
73 0 : myputs(0,file); /* mbz2 */
74 0 : putl(offset,file); /* offset */
75 0 : putl(headersize,file); /* headersize */
76 0 : putl(base->width,file); /* width */
77 0 : putl(base->height,file); /* height */
78 0 : myputs(1,file); /* planes */
79 0 : myputs(bitsperpixel,file); /* bitsperpixel */
80 0 : putl(0,file); /* compression */
81 0 : putl(imagesize,file); /* imagesize */
82 0 : putl(3000,file); /* horizontal res, pixels/meter */
83 0 : putl(3000,file); /* vertical res, pixels/meter */
84 0 : putl(ncol,file); /* colours used */
85 0 : putl(0,file); /* colours important */
86 :
87 0 : if ( clutsize!=0 ) {
88 : int i;
89 0 : if ( base->clut!=NULL ) {
90 0 : for ( i=0; i<ncol; ++i ) {
91 0 : putc(COLOR_BLUE(base->clut->clut[i]),file);
92 0 : putc(COLOR_GREEN(base->clut->clut[i]),file);
93 0 : putc(COLOR_RED(base->clut->clut[i]),file);
94 0 : putc(0,file);
95 : }
96 : } else {
97 0 : putc(0,file); putc(0,file); putc(0,file); putc(0,file);
98 0 : putc(0xff,file); putc(0xff,file); putc(0xff,file); putc(0,file);
99 : }
100 : }
101 :
102 0 : for ( row = base->height-1; row>=0; --row ) {
103 0 : int pad=0;
104 :
105 0 : if ( bitsperpixel==24 ) {
106 0 : uint32 *pt = (uint32 *) (base->data+row*base->bytes_per_line);
107 0 : for ( col=0; col<base->width; ++col ) {
108 0 : putc(COLOR_BLUE(pt[col]),file);
109 0 : putc(COLOR_GREEN(pt[col]),file);
110 0 : putc(COLOR_RED(pt[col]),file);
111 : }
112 0 : pad = base->width&3;
113 0 : } else if ( bitsperpixel==8 ) {
114 0 : unsigned char *pt = (unsigned char *) (base->data+row*base->bytes_per_line);
115 0 : fwrite(pt,1,base->width,file);
116 0 : pad = 4-(base->width&3);
117 0 : } else if ( bitsperpixel==4 ) {
118 0 : unsigned char *pt = (unsigned char *) (base->data+row*base->bytes_per_line);
119 0 : for ( col=0; col<base->width/2; ++col ) {
120 0 : putc( (*pt<<4)|pt[1], file);
121 0 : pt += 2;
122 : }
123 0 : if ( base->width&1 )
124 0 : putc(*pt<<4,file);
125 0 : pad = 4-(((base->width+1)>>1)&3);
126 0 : } else if ( bitsperpixel==1 ) {
127 0 : unsigned char *pt = (unsigned char *) (base->data+row*base->bytes_per_line);
128 0 : fwrite(pt,1,base->bytes_per_line,file);
129 0 : pad = 4-(base->bytes_per_line&3);
130 : }
131 0 : if ( pad&1 ) /* pad to 4byte boundary */
132 0 : putc('\0',file);
133 0 : if ( pad&2 )
134 0 : myputs(0,file);
135 : }
136 0 : fflush(file);
137 0 : i = ferror(file);
138 0 : return( !i );
139 : }
140 :
141 0 : int GImageWriteBmp(GImage *gi, char *filename) {
142 : FILE *file;
143 : int ret;
144 :
145 0 : if ((file=fopen(filename,"wb"))==NULL )
146 0 : return(false);
147 0 : ret = GImageWrite_Bmp(gi,file);
148 0 : fclose(file);
149 0 : return( ret );
150 : }
|