DefineBitsLossLess2Tag.java
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_ARGB);
ALPHACOLORMAPDATA colorMapData = null;
ALPHABITMAPDATA bitmapData = null;
if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED) {
colorMapData = getColorMapData();
}
if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB) {
bitmapData = getBitmapData();
}
int pos32aligned = 0;
int pos = 0;
for (int y = 0; y < bitmapHeight; y++) {
for (int x = 0; x < bitmapWidth; x++) {
int c = 0;
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) {
c = multiplyAlpha(colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff].toInt());
}
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB)) {
c = multiplyAlpha(bitmapData.bitmapPixelData[pos].toInt());
}
bi.setRGB(x, y, c);
pos32aligned++;
pos++;
}
while ((pos32aligned % 4 != 0)) {
pos32aligned++;
}
}
cachedImage = bi;
return bi;
}
ImageExporter.java中调用上述函数
public List<File> exportImages(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, ImageExportSettings settings, EventListener evl) throws IOException {
List<File> ret = new ArrayList<>();
if (tags.isEmpty()) {
return ret;
}
File foutdir = new File(outdir);
if (!foutdir.exists()) {
if (!foutdir.mkdirs()) {
if (!foutdir.exists()) {
throw new IOException("Cannot create directory " + outdir);
}
}
}
int count = 0;
for (Tag t : tags) {
if (t instanceof ImageTag) {
count++;
}
}
int currentIndex = 1;
for (Tag t : tags) {
if (t instanceof ImageTag) {
if (evl != null) {
evl.handleExportingEvent("image", currentIndex, count, t.getName());
}
final ImageTag imageTag = (ImageTag) t;
String fileFormat = imageTag.getImageFormat().toUpperCase(Locale.ENGLISH);
if (settings.mode == ImageExportMode.PNG) {
fileFormat = "png";
}
if (settings.mode == ImageExportMode.JPEG) {
fileFormat = "jpg";
}
if (settings.mode == ImageExportMode.BMP) {
fileFormat = "bmp";
}
{
final File file = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + "." + fileFormat));
final String ffileFormat = fileFormat;
new RetryTask(new RunnableIOEx() {
@Override
public void run() throws IOException {
if (ffileFormat.equals("bmp")) {
BMPFile.saveBitmap(imageTag.getImage().getBufferedImage(), file);
} else {
ImageHelper.write(imageTag.getImage().getBufferedImage(), ffileFormat.toUpperCase(Locale.ENGLISH), file);
}
}
}, handler).run();
ret.add(file);
}
if (evl != null) {
evl.handleExportedEvent("image", currentIndex, count, t.getName());
}
currentIndex++;
}
}
return ret;
}
BMPFile.java中调用上上函数
public static void saveBitmap(Image image, File file) throws IOException {
BMPFile b = new BMPFile();
try (FileOutputStream fos = new FileOutputStream(file)) {
b.fo = fos;
b.save(image, image.getWidth(null), image.getHeight(null));
}
}
/*
* The saveMethod is the main method of the process. This method
* will call the convertImage method to convert the memory image to
* a byte array; method writeBitmapFileHeader creates and writes
* the bitmap file header; writeBitmapInfoHeader creates the
* information header; and writeBitmap writes the image.
*
*/
private void save(Image parImage, int parWidth, int parHeight) throws IOException {
convertImage(parImage, parWidth, parHeight);
writeBitmapFileHeader();
writeBitmapInfoHeader();
writeBitmap();
}
/*
* convertImage converts the memory image to the bitmap format (BRG).
* It also computes some information for the bitmap info header.
*
*/
private boolean convertImage(Image parImage, int parWidth, int parHeight) {
int pad;
bitmap = new int[parWidth * parHeight];
PixelGrabber pg = new PixelGrabber(parImage, 0, 0, parWidth, parHeight,
bitmap, 0, parWidth);
try {
pg.grabPixels();
} catch (InterruptedException e) {
return (false);
}
pad = (4 - ((parWidth * 3) % 4)) * parHeight;
biSizeImage = ((parWidth * parHeight) * 3) + pad;
bfSize = biSizeImage + BITMAPFILEHEADER_SIZE
+ BITMAPINFOHEADER_SIZE;
biWidth = parWidth;
biHeight = parHeight;
return (true);
}
/*
* writeBitmap converts the image returned from the pixel grabber to
* the format required. Remember: scan lines are inverted in
* a bitmap file!
*
* Each scan line must be padded to an even 4-byte boundary.
*/
private void writeBitmap() throws IOException {
int size;
int value;
int j;
int i;
int rowCount;
int rowIndex;
int lastRowIndex;
int pad;
int padCount;
byte[] rgb = new byte[3];
size = (biWidth * biHeight);
pad = (biWidth * 3) % 4;
rowCount = 1;
padCount = 0;
rowIndex = size - biWidth;
lastRowIndex = rowIndex;
for (j = 0; j < size; j++) {
value = bitmap[rowIndex];
rgb[0] = (byte) (value & 0xFF);
rgb[1] = (byte) ((value >> 8) & 0xFF);
rgb[2] = (byte) ((value >> 16) & 0xFF);
fo.write(rgb);
if (rowCount == biWidth) {
padCount += pad;
for (i = 1; i <= pad; i++) {
fo.write(0x00);
}
rowCount = 1;
rowIndex = lastRowIndex - biWidth;
lastRowIndex = rowIndex;
} else {
rowCount++;
}
rowIndex++;
}
//--- Update the size of the file
bfSize += padCount - pad;
biSizeImage += padCount - pad;
}
/*
* writeBitmapFileHeader writes the bitmap file header to the file.
*
*/
private void writeBitmapFileHeader() throws IOException {
fo.write(bfType);
fo.write(intToDWord(bfSize));
fo.write(intToWord(bfReserved1));
fo.write(intToWord(bfReserved2));
fo.write(intToDWord(bfOffBits));
}
/*
*
* writeBitmapInfoHeader writes the bitmap information header
* to the file.
*
*/
private void writeBitmapInfoHeader() throws IOException {
fo.write(intToDWord(biSize));
fo.write(intToDWord(biWidth));
fo.write(intToDWord(biHeight));
fo.write(intToWord(biPlanes));
fo.write(intToWord(biBitCount));
fo.write(intToDWord(biCompression));
fo.write(intToDWord(biSizeImage));
fo.write(intToDWord(biXPelsPerMeter));
fo.write(intToDWord(biYPelsPerMeter));
fo.write(intToDWord(biClrUsed));
fo.write(intToDWord(biClrImportant));
}
/*
*
* intToWord converts an int to a word, where the return
* value is stored in a 2-byte array.
*
*/
private byte[] intToWord(int parValue) {
byte[] retValue = new byte[2];
retValue[0] = (byte) (parValue & 0x00FF);
retValue[1] = (byte) ((parValue >> 8) & 0x00FF);
return (retValue);
}
/*
*
* intToDWord converts an int to a double word, where the return
* value is stored in a 4-byte array.
*
*/
private byte[] intToDWord(int parValue) {
byte[] retValue = new byte[4];
retValue[0] = (byte) (parValue & 0x00FF);
retValue[1] = (byte) ((parValue >> 8) & 0x000000FF);
retValue[2] = (byte) ((parValue >> 16) & 0x000000FF);
retValue[3] = (byte) ((parValue >> 24) & 0x000000FF);
return (retValue);
}