使用 java.awt.image.BufferedImage 创建 BIFF8 BITMAP 记录需要很多时间 - 有没有更好的方法? [英] Using java.awt.image.BufferedImage for creating BIFF8 BITMAP record takes much time - Is there any better approach?

查看:29
本文介绍了使用 java.awt.image.BufferedImage 创建 BIFF8 BITMAP 记录需要很多时间 - 有没有更好的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在创建一个 HSSFSheet,它有一个使用 apache poi 和自己的低级代码设置的背景位图.

为了实现这一点,我的方法是使用类型为 BufferedImage.TYPE_3BYTE_BGRjava.awt.image.BufferedImage.然后以正确的顺序(从底线到顶线)从该 BufferedImage 的栅格中获取所有字节 R G B,并在宽度(x 方向)上填充到 4 的倍数.

查看代码:

import java.io.FileOutputStream;导入 java.io.FileInputStream;导入 org.apache.poi.hssf.usermodel.*;导入 org.apache.poi.hssf.record.RecordBase;导入 org.apache.poi.hssf.record.StandardRecord;导入 org.apache.poi.hssf.model.InternalSheet;导入 org.apache.poi.util.LittleEndianOutput;导入 java.lang.reflect.Field;导入 java.util.List;导入 java.util.ArrayList;导入 java.util.Arrays;导入 java.awt.image.BufferedImage;导入 java.awt.Graphics2D;导入 java.nio.ByteBuffer;导入 java.nio.ByteOrder;导入 javax.imageio.ImageIO;公共类 CreateExcelHSSFSheetBackgroundBitmap {静态列表<字节>getBackgroundBitmapData(String filePath) 抛出异常 {//参见 https://www.openoffice.org/sc/excelfileformat.pdf - 位图列表<字节>数据 = 新的 ArrayList();//获取 BufferedImage.TYPE_3BYTE_BGR 类型的文件字节数据BufferedImage in = ImageIO.read(new FileInputStream(filePath));BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_3BYTE_BGR);Graphics2D 图形 = image.createGraphics();graphics.drawImage(in, null, 0, 0);图形处理();短宽度 = (短)image.getWidth();短高度 = (短)image.getHeight();//每个像素有 3 个字节,但宽度字节必须填充为 4 的倍数int widthBytesMultOf4 = (int)((width * 3 + 3)/4 * 4);//--- 这部分需要很多时间,但我没有找到更好的可能性//将字节 R G B 放入数据中;位图的行必须从底线到顶线整数字节 = 0;for (short y = (short)(height - 1); y >= 0; y--) {for (short x = 0; x <宽度; x++) {int r = image.getData().getSample(x, y, 2);data.add(Byte.valueOf((byte)r));字节++;int g = image.getData().getSample(x, y, 1);data.add(Byte.valueOf((byte)g));字节++;int b = image.getData().getSample(x, y, 0);data.add(Byte.valueOf((byte)b));字节++;}//用 0 字节填充 x 到 4 的倍数for (int x = width * 3; x )_records.get(internalsheet);//获取图像文件的字节数列表<字节>data = getBackgroundBitmapData("dummyText.png");//PNG不能有透明度//从 8220 字节的数据中创建 BitmapRecord 和 ContinueRecordsBitmapRecord bitmapRecord = null;列表<ContinueRecord>continueRecords = new ArrayList();整数字节 = 0;如果(数据大小()> 8220){bitmapRecord = new BitmapRecord(data.subList(0, 8220));字节 = 8220;while (bytes < data.size()) {if ((bytes + 8220) < data.size()) {continueRecords.add(new ContinueRecord(data.subList(bytes, bytes + 8220)));字节 += 8220;} 别的 {continueRecords.add(new ContinueRecord(data.subList(bytes, data.size())));休息;}}} 别的 {bitmapRecord = new BitmapRecord(data);}//在 PageSettingsBlock 之后添加记录int i = 0;for (RecordBase r : 记录) {如果(r instanceof org.apache.poi.hssf.record.aggregates.PageSettingsBlock){休息;}我++;}record.add(++i, bitmapRecord);for (ContinueRecord continueRecord : continueRecords) {record.add(++i, continueRecord);}//调试输出for (RecordBase r : internalsheet.getRecords()) {System.out.println(r);}//写出工作簿workbook.write(new FileOutputStream("CreateExcelHSSFSheetBackgroundBitmap.xls"));workbook.close();}静态类 BitmapRecord 扩展了 StandardRecord {//参见 https://www.openoffice.org/sc/excelfileformat.pdf - 位图列表<字节>数据 = 新的 ArrayList();BitmapRecord(列表<字节>数据){this.data = 数据;}公共 int getDataSize() {返回数据大小();}公共短 getSid() {返回(短)0x00E9;}公共无效序列化(LittleEndianOutput 输出){对于(字节 b:数据){out.writeByte(b);}}}静态类 ContinueRecord 扩展 StandardRecord {//参见 https://www.openoffice.org/sc/excelfileformat.pdf - 继续列表<字节>数据 = 新的 ArrayList();继续记录(列表<字节>数据){this.data = 数据;}公共 int getDataSize() {返回数据大小();}公共短 getSid() {返回(短)0x003C;}公共无效序列化(LittleEndianOutput 输出){对于(字节 b:数据){out.writeByte(b);}}}}

代码有效,但

之间的部分

//--- 这部分需要很多时间,但我没有找到更好的可能性

//---

需要很多时间,因为需要为每个像素获取 3 个字节的 R GB 才能根据上述奇怪的格式获取它们.

有人知道更好的方法吗?也许上面奇怪的格式并没有我想象的那么奇怪,而且已经有其他的用法了?

解决方案

这是对我有用的代码的修改版本,而且速度非常快.

  1. 我正在使用 byte[](和 ByteArrayOutputStream),不再使用 List.
  2. 因为我们已经有一个 TYPE_3BYTE_BGRBufferedImage,我们几乎可以直接使用它作为 BMP 输出.我们只需要 a) 预先添加一个有效的 BMP 标头和 b) 自底向上写入,c) 将每个扫描线(行)填充到 32 位边界和 d) 切换 BGR -> RGB 顺序.
  3. 我正在使用 Raster 将数据行复制(填充)到输出中,因为复制更大的块比复制单个字节更快.

正如评论中已经指出的,该结构是一个标准的 BMP,带有 BITMAPCOREHEADER(没有文件头).不幸的是,ImageIO BMPImageWriter 总是写入文件头并使用 40 字节的 BITMAPINFOHEADER.您可能可以绕过这些问题,并使用标准编写器,通过稍微按摩数据(提示:文件头包含偏移量 10 处像素数据的偏移量),但由于核心 BMP 格式实现起来很简单,它可能和下面一样容易.

虽然文档肯定暗示直接使用其他格式,如 PNG 和 JPEG,但我没有设法正确地做到这一点.

如果你愿意,可能还有改进的余地,以避免一些字节数组复制(即使用偏移量/长度并将整个数据数组传递给 Bitmap/ContinueRecords 而不是 Arrays.copyOfRange()).

代码:

import java.awt.Graphics2D;导入 java.awt.image.BufferedImage;导入 java.awt.image.Raster;导入 java.io.ByteArrayOutputStream;导入 java.io.FileInputStream;导入 java.io.FileOutputStream;导入 java.lang.reflect.Field;导入 java.nio.ByteBuffer;导入 java.nio.ByteOrder;导入 java.util.ArrayList;导入 java.util.Arrays;导入 java.util.List;导入 javax.imageio.ImageIO;导入 org.apache.poi.hssf.model.InternalSheet;导入 org.apache.poi.hssf.record.RecordBase;导入 org.apache.poi.hssf.record.StandardRecord;导入 org.apache.poi.hssf.usermodel.HSSFSheet;导入 org.apache.poi.hssf.usermodel.HSSFWorkbook;导入 org.apache.poi.util.LittleEndianOutput;公共类 CreateExcelHSSFSheetBackgroundBitmap {静态字节[] getBackgroundBitmapData(字符串文件路径)抛出异常{//参见 https://www.openoffice.org/sc/excelfileformat.pdf - 位图//获取 BufferedImage.TYPE_3BYTE_BGR 类型的文件字节数据BufferedImage in = ImageIO.read(new FileInputStream(filePath));BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_3BYTE_BGR);Graphics2D 图形 = image.createGraphics();graphics.drawImage(in, null, 0, 0);图形处理();//计算行大小 (c)int rowSize = ((24 * image.getWidth() + 31)/32) * 4;ByteArrayOutputStream output = new ByteArrayOutputStream(image.getHeight() * rowSize * 3 + 1024);//将记录头放入数据中ByteBuffer 头 = ByteBuffer.allocate(8 + 12);header.order(ByteOrder.LITTLE_ENDIAN);//未记录的 XLS 内容header.putShort((short) 0x09);header.putShort((short) 0x01);header.putInt(image.getHeight() * rowSize + 12);//图像流的大小//位图核心头(a)header.putInt(12);header.putShort((short) image.getWidth());header.putShort((short) image.getHeight());//如果自上而下书写,则使用 -heightheader.putShort((short) 1);//平面,总是 1header.putShort((short) 24);//位数output.write(header.array());//自底向上输出行 (b)光栅 raster = image.getRaster().createChild(0, 0, image.getWidth(), image.getHeight(), 0, 0, new int[]{2, 1, 0});//反向 BGR ->RGB (d)字节[]行=新字节[行大小];//填充 (c)for (int i = image.getHeight() - 1; i >= 0; i--) {row = (byte[]) raster.getDataElements(0, i, image.getWidth(), 1, row);输出.写(行);}返回 output.toByteArray();}public static void main(String[] args) 抛出异常 {HSSFWorkbook 工作簿 = new HSSFWorkbook();HSSFSheet sheet = workbook.createSheet("Sheet2");//这个sheet获取背景图片集//我们需要工作表的二进制记录//获取内部表Field _sheet = HSSFSheet.class.getDeclaredField("_sheet");_sheet.setAccessible(true);InternalSheet internalsheet = (InternalSheet)_sheet.get(sheet);//获取记录库列表Field _records = InternalSheet.class.getDeclaredField("_records");_records.setAccessible(true);@SuppressWarnings("未选中")列表<RecordBase>record = (List)_records.get(internalsheet);//获取图像文件的字节数byte[] data = getBackgroundBitmapData("dummy.png");//PNG不能有透明度//从 8220 字节的数据中创建 BitmapRecord 和 ContinueRecordsBitmapRecord bitmapRecord;列表<ContinueRecord>continueRecords = new ArrayList<>();整数字节;如果(数据长度> 8220){bitmapRecord = new BitmapRecord(Arrays.copyOfRange(data, 0, 8220));字节 = 8220;while (bytes < data.length) {if ((bytes + 8220) 

So I am creating a HSSFSheet having a background bitmap set using apache poi and own low level code. The https://www.openoffice.org/sc/excelfileformat.pdf declares for the Record BITMAP, BIFF8:

Pixel data (array of height lines of the bitmap, from bottom line to top line, see below)

...

In each line all pixels are written from left to right. Each pixel is stored as 3-byte array: the red, green, and blue component of the colour of the pixel, in this order. The size of each line is aligned to multiples of 4 by inserting zero bytes after the last pixel.

See picture of the PDF for complete declaration:

For fulfilling this my approach is using java.awt.image.BufferedImage having type BufferedImage.TYPE_3BYTE_BGR. Then getting all bytes R G B from that BufferedImage's raster in correct order (from bottom line to top line) and filled up up to multiple of 4 in width (x direction).

See code:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.hssf.usermodel.*;

import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.StandardRecord;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.util.LittleEndianOutput;

import java.lang.reflect.Field;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

import java.awt.image.BufferedImage;
import java.awt.Graphics2D;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.imageio.ImageIO;

public class CreateExcelHSSFSheetBackgroundBitmap {

 static List<Byte> getBackgroundBitmapData(String filePath) throws Exception {

  //see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP

  List<Byte> data = new ArrayList<Byte>();

  // get file byte data in type BufferedImage.TYPE_3BYTE_BGR
  BufferedImage in = ImageIO.read(new FileInputStream(filePath));
  BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
  Graphics2D graphics = image.createGraphics();
  graphics.drawImage(in, null, 0, 0);
  graphics.dispose();

  short width = (short)image.getWidth();
  short height = (short)image.getHeight();

  // each pixel has 3 bytes but the width bytes must be filled up to multiple of 4
  int widthBytesMultOf4 = (int)((width * 3 + 3) / 4 * 4);

// --- this part takes much time but I have not found any better possibility

  // put the bytes R G B into the data; lines of the bitmap must be from bottom line to top line
  int bytes = 0;
  for (short y = (short)(height - 1); y >= 0; y--) {
   for (short x = 0; x < width; x++) {
    int r = image.getData().getSample(x, y, 2);
    data.add(Byte.valueOf((byte)r));
    bytes++;
    int g = image.getData().getSample(x, y, 1);
    data.add(Byte.valueOf((byte)g));
    bytes++;
    int b = image.getData().getSample(x, y, 0);
    data.add(Byte.valueOf((byte)b));
    bytes++;
   } 
   // fill up x with 0 bytes up to multiple of 4
   for (int x = width * 3; x < widthBytesMultOf4; x++) {
    data.add(Byte.valueOf((byte)0));
    bytes++;
   }
  }

// ---

  // size  12 bytes (additional headers, see below) + picture bytes
  int size = 12 + bytes;

  // get size int as LITTLE_ENDIAN bytes
  ByteBuffer bSize = ByteBuffer.allocate(4);
  bSize.order(ByteOrder.LITTLE_ENDIAN);
  bSize.putInt(size);

  // get width short as LITTLE_ENDIAN bytes
  ByteBuffer bWidth = ByteBuffer.allocate(2);
  bWidth.order(ByteOrder.LITTLE_ENDIAN);
  bWidth.putShort(width);

  // get height short as LITTLE_ENDIAN bytes
  ByteBuffer bHeight = ByteBuffer.allocate(2);
  bHeight.order(ByteOrder.LITTLE_ENDIAN);
  bHeight.putShort(height);

  // put the record headers into the data
  Byte[] dataPart = new Byte[] { 0x09, 0x00, 0x01, 0x00, 
     bSize.array()[0], bSize.array()[1], bSize.array()[2], bSize.array()[3], // size
     //now 12 bytes follow
     0x0C, 0x00, 0x00, 0x00, 
     bWidth.array()[0], bWidth.array()[1], // width
     bHeight.array()[0], bHeight.array()[1], // height
     0x01, 0x00, 0x18, 0x00
   }; 

  data.addAll(0, Arrays.asList(dataPart));

  return data;
 }

 public static void main(String[] args) throws Exception {

  HSSFWorkbook workbook = new HSSFWorkbook();
  HSSFSheet sheet = workbook.createSheet("Sheet1");
  sheet = workbook.createSheet("Sheet2"); // this sheet gets the background image set

  // we need the binary records of the sheet
  // get InternalSheet
  Field _sheet = HSSFSheet.class.getDeclaredField("_sheet");
  _sheet.setAccessible(true); 
  InternalSheet internalsheet = (InternalSheet)_sheet.get(sheet); 

  // get List of RecordBase
  Field _records = InternalSheet.class.getDeclaredField("_records");
  _records.setAccessible(true);
  @SuppressWarnings("unchecked") 
  List<RecordBase> records = (List<RecordBase>)_records.get(internalsheet);

  // get bytes of the image file
  List<Byte> data = getBackgroundBitmapData("dummyText.png"); //PNG must not have transparency

  // do creating BitmapRecord and ContinueRecords from the data in parts of 8220 bytes
  BitmapRecord bitmapRecord = null;
  List<ContinueRecord> continueRecords = new ArrayList<ContinueRecord>();
  int bytes = 0;
  if (data.size() > 8220) {
   bitmapRecord = new BitmapRecord(data.subList(0, 8220));
   bytes = 8220;
   while (bytes < data.size()) {
    if ((bytes + 8220) < data.size()) {
     continueRecords.add(new ContinueRecord(data.subList(bytes, bytes + 8220)));
     bytes += 8220;
    } else {
     continueRecords.add(new ContinueRecord(data.subList(bytes, data.size())));
     break;
    }
   }
  } else {
   bitmapRecord = new BitmapRecord(data);
  }

  // add the records after PageSettingsBlock
  int i = 0;
  for (RecordBase r : records) {
   if (r instanceof org.apache.poi.hssf.record.aggregates.PageSettingsBlock) {
    break;
   }
   i++;
  }
  records.add(++i, bitmapRecord);
  for (ContinueRecord continueRecord : continueRecords) {
   records.add(++i, continueRecord);  
  }

  // debug output
  for (RecordBase r : internalsheet.getRecords()) {
   System.out.println(r);
  }

  // write out workbook
  workbook.write(new FileOutputStream("CreateExcelHSSFSheetBackgroundBitmap.xls"));
  workbook.close();

 }

 static class BitmapRecord extends StandardRecord {

  //see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP

  List<Byte> data = new ArrayList<Byte>();

  BitmapRecord(List<Byte> data) {
   this.data = data;
  }

  public int getDataSize() { 
   return data.size(); 
  }

  public short getSid() {
   return (short)0x00E9;
  }

  public void serialize(LittleEndianOutput out) {
   for (Byte b : data) {
    out.writeByte(b);
   }
  }
 }

 static class ContinueRecord extends StandardRecord {

  //see https://www.openoffice.org/sc/excelfileformat.pdf - CONTINUE

  List<Byte> data = new ArrayList<Byte>();

  ContinueRecord(List<Byte> data) {
   this.data = data;
  }

  public int getDataSize() { 
   return data.size(); 
  }

  public short getSid() {
   return (short)0x003C;
  }

  public void serialize(LittleEndianOutput out) {
   for (Byte b : data) {
    out.writeByte(b);
   }
  }
 }

}

The code works but the part between

// --- this part takes much time but I have not found any better possibility

and

// ---

takes much time since 3 bytes R G B for each single pixel needs to be got for getting them according to the above strange format.

Does anyone knows of a better approach? Maybe the above strange format is not as strange as I think it is and there are already other usages of it?

解决方案

Here's a modified version of your code that works for me, AND is pretty fast.

  1. I'm using byte[] (and ByteArrayOutputStream) all around, no more List<Byte>.
  2. As we already have a BufferedImage of TYPE_3BYTE_BGR, we can use that almost directly as the BMP output. We just need to a) prepend a valid BMP header and b) write bottom-up, c) pad each scanline (row) to a 32 bit boundary and d) switch BGR -> RGB order.
  3. I'm using the Raster to copy (padded) rows of data into the output, as copying larger chunks is faster than copying single bytes.

As already noted in the comments, the structure is a standard BMP with BITMAPCOREHEADER (and no file header). Unfortunately, the ImageIO BMPImageWriter always write the file header and uses the BITMAPINFOHEADER which is 40 bytes. You could probably get around these things, and use the standard writer, by massaging the data a little (hint: the file header contains an offset to the pixel data at offset 10), but as the core BMP format is trivial to implement, it might be just as easy to do as below.

While the documentation certainly implies that using other formats like PNG and JPEG directly, I haven't managed to do this properly.

There's probably still room for improvement if you like, to avoid some byte array copying (ie. use offset/length and pass the entire data array to the Bitmap/ContinueRecords instead of Arrays.copyOfRange()).

Code:

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.StandardRecord;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.LittleEndianOutput;

public class CreateExcelHSSFSheetBackgroundBitmap {

    static byte[] getBackgroundBitmapData(String filePath) throws Exception {

        //see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP

        // get file byte data in type BufferedImage.TYPE_3BYTE_BGR
        BufferedImage in = ImageIO.read(new FileInputStream(filePath));
        BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D graphics = image.createGraphics();
        graphics.drawImage(in, null, 0, 0);
        graphics.dispose();

        // calculate row size (c)
        int rowSize = ((24 * image.getWidth() + 31) / 32) * 4;

        ByteArrayOutputStream output = new ByteArrayOutputStream(image.getHeight() * rowSize * 3 + 1024);

        // put the record headers into the data
        ByteBuffer header = ByteBuffer.allocate(8 + 12);
        header.order(ByteOrder.LITTLE_ENDIAN);

        // Undocumented XLS stuff
        header.putShort((short) 0x09);
        header.putShort((short) 0x01);
        header.putInt(image.getHeight() * rowSize + 12); // Size of image stream

        // BITMAPCOREHEADER (a)
        header.putInt(12);

        header.putShort((short) image.getWidth());
        header.putShort((short) image.getHeight()); // Use -height if writing top-down

        header.putShort((short) 1); // planes, always 1
        header.putShort((short) 24); // bitcount

        output.write(header.array());

        // Output rows bottom-up (b)
        Raster raster = image.getRaster()
                             .createChild(0, 0, image.getWidth(), image.getHeight(), 0, 0, new int[]{2, 1, 0}); // Reverse BGR -> RGB (d)
        byte[] row = new byte[rowSize]; // padded (c)

        for (int i = image.getHeight() - 1; i >= 0; i--) {
            row = (byte[]) raster.getDataElements(0, i, image.getWidth(), 1, row);
            output.write(row);
        }

        return output.toByteArray();
    }

    public static void main(String[] args) throws Exception {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("Sheet2"); // this sheet gets the background image set

        // we need the binary records of the sheet
        // get InternalSheet
        Field _sheet = HSSFSheet.class.getDeclaredField("_sheet");
        _sheet.setAccessible(true);
        InternalSheet internalsheet = (InternalSheet)_sheet.get(sheet);

        // get List of RecordBase
        Field _records = InternalSheet.class.getDeclaredField("_records");
        _records.setAccessible(true);
        @SuppressWarnings("unchecked")
        List<RecordBase> records = (List<RecordBase>)_records.get(internalsheet);

        // get bytes of the image file
        byte[] data = getBackgroundBitmapData("dummy.png"); //PNG must not have transparency

        // do creating BitmapRecord and ContinueRecords from the data in parts of 8220 bytes
        BitmapRecord bitmapRecord;
        List<ContinueRecord> continueRecords = new ArrayList<>();
        int bytes;

        if (data.length > 8220) {
            bitmapRecord = new BitmapRecord(Arrays.copyOfRange(data, 0, 8220));
            bytes = 8220;
            while (bytes < data.length) {
                if ((bytes + 8220) < data.length) {
                    continueRecords.add(new ContinueRecord(Arrays.copyOfRange(data, bytes, bytes + 8220)));
                    bytes += 8220;
                } else {
                    continueRecords.add(new ContinueRecord(Arrays.copyOfRange(data, bytes, data.length)));
                    break;
                }
            }
        } else {
            bitmapRecord = new BitmapRecord(data);
        }

        // add the records after PageSettingsBlock
        int i = 0;
        for (RecordBase r : records) {
            if (r instanceof org.apache.poi.hssf.record.aggregates.PageSettingsBlock) {
                break;
            }
            i++;
        }
        records.add(++i, bitmapRecord);
        for (ContinueRecord continueRecord : continueRecords) {
            records.add(++i, continueRecord);
        }

        // debug output
        for (RecordBase r : internalsheet.getRecords()) {
            System.out.println(r);
        }

        // write out workbook
        workbook.write(new FileOutputStream("backgroundImage.xls"));
        workbook.close();

    }

    static class BitmapRecord extends StandardRecord {

        //see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP

        byte[] data;

        BitmapRecord(byte[] data) {
            this.data = data;
        }

        public int getDataSize() {
            return data.length;
        }

        public short getSid() {
            return (short)0x00E9;
        }

        public void serialize(LittleEndianOutput out) {
            out.write(data);
        }
    }

    static class ContinueRecord extends StandardRecord {

        //see https://www.openoffice.org/sc/excelfileformat.pdf - CONTINUE

        byte[] data;

        ContinueRecord(byte[] data) {
            this.data = data;
        }

        public int getDataSize() {
            return data.length;
        }

        public short getSid() {
            return (short)0x003C;
        }

        public void serialize(LittleEndianOutput out) {
            out.write(data);
        }
    }
}

这篇关于使用 java.awt.image.BufferedImage 创建 BIFF8 BITMAP 记录需要很多时间 - 有没有更好的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆