/********************************************************************** * File: imgbmp.c (Formerly lz.c) * Description: bmp image reader/writer. * Author: Ray Smith * Created: Tue Jan 06 15:31:25 GMT 1998 * * (C) Copyright 1998, Ray Smith. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/ #include "mfcpch.h" //precompiled headers #ifdef __MSW32__ #include #else #include #endif #include #include "img.h" #include "imgbmp.h" typedef struct { // bmfh char bfType1; //'B' char bfType2; //'M' } BMPHEADER0; typedef struct { // bmfh uinT32 bfSize; //filesize uinT16 bfReserved1; //zero uinT16 bfReserved2; //zero uinT32 bfOffBits; //offset to bitmap } BMPHEADER; typedef struct { // bmih uinT32 biSize; //size of struct inT32 biWidth; //image width inT32 biHeight; //image height uinT16 biPlanes; //1 uinT16 biBitCount; //bpp uinT32 biCompression; //0 for uncompressed uinT32 biSizeImage; //image size inT32 biXPelsPerMeter; //res in pp metre inT32 biYPelsPerMeter; uinT32 biClrUsed; //0 or actual size of colour table uinT32 biClrImportant; //usually 0 } BMPHEADER2; typedef struct { // rgbq uinT8 rgbBlue; uinT8 rgbGreen; uinT8 rgbRed; uinT8 rgbReserved; //0 } WIN32_RGBQUAD; /********************************************************************** * open_bmp_image * * Read the header of a bmp format image and prepare to read the rest. **********************************************************************/ inT8 open_bmp_image( //read header int fd, //file to read inT32 *xsize, //size of image inT32 *ysize, inT8 *bpp, //bits per pixel inT8 *photo, inT32 *res //resolution ) { uinT32 nread; //current bits BMPHEADER0 head0; //first part of header BMPHEADER head1; //first part of header BMPHEADER2 head2; //first part of header *photo = 1; nread = read (fd, &head0, sizeof (head0)); if (nread != sizeof (head0)) return -1; nread = read (fd, &head1, sizeof (head1)); if (nread != sizeof (head1)) return -1; nread = read (fd, &head2, sizeof (head2)); if (nread != sizeof (head2)) return -1; if (head0.bfType1 != 'B') return -1; if (head0.bfType2 != 'M') return -1; lseek (fd, head1.bfOffBits, SEEK_SET); *bpp = head2.biBitCount; *xsize = head2.biWidth; *ysize = head2.biHeight; *res = 300; //make up resolution return -2; //success } /********************************************************************** * read_bmp_image * * Read a whole lz format image and close the file. **********************************************************************/ inT8 read_bmp_image( //read header int fd, //file to read uinT8 *pixels, //pixels of image inT32 xsize, //size of image inT32 ysize, inT8 bpp, //bits per pixel inT32 //bytes per line ) { uinT32 bpl; //bytes per line uinT32 wpl; //words per line uinT32 nread; //current bits inT32 index; //to cols bpl = (xsize * bpp + 7) / 8; //bytes per line wpl = (bpl + 3) / 4; wpl *= 4; for (index = 0; index < ysize; index++) { nread = read (fd, pixels + bpl * (ysize - 1 - index), bpl); if (nread != bpl) return -1; if (wpl != bpl) lseek (fd, wpl - bpl, SEEK_CUR); } return 0; } /********************************************************************** * write_bmp_image * * Write a whole lz format image and close the file. **********************************************************************/ inT8 write_bmp_image( //write whole image int fd, //file to write on uinT8 *pixels, //image pixels inT32 xsize, //size of image inT32 ysize, inT8 bpp, //bits per pixel inT8, inT32 res //resolution ) { uinT32 bpl; //bytes per line uinT32 wpl; //words per line uinT32 nread; //current bits inT32 cols; //entries in table inT32 index; //to cols BMPHEADER0 head0; //first part of header BMPHEADER head1; //first part of header BMPHEADER2 head2; //first part of header WIN32_RGBQUAD coltab[256]; //colour table if (bpp == 24) cols = 0; else cols = 1 << bpp; //size of colour table bpl = (xsize * bpp + 7) / 8; //bytes per line wpl = (bpl + 3) / 4; head2.biSize = sizeof (head2); //size of struct head2.biWidth = xsize; //image width head2.biHeight = ysize; //image height head2.biPlanes = 1; //1 head2.biBitCount = bpp; //bpp head2.biCompression = 0; //0 for uncompressed //image size head2.biSizeImage = wpl * 4 * ysize; //res in pp metre head2.biXPelsPerMeter = (uinT32) (res * 39.37); head2.biYPelsPerMeter = (uinT32) (res * 39.37); head2.biClrUsed = cols; //0 or actual size of colour table head2.biClrImportant = 0; //usually 0 head0.bfType1 = 'B'; head0.bfType2 = 'M'; head1.bfReserved1 = 0; //zero head1.bfReserved2 = 0; //zero //offset to bitmap head1.bfOffBits = sizeof (head0) + sizeof (head1) + sizeof (head2) + sizeof (WIN32_RGBQUAD) * cols; //filesize head1.bfSize = head1.bfOffBits + head2.biSizeImage; for (index = 0; index < cols; index++) { coltab[index].rgbBlue = index * 255 / (cols - 1); coltab[index].rgbGreen = coltab[index].rgbBlue; coltab[index].rgbRed = coltab[index].rgbBlue; coltab[index].rgbReserved = 0; } nread = write (fd, &head0, sizeof (head0)); if (nread != sizeof (head0)) return -1; nread = write (fd, &head1, sizeof (head1)); if (nread != sizeof (head1)) return -1; nread = write (fd, &head2, sizeof (head2)); if (nread != sizeof (head2)) return -1; nread = write (fd, coltab, cols * sizeof (WIN32_RGBQUAD)); if (nread != cols * sizeof (WIN32_RGBQUAD)) return -1; for (index = 0; index < ysize; index++) { nread = write (fd, pixels + bpl * (ysize - 1 - index), wpl * 4); if (nread != wpl * 4) return -1; } close(fd); //done it return 0; }