Pārlūkot izejas kodu

Bugzilla #36224:

This patch ports the 0.20.5 CCITTFaxDecode filter functionality and its support
of direct embedding on certain TIFF images to the trunk.
It also cleans up some of the image handling with respect to consistent closing
of the input stream to avoid dangling open files.
Submitted by: Manuel Mall <mm.at.arcus.com.au>

Changes to the patch:
Fixed a small problem with the NullFilter in the PDF library.
Used tiff_group4.tiff in external-graphic-tiff.xml.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@234261 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_90-alpha1
Jeremias Maerki pirms 19 gadiem
vecāks
revīzija
b5fe4766be

+ 11
- 0
src/java-1.4/org/apache/fop/image/ImageIOImage.java Parādīt failu

@@ -42,9 +42,20 @@ public class ImageIOImage extends AbstractFopImage {
super(info);
}

/**
* @see org.apache.fop.image.AbstractFopImage#loadDimensions()
*/
protected boolean loadDimensions() {
if (this.bitmaps == null) {
return loadBitmap();
}
return true;
}
/** @see org.apache.fop.image.AbstractFopImage#loadBitmap() */
protected boolean loadBitmap() {
try {
inputStream.reset();
BufferedImage imageData = ImageIO.read(inputStream);

this.height = imageData.getHeight();

+ 128
- 83
src/java/org/apache/fop/image/BatikImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 2004 The Apache Software Foundation
* Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,16 @@ public abstract class BatikImage extends AbstractFopImage {

private byte[] softMask = null;

/**
* The InputStream wrapped into a SeekableStream for decoding.
*/
protected SeekableStream seekableInput = null;

/**
* The Batik representation of the image
*/
protected CachableRed cr = null;
/**
* Constructs a new BatikImage instance.
* @param imgReader basic metadata for the image
@@ -54,11 +64,72 @@ public abstract class BatikImage extends AbstractFopImage {
* @see org.apache.fop.image.AbstractFopImage#loadDimensions()
*/
protected boolean loadDimensions() {
if (this.bitmaps == null) {
loadImage();
}
if (seekableInput == null && inputStream != null) {
try {
seekableInput = new FileCacheSeekableStream(inputStream);
} catch (IOException ioe) {
seekableInput = new MemoryCacheSeekableStream(inputStream);
}
try {
this.bitsPerPixel = 8;
cr = decodeImage(seekableInput);
this.height = cr.getHeight();
this.width = cr.getWidth();
this.isTransparent = false;
this.softMask = null;
ColorModel cm = cr.getColorModel();

this.height = cr.getHeight();
this.width = cr.getWidth();
this.isTransparent = false;
this.softMask = null;

int transparencyType = cm.getTransparency();
if (cm instanceof IndexColorModel) {
if (transparencyType == Transparency.BITMASK) {
// Use 'transparent color'.
IndexColorModel icm = (IndexColorModel)cm;
int numColor = icm.getMapSize();
byte [] alpha = new byte[numColor];
icm.getAlphas(alpha);
for (int i = 0; i < numColor; i++) {
if ((alpha[i] & 0xFF) == 0) {
this.isTransparent = true;
int red = (icm.getRed (i)) & 0xFF;
int grn = (icm.getGreen(i)) & 0xFF;
int blu = (icm.getBlue (i)) & 0xFF;
this.transparentColor = new Color(red, grn, blu);
break;
}
}
}
} else {
cr = new Any2sRGBRed(cr);
}

return this.bitmaps != null;
// Get our current ColorModel
cm = cr.getColorModel();
if (this.colorSpace == null) {
this.colorSpace = cm.getColorSpace();
}
} catch (IOException ioe) {
log.error("Error while loading image (Batik): " + ioe.getMessage(), ioe);
try {
seekableInput.close();
} catch (IOException ioex) {
// ignore
}
try {
inputStream.close();
} catch (IOException ioex) {
// ignore
}
seekableInput = null;
inputStream = null;
return false;
}
}
return this.height != -1;
}

/**
@@ -106,88 +177,62 @@ public abstract class BatikImage extends AbstractFopImage {
* Loads the image from the InputStream.
*/
protected void loadImage() {
try {
SeekableStream seekableInput;
try { seekableInput = new FileCacheSeekableStream(inputStream);
} catch (IOException ioe) {
seekableInput = new MemoryCacheSeekableStream(inputStream);
}

CachableRed cr = decodeImage(seekableInput);
ColorModel cm = cr.getColorModel();

this.height = cr.getHeight();
this.width = cr.getWidth();
this.isTransparent = false;
this.softMask = null;
this.bitmapsSize = this.width * this.height * 3;
this.bitmaps = new byte[this.bitmapsSize];
this.bitsPerPixel = 8;

int transparencyType = cm.getTransparency();
if (cm instanceof IndexColorModel) {
if (transparencyType == Transparency.BITMASK) {
// Use 'transparent color'.
IndexColorModel icm = (IndexColorModel)cm;
int numColor = icm.getMapSize();
byte [] alpha = new byte[numColor];
icm.getAlphas(alpha);
for (int i = 0; i < numColor; i++) {
if ((alpha[i] & 0xFF) == 0) {
this.isTransparent = true;
int red = (icm.getRed (i)) & 0xFF;
int grn = (icm.getGreen(i)) & 0xFF;
int blu = (icm.getBlue (i)) & 0xFF;
this.transparentColor = new Color(red, grn, blu);
break;
if (loadDimensions()) {
try {
// Get our current ColorModel
ColorModel cm = cr.getColorModel();

// It has an alpha channel so generate a soft mask.
if (!this.isTransparent && cm.hasAlpha())
this.softMask = new byte[this.width * this.height];

this.bitmapsSize = this.width * this.height * 3;
this.bitmaps = new byte[this.bitmapsSize];

WritableRaster wr = (WritableRaster)cr.getData();
BufferedImage bi = new BufferedImage
(cm, wr.createWritableTranslatedChild(0, 0),
cm.isAlphaPremultiplied(), null);
int [] tmpMap = new int[this.width];
int idx = 0;
int sfIdx = 0;
for (int y = 0; y < this.height; y++) {
tmpMap = bi.getRGB(0, y, this.width, 1, tmpMap, 0, this.width);
if (softMask != null) {
for (int x = 0; x < this.width; x++) {
int pix = tmpMap[x];
this.softMask[sfIdx++] = (byte)(pix >>> 24);
this.bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF);
this.bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF);
this.bitmaps[idx++] = (byte)((pix) & 0xFF);
}
} else {
for (int x = 0; x < this.width; x++) {
int pix = tmpMap[x];
this.bitmaps[idx++] = (byte)((pix >> 16) & 0xFF);
this.bitmaps[idx++] = (byte)((pix >> 8) & 0xFF);
this.bitmaps[idx++] = (byte)((pix) & 0xFF);
}
}
}
}
} else {
cr = new Any2sRGBRed(cr);
}

// Get our current ColorModel
cm = cr.getColorModel();

// It has an alpha channel so generate a soft mask.
if (!this.isTransparent && cm.hasAlpha())
this.softMask = new byte[this.width * this.height];

this.colorSpace = cm.getColorSpace();
WritableRaster wr = (WritableRaster)cr.getData();
BufferedImage bi = new BufferedImage
(cm, wr.createWritableTranslatedChild(0, 0),
cm.isAlphaPremultiplied(), null);
int [] tmpMap = new int[this.width];
int idx = 0;
int sfIdx = 0;
for (int y = 0; y < this.height; y++) {
tmpMap = bi.getRGB(0, y, this.width, 1, tmpMap, 0, this.width);
if (softMask != null) {
for (int x = 0; x < this.width; x++) {
int pix = tmpMap[x];
this.softMask[sfIdx++] = (byte)(pix >>> 24);
this.bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF);
this.bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF);
this.bitmaps[idx++] = (byte)((pix) & 0xFF);
}
} else {
for (int x = 0; x < this.width; x++) {
int pix = tmpMap[x];
this.bitmaps[idx++] = (byte)((pix >> 16) & 0xFF);
this.bitmaps[idx++] = (byte)((pix >> 8) & 0xFF);
this.bitmaps[idx++] = (byte)((pix) & 0xFF);
}
} catch (Exception ex) {
log.error("Error while loading image (Batik): " + ex.getMessage(), ex);
} finally {
// Make sure we clean up
try {
seekableInput.close();
} catch (IOException ioex) {
// ignore
}
try {
inputStream.close();
} catch (IOException ioex) {
// ignore
}
seekableInput = null;
inputStream = null;
cr = null;
}
} catch (Exception ex) {
log.error("Error loading an image" , ex);
/*throw new FopImageException("Error while loading image "
+ "" + " : "
+ ex.getClass() + " - "
+ ex.getMessage());
*/
}
}
};

+ 20
- 16
src/java/org/apache/fop/image/BmpImage.java Parādīt failu

@@ -82,14 +82,17 @@ public class BmpImage extends AbstractFopImage {
countr++;
}
}
} catch (IOException e) {
log.error("Error while loading image "
+ "" + " : "
+ e.getClass() + " - "
+ e.getMessage(), e);
} catch (IOException ex) {
log.error("Error while loading image (Bmp): " + ex.getMessage(), ex);
try {
inputStream.close();
} catch (java.io.IOException ioe) {
// Ignore
}
inputStream = null;
return false;
}
// gets h & w from headermap
// gets h & w from headermap
this.width = headermap[wpos]
+ headermap[wpos + 1] * 256
+ headermap[wpos + 2] * 256 * 256
@@ -140,14 +143,16 @@ public class BmpImage extends AbstractFopImage {
temp[count++] = input;
}
}
inputStream.close();
inputStream = null;
} catch (IOException e) {
log.error("Error while loading image "
+ "" + " : "
+ e.getClass() + " - "
+ e.getMessage(), e);
} catch (IOException ex) {
log.error("Error while loading image (Bmp): " + ex.getMessage(), ex);
return false;
} finally {
try {
inputStream.close();
} catch (java.io.IOException ioe) {
// Ignore
}
inputStream = null;
}

for (int i = 0; i < this.height; i++) {
@@ -159,9 +164,8 @@ public class BmpImage extends AbstractFopImage {
if (this.bitsPerPixel == 24 && x < this.width) {
int countr = 2;
do {
this.bitmaps[3 * (i * this.width + x) + countr] =
(byte)(temp[(this.height - i - 1)
* bytes + j] & 0xFF);
this.bitmaps[3 * (i * this.width + x) + countr]
= (byte)(temp[(this.height - i - 1) * bytes + j] & 0xFF);
j++;
} while (--countr >= 0)
;

+ 25
- 15
src/java/org/apache/fop/image/GifImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import java.net.URLConnection;
* @see FopImage
*/
public class GifImage extends AbstractFopImage {

/**
* Create a new gif image.
*
@@ -52,7 +53,6 @@ public class GifImage extends AbstractFopImage {
* To decode the image a dummy URLConnection is used that
* will do the conversion.
*
* @param ua the user agent for loading
* @return True if the load process succeeded
*/
protected boolean loadBitmap() {
@@ -83,9 +83,6 @@ public class GifImage extends AbstractFopImage {
return false;
}

inputStream.close();
inputStream = null;

ColorModel cm = consumer.getColorModel();
this.bitsPerPixel = 8;
// this.bitsPerPixel = cm.getPixelSize();
@@ -143,11 +140,15 @@ public class GifImage extends AbstractFopImage {
this.isTransparent = false;
}
} catch (Exception ex) {
log.error("Error while loading image "
+ "" + " : "
+ ex.getClass() + " - "
+ ex.getMessage(), ex);
log.error("Error while loading image (Gif): " + ex.getMessage(), ex);
return false;
} finally {
try {
inputStream.close();
} catch (java.io.IOException ioe) {
// Ignore
}
inputStream = null;
}

// Should take care of the ColorSpace and bitsPerPixel
@@ -159,12 +160,9 @@ public class GifImage extends AbstractFopImage {
int r = (p >> 16) & 0xFF;
int g = (p >> 8) & 0xFF;
int b = (p) & 0xFF;
this.bitmaps[3 * (i * this.width + j)] =
(byte)(r & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 1] =
(byte)(g & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 2] =
(byte)(b & 0xFF);
this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF);
}
}
return true;
@@ -181,18 +179,30 @@ public class GifImage extends AbstractFopImage {
inputStream = is;
}

/**
* @see java.net.URLConnection#getInputStream()
*/
public InputStream getInputStream() throws IOException {
return inputStream;
}

/**
* @see java.net.URLConnection#connect()
*/
public void connect() throws IOException {
// do nothing
}

/**
* @see java.net.URLConnection#getContentType()
*/
public String getContentType() {
return "image/gif";
}

/**
* @see java.net.URLConnection#getContentLength()
*/
public int getContentLength() {
try {
return inputStream.available();

+ 2
- 1
src/java/org/apache/fop/image/ImageFactory.java Parādīt failu

@@ -63,7 +63,7 @@ public final class ImageFactory {
ImageProvider jaiImage = new ImageProvider("JAIImage", "org.apache.fop.image.JAIImage");
ImageProvider jimiImage = new ImageProvider("JIMIImage", "org.apache.fop.image.JimiImage");
ImageProvider imageIoImage = new ImageProvider(
"ImageIOImage", "org.apache.fop.image.ImageIoImage");
"ImageIOImage", "org.apache.fop.image.ImageIOImage");
ImageProvider gifImage = new ImageProvider("GIFImage", "org.apache.fop.image.GifImage");
ImageProvider jpegImage = new ImageProvider("JPEGImage", "org.apache.fop.image.JpegImage");
ImageProvider bmpImage = new ImageProvider("BMPImage", "org.apache.fop.image.BmpImage");
@@ -104,6 +104,7 @@ public final class ImageFactory {
imt = new ImageMimeType("image/tiff");
imageMimeTypes.put(imt.getMimeType(), imt);
imt.addProvider(tiffImage);
imt.addProvider(jaiImage);

imt = new ImageMimeType("image/svg+xml");
imageMimeTypes.put(imt.getMimeType(), imt);

+ 47
- 22
src/java/org/apache/fop/image/JAIImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,26 +39,43 @@ import com.sun.media.jai.codec.FileCacheSeekableStream;
*/
public class JAIImage extends AbstractFopImage {

public JAIImage(FopImage.ImageInfo imgReader) {
super(imgReader);
/**
* Create a new JAI image.
*
* @param imgInfo the image info for this JAI image
*/
public JAIImage(FopImage.ImageInfo imgInfo) {
super(imgInfo);
}

/**
* @see org.apache.fop.image.AbstractFopImage#loadDimensions()
*/
protected boolean loadDimensions() {
if (this.bitmaps == null) {
loadImage();
}
return this.bitmaps != null;
}
/**
* Loads the image from the inputstream
*/
protected void loadImage() {
com.sun.media.jai.codec.FileCacheSeekableStream seekableInput = null;
try {
com.sun.media.jai.codec.FileCacheSeekableStream seekableInput =
new FileCacheSeekableStream(inputStream);
seekableInput = new FileCacheSeekableStream(inputStream);
RenderedOp imageOp = JAI.create("stream", seekableInput);
inputStream.close();
inputStream = null;

this.height = imageOp.getHeight();
this.width = imageOp.getWidth();

ColorModel cm = imageOp.getColorModel();
this.bitsPerPixel = 8;
// this.bitsPerPixel = cm.getPixelSize();
this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);

//this.bitsPerPixel = 8;
this.bitsPerPixel = cm.getPixelSize();
//this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
this.colorSpace = cm.getColorSpace();
BufferedImage imageData = imageOp.getAsBufferedImage();
int[] tmpMap = imageData.getRGB(0, 0, this.width,
this.height, null, 0, this.width);
@@ -128,21 +145,29 @@ public class JAIImage extends AbstractFopImage {
int r = (p >> 16) & 0xFF;
int g = (p >> 8) & 0xFF;
int b = (p) & 0xFF;
this.bitmaps[3 * (i * this.width + j)] =
(byte)(r & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 1] =
(byte)(g & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 2] =
(byte)(b & 0xFF);
this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF);
}
}

} catch (Exception ex) {
/*throw new FopImageException("Error while loading image "
+ "" + " : "
+ ex.getClass() + " - "
+ ex.getMessage());
*/}
log.error("Error while loading image (JAI): " + ex.getMessage(), ex);
} finally {
try {
inputStream.close();
} catch (java.io.IOException ioe) {
// Ignore
}
inputStream = null;
if (seekableInput != null) {
try {
seekableInput.close();
} catch (java.io.IOException ioe) {
// Ignore
}
}
}
}

}

+ 25
- 19
src/java/org/apache/fop/image/JimiImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,15 +37,18 @@ import com.sun.jimi.core.Jimi;
*/
public class JimiImage extends AbstractFopImage {

public JimiImage(FopImage.ImageInfo imgReader) {
super(imgReader);
try {
Class c = Class.forName("com.sun.jimi.core.Jimi");
} catch (ClassNotFoundException e) {
//throw new FopImageException("Jimi image library not available");
}
/**
* Create a new Jimi image.
*
* @param imgInfo the image info for this Jimi image
*/
public JimiImage(FopImage.ImageInfo imgInfo) {
super(imgInfo);
}

/**
* @see org.apache.fop.image.AbstractFopImage#loadDimensions()
*/
protected boolean loadDimensions() {
if (this.bitmaps == null) {
loadImage();
@@ -65,6 +68,9 @@ public class JimiImage extends AbstractFopImage {
return this.bitmaps != null;
}

/**
* Loads the image from the inputstream
*/
protected void loadImage() {
int[] tmpMap = null;
try {
@@ -80,9 +86,6 @@ public class JimiImage extends AbstractFopImage {
this.height = consumer.getHeight();
this.width = consumer.getWidth();

inputStream.close();
inputStream = null;

try {
tmpMap = consumer.getImage();
} catch (Exception ex) {
@@ -149,9 +152,15 @@ public class JimiImage extends AbstractFopImage {
this.isTransparent = false;
}
} catch (Throwable ex) {
log.error("Error while loading image "
+ "", ex);
log.error("Error while loading image (Jimi): " + ex.getMessage(), ex);
return;
} finally {
try {
inputStream.close();
} catch (java.io.IOException ioe) {
// Ignore
}
inputStream = null;
}


@@ -164,12 +173,9 @@ public class JimiImage extends AbstractFopImage {
int r = (p >> 16) & 0xFF;
int g = (p >> 8) & 0xFF;
int b = (p) & 0xFF;
this.bitmaps[3 * (i * this.width + j)] =
(byte)(r & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 1] =
(byte)(g & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 2] =
(byte)(b & 0xFF);
this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF);
this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF);
}
}
}

+ 11
- 10
src/java/org/apache/fop/image/JpegImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,13 +65,16 @@ public class JpegImage extends AbstractFopImage {
while ((bytesRead = inputStream.read(readBuf)) != -1) {
baos.write(readBuf, 0, bytesRead);
}
inputStream.close();
inputStream = null;
} catch (java.io.IOException ex) {
log.error("Error while loading image "
+ " : " + ex.getClass()
+ " - " + ex.getMessage(), ex);
log.error("Error while loading image (Jpeg): " + ex.getMessage(), ex);
return false;
} finally {
try {
inputStream.close();
} catch (java.io.IOException ioe) {
// Ignore
}
inputStream = null;
}

this.bitmaps = baos.toByteArray();
@@ -163,10 +166,8 @@ public class JpegImage extends AbstractFopImage {
byte[] align = new byte[((iccStream.size()) % 8) + 8];
try {
iccStream.write(align);
} catch (Exception e) {
log.error("Error while loading image "
+ " : "
+ e.getMessage(), e);
} catch (Exception ex) {
log.error("Error while aligning ICC stream: " + ex.getMessage(), ex);
return false;
}
try {

+ 1
- 1
src/java/org/apache/fop/image/PNGImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 2004 The Apache Software Foundation
* Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

+ 90
- 2
src/java/org/apache/fop/image/TIFFImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 2004 The Apache Software Foundation
* Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@

package org.apache.fop.image;

import java.awt.color.ColorSpace;
import java.io.IOException;

import org.apache.batik.ext.awt.image.codec.SeekableStream;
@@ -31,6 +32,11 @@ import org.apache.batik.ext.awt.image.rendered.CachableRed;
*/
public class TIFFImage extends BatikImage {

private int compression = 0;
private int stripCount = 0;
private long stripOffset = 0;
private long stripLength = 0;
/**
* Constructs a new BatikImage instance.
* @param imgReader basic metadata for the image
@@ -39,6 +45,22 @@ public class TIFFImage extends BatikImage {
super(imgReader);
}

/**
* The compression type set in the TIFF directory
* @return the TIFF compression type
*/
public int getCompression() {
return compression;
}

/**
* The number of strips in the image
* @return the number of strips in the image
*/
public int getStripCount() {
return stripCount;
}

/**
* @see org.apache.fop.image.BatikImage#decodeImage(org.apache.batik.ext.awt.image.codec.SeekableStream)
*/
@@ -67,7 +89,73 @@ public class TIFFImage extends BatikImage {
log.warn("Cannot determine bitmap resolution."
+ " Unimplemented resolution unit: " + resUnit);
}
fld = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION);
if (fld != null) {
compression = fld.getAsInt(0);
}
fld = dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE);
if (fld != null) {
bitsPerPixel = fld.getAsInt(0);
}
fld = dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP);
if (fld == null) {
stripCount = 1;
} else {
stripCount = (int)(dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH)
/ fld.getAsLong(0));
}
stripOffset = dir.getField(TIFFImageDecoder.TIFF_STRIP_OFFSETS).getAsLong(0);
stripLength = dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS).getAsLong(0);
if (this.bitsPerPixel == 1) {
this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
}
return img;
}

/**
* Load the original TIFF data.
* This loads only strip 1 of the original TIFF data.
*
* @return true if loaded false for any error
* @see org.apache.fop.image.AbstractFopImage#loadOriginalData()
*/
protected boolean loadOriginalData() {
if (loadDimensions()) {
byte[] readBuf = new byte[(int)stripLength];
int bytesRead;

try {
this.seekableInput.reset();
this.seekableInput.skip(stripOffset);
bytesRead = seekableInput.read(readBuf);
if (bytesRead != stripLength) {
log.error("Error while loading image: length mismatch on read");
return false;
}

this.bitmaps = readBuf;
return true;
} catch (IOException ioe) {
log.error("Error while loading image strip 1 (TIFF): ", ioe);
return false;
} finally {
try {
this.seekableInput.close();
} catch (IOException ioex) {
// ignore
}
try {
this.inputStream.close();
} catch (IOException ioex) {
// ignore
}
this.seekableInput = null;
this.inputStream = null;
this.cr = null;
}
}
return false;
}

}

+ 8
- 8
src/java/org/apache/fop/pdf/BitmapImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -195,13 +195,6 @@ public class BitmapImage implements PDFImage {
return false;
}

/**
* @see org.apache.fop.pdf.PDFImage#isDCT()
*/
public boolean isDCT() {
return false;
}

/**
* @see org.apache.fop.pdf.PDFImage#getFilterHint()
*/
@@ -209,6 +202,13 @@ public class BitmapImage implements PDFImage {
return PDFFilterList.IMAGE_FILTER;
}

/**
* @see org.apache.fop.pdf.PDFImage#getPDFFilter()
*/
public PDFFilter getPDFFilter() {
return null;
}
}



+ 55
- 0
src/java/org/apache/fop/pdf/CCFFilter.java Parādīt failu

@@ -0,0 +1,55 @@
/*
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */
package org.apache.fop.pdf;

/**
* CCF Filter class. Right now it is just used as a dummy filter flag so
* we can write TIFF images to the PDF. The encode method just returns the
* data passed to it. In the future an actual CCITT Group 4 compression should be
* added to the encode method so other images can be compressed.
*
*/
public class CCFFilter extends NullFilter {

private String decodeParms;

/**
* @see org.apache.fop.pdf.PDFFilter#getName()
*/
public String getName() {
return "/CCITTFaxDecode";
}

/**
* @see org.apache.fop.pdf.PDFFilter#getDecodeParms()
*/
public String getDecodeParms() {
return this.decodeParms;
}

/**
* Sets the CCF decoding parameters
* @param decodeParms The decoding parameters
*/
public void setDecodeParms(String decodeParms) {
this.decodeParms = decodeParms;
}

}


+ 21
- 14
src/java/org/apache/fop/pdf/PDFFilterList.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,6 +45,8 @@ public class PDFFilterList {
public static final String IMAGE_FILTER = "image";
/** Key for the filter used for JPEG images */
public static final String JPEG_FILTER = "jpeg";
/** Key for the filter used for TIFF images */
public static final String TIFF_FILTER = "tiff";
/** Key for the filter used for fonts */
public static final String FONT_FILTER = "font";

@@ -131,15 +133,16 @@ public class PDFFilterList {
}

/**
* Checks the filter list for the DCT filter and adds it in the correct
* Checks the filter list for the filter and adds it in the correct
* place if necessary.
* @param pdfFilter the filter to check / add
*/
public void ensureDCTFilterInPlace() {
public void ensureFilterInPlace(PDFFilter pdfFilter) {
if (this.filters.size() == 0) {
addFilter(new DCTFilter());
addFilter(pdfFilter);
} else {
if (!(this.filters.get(0) instanceof DCTFilter)) {
this.filters.add(0, new DCTFilter());
if (!(this.filters.get(0).equals(pdfFilter))) {
this.filters.add(0, pdfFilter);
}
}
}
@@ -186,7 +189,9 @@ public class PDFFilterList {
PDFFilter filter = (PDFFilter)filters.get(count);
// place the names in our local vector in reverse order
names.add(0, filter.getName());
parms.add(0, filter.getDecodeParms());
if (filter.getDecodeParms() != null) {
parms.add(0, filter.getDecodeParms());
}
}

// now build up the filter entries for the dictionary
@@ -197,20 +202,22 @@ public class PDFFilterList {
}

private String buildFilterEntries(List names) {
boolean needFilterEntry = false;
int filterCount = 0;
StringBuffer sb = new StringBuffer(64);
sb.append("/Filter [ ");
for (int i = 0; i < names.size(); i++) {
final String name = (String)names.get(i);
if (name.length() > 0) {
needFilterEntry = true;
filterCount++;
sb.append(name);
sb.append(" ");
}
}
if (needFilterEntry) {
sb.append("]");
return sb.toString();
if (filterCount > 0) {
if (filterCount > 1) {
return "/Filter [ " + sb.toString() + "]";
} else {
return "/Filter " + sb.toString();
}
} else {
return "";
}
@@ -219,7 +226,7 @@ public class PDFFilterList {
private String buildDecodeParms(List parms) {
StringBuffer sb = new StringBuffer();
boolean needParmsEntry = false;
sb.append("/DecodeParms ");
sb.append("\n/DecodeParms ");

if (parms.size() > 1) {
sb.append("[ ");

+ 8
- 8
src/java/org/apache/fop/pdf/PDFImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,13 +81,6 @@ public interface PDFImage {
*/
boolean isPS();

/**
* Check if this image is a DCT encoded image (for JPEG images).
*
* @return true if this is a DCT image
*/
boolean isDCT();

/**
* Check if this image has a transparent color transparency.
*
@@ -116,6 +109,13 @@ public interface PDFImage {
*/
String getSoftMask();

/**
* Get the PDF Filter to be applied to the image.
*
* @return the PDF Filter or null
*/
PDFFilter getPDFFilter();
// get the image bytes, and bytes properties

/**

+ 4
- 3
src/java/org/apache/fop/pdf/PDFXObject.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -174,8 +174,9 @@ public class PDFXObject extends AbstractPDFStream {
* @see org.apache.fop.pdf.AbstractPDFStream#prepareImplicitFilters()
*/
protected void prepareImplicitFilters() {
if (pdfimage.isDCT()) {
getFilterList().ensureDCTFilterInPlace();
PDFFilter pdfFilter = pdfimage.getPDFFilter();
if (pdfFilter != null) {
getFilterList().ensureFilterInPlace(pdfFilter);
}
}

+ 52
- 19
src/java/org/apache/fop/render/pdf/FopPDFImage.java Parādīt failu

@@ -1,5 +1,5 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
/* $Id$ */

package org.apache.fop.render.pdf;

import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFImage;
import org.apache.fop.pdf.PDFFilter;
@@ -32,11 +31,13 @@ import org.apache.fop.pdf.BitmapImage;
import org.apache.fop.image.FopImage;
import org.apache.fop.image.JpegImage;
import org.apache.fop.image.EPSImage;
import org.apache.fop.image.TIFFImage;

import java.io.IOException;
import java.io.OutputStream;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import org.apache.fop.pdf.CCFFilter;

/**
* PDFImage implementation for the PDF renderer.
@@ -49,6 +50,8 @@ public class FopPDFImage implements PDFImage {
private String maskRef;
private String softMaskRef;
private boolean isPS = false;
private boolean isCCF = false;
private boolean isDCT = false;
private String key;

/**
@@ -77,6 +80,7 @@ public class FopPDFImage implements PDFImage {
if ("image/jpeg".equals(fopImage.getMimeType())) {
pdfFilter = new DCTFilter();
pdfFilter.setApplied(true);
isDCT = true;

JpegImage jpegimage = (JpegImage) fopImage;
ICC_Profile prof = jpegimage.getICCProfile();
@@ -85,8 +89,35 @@ public class FopPDFImage implements PDFImage {
pdfICCStream = doc.getFactory().makePDFICCStream();
pdfICCStream.setColorSpace(prof, pdfCS);
}
} else if ("image/tiff".equals(fopImage.getMimeType())
&& fopImage instanceof TIFFImage) {
TIFFImage tiffImage = (TIFFImage) fopImage;
if (tiffImage.getStripCount() == 1) {
int comp = tiffImage.getCompression();
if (comp == 1) {
// Nothing to do
} else if (comp == 3) {
pdfFilter = new CCFFilter();
pdfFilter.setApplied(true);
isCCF = true;
} else if (comp == 4) {
pdfFilter = new CCFFilter();
pdfFilter.setApplied(true);
((CCFFilter)pdfFilter).setDecodeParms("<< /K -1 /Columns "
+ tiffImage.getWidth() + " >>");
isCCF = true;
} else if (comp == 6) {
pdfFilter = new DCTFilter();
pdfFilter.setApplied(true);
isDCT = true;
}
}
}
if (isPS || isDCT || isCCF) {
fopImage.load(FopImage.ORIGINAL_DATA);
} else {
fopImage.load(FopImage.BITMAP);
}

//Handle transparency mask if applicable
if (fopImage.hasSoftMask()) {
byte [] softMask = fopImage.getSoftMask();
@@ -102,20 +133,6 @@ public class FopPDFImage implements PDFImage {
}
}

/**
* @see org.apache.fop.pdf.PDFImage#isPS()
*/
public boolean isPS() {
return isPS;
}

/**
* @see org.apache.fop.pdf.PDFImage#isDCT()
*/
public boolean isDCT() {
return fopImage.getMimeType().equals("image/jpeg");
}

/**
* @see org.apache.fop.pdf.PDFImage#getWidth()
*/
@@ -175,6 +192,20 @@ public class FopPDFImage implements PDFImage {
return softMaskRef;
}

/**
* @see org.apache.fop.pdf.PDFImage#isPS()
*/
public boolean isPS() {
return isPS;
}

/**
* @see org.apache.fop.pdf.PDFImage#getPDFFilter()
*/
public PDFFilter getPDFFilter() {
return pdfFilter;
}
/**
* @see org.apache.fop.pdf.PDFImage#outputContents(OutputStream)
*/
@@ -268,10 +299,12 @@ public class FopPDFImage implements PDFImage {
* @see org.apache.fop.pdf.PDFImage#getFilterHint()
*/
public String getFilterHint() {
if (isPS()) {
if (isPS) {
return PDFFilterList.CONTENT_FILTER;
} else if (fopImage.getMimeType().equals("image/jpeg")) {
} else if (isDCT) {
return PDFFilterList.JPEG_FILTER;
} else if (isCCF) {
return PDFFilterList.TIFF_FILTER;
} else {
return PDFFilterList.IMAGE_FILTER;
}

+ 11
- 15
src/java/org/apache/fop/render/pdf/PDFRenderer.java Parādīt failu

@@ -14,7 +14,7 @@
* limitations under the License.
*/

/* $Id: PDFRenderer.java,v 1.38 2004/04/07 14:24:17 cbowditch Exp $ */
/* $Id$ */

package org.apache.fop.render.pdf;

@@ -161,6 +161,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
*/
protected PDFPage currentPage;
/** The current Transform */
protected AffineTransform currentBasicTransform;

/** drawing state */
@@ -615,9 +616,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
setColor(uppercol, false, null);
currentStream.add(x1 + " " + ym1 + " m " + x2 + " " + ym1 + " l S\n");
setColor(c, false, null);
currentStream.add(x1 + " " + (ym1 + h3) + " m " + x2 + " " + (ym1 + h3) + " l S\n");
currentStream.add(x1 + " " + (ym1 + h3) + " m "
+ x2 + " " + (ym1 + h3) + " l S\n");
setColor(lowercol, false, null);
currentStream.add(x1 + " " + (ym1 + h3 + h3) + " m " + x2 + " " + (ym1 + h3 + h3) + " l S\n");
currentStream.add(x1 + " " + (ym1 + h3 + h3) + " m "
+ x2 + " " + (ym1 + h3 + h3) + " l S\n");
} else {
Color leftcol = lightenColor(c, -colFactor);
Color rightcol = lightenColor(c, colFactor);
@@ -627,9 +630,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
setColor(leftcol, false, null);
currentStream.add(xm1 + " " + y1 + " m " + xm1 + " " + y2 + " l S\n");
setColor(c, false, null);
currentStream.add((xm1 + w3) + " " + y1 + " m " + (xm1 + w3) + " " + y2 + " l S\n");
currentStream.add((xm1 + w3) + " " + y1 + " m "
+ (xm1 + w3) + " " + y2 + " l S\n");
setColor(rightcol, false, null);
currentStream.add((xm1 + w3 + w3) + " " + y1 + " m " + (xm1 + w3 + w3) + " " + y2 + " l S\n");
currentStream.add((xm1 + w3 + w3) + " " + y1 + " m "
+ (xm1 + w3 + w3) + " " + y2 + " l S\n");
}
break;
}
@@ -1398,16 +1403,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {

renderDocument(doc, ns, pos);
} else if ("image/eps".equals(mime)) {
if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
return;
}
FopPDFImage pdfimage = new FopPDFImage(fopimage, url);
int xobj = pdfDoc.addImage(currentContext, pdfimage).getXNumber();
fact.releaseImage(url, userAgent);
} else if ("image/jpeg".equals(mime)) {
if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
return;
}
} else if ("image/jpeg".equals(mime) || "image/tiff".equals(mime)) {
FopPDFImage pdfimage = new FopPDFImage(fopimage, url);
int xobj = pdfDoc.addImage(currentContext, pdfimage).getXNumber();
fact.releaseImage(url, userAgent);
@@ -1417,9 +1416,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
placeImage((float) pos.getX() / 1000,
(float) pos.getY() / 1000, w, h, xobj);
} else {
if (!fopimage.load(FopImage.BITMAP)) {
return;
}
FopPDFImage pdfimage = new FopPDFImage(fopimage, url);
int xobj = pdfDoc.addImage(currentContext, pdfimage).getXNumber();
fact.releaseImage(url, userAgent);

+ 9
- 1
test/layoutengine/testcases/external-graphic-tiff.xml Parādīt failu

@@ -24,7 +24,7 @@
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:simple-page-master master-name="normal" page-width="8in" page-height="8in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
@@ -38,6 +38,10 @@
<fo:block>
<fo:external-graphic src="../../resources/images/bgimg72dpi.tif"/>EOG
</fo:block>
<fo:block>TIFF external-graphic (CCITT group 4 encoding)</fo:block>
<fo:block>
<fo:external-graphic src="../../resources/images/tiff_group4.tif"/>EOG
</fo:block>
<fo:block>EOF</fo:block>
</fo:flow>
</fo:page-sequence>
@@ -52,5 +56,9 @@
<eval expected="192000" xpath="//flow/block[4]/lineArea/viewport/@ipda"/>
<eval expected="192000" xpath="//flow/block[4]/lineArea/viewport/@bpd"/>
<eval expected="192000" xpath="//flow/block[4]/lineArea/viewport/@bpda"/>
<eval expected="550588" xpath="//flow/block[6]/lineArea/viewport/@ipd"/>
<eval expected="550588" xpath="//flow/block[6]/lineArea/viewport/@ipda"/>
<eval expected="66705" xpath="//flow/block[6]/lineArea/viewport/@bpd"/>
<eval expected="66705" xpath="//flow/block[6]/lineArea/viewport/@bpda"/>
</checks>
</testcase>

Binārs
test/resources/images/tiff_group4.tif Parādīt failu


Notiek ielāde…
Atcelt
Saglabāt