001: /**
002: * Copyright (c) 2005, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package org.pdfbox.pdmodel.graphics.predictor;
031:
032: import java.util.Random;
033:
034: /**
035: * Implements different PNG predictor algorithms that is used in PDF files.
036: *
037: * @author xylifyx@yahoo.co.uk
038: * @version $Revision: 1.3 $
039: * @see <a href="http://www.w3.org/TR/PNG-Filters.html">PNG Filters</a>
040: */
041: public abstract class PredictorAlgorithm {
042: private int width;
043:
044: private int height;
045:
046: private int bpp;
047:
048: /**
049: * check that buffer sizes matches width,height,bpp. This implementation is
050: * used by most of the filters, but not Uptimum.
051: *
052: * @param src The source buffer.
053: * @param dest The destination buffer.
054: */
055: public void checkBufsiz(byte[] src, byte[] dest) {
056: if (src.length != dest.length) {
057: throw new IllegalArgumentException(
058: "src.length != dest.length");
059: }
060: if (src.length != getWidth() * getHeight() * getBpp()) {
061: throw new IllegalArgumentException(
062: "src.length != width * height * bpp");
063: }
064: }
065:
066: /**
067: * encode line of pixel data in src from srcOffset and width*bpp bytes
068: * forward, put the decoded bytes into dest.
069: *
070: * @param src
071: * raw image data
072: * @param dest
073: * encoded data
074: * @param srcDy
075: * byte offset between lines
076: * @param srcOffset
077: * beginning of line data
078: * @param destDy
079: * byte offset between lines
080: * @param destOffset
081: * beginning of line data
082: */
083: public abstract void encodeLine(byte[] src, byte[] dest, int srcDy,
084: int srcOffset, int destDy, int destOffset);
085:
086: /**
087: * decode line of pixel data in src from src_offset and width*bpp bytes
088: * forward, put the decoded bytes into dest.
089: *
090: * @param src
091: * encoded image data
092: * @param dest
093: * raw data
094: * @param srcDy
095: * byte offset between lines
096: * @param srcOffset
097: * beginning of line data
098: * @param destDy
099: * byte offset between lines
100: * @param destOffset
101: * beginning of line data
102: */
103: public abstract void decodeLine(byte[] src, byte[] dest, int srcDy,
104: int srcOffset, int destDy, int destOffset);
105:
106: /**
107: * Simple command line program to test the algorithm.
108: *
109: * @param args The command line arguments.
110: */
111: public static void main(String[] args) {
112: Random rnd = new Random();
113: int width = 5;
114: int height = 5;
115: int bpp = 3;
116: byte[] raw = new byte[width * height * bpp];
117: rnd.nextBytes(raw);
118: System.out.println("raw: ");
119: dump(raw);
120: for (int i = 10; i < 15; i++) {
121: byte[] decoded = new byte[width * height * bpp];
122: byte[] encoded = new byte[width * height * bpp];
123:
124: PredictorAlgorithm filter = PredictorAlgorithm.getFilter(i);
125: filter.setWidth(width);
126: filter.setHeight(height);
127: filter.setBpp(bpp);
128: filter.encode(raw, encoded);
129: filter.decode(encoded, decoded);
130: System.out.println(filter.getClass().getName());
131: dump(decoded);
132: }
133: }
134:
135: /**
136: * Get the left pixel from the buffer.
137: *
138: * @param buf The buffer.
139: * @param offset The offset into the buffer.
140: * @param dy The dy value.
141: * @param x The x value.
142: *
143: * @return The left pixel.
144: */
145: public int leftPixel(byte[] buf, int offset, int dy, int x) {
146: return x >= getBpp() ? buf[offset + x - getBpp()] : 0;
147: }
148:
149: /**
150: * Get the above pixel from the buffer.
151: *
152: * @param buf The buffer.
153: * @param offset The offset into the buffer.
154: * @param dy The dy value.
155: * @param x The x value.
156: *
157: * @return The above pixel.
158: */
159: public int abovePixel(byte[] buf, int offset, int dy, int x) {
160: return offset >= dy ? buf[offset + x - dy] : 0;
161: }
162:
163: /**
164: * Get the above-left pixel from the buffer.
165: *
166: * @param buf The buffer.
167: * @param offset The offset into the buffer.
168: * @param dy The dy value.
169: * @param x The x value.
170: *
171: * @return The above-left pixel.
172: */
173: public int aboveLeftPixel(byte[] buf, int offset, int dy, int x) {
174: return offset >= dy && x >= getBpp() ? buf[offset + x - dy
175: - getBpp()] : 0;
176: }
177:
178: /**
179: * Simple helper to print out a buffer.
180: *
181: * @param raw The bytes to print out.
182: */
183: private static void dump(byte[] raw) {
184: for (int i = 0; i < raw.length; i++) {
185: System.out.print(raw[i] + " ");
186: }
187: System.out.println();
188: }
189:
190: /**
191: * @return Returns the bpp.
192: */
193: public int getBpp() {
194: return bpp;
195: }
196:
197: /**
198: * @param newBpp
199: * The bpp to set.
200: */
201: public void setBpp(int newBpp) {
202: bpp = newBpp;
203: }
204:
205: /**
206: * @return Returns the height.
207: */
208: public int getHeight() {
209: return height;
210: }
211:
212: /**
213: * @param newHeight
214: * The height to set.
215: */
216: public void setHeight(int newHeight) {
217: height = newHeight;
218: }
219:
220: /**
221: * @return Returns the width.
222: */
223: public int getWidth() {
224: return width;
225: }
226:
227: /**
228: * @param newWidth
229: * The width to set.
230: */
231: public void setWidth(int newWidth) {
232: this .width = newWidth;
233: }
234:
235: /**
236: * encode a byte array full of image data using the filter that this object
237: * implements.
238: *
239: * @param src
240: * buffer
241: * @param dest
242: * buffer
243: */
244: public void encode(byte[] src, byte[] dest) {
245: checkBufsiz(dest, src);
246: int dy = getWidth() * getBpp();
247: for (int y = 0; y < height; y++) {
248: int yoffset = y * dy;
249: encodeLine(src, dest, dy, yoffset, dy, yoffset);
250: }
251: }
252:
253: /**
254: * decode a byte array full of image data using the filter that this object
255: * implements.
256: *
257: * @param src
258: * buffer
259: * @param dest
260: * buffer
261: */
262: public void decode(byte[] src, byte[] dest) {
263: checkBufsiz(src, dest);
264: int dy = width * bpp;
265: for (int y = 0; y < height; y++) {
266: int yoffset = y * dy;
267: decodeLine(src, dest, dy, yoffset, dy, yoffset);
268: }
269: }
270:
271: /**
272: * @param predictor
273: * <ul>
274: * <li>1 No prediction (the default value)
275: * <li>2 TIFF Predictor 2
276: * <li>10 PNG prediction (on encoding, PNG None on all rows)
277: * <li>11 PNG prediction (on encoding, PNG Sub on all rows)
278: * <li>12 PNG prediction (on encoding, PNG Up on all rows)
279: * <li>13 PNG prediction (on encoding, PNG Average on all rows)
280: * <li>14 PNG prediction (on encoding, PNG Paeth on all rows)
281: * <li>15 PNG prediction (on encoding, PNG optimum)
282: * </ul>
283: *
284: * @return The predictor class based on the predictor code.
285: */
286: public static PredictorAlgorithm getFilter(int predictor) {
287: PredictorAlgorithm filter;
288: switch (predictor) {
289: case 10:
290: filter = new None();
291: break;
292: case 11:
293: filter = new Sub();
294: break;
295: case 12:
296: filter = new Up();
297: break;
298: case 13:
299: filter = new Average();
300: break;
301: case 14:
302: filter = new Paeth();
303: break;
304: case 15:
305: filter = new Uptimum();
306: break;
307: default:
308: filter = new None();
309: }
310: return filter;
311: }
312: }
|