blob: ea9d0cf148b76a478130cfcb510018ff490d3afc [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.
*/
/* $Id$ */
package org.apache.fop.image;
// Java
import java.io.IOException;
import java.awt.color.ColorSpace;
/**
* Bitmap image.
* This supports loading a bitmap image into bitmap data.
*
* @author Art WELCH
* @see AbstractFopImage
* @see FopImage
*/
public class BmpImage extends AbstractFopImage {
/**
* Create a bitmap image with the image data.
*
* @param imgInfo the image information
*/
public BmpImage(FopImage.ImageInfo imgInfo) {
super(imgInfo);
}
/**
* Load the bitmap.
* This laods the bitmap data from the bitmap image.
*
* @param ua the user agent
* @return true if it was loaded successfully
*/
protected boolean loadBitmap() {
int wpos = 18;
int hpos = 22; // offset positioning for w and height in bmp files
int[] headermap = new int[54];
int filepos = 0;
byte palette[] = null;
try {
boolean eof = false;
while ((!eof) && (filepos < 54)) {
int input = inputStream.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 = inputStream.read();
if (input == -1) {
eof = true;
} else if (count2 >= 0) {
palette[countr * 3 + count2] =
(byte)(input & 0xFF);
}
count2--;
filepos++;
}
countr++;
}
}
} catch (IOException e) {
log.error("Error while loading image "
+ "" + " : "
+ e.getClass() + " - "
+ e.getMessage(), e);
return false;
}
// gets h & w from headermap
this.width = headermap[wpos]
+ headermap[wpos + 1] * 256
+ headermap[wpos + 2] * 256 * 256
+ headermap[wpos + 3] * 256 * 256 * 256;
this.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.bitsPerPixel = headermap[28];
this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
int bytes = 0;
if (this.bitsPerPixel == 1) {
bytes = (this.width + 7) / 8;
} else if (this.bitsPerPixel == 24) {
bytes = this.width * 3;
} else if (this.bitsPerPixel == 4 || this.bitsPerPixel == 8) {
bytes = this.width / (8 / this.bitsPerPixel);
} else {
log.error("Image (" + ""
+ ") has " + this.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.bitmapsSize = this.width * this.height * 3;
this.bitmaps = new byte[this.bitmapsSize];
int[] temp = new int[bytes * this.height];
try {
int input;
int count = 0;
inputStream.skip((long)(imagestart - filepos));
while ((input = inputStream.read()) != -1) {
temp[count++] = input;
}
inputStream.close();
inputStream = null;
} catch (IOException e) {
log.error("Error while loading image "
+ "" + " : "
+ e.getClass() + " - "
+ e.getMessage(), e);
return false;
}
for (int i = 0; i < this.height; i++) {
int x = 0;
int j = 0;
while (j < bytes) {
int p = temp[(this.height - i - 1) * bytes + j];
if (this.bitsPerPixel == 24 && x < this.width) {
int countr = 2;
do {
this.bitmaps[3 * (i * this.width + x) + countr] =
(byte)(temp[(this.height - i - 1)
* bytes + j] & 0xFF);
j++;
} while (--countr >= 0)
;
x++;
} else if (this.bitsPerPixel == 1) {
for (int countr = 0;
countr < 8 && x < this.width; countr++) {
if ((p & 0x80) != 0) {
this.bitmaps[3 * (i * this.width + x)] = (byte) 0xFF;
this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0xFF;
this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0xFF;
} else {
this.bitmaps[3 * (i * this.width + x)] = (byte) 0;
this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0;
this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0;
}
p <<= 1;
x++;
}
j++;
} else if (this.bitsPerPixel == 4) {
for (int countr = 0;
countr < 2 && x < this.width; countr++) {
int pal = ((p & 0xF0) >> 4) * 3;
this.bitmaps[3 * (i * this.width + x)] = palette[pal];
this.bitmaps[3 * (i * this.width + x) + 1] = palette[pal + 1];
this.bitmaps[3 * (i * this.width + x) + 2] = palette[pal + 2];
p <<= 4;
x++;
}
j++;
} else if (this.bitsPerPixel == 8) {
if (x < this.width) {
p *= 3;
this.bitmaps[3 * (i * this.width + x)] = palette[p];
this.bitmaps[3 * (i * this.width + x) + 1] = palette[p + 1];
this.bitmaps[3 * (i * this.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 bitsPerPixel to 8. If I do not
// do this Acrobat is unable to read the resultant PDF,
// so we will hardcode this...
this.bitsPerPixel = 8;
return true;
}
}