Imported Upstream version 4.6.0
[debian/atlc] / src / non_gui / read_bitmap_file_headers.c
1 /* atlc - arbitrary transmission line calculator, for the analysis of
2 transmission lines are directional couplers. 
3
4 Copyright (C) 2002. Dr. David Kirkby, PhD (G8WRB).
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either package_version 2
9 of the License, or (at your option) any later package_version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
19 USA.
20
21 Dr. David Kirkby, e-mail drkirkby at ntlworld.com 
22
23 */
24
25 #include "config.h"
26
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #endif
30
31 #ifdef HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
34
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38
39 #include "definitions.h"
40 #include "exit_codes.h"
41
42 unsigned char *bmp_buff;
43
44 /* We make the bitmap header public, as we write it back 
45 later, when saving bmp files. It saves a lot of hassle,
46 just writing what we read back, rather than correctly 
47 calculating all the data in the header correctly */
48
49 /* #define DEBUG */
50
51 #define BITMAP_HEADER_SIZE 0x36 /* 54 */
52
53 void read_bitmap_file_headers(char *filename, int *offset, size_t *size, int *width, int *height)
54 {
55    FILE *fp;
56
57    struct Bitmap_File_Head_Struct Bitmap_File_Head;
58    struct Bitmap_Head_Struct Bitmap_Head;
59    int ColormapSize, Maps;
60    int length_of_file; /* Appently Photoshop versions < 7.01
61                        don't write this into Bitmap_Head.biSizeIm
62                        so it causes a problem. So we will work out
63                        the length by seeking to the end of the file
64                        and finding the position of the file 
65                        pointer */
66
67    bmp_buff=ustring(0,BITMAP_HEADER_SIZE);
68    if(strcmp(filename,"-")==0)
69    {
70       fp=stdin;   
71    }
72    else  
73       fp=fopen(filename,"rb");
74
75    if(fp==NULL)
76    {
77       fprintf(stderr,"cannot open %s\n", filename);
78       exit_with_msg_and_exit_code("",CANT_OPEN_FILE_FOR_READING);
79    }
80
81    /* deternine the length of the file, as its not always 
82    written into the bitmap. I thought it needed to be, but
83    apparently it does not and photoshop versions < 7.01 
84    don't do it. */
85    if( fseek(fp, 0, SEEK_END)  == -1)
86    {
87      fprintf(stderr," Can't seek to the end of the file in read_bitmap_file_headers.c\n");
88      exit(FSEEK_FAILURE);
89    }
90    if( (length_of_file=ftell(fp))  == -1)
91      exit_with_msg_and_exit_code("Can't find length of file in read_bitmap_file_headers.c",FTELL_FAILURE);
92
93    if( (fseek(fp, 0, SEEK_SET) ) == -1)
94    {
95      fprintf(stderr," Can't seek to the beggining of the file in read_bitmap_file_headers.c\n");
96      exit(FSEEK_FAILURE);
97    }
98    /* Read the .bmp file header into a bmp_buff */
99    if (!(fread(bmp_buff, 1,BITMAP_HEADER_SIZE,fp))||(strncmp((char *) bmp_buff,"BM",2)))
100    {
101       fprintf(stderr,"%s is not a valid BMP file\n", filename);
102       exit_with_msg_and_exit_code("",NOT_A_VALID_BITMAP_FILE);
103    }
104
105 /* On most machines, sizeof(short)==2 and sizeof(int)==4. This is so no matter
106 if the machine is 32 or 64 bis. An exception is the Cray Y-MP, which has  
107 sizeof(short)=8
108 sizeof(int)=8
109 sizeof(long)=8.
110
111 In this case, it is much more difficult to write the header for the bitmap. But in
112 the aid of portability, this is done. So these is a section of code that will work
113 even if sizeof(short)=8 and sizeof(int)=8. See below for that. */
114
115
116    /* Read the bmp_buff into the two structures we want */
117
118    Bitmap_File_Head.zzMagic[0x0] = bmp_buff[0];
119    Bitmap_File_Head.zzMagic[0x1] = bmp_buff[1];
120    Bitmap_File_Head.bfSize = bmp_buff[0x2] + ((bmp_buff[3] + ((bmp_buff[4] + (bmp_buff[5] << 8)) << 8)) <<8);
121    Bitmap_File_Head.zzHotX = bmp_buff[0x6] + (bmp_buff[7] << 8);
122    Bitmap_File_Head.zzHotY = bmp_buff[0x8] + (bmp_buff[0x09] << 8);
123    Bitmap_File_Head.bfOffs = bmp_buff[0x0a] + ((bmp_buff[0xb] + ((bmp_buff[0xc] + (bmp_buff[0x0d] << 8)) << 8)) <<8);
124    Bitmap_File_Head.biSize = bmp_buff[0x0E] + ((bmp_buff[0x0f] + ((bmp_buff[0x10] + (bmp_buff[0x11] << 8)) << 8)) <<8);
125 #ifdef DEBUG
126    printf("Bitmap_File_Head.bfSize = %d \n",Bitmap_File_Head.bfSize);
127    printf("Bitmap_File_Head.zzHotX = %d\n",Bitmap_File_Head.zzHotX);
128    printf("Bitmap_File_Head.zzHotY = %d\n",Bitmap_File_Head.zzHotY);
129    printf("Bitmap_File_Head.bfOffs = %d\n",Bitmap_File_Head.bfOffs);
130    printf("Bitmap_File_Head.biSize = %d\n\n",Bitmap_File_Head.biSize); 
131 #endif
132
133    Bitmap_Head.biWidth=bmp_buff[0x12] + ((bmp_buff[0x13] + ((bmp_buff[0x14] + (bmp_buff[0x15] << 8)) << 8)) <<8);
134    Bitmap_Head.biHeight=bmp_buff[0x16] + ((bmp_buff[0x17] + ((bmp_buff[0x18] + (bmp_buff[0x19] << 8)) << 8)) <<8);
135    Bitmap_Head.biPlanes = bmp_buff[0x1A] + (bmp_buff[0x1b] << 8);
136    Bitmap_Head.biBitCnt = bmp_buff[0x1C] + (bmp_buff[0x1d] << 8);
137    Bitmap_Head.biCompr= bmp_buff[0x1E] + ((bmp_buff[0x1f] + ((bmp_buff[0x20] + (bmp_buff[0x21] << 8)) << 8)) <<8);
138    Bitmap_Head.biSizeIm=bmp_buff[0x22] + ((bmp_buff[0x23] + ((bmp_buff[0x24] + (bmp_buff[0x25] << 8)) << 8)) <<8);
139    /* I thought the length of the image was always stored in Bitmap_Head.biSizeIm, but 
140    this appears not to be so. Hence it is now calculated from the length of the file
141    */ 
142    Bitmap_Head.biSizeIm=length_of_file-BITMAP_HEADER_SIZE;
143    Bitmap_Head.biXPels  = bmp_buff[0x26] + ((bmp_buff[0x27] + ((bmp_buff[0x28] + (bmp_buff[0x29] << 8)) << 8)) <<8);
144    Bitmap_Head.biYPels= bmp_buff[0x2A] + ((bmp_buff[0x2b] + ((bmp_buff[0x2c] + (bmp_buff[0x2d] << 8)) << 8)) <<8);
145    Bitmap_Head.biClrUsed = bmp_buff[0x2E] + ((bmp_buff[0x2f] + ((bmp_buff[0x30] + (bmp_buff[0x31] << 8)) << 8)) <<8);
146    Bitmap_Head.biClrImp  = bmp_buff[0x32] + ((bmp_buff[0x33] + ((bmp_buff[0x34] + (bmp_buff[0x35] << 8)) << 8)) <<8);
147
148    Maps=4;
149    if(Bitmap_Head.biBitCnt!=24)
150    {
151       fprintf(stderr,"Sorry, the .bmp bitmap must have 24 bits per colour,\n");
152       fprintf(stderr,"but it has %d bits. Resave the \n",Bitmap_Head.biBitCnt);
153       fprintf(stderr,"image using 24-bit colour\n");
154       exit_with_msg_and_exit_code("mage using 24-bit colour",BITMAP_NOT_24_BIT);
155    }
156 #ifdef DEBUG
157    printf("Bitmap_Head.biWidth   =%d =0x%x\n",Bitmap_Head.biWidth,Bitmap_Head.biWidth);
158    printf("Bitmap_Head.biHeight  =%d =0x%x\n",Bitmap_Head.biHeight,Bitmap_Head.biHeight);
159    printf("Bitmap_Head.biPlanes  =%d =0x%x\n",Bitmap_Head.biPlanes,Bitmap_Head.biPlanes);
160    printf("Bitmap_Head.biBitCnt  =%d =0x%x\n",Bitmap_Head.biBitCnt,Bitmap_Head.biBitCnt);
161    printf("Bitmap_Head.biCompr   =%d =0x%x\n",Bitmap_Head.biCompr,Bitmap_Head.biCompr );
162    printf("Bitmap_Head.biSizeIm  =%d =0x%x\n",Bitmap_Head.biSizeIm,Bitmap_Head.biSizeIm);
163    printf("size by ftell=%d\n", length_of_file);
164    printf("Bitmap_Head.biXPels   =%d =0x%x\n",Bitmap_Head.biXPels,Bitmap_Head.biXPels);
165    printf("Bitmap_Head.biYPels   =%d =0x%x\n",Bitmap_Head.biYPels,Bitmap_Head.biYPels);
166    printf("Bitmap_Head.biClrUsed =%d =0x%x\n",Bitmap_Head.biClrUsed,Bitmap_Head.biClrUsed);
167    printf("Bitmap_Head.biClrImp  =%d =0x%x\n",Bitmap_Head.biClrImp,Bitmap_Head.biClrImp);
168 #endif
169    ColormapSize = (Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps;
170
171    if ((Bitmap_Head.biClrUsed == 0) && (Bitmap_Head.biBitCnt <= 8))
172            Bitmap_Head.biClrUsed = ColormapSize;
173
174    /* Sanity checks */
175
176    if (Bitmap_Head.biHeight == 0 || Bitmap_Head.biWidth == 0) 
177    {
178       fprintf(stderr,"error reading BMP file header of %s - width or height is zero\n",filename);
179       exit_with_msg_and_exit_code("",WIDTH_OR_HEIGHT_ZERO_IN_BITMAP);
180    } 
181    if (Bitmap_Head.biPlanes != 1) 
182    {
183       fprintf(stderr,"error reading BMP file header of %s - bitplanes not equal to 1\n",filename);
184       exit_with_msg_and_exit_code("",BITPLANES_NOT_1_IN_BITMAP);
185    }
186    if (ColormapSize > 256 || Bitmap_Head.biClrUsed > 256)
187    {
188       fprintf(stderr,"error reading BMP file header of %s - colourmap size error\n",filename);
189       exit_with_msg_and_exit_code("",COLOURMAP_GREATER_THAN_256);
190    }
191    /* Windows and OS/2 declare filler so that rows are a multiple of
192       word length (32 bits == 4 bytes)
193    */
194
195    /*fclose(fp); I'm not sure if this should be closed or not. Why did I ??? */
196    *width=Bitmap_Head.biWidth;
197    *height=Bitmap_Head.biHeight;
198    *offset=Bitmap_File_Head.bfOffs;
199    *size=Bitmap_Head.biSizeIm;
200    if( *size < 3 * (*width) * (*height) )
201    {
202      fprintf(stderr,"Internal error in read_bitmap_file_headers.c\n"); 
203      exit(1);
204   }
205 }