gpt4 book ai didi

java - [Java][POI]将 EMF 图像插入 HSSFWorkbook

转载 作者:行者123 更新时间:2023-12-01 14:32:50 26 4
gpt4 key购买 nike

我正在尝试将 EMF 图像插入 HSSFWorkbook(apache poi 3.9)。但是当我打开结果文档时 - 我发现内容错误。我正在寻找问题的解决方案,并在 apache 邮件上找到了这封信: http://mail-archives.apache.org/mod_mbox/poi-user/200710.mbox/%3C1011226198.20071009084134@dinom.ru%3E

据我了解 - emf 需要对数据进行特殊(!)预处理。

我研究了一个 EMF 类 (org.apache.poi.hslf.blip) 并尝试从中获取 rawData。但这也没有帮助。

有人对这个问题有任何想法

最佳答案

好的,这是一个 hack,我在以下信息的帮助下将其混合在一起:

  • HSSFWorkbook.addPicture的来源
  • Chicago project 的一些信息
  • 来自 Libre Office 的带有 EMF 图形的简单 .xls
  • 并通过 BiffViewer 检查我的试错结果

免责声明:因为此代码只是一个快速破解,仅使用一张图片进行了测试,包含一些我不理解的复制和粘贴行以及试错值,如果您提供一些反馈,如果它适用于您的环境,那就太好了......

检查代码注释中的部分,我不太确定。

(使用 POI 3.9、Libre Office 4.0 和 MS Excel Viewer 进行测试)

import java.awt.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.List;
import java.util.zip.DeflaterOutputStream;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.dev.BiffViewer;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;

@SuppressWarnings("unused")
public class HssfEmfPicture {
public static void main(String[] args) throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
FileInputStream fis = new FileInputStream("src/test/resources/allianz.emf");
byte[] img_bytes = IOUtils.toByteArray(fis);
fis.close();

// code taken from HSSFWorkbook.addPicture
Method m = HSSFWorkbook.class.getDeclaredMethod("initDrawings");
m.setAccessible(true);
m.invoke(wb);

int format = HSSFWorkbook.PICTURE_TYPE_EMF;

byte[] uid = DigestUtils.md5(img_bytes);
EscherMetafileBlip blipRecord = new EscherMetafileBlip();
blipRecord.setRecordId((short) (EscherMetafileBlip.RECORD_ID_START + format));
blipRecord.setOptions(HSSFPictureData.MSOBI_EMF);
blipRecord.setUID(uid);
blipRecord.setCompressed(true);
blipRecord.setPictureData(img_bytes);
blipRecord.setUncompressedSize(img_bytes.length);

// info of chicago project:
// "... LZ compression algorithm in the format used by GNU Zip deflate/inflate with a 32k window ..."
// not sure what to do, when lookup tables exceed 32k ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(bos);
dos.write(img_bytes);
dos.close();
byte img_bytes_lz[] = bos.toByteArray();
blipRecord.setCompressedSize(img_bytes_lz.length);

Field field = EscherMetafileBlip.class.getDeclaredField("raw_pictureData");
field.setAccessible(true);
field.set(blipRecord, img_bytes_lz);

// trial-and-error, it won't open, if this is left to 0
field = EscherMetafileBlip.class.getDeclaredField("field_7_fFilter");
field.setAccessible(true);
field.set(blipRecord, (byte) -2);

EscherBSERecord r = new EscherBSERecord();
r.setRecordId(EscherBSERecord.RECORD_ID);
r.setOptions((short) (0x0002 | (format << 4)));
// libre office sets a png format for mac ... need to be tested ...
r.setBlipTypeMacOS((byte) format);
r.setBlipTypeWin32((byte) format);
r.setUid(uid);
r.setTag((short) 0x0);
// trial-and-error, with pngs (EscherBitmapBlip?) its 25
// ... with emf (EscherMetafileBlip) it seems to be 58
r.setSize(img_bytes_lz.length + 58);
r.setRef(0);
r.setOffset(0);
r.setBlipRecord(blipRecord);

field = HSSFWorkbook.class.getDeclaredField("workbook");
field.setAccessible(true);
InternalWorkbook iWb = (InternalWorkbook) field.get(wb);

m = InternalWorkbook.class.getDeclaredMethod("addBSERecord", EscherBSERecord.class);
m.setAccessible(true);
int index = (Integer) m.invoke(iWb, r);

// Anchor has to be valid ... otherwise the emf is not shown
CreationHelper ch = wb.getCreationHelper();
ClientAnchor anchor = ch.createClientAnchor();
anchor.setCol1(2);
anchor.setCol2(6);
anchor.setRow1(1);
anchor.setRow2(6);
anchor.setAnchorType(ClientAnchor.DONT_MOVE_AND_RESIZE);

HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFPicture pict = patriarch.createPicture(anchor, index);

FileOutputStream fos = new FileOutputStream("hssf-emf.xls");
wb.write(fos);
fos.flush();
fos.close();
}
}

关于java - [Java][POI]将 EMF 图像插入 HSSFWorkbook,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16722044/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com