1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.formats.png.scanlinefilters;
18
19 import java.io.IOException;
20
21 import org.apache.commons.imaging.ImageReadException;
22
23 public class ScanlineFilterPaeth implements ScanlineFilter {
24 private final int bytesPerPixel;
25
26 public ScanlineFilterPaeth(final int bytesPerPixel) {
27 this.bytesPerPixel = bytesPerPixel;
28 }
29
30 private int paethPredictor(final int a, final int b, final int c) {
31
32 final int p = a + b - c;
33 final int pa = Math.abs(p - a);
34 final int pb = Math.abs(p - b);
35 final int pc = Math.abs(p - c);
36
37
38 if ((pa <= pb) && (pa <= pc)) {
39 return a;
40 }
41 if (pb <= pc) {
42 return b;
43 }
44 return c;
45 }
46
47 @Override
48 public void unfilter(final byte[] src, final byte[] dst, final byte[] up)
49 throws ImageReadException, IOException {
50 for (int i = 0; i < src.length; i++) {
51 int left = 0;
52 final int prevIndex = i - bytesPerPixel;
53 if (prevIndex >= 0) {
54 left = dst[prevIndex];
55 }
56
57 int above = 0;
58 if (up != null) {
59 above = up[i];
60 }
61
62
63 int upperLeft = 0;
64 if ((prevIndex >= 0) && (up != null)) {
65 upperLeft = up[prevIndex];
66 }
67
68
69 final int paethPredictor = paethPredictor(0xff & left, 0xff & above, 0xff & upperLeft);
70
71 dst[i] = (byte) ((src[i] + paethPredictor) % 256);
72
73
74
75
76 }
77 }
78 }