introduce picture descriptor structure (internal), now Picture class extends it;
add test case with correctly cropped picture info git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1147450 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
572c611187
commit
6815f67967
@ -59,22 +59,6 @@ import static org.apache.poi.hwpf.converter.AbstractWordUtils.TWIPS_PER_INCH;
|
||||
public class WordToHtmlConverter extends AbstractWordConverter
|
||||
{
|
||||
|
||||
/**
|
||||
* Holds properties values, applied to current <tt>p</tt> element. Those
|
||||
* properties shall not be doubled in children <tt>span</tt> elements.
|
||||
*/
|
||||
private static class BlockProperies
|
||||
{
|
||||
final String pFontName;
|
||||
final int pFontSize;
|
||||
|
||||
public BlockProperies( String pFontName, int pFontSize )
|
||||
{
|
||||
this.pFontName = pFontName;
|
||||
this.pFontSize = pFontSize;
|
||||
}
|
||||
}
|
||||
|
||||
private static final POILogger logger = POILogFactory
|
||||
.getLogger( WordToHtmlConverter.class );
|
||||
|
||||
@ -248,19 +232,12 @@ public class WordToHtmlConverter extends AbstractWordConverter
|
||||
basicLink );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processLineBreak( Element block, CharacterRun characterRun )
|
||||
{
|
||||
block.appendChild( htmlDocumentFacade.createLineBreak() );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method shall store image bytes in external file and convert it if
|
||||
* necessary. Images shall be stored using PNG format. Other formats may be
|
||||
* not supported by user browser.
|
||||
* <p>
|
||||
* Please note the
|
||||
* {@link WordToHtmlUtils#setPictureProperties(Picture, Element)} method.
|
||||
* Please note the {@link #processImage(Element, boolean, Picture, String)}.
|
||||
*
|
||||
* @param currentBlock
|
||||
* currently processed HTML element, like <tt>p</tt>. Shall be
|
||||
@ -279,6 +256,99 @@ public class WordToHtmlConverter extends AbstractWordConverter
|
||||
+ picture.suggestFullFileName() + "' can be here" ) );
|
||||
}
|
||||
|
||||
protected void processImage( Element currentBlock, boolean inlined,
|
||||
Picture picture, String imageSourcePath )
|
||||
{
|
||||
final int aspectRatioX = picture.getHorizontalScalingFactor();
|
||||
final int aspectRatioY = picture.getVerticalScalingFactor();
|
||||
|
||||
StringBuilder style = new StringBuilder();
|
||||
|
||||
final float imageWidth;
|
||||
final float imageHeight;
|
||||
|
||||
final float cropTop;
|
||||
final float cropBottom;
|
||||
final float cropLeft;
|
||||
final float cropRight;
|
||||
|
||||
if ( aspectRatioX > 0 )
|
||||
{
|
||||
imageWidth = picture.getDxaGoal() * aspectRatioX / 1000
|
||||
/ TWIPS_PER_INCH;
|
||||
cropRight = picture.getDxaCropRight() * aspectRatioX / 1000
|
||||
/ TWIPS_PER_INCH;
|
||||
cropLeft = picture.getDxaCropLeft() * aspectRatioX / 1000
|
||||
/ TWIPS_PER_INCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageWidth = picture.getDxaGoal() / TWIPS_PER_INCH;
|
||||
cropRight = picture.getDxaCropRight() / TWIPS_PER_INCH;
|
||||
cropLeft = picture.getDxaCropLeft() / TWIPS_PER_INCH;
|
||||
}
|
||||
|
||||
if ( aspectRatioY > 0 )
|
||||
{
|
||||
imageHeight = picture.getDyaGoal() * aspectRatioY / 1000
|
||||
/ TWIPS_PER_INCH;
|
||||
cropTop = picture.getDyaCropTop() * aspectRatioY / 1000
|
||||
/ TWIPS_PER_INCH;
|
||||
cropBottom = picture.getDyaCropBottom() * aspectRatioY / 1000
|
||||
/ TWIPS_PER_INCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageHeight = picture.getDyaGoal() / TWIPS_PER_INCH;
|
||||
cropTop = picture.getDyaCropTop() / TWIPS_PER_INCH;
|
||||
cropBottom = picture.getDyaCropBottom() / TWIPS_PER_INCH;
|
||||
}
|
||||
|
||||
Element root;
|
||||
if ( cropTop != 0 || cropRight != 0 || cropBottom != 0 || cropLeft != 0 )
|
||||
{
|
||||
float visibleWidth = Math
|
||||
.max( 0, imageWidth - cropLeft - cropRight );
|
||||
float visibleHeight = Math.max( 0, imageHeight - cropTop
|
||||
- cropBottom );
|
||||
|
||||
root = htmlDocumentFacade.document.createElement( "div" );
|
||||
root.setAttribute( "style", "vertical-align:text-bottom;width:"
|
||||
+ visibleWidth + "in;height:" + visibleHeight + "in;" );
|
||||
|
||||
// complex
|
||||
Element inner = htmlDocumentFacade.document.createElement( "div" );
|
||||
inner.setAttribute( "style", "position:relative;width:"
|
||||
+ visibleWidth + "in;height:" + visibleHeight
|
||||
+ "in;overflow:hidden;" );
|
||||
root.appendChild( inner );
|
||||
|
||||
Element image = htmlDocumentFacade.document.createElement( "img" );
|
||||
image.setAttribute( "src", imageSourcePath );
|
||||
image.setAttribute( "style", "position:absolute;left:-" + cropLeft
|
||||
+ ";top:-" + cropTop + ";width:" + imageWidth
|
||||
+ "in;height:" + imageHeight + "in;" );
|
||||
inner.appendChild( image );
|
||||
|
||||
style.append( "overflow:hidden;" );
|
||||
}
|
||||
else
|
||||
{
|
||||
root = htmlDocumentFacade.document.createElement( "img" );
|
||||
root.setAttribute( "src", imageSourcePath );
|
||||
root.setAttribute( "style", "width:" + imageWidth + "in;height:"
|
||||
+ imageHeight + "in;vertical-align:text-bottom;" );
|
||||
}
|
||||
|
||||
currentBlock.appendChild( root );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processLineBreak( Element block, CharacterRun characterRun )
|
||||
{
|
||||
block.appendChild( htmlDocumentFacade.createLineBreak() );
|
||||
}
|
||||
|
||||
protected void processPageref( HWPFDocumentCore hwpfDocument,
|
||||
Element currentBlock, Range textRange, int currentTableLevel,
|
||||
String pageref )
|
||||
@ -506,4 +576,20 @@ public class WordToHtmlConverter extends AbstractWordConverter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds properties values, applied to current <tt>p</tt> element. Those
|
||||
* properties shall not be doubled in children <tt>span</tt> elements.
|
||||
*/
|
||||
private static class BlockProperies
|
||||
{
|
||||
final String pFontName;
|
||||
final int pFontSize;
|
||||
|
||||
public BlockProperies( String pFontName, int pFontSize )
|
||||
{
|
||||
this.pFontName = pFontName;
|
||||
this.pFontSize = pFontSize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -232,34 +232,27 @@ public class WordToHtmlUtils extends AbstractWordUtils
|
||||
final int aspectRatioX = picture.getAspectRatioX();
|
||||
final int aspectRatioY = picture.getAspectRatioY();
|
||||
|
||||
StringBuilder style = new StringBuilder();
|
||||
|
||||
if ( aspectRatioX > 0 )
|
||||
{
|
||||
graphicElement
|
||||
.setAttribute( "content-width", ( ( picture.getDxaGoal()
|
||||
* aspectRatioX / 100 ) / TWIPS_PER_PT )
|
||||
+ "pt" );
|
||||
style.append( "width:"
|
||||
+ ( ( picture.getDxaGoal() * aspectRatioX / 1000 ) / TWIPS_PER_INCH )
|
||||
+ "in;" );
|
||||
}
|
||||
else
|
||||
graphicElement.setAttribute( "content-width",
|
||||
( picture.getDxaGoal() / TWIPS_PER_PT ) + "pt" );
|
||||
style.append( "width:" + ( picture.getDxaGoal() / TWIPS_PER_INCH )
|
||||
+ "in;" );
|
||||
|
||||
if ( aspectRatioY > 0 )
|
||||
graphicElement
|
||||
.setAttribute( "content-height", ( ( picture.getDyaGoal()
|
||||
* aspectRatioY / 100 ) / TWIPS_PER_PT )
|
||||
+ "pt" );
|
||||
else
|
||||
graphicElement.setAttribute( "content-height",
|
||||
( picture.getDyaGoal() / TWIPS_PER_PT ) + "pt" );
|
||||
|
||||
if ( aspectRatioX <= 0 || aspectRatioY <= 0 )
|
||||
{
|
||||
graphicElement.setAttribute( "scaling", "uniform" );
|
||||
style.append( "height:"
|
||||
+ ( ( picture.getDyaGoal() * aspectRatioY / 1000 ) / TWIPS_PER_INCH )
|
||||
+ "in;" );
|
||||
}
|
||||
else
|
||||
{
|
||||
graphicElement.setAttribute( "scaling", "non-uniform" );
|
||||
}
|
||||
style.append( "height:" + ( picture.getDyaGoal() / TWIPS_PER_INCH )
|
||||
+ "in;" );
|
||||
|
||||
graphicElement.setAttribute( "vertical-align", "text-bottom" );
|
||||
|
||||
@ -267,15 +260,18 @@ public class WordToHtmlUtils extends AbstractWordUtils
|
||||
|| picture.getDyaCropBottom() != 0
|
||||
|| picture.getDxaCropLeft() != 0 )
|
||||
{
|
||||
int rectTop = picture.getDyaCropTop() / TWIPS_PER_PT;
|
||||
int rectRight = picture.getDxaCropRight() / TWIPS_PER_PT;
|
||||
int rectBottom = picture.getDyaCropBottom() / TWIPS_PER_PT;
|
||||
int rectLeft = picture.getDxaCropLeft() / TWIPS_PER_PT;
|
||||
graphicElement.setAttribute( "clip", "rect(" + rectTop + "pt, "
|
||||
+ rectRight + "pt, " + rectBottom + "pt, " + rectLeft
|
||||
+ "pt)" );
|
||||
graphicElement.setAttribute( "oveerflow", "hidden" );
|
||||
float rectTop = picture.getDyaCropTop() / TWIPS_PER_INCH;
|
||||
float rectRight = picture.getDxaCropRight() / TWIPS_PER_INCH;
|
||||
float rectBottom = picture.getDyaCropBottom() / TWIPS_PER_INCH;
|
||||
float rectLeft = picture.getDxaCropLeft() / TWIPS_PER_INCH;
|
||||
|
||||
style.append( "clip:rect(" + rectTop + "in," + rectRight + "in, "
|
||||
+ rectBottom + "in, " + rectLeft + "in);" );
|
||||
style.append( "overflow:hidden;" );
|
||||
}
|
||||
|
||||
graphicElement.setAttribute( "style", style.toString() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,203 @@
|
||||
package org.apache.poi.hwpf.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Picture Descriptor (on File) (PICF)
|
||||
* <p>
|
||||
* Based on Microsoft Office Word 97-2007 Binary File Format (.doc)
|
||||
* Specification; Page 181 of 210
|
||||
*
|
||||
* @author Sergey Vladimirov ( vlsergey {at} gmail {dot} com )
|
||||
*/
|
||||
public class PictureDescriptor
|
||||
{
|
||||
private static final int LCB_OFFSET = 0x00;
|
||||
private static final int CBHEADER_OFFSET = 0x04;
|
||||
|
||||
private static final int MFP_MM_OFFSET = 0x06;
|
||||
private static final int MFP_XEXT_OFFSET = 0x08;
|
||||
private static final int MFP_YEXT_OFFSET = 0x0A;
|
||||
private static final int MFP_HMF_OFFSET = 0x0C;
|
||||
|
||||
private static final int DXAGOAL_OFFSET = 0x1C;
|
||||
private static final int DYAGOAL_OFFSET = 0x1E;
|
||||
|
||||
private static final int MX_OFFSET = 0x20;
|
||||
private static final int MY_OFFSET = 0x22;
|
||||
|
||||
private static final int DXACROPLEFT_OFFSET = 0x24;
|
||||
private static final int DYACROPTOP_OFFSET = 0x26;
|
||||
private static final int DXACROPRIGHT_OFFSET = 0x28;
|
||||
private static final int DYACROPBOTTOM_OFFSET = 0x2A;
|
||||
|
||||
/**
|
||||
* Number of bytes in the PIC structure plus size of following picture data
|
||||
* which may be a Window's metafile, a bitmap, or the filename of a TIFF
|
||||
* file. In the case of a Macintosh PICT picture, this includes the size of
|
||||
* the PIC, the standard "x" metafile, and the Macintosh PICT data. See
|
||||
* Appendix B for more information.
|
||||
*/
|
||||
protected int lcb;
|
||||
|
||||
/**
|
||||
* Number of bytes in the PIC (to allow for future expansion).
|
||||
*/
|
||||
protected int cbHeader;
|
||||
|
||||
/*
|
||||
* Microsoft Office Word 97-2007 Binary File Format (.doc) Specification
|
||||
*
|
||||
* Page 181 of 210
|
||||
*
|
||||
* If a Windows metafile is stored immediately following the PIC structure,
|
||||
* the mfp is a Window's METAFILEPICT structure. See
|
||||
* http://msdn2.microsoft.com/en-us/library/ms649017(VS.85).aspx for more
|
||||
* information about the METAFILEPICT structure and
|
||||
* http://download.microsoft.com/download/0/B/E/0BE8BDD7-E5E8-422A-ABFD-
|
||||
* 4342ED7AD886/WindowsMetafileFormat(wmf)Specification.pdf for Windows
|
||||
* Metafile Format specification.
|
||||
*
|
||||
* When the data immediately following the PIC is a TIFF filename,
|
||||
* mfp.mm==98 If a bitmap is stored after the pic, mfp.mm==99.
|
||||
*
|
||||
* When the PIC describes a bitmap, mfp.xExt is the width of the bitmap in
|
||||
* pixels and mfp.yExt is the height of the bitmap in pixels.
|
||||
*/
|
||||
|
||||
protected int mfp_mm;
|
||||
protected int mfp_xExt;
|
||||
protected int mfp_yExt;
|
||||
protected int mfp_hMF;
|
||||
|
||||
/**
|
||||
* <li>Window's bitmap structure when PIC describes a BITMAP (14 bytes)
|
||||
*
|
||||
* <li>Rectangle for window origin and extents when metafile is stored --
|
||||
* ignored if 0 (8 bytes)
|
||||
*/
|
||||
protected byte[] offset14 = new byte[14];
|
||||
|
||||
/**
|
||||
* Horizontal measurement in twips of the rectangle the picture should be
|
||||
* imaged within
|
||||
*/
|
||||
protected short dxaGoal = 0;
|
||||
|
||||
/**
|
||||
* Vertical measurement in twips of the rectangle the picture should be
|
||||
* imaged within
|
||||
*/
|
||||
protected short dyaGoal = 0;
|
||||
|
||||
/**
|
||||
* Horizontal scaling factor supplied by user expressed in .001% units
|
||||
*/
|
||||
protected short mx;
|
||||
|
||||
/**
|
||||
* Vertical scaling factor supplied by user expressed in .001% units
|
||||
*/
|
||||
protected short my;
|
||||
|
||||
/**
|
||||
* The amount the picture has been cropped on the left in twips
|
||||
*/
|
||||
protected short dxaCropLeft = 0;
|
||||
|
||||
/**
|
||||
* The amount the picture has been cropped on the top in twips
|
||||
*/
|
||||
protected short dyaCropTop = 0;
|
||||
|
||||
/**
|
||||
* The amount the picture has been cropped on the right in twips
|
||||
*/
|
||||
protected short dxaCropRight = 0;
|
||||
|
||||
/**
|
||||
* The amount the picture has been cropped on the bottom in twips
|
||||
*/
|
||||
protected short dyaCropBottom = 0;
|
||||
|
||||
public PictureDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
public PictureDescriptor( byte[] _dataStream, int startOffset )
|
||||
{
|
||||
this.lcb = LittleEndian.getInt( _dataStream, startOffset + LCB_OFFSET );
|
||||
this.cbHeader = LittleEndian.getUShort( _dataStream, startOffset
|
||||
+ CBHEADER_OFFSET );
|
||||
|
||||
this.mfp_mm = LittleEndian.getUShort( _dataStream, startOffset
|
||||
+ MFP_MM_OFFSET );
|
||||
this.mfp_xExt = LittleEndian.getUShort( _dataStream, startOffset
|
||||
+ MFP_XEXT_OFFSET );
|
||||
this.mfp_yExt = LittleEndian.getUShort( _dataStream, startOffset
|
||||
+ MFP_YEXT_OFFSET );
|
||||
this.mfp_hMF = LittleEndian.getUShort( _dataStream, startOffset
|
||||
+ MFP_HMF_OFFSET );
|
||||
|
||||
this.offset14 = LittleEndian.getByteArray( _dataStream,
|
||||
startOffset + 0x0E, 14 );
|
||||
|
||||
this.dxaGoal = LittleEndian.getShort( _dataStream, startOffset
|
||||
+ DXAGOAL_OFFSET );
|
||||
this.dyaGoal = LittleEndian.getShort( _dataStream, startOffset
|
||||
+ DYAGOAL_OFFSET );
|
||||
|
||||
this.mx = LittleEndian.getShort( _dataStream, startOffset + MX_OFFSET );
|
||||
this.my = LittleEndian.getShort( _dataStream, startOffset + MY_OFFSET );
|
||||
|
||||
this.dxaCropLeft = LittleEndian.getShort( _dataStream, startOffset
|
||||
+ DXACROPLEFT_OFFSET );
|
||||
this.dyaCropTop = LittleEndian.getShort( _dataStream, startOffset
|
||||
+ DYACROPTOP_OFFSET );
|
||||
this.dxaCropRight = LittleEndian.getShort( _dataStream, startOffset
|
||||
+ DXACROPRIGHT_OFFSET );
|
||||
this.dyaCropBottom = LittleEndian.getShort( _dataStream, startOffset
|
||||
+ DYACROPBOTTOM_OFFSET );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append( "[PICF]\n" );
|
||||
stringBuilder.append( " lcb = " ).append( this.lcb )
|
||||
.append( '\n' );
|
||||
stringBuilder.append( " cbHeader = " )
|
||||
.append( this.cbHeader ).append( '\n' );
|
||||
|
||||
stringBuilder.append( " mfp.mm = " ).append( this.mfp_mm )
|
||||
.append( '\n' );
|
||||
stringBuilder.append( " mfp.xExt = " )
|
||||
.append( this.mfp_xExt ).append( '\n' );
|
||||
stringBuilder.append( " mfp.yExt = " )
|
||||
.append( this.mfp_yExt ).append( '\n' );
|
||||
stringBuilder.append( " mfp.hMF = " )
|
||||
.append( this.mfp_hMF ).append( '\n' );
|
||||
|
||||
stringBuilder.append( " offset14 = " )
|
||||
.append( Arrays.toString( this.offset14 ) ).append( '\n' );
|
||||
stringBuilder.append( " dxaGoal = " )
|
||||
.append( this.dxaGoal ).append( '\n' );
|
||||
stringBuilder.append( " dyaGoal = " )
|
||||
.append( this.dyaGoal ).append( '\n' );
|
||||
|
||||
stringBuilder.append( " dxaCropLeft = " )
|
||||
.append( this.dxaCropLeft ).append( '\n' );
|
||||
stringBuilder.append( " dyaCropTop = " )
|
||||
.append( this.dyaCropTop ).append( '\n' );
|
||||
stringBuilder.append( " dxaCropRight = " )
|
||||
.append( this.dxaCropRight ).append( '\n' );
|
||||
stringBuilder.append( " dyaCropBottom = " )
|
||||
.append( this.dyaCropBottom ).append( '\n' );
|
||||
|
||||
stringBuilder.append( "[/PICF]" );
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import org.apache.poi.hwpf.model.PictureDescriptor;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
@ -31,7 +32,7 @@ import org.apache.poi.util.POILogger;
|
||||
* Represents embedded picture extracted from Word Document
|
||||
* @author Dmitry Romanov
|
||||
*/
|
||||
public final class Picture
|
||||
public final class Picture extends PictureDescriptor
|
||||
{
|
||||
private static final POILogger log = POILogFactory.getLogger(Picture.class);
|
||||
|
||||
@ -41,14 +42,6 @@ public final class Picture
|
||||
static final int PICT_HEADER_OFFSET = 0x4;
|
||||
static final int MFPMM_OFFSET = 0x6;
|
||||
static final int PICF_SHAPE_OFFSET = 0xE;
|
||||
static final int DXAGOAL_OFFSET = 0x1C;
|
||||
static final int DYAGOAL_OFFSET = 0x1E;
|
||||
static final int MX_OFFSET = 0x20;
|
||||
static final int MY_OFFSET = 0x22;
|
||||
static final int DXACROPLEFT_OFFSET = 0x24;
|
||||
static final int DYACROPTOP_OFFSET = 0x26;
|
||||
static final int DXACROPRIGHT_OFFSET = 0x28;
|
||||
static final int DYACROPBOTTOM_OFFSET = 0x2A;
|
||||
static final int UNKNOWN_HEADER_SIZE = 0x49;
|
||||
|
||||
public static final byte[] GIF = new byte[]{'G', 'I', 'F'};
|
||||
@ -76,21 +69,13 @@ public final class Picture
|
||||
private byte[] rawContent;
|
||||
private byte[] content;
|
||||
private byte[] _dataStream;
|
||||
private int aspectRatioX;
|
||||
private int aspectRatioY;
|
||||
private int height = -1;
|
||||
private int width = -1;
|
||||
|
||||
private int dxaGoal = -1;
|
||||
private int dyaGoal = -1;
|
||||
|
||||
private int dxaCropLeft = -1;
|
||||
private int dyaCropTop = -1;
|
||||
private int dxaCropRight = -1;
|
||||
private int dyaCropBottom = -1;
|
||||
|
||||
public Picture(int dataBlockStartOfsset, byte[] _dataStream, boolean fillBytes)
|
||||
{
|
||||
super (_dataStream, dataBlockStartOfsset);
|
||||
|
||||
this._dataStream = _dataStream;
|
||||
this.dataBlockStartOfsset = dataBlockStartOfsset;
|
||||
this.dataBlockSize = LittleEndian.getInt(_dataStream, dataBlockStartOfsset);
|
||||
@ -101,17 +86,6 @@ public final class Picture
|
||||
|
||||
}
|
||||
|
||||
this.dxaGoal = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DXAGOAL_OFFSET);
|
||||
this.dyaGoal = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DYAGOAL_OFFSET);
|
||||
|
||||
this.aspectRatioX = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+MX_OFFSET)/10;
|
||||
this.aspectRatioY = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+MY_OFFSET)/10;
|
||||
|
||||
this.dxaCropLeft = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DXACROPLEFT_OFFSET);
|
||||
this.dyaCropTop = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DYACROPTOP_OFFSET);
|
||||
this.dxaCropRight = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DXACROPRIGHT_OFFSET);
|
||||
this.dyaCropBottom = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DYACROPBOTTOM_OFFSET);
|
||||
|
||||
if (fillBytes)
|
||||
{
|
||||
fillImageContent();
|
||||
@ -120,6 +94,8 @@ public final class Picture
|
||||
|
||||
public Picture(byte[] _dataStream)
|
||||
{
|
||||
super();
|
||||
|
||||
this._dataStream = _dataStream;
|
||||
this.dataBlockStartOfsset = 0;
|
||||
this.dataBlockSize = _dataStream.length;
|
||||
@ -207,16 +183,39 @@ public final class Picture
|
||||
|
||||
/**
|
||||
* @return the horizontal aspect ratio for picture provided by user
|
||||
* @deprecated use more precise {@link #getHorizontalScalingFactor()}
|
||||
*/
|
||||
public int getAspectRatioX() {
|
||||
return aspectRatioX;
|
||||
@Deprecated
|
||||
public int getAspectRatioX()
|
||||
{
|
||||
return mx / 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Horizontal scaling factor supplied by user expressed in .001%
|
||||
* units
|
||||
*/
|
||||
public int getHorizontalScalingFactor()
|
||||
{
|
||||
return mx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @retrn the vertical aspect ratio for picture provided by user
|
||||
* @deprecated use more precise {@link #getVerticalScalingFactor()}
|
||||
*/
|
||||
public int getAspectRatioY() {
|
||||
return aspectRatioY;
|
||||
@Deprecated
|
||||
public int getAspectRatioY()
|
||||
{
|
||||
return my / 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vertical scaling factor supplied by user expressed in .001% units
|
||||
*/
|
||||
public int getVerticalScalingFactor()
|
||||
{
|
||||
return my;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,6 +29,9 @@ import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.hwpf.usermodel.Picture;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Test cases for {@link WordToHtmlConverter}
|
||||
@ -47,13 +50,28 @@ public class TestWordToHtmlConverter extends TestCase
|
||||
|
||||
private static String getHtmlText( final String sampleFileName )
|
||||
throws Exception
|
||||
{
|
||||
return getHtmlText( sampleFileName, false );
|
||||
}
|
||||
|
||||
private static String getHtmlText( final String sampleFileName,
|
||||
boolean emulatePictureStorage ) throws Exception
|
||||
{
|
||||
HWPFDocument hwpfDocument = new HWPFDocument( POIDataSamples
|
||||
.getDocumentInstance().openResourceAsStream( sampleFileName ) );
|
||||
|
||||
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
|
||||
DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
.newDocument() );
|
||||
Document newDocument = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder().newDocument();
|
||||
WordToHtmlConverter wordToHtmlConverter = !emulatePictureStorage ? new WordToHtmlConverter(
|
||||
newDocument ) : new WordToHtmlConverter( newDocument )
|
||||
{
|
||||
@Override
|
||||
protected void processImage( Element currentBlock, boolean inlined,
|
||||
Picture picture )
|
||||
{
|
||||
processImage( currentBlock, inlined, picture, "picture.bin" );
|
||||
}
|
||||
};
|
||||
wordToHtmlConverter.processDocument( hwpfDocument );
|
||||
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
@ -130,6 +148,20 @@ public class TestWordToHtmlConverter extends TestCase
|
||||
assertContains( result, "<!--Image link to '0.emf' can be here-->" );
|
||||
}
|
||||
|
||||
public void testPicture() throws Exception
|
||||
{
|
||||
String result = getHtmlText( "picture.doc", true );
|
||||
|
||||
// picture
|
||||
assertContains( result, "src=\"picture.bin\"" );
|
||||
// visible size
|
||||
assertContains( result, "width:3.1305554in;height:1.7250001in;" );
|
||||
// shift due to crop
|
||||
assertContains( result, "left:-0.09375;top:-0.25694445;" );
|
||||
// size without crop
|
||||
assertContains( result, "width:3.4125in;height:2.325in;" );
|
||||
}
|
||||
|
||||
public void testHyperlink() throws Exception
|
||||
{
|
||||
String result = getHtmlText( "hyperlink.doc" );
|
||||
|
@ -303,6 +303,7 @@ public final class TestPictures extends TestCase {
|
||||
assertEquals(0, plain8s);
|
||||
}
|
||||
|
||||
@SuppressWarnings( "deprecation" )
|
||||
public void testCroppedPictures() {
|
||||
HWPFDocument doc = HWPFTestDataSamples.openSampleFile("testCroppedPictures.doc");
|
||||
List<Picture> pics = doc.getPicturesTable().getAllPictures();
|
||||
@ -312,7 +313,9 @@ public final class TestPictures extends TestCase {
|
||||
|
||||
Picture pic1 = pics.get(0);
|
||||
assertEquals(27, pic1.getAspectRatioX());
|
||||
assertEquals(270, pic1.getHorizontalScalingFactor());
|
||||
assertEquals(27, pic1.getAspectRatioY());
|
||||
assertEquals(271, pic1.getVerticalScalingFactor());
|
||||
assertEquals(12000, pic1.getDxaGoal()); // 21.17 cm / 2.54 cm/inch * 72dpi * 20 = 12000
|
||||
assertEquals(9000, pic1.getDyaGoal()); // 15.88 cm / 2.54 cm/inch * 72dpi * 20 = 9000
|
||||
assertEquals(0, pic1.getDxaCropLeft());
|
||||
@ -323,7 +326,9 @@ public final class TestPictures extends TestCase {
|
||||
Picture pic2 = pics.get(1);
|
||||
System.out.println(pic2.getWidth());
|
||||
assertEquals(76, pic2.getAspectRatioX());
|
||||
assertEquals(764, pic2.getHorizontalScalingFactor());
|
||||
assertEquals(68, pic2.getAspectRatioY());
|
||||
assertEquals(685, pic2.getVerticalScalingFactor());
|
||||
assertEquals(12000, pic2.getDxaGoal()); // 21.17 cm / 2.54 cm/inch * 72dpi * 20 = 12000
|
||||
assertEquals(9000, pic2.getDyaGoal()); // 15.88 cm / 2.54 cm/inch * 72dpi * 20 = 9000
|
||||
assertEquals(0, pic2.getDxaCropLeft()); // TODO YK: The Picture is cropped but HWPF reads the crop parameters all zeros
|
||||
|
BIN
test-data/document/picture.doc
Normal file
BIN
test-data/document/picture.doc
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user