PDImageXObject.java (pdfbox-2.0.23-src) | : | PDImageXObject.java (pdfbox-2.0.24-src) | ||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
import java.awt.image.WritableRaster; | import java.awt.image.WritableRaster; | |||
import java.io.BufferedInputStream; | import java.io.BufferedInputStream; | |||
import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | |||
import java.io.File; | import java.io.File; | |||
import java.io.FileInputStream; | import java.io.FileInputStream; | |||
import java.io.IOException; | import java.io.IOException; | |||
import java.io.InputStream; | import java.io.InputStream; | |||
import java.io.OutputStream; | import java.io.OutputStream; | |||
import java.lang.ref.SoftReference; | import java.lang.ref.SoftReference; | |||
import java.util.List; | import java.util.List; | |||
import javax.imageio.ImageIO; | import javax.imageio.ImageIO; | |||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | |||
import org.apache.pdfbox.cos.COSArray; | import org.apache.pdfbox.cos.COSArray; | |||
import org.apache.pdfbox.cos.COSBase; | import org.apache.pdfbox.cos.COSBase; | |||
import org.apache.pdfbox.cos.COSDictionary; | import org.apache.pdfbox.cos.COSDictionary; | |||
import org.apache.pdfbox.cos.COSInputStream; | import org.apache.pdfbox.cos.COSInputStream; | |||
import org.apache.pdfbox.cos.COSName; | import org.apache.pdfbox.cos.COSName; | |||
import org.apache.pdfbox.cos.COSObject; | import org.apache.pdfbox.cos.COSObject; | |||
import org.apache.pdfbox.cos.COSStream; | import org.apache.pdfbox.cos.COSStream; | |||
import org.apache.pdfbox.filter.DecodeOptions; | import org.apache.pdfbox.filter.DecodeOptions; | |||
skipping to change at line 589 | skipping to change at line 591 | |||
{ | { | |||
return image; | return image; | |||
} | } | |||
int width = image.getWidth(); | int width = image.getWidth(); | |||
int height = image.getHeight(); | int height = image.getHeight(); | |||
// scale mask to fit image, or image to fit mask, whichever is larger | // scale mask to fit image, or image to fit mask, whichever is larger | |||
if (mask.getWidth() < width || mask.getHeight() < height) | if (mask.getWidth() < width || mask.getHeight() < height) | |||
{ | { | |||
mask = scaleImage(mask, width, height); | mask = scaleImage(mask, width, height, BufferedImage.TYPE_BYTE_GRAY) ; | |||
} | } | |||
else if (mask.getWidth() > width || mask.getHeight() > height) | ||||
if (mask.getWidth() > width || mask.getHeight() > height) | ||||
{ | { | |||
width = mask.getWidth(); | width = mask.getWidth(); | |||
height = mask.getHeight(); | height = mask.getHeight(); | |||
image = scaleImage(image, width, height); | image = scaleImage(image, width, height, BufferedImage.TYPE_INT_ARGB ); | |||
} | } | |||
else if (image.getRaster().getPixel(0, 0, (int[]) null).length < 3) | else if (image.getType() != BufferedImage.TYPE_INT_ARGB) | |||
{ | { | |||
// always convert to ARGB to allow bulk read / write | ||||
// PDFBOX-4470 bitonal image has only one element => copy into RGB | // PDFBOX-4470 bitonal image has only one element => copy into RGB | |||
image = scaleImage(image, width, height); | image = scaleImage(image, width, height, BufferedImage.TYPE_INT_ARGB ); | |||
} | } | |||
// compose to ARGB | // compose to ARGB | |||
BufferedImage masked = new BufferedImage(width, height, BufferedImage.TY PE_INT_ARGB); | BufferedImage masked = new BufferedImage(width, height, BufferedImage.TY PE_INT_ARGB); | |||
WritableRaster src = image.getRaster(); | WritableRaster src = image.getRaster(); | |||
WritableRaster dest = masked.getRaster(); | WritableRaster dest = masked.getRaster(); | |||
WritableRaster alpha = mask.getRaster(); | WritableRaster alpha = mask.getRaster(); | |||
float[] rgb = new float[4]; | int[] alphaRow = new int[width]; | |||
float[] rgba = new float[4]; | int[] rgbaRow = new int[4 * width]; | |||
float[] alphaPixel = null; | ||||
for (int y = 0; y < height; y++) | for (int y = 0; y < height; y++) | |||
{ | { | |||
src.getPixels(0, y, width, 1, rgbaRow); | ||||
alpha.getSamples(0, y, width, 1, 0, alphaRow); | ||||
for (int x = 0; x < width; x++) | for (int x = 0; x < width; x++) | |||
{ | { | |||
src.getPixel(x, y, rgb); | int offset = x * 4; | |||
rgba[0] = rgb[0]; | ||||
rgba[1] = rgb[1]; | ||||
rgba[2] = rgb[2]; | ||||
alphaPixel = alpha.getPixel(x, y, alphaPixel); | ||||
if (isSoft) | if (isSoft) | |||
{ | { | |||
rgba[3] = alphaPixel[0]; | rgbaRow[offset + 3] = alphaRow[x]; | |||
if (matte != null && Float.compare(alphaPixel[0], 0) != 0) | if (matte != null && alphaRow[x] != 0) | |||
{ | { | |||
rgba[0] = clampColor(((rgba[0] / 255 - matte[0]) / (alph | float k = alphaRow[x] / 255f; | |||
aPixel[0] / 255) + matte[0]) * 255); | rgbaRow[offset + 0] = clampColor(((rgbaRow[offset + 0] / | |||
rgba[1] = clampColor(((rgba[1] / 255 - matte[1]) / (alph | 255f - matte[0]) / k + matte[0]) * 255f); | |||
aPixel[0] / 255) + matte[1]) * 255); | rgbaRow[offset + 1] = clampColor(((rgbaRow[offset + 1] / | |||
rgba[2] = clampColor(((rgba[2] / 255 - matte[2]) / (alph | 255f - matte[1]) / k + matte[1]) * 255f); | |||
aPixel[0] / 255) + matte[2]) * 255); | rgbaRow[offset + 2] = clampColor(((rgbaRow[offset + 2] / | |||
255f - matte[2]) / k + matte[2]) * 255f); | ||||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
rgba[3] = 255 - alphaPixel[0]; | rgbaRow[offset + 3] = 255 - alphaRow[x]; | |||
} | } | |||
dest.setPixel(x, y, rgba); | ||||
} | } | |||
dest.setPixels(0, y, width, 1, rgbaRow); | ||||
} | } | |||
return masked; | return masked; | |||
} | } | |||
private float clampColor(float color) | private int clampColor(float color) | |||
{ | { | |||
return color < 0 ? 0 : (color > 255 ? 255 : color); | return color < 0 ? 0 : (color > 255 ? 255 : Math.round(color)); | |||
} | } | |||
/** | /** | |||
* High-quality image scaling. | * High-quality image scaling. | |||
*/ | */ | |||
private BufferedImage scaleImage(BufferedImage image, int width, int height) | private BufferedImage scaleImage(BufferedImage image, int width, int height, int type) | |||
{ | { | |||
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TY PE_INT_RGB); | BufferedImage image2 = new BufferedImage(width, height, type); | |||
Graphics2D g = image2.createGraphics(); | Graphics2D g = image2.createGraphics(); | |||
if (getInterpolate()) | if (getInterpolate()) | |||
{ | { | |||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, | g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, | |||
RenderingHints.VALUE_INTERPOLATION_BICUBIC); | RenderingHints.VALUE_INTERPOLATION_BICUBIC); | |||
g.setRenderingHint(RenderingHints.KEY_RENDERING, | g.setRenderingHint(RenderingHints.KEY_RENDERING, | |||
RenderingHints.VALUE_RENDER_QUALITY); | RenderingHints.VALUE_RENDER_QUALITY); | |||
} | } | |||
g.drawImage(image, 0, 0, width, height, 0, 0, image.getWidth(), image.ge tHeight(), null); | g.drawImage(image, 0, 0, width, height, 0, 0, image.getWidth(), image.ge tHeight(), null); | |||
g.dispose(); | g.dispose(); | |||
End of changes. 21 change blocks. | ||||
31 lines changed or deleted | 29 lines changed or added |