0N/A/*
2362N/A * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.imageio.plugins.png;
0N/A
0N/Apublic class RowFilter {
0N/A
0N/A private static final int abs(int x) {
0N/A return (x < 0) ? -x : x;
0N/A }
0N/A
0N/A // Returns the sum of absolute differences
0N/A protected static int subFilter(byte[] currRow,
0N/A byte[] subFilteredRow,
0N/A int bytesPerPixel,
0N/A int bytesPerRow) {
0N/A int badness = 0;
0N/A for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
0N/A int curr = currRow[i] & 0xff;
0N/A int left = currRow[i - bytesPerPixel] & 0xff;
0N/A int difference = curr - left;
0N/A subFilteredRow[i] = (byte)difference;
0N/A
0N/A badness += abs(difference);
0N/A }
0N/A
0N/A return badness;
0N/A }
0N/A
0N/A // Returns the sum of absolute differences
0N/A protected static int upFilter(byte[] currRow,
0N/A byte[] prevRow,
0N/A byte[] upFilteredRow,
0N/A int bytesPerPixel,
0N/A int bytesPerRow) {
0N/A int badness = 0;
0N/A for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
0N/A int curr = currRow[i] & 0xff;
0N/A int up = prevRow[i] & 0xff;
0N/A int difference = curr - up;
0N/A upFilteredRow[i] = (byte)difference;
0N/A
0N/A badness += abs(difference);
0N/A }
0N/A
0N/A return badness;
0N/A }
0N/A
0N/A protected final int paethPredictor(int a, int b, int c) {
0N/A int p = a + b - c;
0N/A int pa = abs(p - a);
0N/A int pb = abs(p - b);
0N/A int pc = abs(p - c);
0N/A
0N/A if ((pa <= pb) && (pa <= pc)) {
0N/A return a;
0N/A } else if (pb <= pc) {
0N/A return b;
0N/A } else {
0N/A return c;
0N/A }
0N/A }
0N/A
0N/A public int filterRow(int colorType,
0N/A byte[] currRow,
0N/A byte[] prevRow,
0N/A byte[][] scratchRows,
0N/A int bytesPerRow,
0N/A int bytesPerPixel) {
0N/A
0N/A // Use type 0 for palette images
0N/A if (colorType != PNGImageReader.PNG_COLOR_PALETTE) {
0N/A System.arraycopy(currRow, bytesPerPixel,
0N/A scratchRows[0], bytesPerPixel,
0N/A bytesPerRow);
0N/A return 0;
0N/A }
0N/A
0N/A int[] filterBadness = new int[5];
0N/A for (int i = 0; i < 5; i++) {
0N/A filterBadness[i] = Integer.MAX_VALUE;
0N/A }
0N/A
0N/A {
0N/A int badness = 0;
0N/A
0N/A for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
0N/A int curr = currRow[i] & 0xff;
0N/A badness += curr;
0N/A }
0N/A
0N/A filterBadness[0] = badness;
0N/A }
0N/A
0N/A {
0N/A byte[] subFilteredRow = scratchRows[1];
0N/A int badness = subFilter(currRow,
0N/A subFilteredRow,
0N/A bytesPerPixel,
0N/A bytesPerRow);
0N/A
0N/A filterBadness[1] = badness;
0N/A }
0N/A
0N/A {
0N/A byte[] upFilteredRow = scratchRows[2];
0N/A int badness = upFilter(currRow,
0N/A prevRow,
0N/A upFilteredRow,
0N/A bytesPerPixel,
0N/A bytesPerRow);
0N/A
0N/A filterBadness[2] = badness;
0N/A }
0N/A
0N/A {
0N/A byte[] averageFilteredRow = scratchRows[3];
0N/A int badness = 0;
0N/A
0N/A for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
0N/A int curr = currRow[i] & 0xff;
0N/A int left = currRow[i - bytesPerPixel] & 0xff;
0N/A int up = prevRow[i] & 0xff;
0N/A int difference = curr - (left + up)/2;;
0N/A averageFilteredRow[i] = (byte)difference;
0N/A
0N/A badness += abs(difference);
0N/A }
0N/A
0N/A filterBadness[3] = badness;
0N/A }
0N/A
0N/A {
0N/A byte[] paethFilteredRow = scratchRows[4];
0N/A int badness = 0;
0N/A
0N/A for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
0N/A int curr = currRow[i] & 0xff;
0N/A int left = currRow[i - bytesPerPixel] & 0xff;
0N/A int up = prevRow[i] & 0xff;
0N/A int upleft = prevRow[i - bytesPerPixel] & 0xff;
0N/A int predictor = paethPredictor(left, up, upleft);
0N/A int difference = curr - predictor;
0N/A paethFilteredRow[i] = (byte)difference;
0N/A
0N/A badness += abs(difference);
0N/A }
0N/A
0N/A filterBadness[4] = badness;
0N/A }
0N/A
0N/A int minBadness = filterBadness[0];
0N/A int filterType = 0;
0N/A
0N/A for (int i = 1; i < 5; i++) {
0N/A if (filterBadness[i] < minBadness) {
0N/A minBadness = filterBadness[i];
0N/A filterType = i;
0N/A }
0N/A }
0N/A
0N/A if (filterType == 0) {
0N/A System.arraycopy(currRow, bytesPerPixel,
0N/A scratchRows[0], bytesPerPixel,
0N/A bytesPerRow);
0N/A }
0N/A
0N/A return filterType;
0N/A }
0N/A}