blob: d58fe94e982fcecfdf226e6d9b26ebcbc291248d [file] [log] [blame]
/*
* $Id$
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources.
*/
/**
* FopImage object for BMP images.
* @author Art WELCH
* @see AbstractFopImage
* @see FopImage
*/
package org.apache.fop.image;
// Java
import java.net.URL;
import java.io.InputStream;
import java.io.IOException;
// FOP
import org.apache.fop.datatypes.ColorSpace;
import org.apache.fop.pdf.PDFColor;
import org.apache.fop.image.analyser.ImageReader;
import org.apache.fop.fo.FOUserAgent;
public class BmpImage extends AbstractFopImage {
public BmpImage(URL href, FopImage.ImageInfo imgReader) {
super(href, imgReader);
}
protected boolean loadBitmap(FOUserAgent ua) {
int wpos = 18;
int hpos = 22; // offset positioning for w and height in bmp files
int[] headermap = new int[54];
int filepos = 0;
InputStream file = null;
byte palette[] = null;
try {
file = this.m_href.openStream();
boolean eof = false;
while ((!eof) && (filepos < 54)) {
int input = file.read();
if (input == -1)
eof = true;
else
headermap[filepos++] = input;
}
if (headermap[28] == 4 || headermap[28] == 8) {
int palettesize = 1 << headermap[28];
palette = new byte[palettesize * 3];
int countr = 0;
while (!eof && countr < palettesize) {
int count2 = 2;
while (!eof && count2 >= -1) {
int input = file.read();
if (input == -1)
eof = true;
else if (count2 >= 0) {
palette[countr * 3 + count2] =
(byte)(input & 0xFF);
}
count2--;
filepos++;
}
countr++;
}
}
} catch (IOException e) {
ua.getLogger().error("Error while loading image "
+ this.m_href.toString() + " : "
+ e.getClass() + " - "
+ e.getMessage(), e);
return false;
}
// gets h & w from headermap
this.m_width = headermap[wpos] + headermap[wpos + 1] * 256 +
headermap[wpos + 2] * 256 * 256 +
headermap[wpos + 3] * 256 * 256 * 256;
this.m_height = headermap[hpos] + headermap[hpos + 1] * 256 +
headermap[hpos + 2] * 256 * 256 +
headermap[hpos + 3] * 256 * 256 * 256;
int imagestart = headermap[10] + headermap[11] * 256 +
headermap[12] * 256 * 256 + headermap[13] * 256 * 256 * 256;
this.m_bitsPerPixel = headermap[28];
this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
int bytes = 0;
if (this.m_bitsPerPixel == 1)
bytes = (this.m_width + 7) / 8;
else if (this.m_bitsPerPixel == 24)
bytes = this.m_width * 3;
else if (this.m_bitsPerPixel == 4 || this.m_bitsPerPixel == 8)
bytes = this.m_width / (8 / this.m_bitsPerPixel);
else {
ua.getLogger().error("Image (" + this.m_href.toString()
+ ") has " + this.m_bitsPerPixel
+ " which is not a supported BMP format.");
return false;
}
if ((bytes & 0x03) != 0) {
bytes |= 0x03;
bytes++;
}
// Should take care of the ColorSpace and bitsPerPixel
this.m_bitmapsSize = this.m_width * this.m_height * 3;
this.m_bitmaps = new byte[this.m_bitmapsSize];
int[] temp = new int[bytes * this.m_height];
try {
int input;
int count = 0;
file.skip((long)(imagestart - filepos));
while ((input = file.read()) != -1)
temp[count++] = input;
file.close();
} catch (IOException e) {
ua.getLogger().error("Error while loading image "
+ this.m_href.toString() + " : "
+ e.getClass() + " - "
+ e.getMessage(), e);
return false;
}
for (int i = 0; i < this.m_height; i++) {
int x = 0;
int j = 0;
while (j < bytes) {
int p = temp[(this.m_height - i - 1) * bytes + j];
if (this.m_bitsPerPixel == 24 && x < this.m_width) {
int countr = 2;
do {
this.m_bitmaps[3 * (i * this.m_width + x) +
countr] =
(byte)(temp[(this.m_height - i - 1) *
bytes + j] & 0xFF);
j++;
} while (--countr >= 0)
;
x++;
} else if (this.m_bitsPerPixel == 1) {
for (int countr = 0;
countr < 8 && x < this.m_width; countr++) {
if ((p & 0x80) != 0) {
this.m_bitmaps[3 *
(i * this.m_width + x)] = (byte) 0xFF;
this.m_bitmaps[3 * (i * this.m_width + x) +
1] = (byte) 0xFF;
this.m_bitmaps[3 * (i * this.m_width + x) +
2] = (byte) 0xFF;
} else {
this.m_bitmaps[3 *
(i * this.m_width + x)] = (byte) 0;
this.m_bitmaps[3 * (i * this.m_width + x) +
1] = (byte) 0;
this.m_bitmaps[3 * (i * this.m_width + x) +
2] = (byte) 0;
}
p <<= 1;
x++;
}
j++;
} else if (this.m_bitsPerPixel == 4) {
for (int countr = 0;
countr < 2 && x < this.m_width; countr++) {
int pal = ((p & 0xF0) >> 4) * 3;
this.m_bitmaps[3 * (i * this.m_width + x)] =
palette[pal];
this.m_bitmaps[3 * (i * this.m_width + x) +
1] = palette[pal + 1];
this.m_bitmaps[3 * (i * this.m_width + x) +
2] = palette[pal + 2];
p <<= 4;
x++;
}
j++;
} else if (this.m_bitsPerPixel == 8) {
if (x < this.m_width) {
p *= 3;
this.m_bitmaps[3 * (i * this.m_width + x)] =
palette[p];
this.m_bitmaps[3 * (i * this.m_width + x) +
1] = palette[p + 1];
this.m_bitmaps[3 * (i * this.m_width + x) +
2] = palette[p + 2];
j++;
x++;
} else
j = bytes;
} else
j++;
}
}
// This seems really strange to me, but I noticed that JimiImage hardcodes
// m_bitsPerPixel to 8. If I do not do this Acrobat is unable to read the resultant PDF,
// so we will hardcode this...
this.m_bitsPerPixel = 8;
return true;
}
}