Skip to content

Commit

Permalink
#40: Correctly handle image interpolation and also respect this in t…
Browse files Browse the repository at this point in the history
…he image cache.
  • Loading branch information
rototor committed Dec 17, 2022
1 parent e5ab57d commit 6ce5ef8
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 143 deletions.
24 changes: 17 additions & 7 deletions README.md
Expand Up @@ -14,8 +14,8 @@ pages and change certain aspects. E.g.
[change the color mapping and perform an overfill](graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/PdfRerenderTest.java).
Now also it's possible to setup masking of all draw()/fill() calls. Think of this like an
additional clipping, just that this supports bitmap images and complete complex drawings (XForm's)
as alpha masks. See
[here](https://github.com/rototor/pdfbox-graphics2d/blob/master/graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/TestMaskedDraws.java)
as alpha masks. See
[here](https://github.com/rototor/pdfbox-graphics2d/blob/master/graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/TestMaskedDraws.java)
how that works.

The following features are supported:
Expand Down Expand Up @@ -325,16 +325,26 @@ graphs
## Changes

Version 0.42 (not yet released):

- Upgraded PDFBox to 2.0.27
- [#46](https://github.com/rototor/pdfbox-graphics2d/issues/46): Also override drawRect() and use a
Rectangle with drawShape(). Thanks @fransbouwmans for the report.
- [#40](https://github.com/rototor/pdfbox-graphics2d/issues/40): Correctly implement image
interpolation and respect the chosen interpolation when caching an image. NOTE: This is a
API breaking change on the IPdfBoxGraphics2DImageEncoder. So if you have implemeted this interface
you need to adapt to the new signature (env parameter).

Version 0.41:
- #45 Copy & paste error in drawImage() call forwarding. sy1 should be passed for sy1, not sy2... Thanks @fransbouwmans for pointing this out. This affected one
specifc drawImage() overload.


- #45 Copy & paste error in drawImage() call forwarding. sy1 should be passed for sy1, not sy2...
Thanks @fransbouwmans for pointing this out. This affected one
specifc drawImage() overload.

Version 0.40:

- Messed up the access permissions for `PdfBoxGraphics2DPaintApplier.PaintApplierState::setupLuminosityMasking`. They are
now accessible.
- Messed up the access permissions
for `PdfBoxGraphics2DPaintApplier.PaintApplierState::setupLuminosityMasking`. They are
now accessible.

Version 0.39:

Expand Down
Expand Up @@ -24,17 +24,43 @@
/**
* Encode and compress an image as PDImageXObject
*/
public interface IPdfBoxGraphics2DImageEncoder {
/**
* Encode the given image into the a PDImageXObject
*
* @param document
* the PDF document
* @param contentStream
* the content stream of the page
* @param image
* the image to encode
* @return the encoded image
*/
PDImageXObject encodeImage(PDDocument document, PDPageContentStream contentStream, Image image);
public interface IPdfBoxGraphics2DImageEncoder
{
/**
* Environment for image encoding
*/
interface IPdfBoxGraphics2DImageEncoderEnv
{

/*
* What kind of image interpolations are possible?
*/
enum ImageInterpolation
{
/*
* "Pixel Art" rendering.
*/
NearestNeigbor, //
/*
* Interpolate the image. What algorithmus is used depends on the PDF viewer.
*/
Interpolate
}

/**
* @return the RenderingHints.KEY_INTERPOLATION value mapped to the Interpolation enum
*/
ImageInterpolation getImageInterpolation();
}

/**
* Encode the given image into the a PDImageXObject
*
* @param document the PDF document
* @param contentStream the content stream of the page
* @param image the image to encode
* @return the encoded image
*/
PDImageXObject encodeImage(PDDocument document, PDPageContentStream contentStream, Image image,
IPdfBoxGraphics2DImageEncoderEnv env);
}
Expand Up @@ -655,6 +655,18 @@ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1,
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
}

final IPdfBoxGraphics2DImageEncoder.IPdfBoxGraphics2DImageEncoderEnv imageEncoderEnv = new IPdfBoxGraphics2DImageEncoder.IPdfBoxGraphics2DImageEncoderEnv()
{
@Override
public ImageInterpolation getImageInterpolation()
{
Object renderingHint = getRenderingHint(RenderingHints.KEY_INTERPOLATION);
if (renderingHint == RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
return ImageInterpolation.NearestNeigbor;
return ImageInterpolation.Interpolate;
}
};

public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
{
checkNoCopyActive();
Expand All @@ -664,7 +676,8 @@ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
if (xform != null)
tf.concatenate((AffineTransform) xform.clone());

PDImageXObject pdImage = imageEncoder.encodeImage(document, contentStream, img);
PDImageXObject pdImage = imageEncoder.encodeImage(document, contentStream, img,
imageEncoderEnv);
try
{
contentStreamSaveState();
Expand All @@ -673,10 +686,6 @@ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
tf.scale(1, -1);
contentStream.transform(new Matrix(tf));

Object keyInterpolation = renderingHints.get(RenderingHints.KEY_INTERPOLATION);
if (RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR.equals(keyInterpolation))
pdImage.setInterpolate(false);

if (composite != null)
{
// We got an AlphaComposite, we must set the extended graphics dictionary correctly.
Expand Down

0 comments on commit 6ce5ef8

Please sign in to comment.