blob: 6fd21f4dd21e000a470c31c45d8215f2ee22db59 [file] [log] [blame]
/**********************************************************************
* 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 <io.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#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;
}