You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@poi.apache.org by Zachary Mitchell <za...@internode.on.net> on 2010/09/24 08:09:33 UTC
Find start and finish point in HWPFDocument bytes.
It looks like I was looking at the wrong HWPFDocument byte [] after all.
I have a demo HWPFDocument file,
which is read from a Word file that has two gif
images inserted and embedded.
I have been told that the bytes for the images
inside the doc file, the HWPFDocument file
I am programming with, starts at
Character point 0x01
byte 01.
I have found 48 such bytes in the file, 72 such characters This holds correct even if I cast bytes as type (char).
What is the start byte for one image's data, and where does that image's data end?
FileInputStream input = new FileInputStream(new File("demo.doc"));
POIFSFileSystem fileSystem = HWPFDocument.verifyAndBuildPOIFS(input);
HWPFDocument document = new HWPFDocument(fileSystem);
input.close();
Field dataStream = document.getClass().getDeclaredField("_mainStream");
dataStream.setAccessible(true);
byte [] dataArray = (byte [])dataStream.get(document);
System.out.println(Arrays.toString(dataArray));
// 0x01 in text content.
byte marker = 0x01; //(char 01)
int found = 0;
for (int i=0;i<dataArray.length;i++)
{
if(dataArray[i]==marker)
{
System.out.println("Found!");
System.out.println(marker++);
}
}
Re: Find start and finish point in HWPFDocument bytes.
Posted by Nick Burch <ni...@alfresco.com>.
On Sat, 25 Sep 2010, Zachary Mitchell wrote:
> I'm still confused. With my "array search" algorithm, I try to
>
> search my word document byte [] for occurences of my picture byte [].
That'll only work for pictures that don't get compressed.
Sometimes a "picture" in the word datastream is made up of header + bytes
of real image, sometimes it's header + compressed bytes of real image.
Sometimes it seems to be header + most of the bytes of the real image, but
missing a few bits off the start that were instead stored in the word
header...
Nick
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
For additional commands, e-mail: user-help@poi.apache.org
Re: Find start and finish point in HWPFDocument bytes.
Posted by Zachary Mitchell <za...@internode.on.net>.
----- Original Message -----
From: "Nick Burch" <ni...@alfresco.com>
To: "POI Users List" <us...@poi.apache.org>; "Zachary Mitchell"
<za...@internode.on.net>
Sent: Friday, September 24, 2010 8:42 PM
Subject: Re: Find start and finish point in HWPFDocument bytes.
> On Fri, 24 Sep 2010, Zachary Mitchell wrote:
>> I wish to create the document, and
>> based on a Picture file, as an array of type
>> primitive byte [],
>> insert these bytes, in the write way,
>> into the document byte [] bytes
>
> That won't work - Word doesn't store the raw picture data at the offset.
> Instead, at that offset you'll find a series of header, and if you're
> lucky, the picture data somewhere after that...
>
> See my earlier reply for more information on what you'd need to do if you
> wanted to add pictures
>
> Nick
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
> For additional commands, e-mail: user-help@poi.apache.org
>
I'm still confused. With my "array search" algorithm, I try to
search my word document byte [] for occurences of my picture byte [].
I am also trying to reverse engineer from Picture, HWPFDocument....
I suspect that I am confusing myself.
Should I compare byte [] from
DataInputStream of picture file, word file or
byte [] from hwpfdocument, Picture?
Any help at all (have had a look at poi source code).
?
//-------------------------------------------
import java.io.*;
import java.nio.*;
import java.util.*;
import java.util.concurrent.*;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.poifs.storage.*;
//-------------------------------------------
import org.apache.poi.hwpf.*;
//import org.apache.poi.hwpf.model.*;
//import org.apache.poi.hwpf.model.io.*;
import org.apache.poi.hwpf.usermodel.*;
//-------------------------------------------
//import org.apache.poi.hssf.usermodel .*;
//-------------------------------------------
import java.lang.reflect.*;
//-------------------------------------------
//import javax.management.openmbean.*;
//-------------------------------------------
import javax.imageio.stream.*;
//-------------------------------------------
public class MSImageEmbedAttempt {
public static void main (String [] args)
{
try{
////////////////////////////////////////////////////////////////////////////
FileInputStream input = new FileInputStream(new File("demo.doc"));
POIFSFileSystem fileSystem = HWPFDocument.verifyAndBuildPOIFS(input);
HWPFDocument document = new HWPFDocument(fileSystem);
input.close();
Field dataStream = document.getClass().getDeclaredField("_mainStream");
dataStream.setAccessible(true);
byte [] fileArray = (byte [])dataStream.get(document);
////////////////////////////////////////////////////////////////////////////
//7828 bytes read. how big does File API say it is?
File flanders = new File("flanders.gif");
System.out.println("flanders.gif: " + flanders.length());
System.out.println("---------------------------------------------------------------------");
//Indeed, works for demonstration single file.
//How to write image file bytes out to file?
DataInputStream inputTwo = new DataInputStream(new
FileInputStream("flanders.gif"));
ConcurrentLinkedQueue<Byte> queue = new ConcurrentLinkedQueue<Byte>();
Byte datum = null;
while(inputTwo.available() > 0 )
{
datum = new Byte(inputTwo.readByte());
if(datum instanceof Byte)
{ queue.add(datum);}
}
inputTwo.close();
byte [] pictureArray = new byte[queue.size()];
for(int i=0;i<pictureArray.length;i++)
{
pictureArray[i] = queue.poll().byteValue();
}
Picture picture = new Picture(pictureArray);
pictureArray = picture.getContent();
//??????????????????????????????????????????????????????????????????????????????????????????
//picture << file => one is an aggregate of the other.
//THIS SECTION NEEDS DEBUGGING AND FURTHER WORK for multiple images in word
file.
byte [] resultArray = new byte[pictureArray.length];
boolean first = false;
boolean last = false;
int a = 0;
int b = 0;
int k = 0;
for (int i=0; i<fileArray.length; i++)
{
for (int j=0; j<pictureArray.length; j++)
{
if (fileArray[i] == pictureArray[j])
{
first = true;
resultArray[k] = fileArray[i];
k++;
a = i;
}
else
{
if(first == true)
{
last = true;
first = false;
b = i;
if(k != pictureArray.length)
{
Arrays.fill(resultArray,(new Integer(0)).byteValue());
}
break;
}
}
}
if (last == true)
{
last = false;
break;
}
}
//??????????????????????????????????????????????????????????????????????????????????????????
//What about when the picture ends, with more file?
System.out.println("Search completed.");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("Picture array, read by binary from GIF file:");
System.out.println(Arrays.toString(pictureArray)); //A
System.out.println("Word File array, read from HWPFDocument Word document
file.");
System.out.println(Arrays.toString(fileArray)); //B
System.out.println("Image result array, extracted by binary from Word
document:");
System.out.println(Arrays.toString(resultArray)); //C
System.out.println("---------------------------------------------------------------------");
System.out.println("Number of bytes: " + pictureArray.length);
//because of this, one knows that file data is being reinterpreted.
for (int i=0;i<fileArray.length;i++)
{
if(fileArray[i] == -119)
{
System.out.println("Found start.");
//if((i<fileArray.length) && (fileArray[i+1] == 80))
//{System.out.println("Found start.");}
}
}
FileImageOutputStream output = new FileImageOutputStream(new File
("destination.gif"));
output.write(pictureArray,0,pictureArray.length);
output.close();
}
catch (Exception e)
{e.printStackTrace();}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
For additional commands, e-mail: user-help@poi.apache.org
Re: Find start and finish point in HWPFDocument bytes.
Posted by Nick Burch <ni...@alfresco.com>.
On Fri, 24 Sep 2010, Zachary Mitchell wrote:
> I wish to create the document, and
> based on a Picture file, as an array of type
> primitive byte [],
> insert these bytes, in the write way,
> into the document byte [] bytes
That won't work - Word doesn't store the raw picture data at the offset.
Instead, at that offset you'll find a series of header, and if you're
lucky, the picture data somewhere after that...
See my earlier reply for more information on what you'd need to do if you
wanted to add pictures
Nick
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
For additional commands, e-mail: user-help@poi.apache.org
Re: Find start and finish point in HWPFDocument bytes.
Posted by Zachary Mitchell <za...@internode.on.net>.
I don't wish to "extract" the image from
an existant HWPFDocument based Word file.
I wish to create the document, and
based on a Picture file, as an array of type
primitive byte [],
insert these bytes, in the write way,
into the document byte [] bytes
(for one or more Picture files).
It seems one can't match them up, as HWPFDocument apparently reinterprets
embedded image bytes.
Here is my following code.
How does insert a Picture object,
with its byte [],
as described?
//-------------------------------------------
import java.io.*;
import java.nio.*;
import java.util.*;
import java.util.concurrent.*;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.poifs.storage.*;
//-------------------------------------------
import org.apache.poi.hwpf.*;
//import org.apache.poi.hwpf.model.*;
//import org.apache.poi.hwpf.model.io.*;
import org.apache.poi.hwpf.usermodel.*;
//-------------------------------------------
//import org.apache.poi.hssf.usermodel .*;
//-------------------------------------------
import java.lang.reflect.*;
//-------------------------------------------
//import javax.management.openmbean.*;
//-------------------------------------------
import javax.imageio.stream.*;
//-------------------------------------------
public class MSImageEmbedAttempt {
public static void main (String [] args)
{
try{
////////////////////////////////////////////////////////////////////////////
FileInputStream input = new FileInputStream(new
File("demo.doc"));
POIFSFileSystem fileSystem =
HWPFDocument.verifyAndBuildPOIFS(input);
HWPFDocument document = new HWPFDocument(fileSystem);
input.close();
Field dataStream =
document.getClass().getDeclaredField("_mainStream");
dataStream.setAccessible(true);
byte [] fileArray = (byte [])dataStream.get(document);
////////////////////////////////////////////////////////////////////////////
//7828 bytes read. how big does File API say it is?
File flanders = new File("flanders.gif");
System.out.println("flanders.gif: " + flanders.length());
System.out.println("---------------------------------------------------------------------");
//Indeed, works for demonstration single file.
//How to write image file bytes out to file?
DataInputStream inputTwo = new DataInputStream(new
FileInputStream("flanders.gif"));
ConcurrentLinkedQueue<Byte> queue = new
ConcurrentLinkedQueue<Byte>();
Byte datum = null;
while(inputTwo.available() > 0 )
{
datum = new Byte(inputTwo.readByte());
if(datum instanceof Byte)
{ queue.add(datum);}
}
inputTwo.close();
byte [] pictureArray = new byte[queue.size()];
for(int i=0;i<pictureArray.length;i++)
{
pictureArray[i] = queue.poll().byteValue();
}
//??????????????????????????????????????????????????????????????????????????????????????????
//picture << file => one is an aggregate of the other.
//THIS SECTION NEEDS DEBUGGING AND FURTHER WORK for multiple
images in word file.
byte [] resultArray = new byte[pictureArray.length];
boolean first = false;
boolean last = false;
int a = 0;
int b = 0;
int k = 0;
for (int i=0; i<fileArray.length; i++)
{
for (int j=0; j<pictureArray.length; j++)
{
if (fileArray[i] == pictureArray[j])
{
first = true;
resultArray[k] = fileArray[i];
k++;
a = i;
}
else
{
if(first == true)
{
last = true;
b = i;
break;
}
}
}
if (last == true)
{
last = true;
break;
}
}
//??????????????????????????????????????????????????????????????????????????????????????????
//What about when the picture ends, with more file?
System.out.println("Comparison completed.");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("Picture array, read directly from GIF
file:");
System.out.println(Arrays.toString(pictureArray));
System.out.println("File array, read from Word document file.");
System.out.println(Arrays.toString(fileArray));
//System.out.println("Result Array, extracted from word
document:");
//System.out.println(Arrays.toString(resultArray));
//System.out.println("Number of bytes: " + pictureArray.length);
// => that things may not be so simple as picture bytes somewhere
in file bytes.
//because of this, one knows that file data is being reinterpreted.
for (int i=0;i<fileArray.length;i++)
{
if(fileArray[i] == 71)
{
if((i<fileArray.length) && (fileArray[i+1] == 73))
{
System.out.println("Found start.");
}
}
}
Picture gif = new Picture(pictureArray);
FileImageOutputStream output = new FileImageOutputStream(new
File ("destination.gif"));
output.write(pictureArray,0,pictureArray.length);
output.close();
/*
// 0x01 in text content.
byte marker = 0x01; //(char 01)
int found = 0;
for (int i=0;i<dataArray.length;i++)
{
if(dataArray[i]==marker)
{
System.out.println("Found!");
System.out.println(marker++);
}
}
*/
}
catch (Exception e)
{e.printStackTrace();}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
For additional commands, e-mail: user-help@poi.apache.org
Re: Find start and finish point in HWPFDocument bytes.
Posted by Nick Burch <ni...@alfresco.com>.
On Fri, 24 Sep 2010, Cédric Bosdonnat wrote:
> I am too lazy to make a code snippet, but this shouldn't be too hard to
> get all the pictures from a doc file using HWPFDocument...
It's actually very easy, as the logic you described is already implemented
in hwpf :)
HWPFDocument doc = new HWPFDocument(stream);
PicturesTable pictures = doc.getPicturesTable();
for(Picture picture : pictures.getAllPictures()) {
// Do something useful
}
PictureTable.hasPicture(CharacterRun) is also worth a look, as it does the
\0001 detection for you
Nick
Re: Find start and finish point in HWPFDocument bytes.
Posted by Cédric Bosdonnat <ce...@free.fr>.
Hi Zachary,
On Fri, 2010-09-24 at 15:39 +0930, Zachary Mitchell wrote:
> It looks like I was looking at the wrong HWPFDocument byte [] after all.
>
> I have a demo HWPFDocument file,
> which is read from a Word file that has two gif
> images inserted and embedded.
>
> I have been told that the bytes for the images
> inside the doc file, the HWPFDocument file
> I am programming with, starts at
> Character point 0x01
> byte 01.
It seems you missunderstood me with that 0x01 character. In the Document
stream of a word file you can find all the text (starting from
fib.fcMin). In these text data, the pictures are marked by a 0x01
character.
The trick there is that all 0x01 aren't necessary pictures: it also need
the fcPicLoc SPRM (see the Table stream and the CHP plex). The fcPicLoc
then provides the offset to the beginning of the PICF structure in the
data stream.
I am too lazy to make a code snippet, but this shouldn't be too hard to
get all the pictures from a doc file using HWPFDocument...
Regards,
--
Cédric Bosdonnat
Go-oo hacker
http://go-oo.org
OOo Eclipse Integration developer
http://cedric.bosdonnat.free.fr
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
For additional commands, e-mail: user-help@poi.apache.org