java image bitmap_使用java.awt.image.BufferedImage创建BIFF8 BITMAP记...

所以我正在创建一个HSSFSheet,它使用apache poi和自己的低级代码设置背景位图. https://www.openoffice.org/sc/excelfileformat.pdf声明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.

有关完整声明,请参见PDF图片:

Jy3dA.png

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

看代码:

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 getBackgroundBitmapData(String filePath) throws Exception {

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

List data = new ArrayList();

// 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 records = (List)_records.get(internalsheet);

// get bytes of the image file

List 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 continueRecords = new ArrayList();

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 data = new ArrayList();

BitmapRecord(List 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 data = new ArrayList();

ContinueRecord(List 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);

}

}

}

}

代码可以工作但是之间的部分

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

// ---

需要花费很多时间,因为根据上述奇怪的格式,需要获得每个单个像素的3个字节R G B.

有谁知道更好的方法?也许以上奇怪的格式并不像我想的那样奇怪,而且已经有其他用法了吗?

在 Android Studio 中,`java.awt.image.BufferedImage` 这类属于 Java AWT(Abstract Window Toolkit)的类不能直接使用,因为 AWT 是为桌面应用设计的,而 Android 有自己独立的图形和图像处理库。不过,可以使用 Android 提供的 `Bitmap` 类来替代 `BufferedImage` 实现类似的功能。 以下是在 Android 中使用 `Bitmap` 进行图像处理的示例代码: ```java import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { // 从文件中加载图片 File file = new File("/sdcard/1.png"); Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); // 这里可以对 bitmap 进行处理 // 将处理后的 bitmap 保存到文件 File outputFile = new File("/sdcard/2.png"); FileOutputStream fos = new FileOutputStream(outputFile); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 在上述代码中,使用 `BitmapFactory.decodeFile` 方法从文件中加载图片,得到 `Bitmap` 对象,之后可以对 `Bitmap` 进行各种处理,最后使用 `compress` 方法将处理后的 `Bitmap` 保存到文件。 需要注意的是,在 Android 中访问外部存储需要在 `AndroidManifest.xml` 中添加相应的权限: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 并且在 Android 6.0(API 级别 23)及以上版本,还需要在运行时请求这些权限。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值