Display Image in Header of Word Document Generated by Docx4j - java

am using Docx4j to generate a word document in a swing application.I want to add a picture to the header. The document is created successfully but the picture is not displayed. Below is the code snippets of the applications. I am using the docx4j-nightly-20141016.jar file.
import org.docx4j.wml.ObjectFactory;
public class WordDoc {
private WordprocessingMLPackage wordMLPackage;
private ObjectFactory factory;
private Hdr header;
public WordDoc() {
}
public void createWordDoc() throws Docx4JException, IOException, Exception {
wordMLPackage = WordprocessingMLPackage.createPackage();
factory = Context.getWmlObjectFactory();
Relationship relationship = createHeaderPart();
createHeaderReference(relationship);
wordMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!");
File file = new File("src/resources/images/logo.jpg");
byte[] bytes = convertImageToByteArray(file);
addImageInline(bytes);
wordMLPackage.save(new java.io.File("src/files/HelloWord14.docx"));
}
private Relationship createHeaderPart() throws InvalidFormatException {
HeaderPart headerPart = new HeaderPart();
headerPart.setPackage(wordMLPackage);
headerPart.setJaxbElement(createHeader("Text"));
return wordMLPackage.getMainDocumentPart().addTargetPart(headerPart);
}
private Hdr createHeader(String content) {
header = factory.createHdr();
P paragraph = factory.createP();
R run = factory.createR();
Text text = new Text();
text.setValue(content);
run.getContent().add(text);
paragraph.getContent().add(run);
header.getContent().add(paragraph);
return header;
}
private void createHeaderReference(Relationship relationship) {
List<SectionWrapper> sections
= wordMLPackage.getDocumentModel().getSections();
SectPr sectionProperties = sections.get(sections.size() - 1).getSectPr();
// There is always a section wrapper, but it might not contain a sectPr
if (sectionProperties == null) {
sectionProperties = factory.createSectPr();
wordMLPackage.getMainDocumentPart().addObject(sectionProperties);
sections.get(0).setSectPr(sectionProperties);
}
HeaderReference headerReference = factory.createHeaderReference();
headerReference.setId(relationship.getId());
headerReference.setType(HdrFtrRef.DEFAULT);
sectionProperties.getEGHdrFtrReferences().add(headerReference);
}
private byte[] convertImageToByteArray(File file)
throws FileNotFoundException, IOException {
InputStream is = new FileInputStream(file);
long length = file.length();
// You cannot create an array using a long, it needs to be an int.
if (length > Integer.MAX_VALUE) {
System.out.println("File too large!!");
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length -
offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read
if (offset < bytes.length) {
System.out.println("Could not completely read file "
+ file.getName());
}
is.close();
return bytes;
}
private void addImageInline(byte[] bytes) throws Exception {
BinaryPartAbstractImage imagePart
= BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);
int docPrId = 1;
int cNvPrId = 2;
Inline inLine = imagePart.createImageInline("Filename hint",
"Alternative text", docPrId, cNvPrId, false);
if (header != null) {
addInlineImageToHeader(inLine);
}
}
private void addInlineImageToHeader(Inline inline) {
// Now add the in-line image to a paragraph
ObjectFactory factory2 = new ObjectFactory();
P paragraph2 = factory2.createP();
R run = factory.createR();
paragraph2.getContent().add(run);
Drawing drawing = factory.createDrawing();
run.getContent().add(drawing);
drawing.getAnchorOrInline().add(inline);
header.getContent().add(paragraph2);
}
}
the screen capture of the generated word document is displayed below
Will be very glad to take any suggestions.

Instead of:
BinaryPartAbstractImage imagePart
= BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);
you need to add the image part as a rel of your header part, so use:
public static BinaryPartAbstractImage createImagePart(
OpcPackage opcPackage,
Part sourcePart, byte[] bytes) throws Exception
passing it headerPart

Related

parsing ASN files using bouncy castle

am trying to parse binary CDRs using JASN1
I have successfully generated Java classes using grammer file
not I have a CDR which I need to decode, but I can't get it to work, I don't understand what kind of inputs it requires
I have reached a point where I can parse CDR into lines like below
[1][[0]#01, [1]#26fd, [3]#4131002400, [8]#14040020236233, [9]#21436500000041, [10]#196105000045ffffffffffff, [13]#13900049999957, [14]#21436549999961, [15]#05, [16]#05, [17]#116102999954ffffffffffff, [22]#00a2, [23]#0001, [37]#0010, [38]#03, [40]#0324, [46]#06, [47]#05, [54]#00580720111220, [85]#04f4]
Java code
public class JASN1 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ByteArrayInputStream bais = new ByteArrayInputStream(readContentIntoByteArray(new File("sample.asn")));
ASN1InputStream ais = new ASN1InputStream(new FileInputStream(new File("sample.asn")));
while (ais.available() > 0) {
DERTaggedObject primitive = (DERTaggedObject) ais.readObject();
System.out.println(primitive.toASN1Object());
String encoded = toHexadecimal(new String(primitive.getEncoded()));
bais = new ByteArrayInputStream(encoded.getBytes());
MobileSampleMsg mobileSampleMsg = new MobileSampleMsg();
mobileSampleMsg.decode(bais, true);
System.out.println("MobileSampleMsg = " + mobileSampleMsg);
}
ais.close();
/*
* System.out.println(bais); MobileSampleMsg personnelRecord_decoded =
* new MobileSampleMsg(); personnelRecord_decoded.decode(bais, true);
*
* System.out.println("");
* System.out.println("PersonnelRecord.name.givenName = " +
* personnelRecord_decoded);
*/
}
private static byte[] readContentIntoByteArray(File file) {
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) file.length()];
try {
// convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bFile;
}
public static String toHexadecimal(String text) throws UnsupportedEncodingException {
byte[] myBytes = text.getBytes("UTF-8");
return DatatypeConverter.printHexBinary(myBytes);
}
}
download samples from here
download grammer from here
I was able to encode/decode the file with the help of JASN1 and BouncyCastle, I used JASN1 to compile grammer file into java classes then used BouncyCastle to decode/encode new objects, below is code snippet used to show how I did that
public class BouncyCastle {
public static void main(String[] args) throws IOException {
DetailOutputRecord detailOutputRecord = new DetailOutputRecord();
MyRecord myRecord = new MyRecord();
myRecord.setOriginNodeType(new NodeType("xxxx".getBytes()));
myRecord.setTransactionAmount(new MoneyAmount("xxxx".getBytes()));
myRecord.setSubscriberNumber(new NumberString("xxxx".getBytes()));
ReverseByteArrayOutputStream ros = new ReverseByteArrayOutputStream(1000);
detailOutputRecord.setMyRecord(myRecord);
myRecord.encode(ros);
System.out.println(DatatypeConverter.printHexBinary(ros.getArray()));
System.out.println(print(ros.getArray()));
DERTaggedObject dermyRecord = new DERTaggedObject(false, 6, ASN1Primitive.fromByteArray(ros.getArray()));
File f = new File(String.valueOf("1_dermyRecord.ASN"));
FileOutputStream stream = new FileOutputStream(f);
try {
stream.write(dermyRecord.getEncoded());
} finally {
stream.close();
}
ros = new ReverseByteArrayOutputStream(1000);
detailOutputRecord.encode(ros);
DLSequence ddetailOutputRecord = new DLSequence(ASN1Primitive.fromByteArray(ros.getArray()));
stream = new FileOutputStream(new File("detailOutputRecord.ASN"));
try {
stream.write(ros.buffer);
} finally {
stream.close();
}
}
public static String print(byte[] bytes) {
StringBuilder sb = new StringBuilder();
sb.append("[ ");
for (byte b : bytes) {
// sb.append(String.format("0x%02X ", b));
sb.append(String.format("\\x%02X", b));
}
sb.append("]");
return sb.toString();
}
private static DERTaggedObject toDERObject(byte[] data) throws IOException {
ByteArrayInputStream inStream = new ByteArrayInputStream(data);
ASN1InputStream asnInputStream = new ASN1InputStream(inStream);
return (DERTaggedObject) asnInputStream.readObject();
}
}
Here is alternative way of processing given binary record files using org.bouncycastle.asn1 package only :
/*Sequence Tags */
static final int MSCRecordType = 0;
static final int RecordNumber = 1;
static final int RecordStatus = 3;
static final int CallingImsi = 8;
static final int CallingImei = 9;
void process() throws IOException, ClassNotFoundException {
String path = System.getProperty("user.dir") + "/telconetqual_sampledata/CDR_RGN0_20121120081859.asn";
File file = new File(path);
byte[] bFile = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(bFile);
ASN1InputStream in = new ASN1InputStream(bFile);
while (in.available() > 0) {
ASN1Primitive primitive = in.readObject();
DERTaggedObject derTaggedObject = (DERTaggedObject) primitive;
DLSequence sequence = (DLSequence)derTaggedObject.getObject();
for(int i =0; i < sequence.size(); i++){
DERTaggedObject seqElement = (DERTaggedObject)sequence.getObjectAt(i);
switch (seqElement.getTagNo()) {
case MSCRecordType:
DEROctetString recordTypeOctet =(DEROctetString)seqElement.getObject();
int recordType = Integer.valueOf(Hex.toHexString(recordTypeOctet.getOctets()));
break;
case CallingImsi:
DEROctetString CallingImsiOctet =(DEROctetString)seqElement.getObject();
String CallingImsi = Hex.toHexString(CallingImsiOctet.getOctets());
...
}
}
}
}

captured photo have grey line at bottom and size of image is very small in codenameone

I am capturing an image, and I am storing it in my file system. Whereas I preview the photo by reading the byte stream.
Somewhere its not reading the byte data completely due to which I get the dark line at bottom of image. How I can use readfully() or readAll() here. When I tried using readall() method, the half of image didnt load properly. So, I am confused how to use this. I cant use File URI here as my image is having unique ID. Its working fine on simulator, but having issue on device. Any help on this would be really appreciated like how to use readfully() or readAll() method if that's the only solution.
public void saveFromFile(final String file, final boolean launchPreviewIfAnnotateAllowed) {
FileSystemStorage fss = FileSystemStorage.getInstance();
InputStream is = fss.openInputStream(file);
final byte[] bytes = getBytes(is);
is.close();
is = null;
model.updateMediaData(bytes);
Image im = Image.createImage(bytes, 0, bytes.length);
}
private static byte[] getBytes(InputStream is) throws IOException {
int len;
int size = 1024;
byte[] buf;
if (is instanceof ByteArrayInputStream) {
size = is.available();
buf = new byte[size];
len = is.read(buf, 0, size);
} else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
buf = new byte[size];
while ((len = is.read(buf, 0, size)) != -1)
bos.write(buf, 0, len);
buf = bos.toByteArray();
}
return buf;
}
the updateMediaData() looks something like this
public void updateMediaData(byte[] binaryData) {
updateMediaData(binaryData, null);
}
public void updateMediaData(final byte[] binaryData, final String filename) {
mcHelper.updateMediaData(binaryData, photoId, filename);
}
public void updateMediaData(byte[] binaryData, String componentId, String filename) {
if (binaryData != null) {
String userName = pj;
userName = Strings.replaceAll(userName, " ", "_"); //USERNAME RENAME
//now strip any bizzare chars from it
String altered = "";
for (int i = 0; i < userName.length(); i++) {
char c = userName.charAt(i);
if (c == '_' || Character.isDigit(c) || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
altered += c;
}
}
userName = altered;
final String muid = userName + DateTime.getMediaFileTimeStamp() + "_" + new Guid() + "_" + componentId
+ "." + getExtension(binaryData);
mediaData = new MediaData(muid);
mediaData.setFormFieldId(owner.getIdInt());
mediaData.setMediaType(MediaData.MEDIA_TYPE_PHOTO);
if (muid != null && muid.indexOf(".jpg") != -1) {
mediaData.setFilename(muid);
}
else {
mediaData.setFilename(filename != null ? filename : muid); // If filename isn't specified, use MUID.
}
mediaData.setRevisionNumber(0);
mediaData.setData(binaryData);
mediaData.setMimeType(getMimeType(binaryData));
if (mediaData.getMimeType().indexOf("octet-stream") != -1) {
mediaData.setMimeType("image/jpeg"); //can happen when encrytion used
}
// Save the data to persistent storage.
try {
mm.saveData(mediaData);
} catch (DataAccessException e) {
Application.log(Application.LOG_LEVEL_WARNING, "Failed to save media data for MediaComponent.", e);
}
}
}
Replace getBytes with:
private static byte[] getBytes(InputStream is) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Util.copy(is, bos);
return bos.bos.toByteArray();
}
This performs the stream copy correctly.

java: Length of data changes after write in stream

I have saved a binary data in FileOutputStream but when I check the length of the data before and after I found that it changes from 72 to 106.
This is my method:
inputStream = new FileInputStream(certificate_file);
/*Certificate file is a Path of a binary file */
pubkey = readFromStream(inputStream, 0, 71);
System.out.println("length of pubkey: "+pubkey.length());
/* This return : length of pubkey: 72 */
writeToStream(path + "pubkey.bin", pubkey);
inputStream = new FileInputStream(path + "pubkey.bin");
pubkey = readFromStream(inputStream);
System.out.println("length of pubkey: "+pubkey.length());
/* This return : length of pubkey: 106 */
writeToStream method to write data into outputstream:
public void writeToStream(String path, String data)
throws FileNotFoundException {
OutputStream os = new FileOutputStream(path);
PrintStream printStream = new PrintStream(os);
printStream.print(data);
}
readFromStream method to read data from stream:
public static String readFromStream(InputStream inputStream, int begin, int end) throws Exception {
int i = 0;
int data = inputStream.read();
String out = "";
while (data != -1) {
if (i >= begin && i <= end) {
out += (char) data;
}
data = inputStream.read();
i++;
}
return out;
}
public static String readFromStream(InputStream inputStream) throws Exception {
int i = 0;
int data = inputStream.read();
String out = "";
while (data != -1) {
out += (char) data;
data = inputStream.read();
i++;
}
return out;
}
Why I have this problem?
I have solved the problem, I transformed the data from String to bytes[] and I changed the read in readFromStream to readAllBytes.

java zip to binary format and then decompress

I have a task that
read a zip file from local into binary message
transfer binary message through EMS as String (done by java API)
receive transferred binary message as String (done by java API)
decompress the binary message and then print it out
The problem I am facing is DataFormatException while decompress the message.
I have no idea which part went wrong.
I use this to read file into binary message:
static String readFile_Stream(String fileName) throws IOException {
File file = new File(fileName);
byte[] fileData = new byte[(int) file.length()];
FileInputStream in = new FileInputStream(file);
in.read(fileData);
String content = "";
System.out.print("Sent message: ");
for(byte b : fileData)
{
System.out.print(getBits(b));
content += getBits(b);
}
in.close();
return content;
}
static String getBits(byte b)
{
String result = "";
for(int i = 0; i < 8; i++)
result = ((b & (1 << i)) == 0 ? "0" : "1") + result;
return result;
}
I use this to decompress message:
private static byte[] toByteArray(String input)
{
byte[] byteArray = new byte[input.length()/8];
for (int i=0;i<input.length()/8;i++)
{
String read_data = input.substring(i*8, i*8+8);
short a = Short.parseShort(read_data, 2);
byteArray[i] = (byte) a;
}
return byteArray;
}
public static byte[] unzipByteArray(byte[] file) throws IOException {
byte[] byReturn = null;
Inflater oInflate = new Inflater(false);
oInflate.setInput(file);
ByteArrayOutputStream oZipStream = new ByteArrayOutputStream();
try {
while (! oInflate.finished() ){
byte[] byRead = new byte[4 * 1024];
int iBytesRead = oInflate.inflate(byRead);
if (iBytesRead == byRead.length){
oZipStream.write(byRead);
}
else {
oZipStream.write(byRead, 0, iBytesRead);
}
}
byReturn = oZipStream.toByteArray();
}
catch (DataFormatException ex){
throw new IOException("Attempting to unzip file that is not zipped.");
}
finally {
oZipStream.close();
}
return byReturn;
}
The message I got is
java.io.IOException: Attempting to unzip file that is not zipped.
at com.sourcefreak.example.test.TibcoEMSQueueReceiver.unzipByteArray(TibcoEMSQueueReceiver.java:144)
at com.sourcefreak.example.test.TibcoEMSQueueReceiver.main(TibcoEMSQueueReceiver.java:54)
After check, the binary message does not corrupted after transmission.
Please help to figure out the problem.
Have you tried using InflaterInputStream? Based on my experience, using Inflater directly is rather tricky. You can use this to get started:
public static byte[] unzipByteArray(byte[] file) throws IOException {
InflaterInputStream iis = new InflaterInputStream(new ByteArrayInputStream(file));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
int length = 0;
while ((length = iis.read(buffer, 0, buffer.length) != 0) {
baos.write(buffer, 0, length);
}
iis.close();
baos.close();
return baos.toByteArray();
}
I finally figure out the problem.
The problem is the original file is a .zip file, so I should use zipInputStream to unzip the file before further processing.
public static byte[] unzipByteArray(byte[] file) throws IOException {
// create a buffer to improve copy performance later.
byte[] buffer = new byte[2048];
byte[] content ;
// open the zip file stream
InputStream theFile = new ByteArrayInputStream(file);
ZipInputStream stream = new ZipInputStream(theFile);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try
{
ZipEntry entry;
while((entry = stream.getNextEntry())!=null)
{
//String s = String.format("Entry: %s len %d added %TD", entry.getName(), entry.getSize(), new Date(entry.getTime()));
//System.out.println(s);
// Once we get the entry from the stream, the stream is
// positioned read to read the raw data, and we keep
// reading until read returns 0 or less.
//String outpath = outdir + "/" + entry.getName();
try
{
//output = new FileOutputStream(outpath);
int len = 0;
while ((len = stream.read(buffer)) > 0)
{
output.write(buffer, 0, len);
}
}
finally
{
// we must always close the output file
if(output!=null) output.close();
}
}
}
finally
{
// we must always close the zip file.
stream.close();
}
content = output.toByteArray();
return content;
}
This code work for zip file containing single file inside.

Java - Cannot view modified metadata

I have been trying to access modified metadata of images in Java for the past few hours. I know I am one or two steps away from getting the correct output. Would really appreciate if someone can help me with this.
I want to add an extra field in the metadata, which is like an text similar to:
Writing image metadata in Java, preferably PNG
My issue is that when i add the custom data to my image and when i read the image, i do not see the change in the modified metadata when i call the method readAndDisplay. I think the reason is that i am not saving the image properly into a new file with the modified metadata. Can someone have a look at what i am missing from my code:
public class Metadata {
public static void main(String[] args) throws Exception {
String imageFile = "134.png";
BufferedImage img = null;
try {
img = ImageIO.read(new File(imageFile));
} catch (IOException e) {
System.out.println(e.getMessage());
}
Metadata meta = new Metadata();
byte[] result = meta.writeCustomData(img, "decimalID", "211");
BufferedImage output = ImageIO.read(new ByteArrayInputStream(result));
ImageIO.write(output, "png", new File("output.png"));
meta.readAndDisplayMetadata("output.png");
}
void readAndDisplayMetadata( String fileName ) {
try {
File file = new File( fileName );
ImageInputStream iis = ImageIO.createImageInputStream(file);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
if (readers.hasNext()) {
// pick the first available ImageReader
ImageReader reader = readers.next();
// attach source to the reader
reader.setInput(iis, true);
// read metadata of first image
IIOMetadata metadata = reader.getImageMetadata(0);
String[] names = metadata.getMetadataFormatNames();
int length = names.length;
System.out.println(length);
for (int i = 0; i < length; i++) {
System.out.println( "Format name: " + names[ i ] );
displayMetadata(metadata.getAsTree(names[i]));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
void readAndDisplayMetadata( byte[] image ) {
try {
// File file = new File( fileName );
ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(image));
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
if (readers.hasNext()) {
// pick the first available ImageReader
ImageReader reader = readers.next();
// attach source to the reader
reader.setInput(iis, true);
// read metadata of first image
IIOMetadata metadata = reader.getImageMetadata(0);
String[] names = metadata.getMetadataFormatNames();
int length = names.length;
System.out.println(length);
for (int i = 0; i < length; i++) {
System.out.println( "Format name: " + names[ i ] );
displayMetadata(metadata.getAsTree(names[i]));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
void displayMetadata(Node root) {
displayMetadata(root, 0);
}
void indent(int level) {
for (int i = 0; i < level; i++)
System.out.print(" ");
}
void displayMetadata(Node node, int level) {
// print open tag of element
indent(level);
//System.out.println("Attributes: " + node.getAttributes().getLength());
System.out.print("<" + node.getNodeName());
NamedNodeMap map = node.getAttributes();
if (map != null) {
// print attribute values
int length = map.getLength();
for (int i = 0; i < length; i++) {
Node attr = map.item(i);
System.out.print(" " + attr.getNodeName() +
"=\"" + attr.getNodeValue() + "\"");
}
}
Node child = node.getFirstChild();
if (child == null) {
// no children, so close element and return
System.out.println("/>");
return;
}
// children, so close current tag
System.out.println(">");
while (child != null) {
// print children recursively
displayMetadata(child, level + 1);
child = child.getNextSibling();
}
// print close tag of element
indent(level);
System.out.println("</" + node.getNodeName() + ">");
}
public byte[] writeCustomData(BufferedImage buffImg, String key, String value) throws Exception {
ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next();
ImageWriteParam writeParam = writer.getDefaultWriteParam();
ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
//adding metadata
IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
IIOMetadataNode textEntry = new IIOMetadataNode("tEXtEntry");
textEntry.setAttribute("keyword", key);
textEntry.setAttribute("value", value);
IIOMetadataNode text = new IIOMetadataNode("tEXt");
text.appendChild(textEntry);
IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
root.appendChild(text);
metadata.mergeTree("javax_imageio_png_1.0", root);
//writing the data
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream stream = ImageIO.createImageOutputStream(baos);
writer.setOutput(stream);
writer.write(metadata, new IIOImage(buffImg, null, metadata), writeParam);
stream.close();
return baos.toByteArray();
}

Categories