package javaforce;
//BMP - M$-Windows Bitmap file format
import javaforce.*;
import java.awt.Dimension;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Internal class to provide BMP file support.
*
* @author Peter Quiring
*/
public class bmp {
/*/
struct _bmp_main { //18 bytes
char sig[2]; //signature = 'BM'
uint32 filesize; //entire file size
uint8 junk[4];
uint32 bitoffset; //offset of bits
uint32 siz; //1st element of win/os2 (to detect which one it is)
}; //main header (always 1st)
// * = ignored!
struct _bmp_win { //36 //Win 3.0 BMP info block (2nd part if Win 3.0)
// uint32 siz; //40
uint32 x;
uint32 y;
uint16 planes; //1 //*
uint16 bpp;
uint32 comp; //0=none 1=RLE8 2=RLE4
uint32 size_image; //*
uint32 xpm; //*
uint32 ypm; //*
uint32 clrused; // must be 0
uint32 clrimp; //*
};
struct _bmp_os2 { //8 //OS/2 info block (2nd part if OS/2)
// uint32 siz; //12
uint16 x; //DF/1.2.2 - this was uint32
uint16 y;
uint16 planes; //1 *
uint16 bpp;
};
struct _icon {
short reserved;
short type; //1=icon 2=cursor
short imageCount;
}
struct _icon_entry {
byte width, height, colorsPalette, reserved;
short planes, bpp;
int imageDataSize, dataOffset;
}
/*/
protected static int[] load(InputStream in, Dimension size) {
int a;
int clrs;
int bmp_x, bmp_y, bmp_bpp, bmp_bypp;
int fs;
int bo;
int siz;
int ret[];
//read signature
try {
if (in.read() != 'B') {
return null;
}
if (in.read() != 'M') {
return null;
}
} catch (Exception e) {
return null;
}
fs = JF.readuint32(in);
a = JF.readuint32(in); //junk
bo = JF.readuint32(in);
siz = JF.readuint32(in);
switch (siz) {
case 14: //OS/2
bmp_x = JF.readuint16(in);
bmp_y = JF.readuint16(in);
a = JF.readuint16(in); //planes - ignore
if (JF.readuint16(in) != 24) {
return null;
}
break;
case 40: //win 3.0
bmp_x = JF.readuint32(in);
bmp_y = JF.readuint32(in);
a = JF.readuint16(in); //planes - ignore
if (JF.readuint16(in) != 24) {
return null;
}
if (JF.readuint32(in) != 0) {
return null; //no compression supported
}
for (a = 0; a < 5; a++) {
JF.readuint32(in);
}
break;
default:
return null;
}
//each scan-line is DWORD aligned!
int slsiz = (bmp_x * 3 + 3) & 0x7ffffffc;
int sbufsiz = slsiz * bmp_y;
byte simg[] = new byte[sbufsiz];
try {
if (in.read(simg) != sbufsiz) {
return null;
}
} catch (Exception e) {
return null;
}
ret = new int[bmp_x * bmp_y];
int sidx = slsiz * (bmp_y - 1);
int didx = 0;
for (int y = 0; y < bmp_y; y++) {
for (int x = 0; x < bmp_x; x++) {
ret[didx++] = (((int) simg[sidx + x * 3 + 2] & 0xff) << 16 | ((int) simg[sidx + x * 3 + 1] & 0xff) << 8 | (int) simg[sidx + x * 3] & 0xff) | JFImage.OPAQUE;
}
sidx -= slsiz;
}
size.width = bmp_x;
size.height = bmp_y;
return ret;
}
protected static boolean save24(OutputStream out, int buf[], Dimension size, boolean noheader) {
int a;
int slsiz = size.width * 3;
int dlsiz = (slsiz + 3) & 0xfffffffc;
int padding = dlsiz - slsiz;
int dbufsiz = dlsiz * size.height;
int fs;
if (!noheader) {
JF.writeuint8(out, 'B');
JF.writeuint8(out, 'M');
fs = dbufsiz + 54;
JF.writeuint32(out, fs);
a = 0;
JF.writeuint32(out, a);
a = 54; //offset of bits
JF.writeuint32(out, a);
a = 40; //size of win header
JF.writeuint32(out, a);
JF.writeuint32(out, size.width);
JF.writeuint32(out, size.height);
JF.writeuint16(out, 1); //planes
JF.writeuint16(out, 24); //bpp
JF.writeuint32(out, 0); //comp
JF.writeuint32(out, dbufsiz);
for (a = 0; a < 4; a++) {
JF.writeuint32(out, 0);
}
}
byte dbuf[] = new byte[dbufsiz];
int sidx = size.width * (size.height - 1);
int didx = 0;
//Invert BMP! (Image is stored Upside Down!!!)
for (int y = 0; y < size.height; y++) {
for (int x = 0; x < size.width; x++) {
dbuf[didx++] = (byte) (buf[sidx] & 0xff);
dbuf[didx++] = (byte) ((buf[sidx] >> 8) & 0xff);
dbuf[didx++] = (byte) ((buf[sidx] >> 16) & 0xff);
sidx++;
}
didx += padding;
sidx -= (size.width * 2);
}
try {
out.write(dbuf);
} catch (Exception e) {
return false;
}
return true;
}
protected static boolean save32(OutputStream out, int buf[], Dimension size, boolean noheader, boolean icon) {
int a;
int slsiz = size.width * 4;
int dlsiz = (slsiz + 3) & 0xfffffffc;
int padding = dlsiz - slsiz;
int dbufsiz = dlsiz * size.height;
int fs;
if (!noheader) {
if (!icon) {
JF.writeuint8(out, 'B');
JF.writeuint8(out, 'M');
fs = dbufsiz + 54;
JF.writeuint32(out, fs);
a = 0;
JF.writeuint32(out, a);
a = 54; //offset of bits
JF.writeuint32(out, a);
} else {
//_icon
JF.writeuint16(out, 0); //reserved
JF.writeuint16(out, 1); //1=ICO
JF.writeuint16(out, 1); //# of images
//_icon_entry
JF.writeuint8(out, size.width);
JF.writeuint8(out, size.height);
JF.writeuint8(out, 0); //colors in palette (not used)
JF.writeuint8(out, 0); //reserved
JF.writeuint16(out, 1); //planes
JF.writeuint16(out, 32); //bpp
JF.writeuint32(out, 40 + dbufsiz); //size of image data
JF.writeuint32(out, 0x16); //offset to image data
}
a = 40; //size of win header
JF.writeuint32(out, a);
JF.writeuint32(out, size.width);
JF.writeuint32(out, size.height * (icon ? 2 : 1));
JF.writeuint16(out, 1); //planes
JF.writeuint16(out, 32); //bpp
JF.writeuint32(out, 0); //comp
JF.writeuint32(out, dbufsiz);
for (a = 0; a < 4; a++) {
JF.writeuint32(out, 0);
}
}
byte dbuf[] = new byte[dbufsiz];
int sidx = size.width * (size.height - 1);
int didx = 0;
//Invert BMP! (Image is stored Upside Down!!!)
for (int y = 0; y < size.height; y++) {
for (int x = 0; x < size.width; x++) {
dbuf[didx++] = (byte) (buf[sidx] & 0xff);
dbuf[didx++] = (byte) ((buf[sidx] >> 8) & 0xff);
dbuf[didx++] = (byte) ((buf[sidx] >> 16) & 0xff);
dbuf[didx++] = (byte) ((buf[sidx] >> 24) & 0xff); //alpha
sidx++;
}
didx += padding;
sidx -= (size.width * 2);
}
try {
out.write(dbuf);
} catch (Exception e) {
return false;
}
return true;
}
}