Package edu.emory.cellbio.svg
Class EmbedAndCrop
java.lang.Object
edu.emory.cellbio.svg.EmbedAndCrop
Inkscape extension: Embed and Crop Images
This java-based extension for Inkscape facilitates image embedding by:
- Automatically identifying all linked images.
- Cropping image data that lies outside the images' clipping frame.
- Optionally applying jpeg compression.
- Optionally resampling images.
- Writing the cropped and possibly compressed image data directly in the SVG file.
By cropping image data that lies outside the clipping frame, applying jpeg compression, or resampling to lower resolution, the resulting file size can be reduced significantly. If preserving image quality is a priority jpeg compression and resampling can be explicitly avoided.
- Author:
- Benjamin Nanes
-
Field Summary
Modifier and TypeFieldDescriptionprivate float
private boolean
private long
private String
private double
private double
private final boolean
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionprivate void
adjustImgPlacement
(Element img, double[] crop) Adjust placement of the image element to account for croppingprivate void
Validate the image output typeprivate BufferedImage
Quick and dirty conversion to TYPE_INT_RGBprivate double
distanceFromLine
(double[] lp0, double[] lp1, double[] x) Get the minimum distance between a pont and a line defined by two other pointsprivate double[]
distanceFromRect
(double[] p, double[] r) How far is a point from each edge of a rectangle?private Element
getClipPath
(Element img, Document dom) Get the clipping path of an imageprivate double[][]
getClipPoints
(Element clip) Extract the coordinates of a clip pathprivate double[]
getCropFraction
(Element img, Element clip) Get the fraction of image that should be cropped off each sideprivate double[]
Transform the width and height attributes of an element to document space.private void
Harvest output parameters from dialogprivate double[][]
getPathPointList
(Element path) Get the points along a path ////Not workingprivate double[]
Get the boundaries of a rect element (or similar) without transformationprivate boolean
isPointInRect
(double[] p, double[] r) Is a point within a rectangle (edges excluded)?private BufferedImage
limitResolution
(BufferedImage I, double[] wh, double rTarget, double rMax) Down-sample an image if above a maximum resolutionprivate BufferedImage
loadImageData
(Element imgElement, String basePath, long embedSizeMin) Load image data from an SVG image elementstatic void
private File
Get a file using a file open dialogprivate void
private double[]
parseTransform
(double[] point, String transform) Transform a coordinate pair using a transform attributeprivate void
Process an SVG DOMprivate long
Turn a file size string into the number of bytesprivate void
processImg
(Element img, Element clip, String basePath) Process an image elementprivate void
putImgData
(Element img, BufferedImage origImg, double[] crop) Load image data to embedprivate Map.Entry<BufferedImage,
Integer> readEmbeddedImageData
(String imgString) Read a BufferedImage from image data embedded in the SVG file.private Document
Read an XML file and return a DOMprivate double[][]
rectBoundsToPointList
(double[] b) Convert rect boundary points to a list of corner pointsvoid
runInkscapeExtension
(String[] args) Run the extensionboolean
runWithoutExit
(String[] args) Run the extension, but do not exit the JVM when finished.private void
Save an XML(SVG) fileprivate void
Save an XML(SVG) fileprivate double[]
scaleToRectFraction
(double[] d, double[] r) Scale a set of distances from rectangle edges by the width and height of the rectangle.private void
SVGToStream
(Document dom, OutputStream os) Push XML(SVG) to a streamvoid
test()
private double[]
transformMatrix
(double[] point, double[] matrix) Apply a matrix transformation.private double[]
transformRotate
(double[] point, double a) Apply a rotation about the originprivate double[]
transformRotate
(double[] point, double a, double cx, double cy) Apply a rotation about center point{cx,cy}
private double[]
transformScale
(double[] point, double sx, double sy) Apply a scaleprivate double[]
transformSkewX
(double[] point, double a) Skew along the x-axisprivate double[]
transformSkewY
(double[] point, double a) Skew along the y-axisprivate double[][]
transformToDocumentSpace
(double[][] points, Node n) Transform a set of points to document spaceprivate double[]
transformToDocumentSpace
(double[] point, Node n) Transform a point ({x,y}
) to document space by recursively looking for transform attributes in the given nodes and all parent nodes.private double[]
transformTranslate
(double[] point, double tx, double ty) Apply a translation
-
Field Details
-
imgFileType
-
compQual
private float compQual -
doResampling
private boolean doResampling -
targetRes
private double targetRes -
maxRes
private double maxRes -
embeddedImageSizeMin
private long embeddedImageSizeMin -
VERBOSE
private final boolean VERBOSE- See Also:
-
-
Constructor Details
-
EmbedAndCrop
public EmbedAndCrop()
-
-
Method Details
-
runInkscapeExtension
Run the extension- Parameters:
args
- Command line arguments
[<input>] [-o <output> | -s] [-t <type> [-q <quality>]] [-r [<target res.> [<max res.>]]] [-e <size>]
-
<input>
Path to the input SVG file. If missing, the user will be presented with a file open dialog box. -
-o <output>
Path to save the output SVG file with embedded images -
-s
Present the user with a file save dialog to specify the output file
Note: If neither-o
nor-s
is specified, the output is sent to the standard output stream -
-t <type>
Specify the type of image for encoding. Supported options arepng
,jpeg
, ormix
. The latter option indicates that for each image, the format resulting in the smaller file size should be used. If this flag is not set, the user will be presented with a selection dialog. -
-q <quality>
Quality parameter for jpeg compression. Default value is0.85
. -
-r <target res.> <max res.>
Images with resolution above<max res.>
should be downsampled to<target res.>
. Resolution is specified in pixels per mm. If this flag is not set, no resampling will be done. If this flag is set, but no target resolution is provided, the default value is11.811
, approximately equal to 300dpi. If only the target resolution is provided, the max resolution defaults to 4/3 of the target resolution. -
-e <size>
Minimum size at which already embedded images will be processed. Set to -1 to skip processing of all embedded images (default behavior). Format using common units (20KB, 1MB, etc.)
input.svg -s -t jpeg -q 0.95
input.svg -o output.svg
-
-
runWithoutExit
Run the extension, but do not exit the JVM when finished. This method allows an alternate entry point to allow use of the extension programmatically, rather than from Inkscape or the command line.- See Also:
-
parseArgs
-
process
Process an SVG DOM- Throws:
EmbedAndCropException
-
SVGToStream
Push XML(SVG) to a stream- Throws:
EmbedAndCropException
-
getOutputParams
Harvest output parameters from dialog- Throws:
EmbedAndCropException
-
checkImageOutputType
Validate the image output type- Throws:
EmbedAndCropException
-
saveAs
Save an XML(SVG) file- Throws:
EmbedAndCropException
-
save
Save an XML(SVG) file- Throws:
EmbedAndCropException
-
processImg
Process an image element- Throws:
EmbedAndCropException
-
loadImageData
private BufferedImage loadImageData(Element imgElement, String basePath, long embedSizeMin) throws EmbedAndCropException Load image data from an SVG image element- Parameters:
imgElement
-basePath
-embedSizeMin
- Do not process (i.e. return null) embedded images below this size (bytes). Set to -1 to skip all embedded images.- Returns:
- Returns the image data in a BufferedImage, or null if an embedded image cannot be loaded and the element should be skipped.
- Throws:
EmbedAndCropException
- Image data cannot be loaded and simply skipping the element is not appropriate (i.e. broken link).
-
putImgData
private void putImgData(Element img, BufferedImage origImg, double[] crop) throws EmbedAndCropException Load image data to embed- Parameters:
img
- Image elementorigImg
- Image data as a BufferedImagecrop
- Fraction of image to crop from each edge,{top, bottom, left, right}
- Throws:
EmbedAndCropException
-
readEmbeddedImageData
private Map.Entry<BufferedImage,Integer> readEmbeddedImageData(String imgString) throws EmbedAndCropException Read a BufferedImage from image data embedded in the SVG file. Following the SVG standard, PNG and Jpeg images are supported. Requires base64 encoding. Transparency is not supported.- Parameters:
imgString
-- Returns:
- Throws:
EmbedAndCropException
-
convertToRGB
Quick and dirty conversion to TYPE_INT_RGB- Parameters:
img
-- Returns:
-
adjustImgPlacement
Adjust placement of the image element to account for cropping- Parameters:
img
- The image elementcrop
- Fraction of image actually cropped from each edge,{top, bottom, left, right}
; note that this must account for rounding to pixels
-
getElementDims
Transform the width and height attributes of an element to document space.- Parameters:
e
-- Returns:
-
limitResolution
Down-sample an image if above a maximum resolution- Parameters:
I
- Source imagewh
- Image dimensions, width x height (physical units)rTarget
- Target resolution (pixels per physical unit)rMax
- Max resolution (pixels per physical unit)- Returns:
- A resampled image with the lowest possible resolution not less than r, or the source image unchanged if the source image resolution is less than or equal to r.
-
getCropFraction
Get the fraction of image that should be cropped off each side- Parameters:
img
- The image elementclip
- The clip-path element- Returns:
- Fraction of image to crop from each edge,
{top, bottom, left, right}
- Throws:
EmbedAndCropException
-
isPointInRect
private boolean isPointInRect(double[] p, double[] r) Is a point within a rectangle (edges excluded)?- Parameters:
p
-{x,y}
r
- Bounding points of the rectangle,{x0, x1, y0, y1}
-
distanceFromRect
private double[] distanceFromRect(double[] p, double[] r) How far is a point from each edge of a rectangle?- Parameters:
p
-{x,y}
r
- Bounding points of the rectangle,{x0, x1, y0, y1}
- Returns:
- Distance from each edge (negative if point is on exterior side of the edge),
{top, bottom, left, right}
-
scaleToRectFraction
private double[] scaleToRectFraction(double[] d, double[] r) Scale a set of distances from rectangle edges by the width and height of the rectangle.- Parameters:
d
- Absolute distances,{top, bottom, left, right}
r
- Bounding points of the rectangle,{x0, x1, y0, y1}
- Returns:
- Relative distances,
{top/height, bottom/height, left/width, right/width}
-
distanceFromLine
private double distanceFromLine(double[] lp0, double[] lp1, double[] x) Get the minimum distance between a pont and a line defined by two other points- Parameters:
lp0
- 1st point on the line,{x,y}
lp1
- 2nd point on the line,{x,y}
x
- How far is this point from the line,{x,y}
- Returns:
- Distance of point
x
from the line
-
getClipPoints
Extract the coordinates of a clip path- Returns:
double[][] coordinates[point]{x,y}
- Throws:
EmbedAndCropException
-
getPathPointList
Get the points along a path ////Not working- Returns:
double[point][{x,y}]
- Throws:
EmbedAndCropException
-
getRectBounds
Get the boundaries of a rect element (or similar) without transformation- Returns:
- An array:
{x0, x1, y0, y1}
-
rectBoundsToPointList
private double[][] rectBoundsToPointList(double[] b) Convert rect boundary points to a list of corner points- Parameters:
b
-{x0, x1, y0, y1}
, as returned bygetRectBounds(org.w3c.dom.Element)
- Returns:
double[point][{x,y}]
-
transformToDocumentSpace
Transform a point ({x,y}
) to document space by recursively looking for transform attributes in the given nodes and all parent nodes.- Parameters:
point
-n
-- Returns:
{x,y}
-
transformToDocumentSpace
Transform a set of points to document space- Parameters:
points
- Array of points ({x,y}
)n
-- Returns:
-
parseTransform
Transform a coordinate pair using a transform attribute- Parameters:
point
-{x,y}
transform
- The transform atribute value- Returns:
{x,y}
-
transformMatrix
private double[] transformMatrix(double[] point, double[] matrix) Apply a matrix transformation.WARNING - Matrix specification (by row) differs from standard SVG order (by column)
- Parameters:
point
-{x,y}
matrix
-{a,c,e,b,d,f}
- Returns:
{x,y}
-
transformTranslate
private double[] transformTranslate(double[] point, double tx, double ty) Apply a translation- Parameters:
point
-{x,y}
tx
- Delta xty
- Delta y- Returns:
{x,y}
-
transformScale
private double[] transformScale(double[] point, double sx, double sy) Apply a scale- Parameters:
point
-{x,y}
sx
- x scale factorsy
- y scale factor- Returns:
{x,y}
-
transformRotate
private double[] transformRotate(double[] point, double a) Apply a rotation about the origin- Parameters:
point
-{x,y}
a
- Angle, in degrees- Returns:
{x,y}
-
transformRotate
private double[] transformRotate(double[] point, double a, double cx, double cy) Apply a rotation about center point{cx,cy}
- Parameters:
point
-{x,y}
a
- Angle, in degrees- Returns:
{x,y}
-
transformSkewX
private double[] transformSkewX(double[] point, double a) Skew along the x-axis- Parameters:
point
-{x,y}
a
- Angle, in degrees- Returns:
{x,y}
-
transformSkewY
private double[] transformSkewY(double[] point, double a) Skew along the y-axis- Parameters:
point
-{x,y}
a
- Angle, in degrees- Returns:
{x,y}
-
getClipPath
Get the clipping path of an image -
openDialog
Get a file using a file open dialog -
readSVG
Read an XML file and return a DOM- Throws:
EmbedAndCropException
-
processFileSize
Turn a file size string into the number of bytes- Parameters:
s
-- Returns:
-
test
- Throws:
EmbedAndCropException
-
main
-