| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| package org.apache.pdfbox.jbig2.image; |
| |
| import java.awt.image.WritableRaster; |
| |
| import org.apache.pdfbox.jbig2.Bitmap; |
| |
| final class BitmapScanline extends Scanline { |
| |
| private Bitmap bitmap; |
| private WritableRaster raster; |
| |
| private int[] lineBuffer; |
| |
| public BitmapScanline(final Bitmap src, final WritableRaster dst, final int width) { |
| super(width); |
| this.bitmap = src; |
| this.raster = dst; |
| lineBuffer = new int[length]; |
| } |
| |
| @Override |
| protected void clear() { |
| lineBuffer = new int[length]; |
| } |
| |
| @Override |
| protected void fetch(int x, final int y) { |
| lineBuffer = new int[length]; // really required? |
| int srcByteIdx = bitmap.getByteIndex(x, y); |
| while (x < length) { |
| final byte srcByte = (byte) ~bitmap.getByte(srcByteIdx++); |
| final int bits = bitmap.getWidth() - x > 8 ? 8 : bitmap.getWidth() - x; |
| for (int bitPosition = bits - 1; bitPosition >= 0; bitPosition--, x++) { |
| if (((srcByte >> bitPosition) & 0x1) != 0) |
| lineBuffer[x] = 255; |
| } |
| } |
| } |
| |
| @Override |
| protected void filter(final int[] preShift, final int[] postShift, final Weighttab[] tabs, final Scanline dst) { |
| final BitmapScanline dstBitmapScanline = (BitmapScanline) dst; |
| final int dstLength = dst.length; |
| |
| // start sum at 1 << shift - 1 for rounding |
| final int start = 1 << postShift[0] - 1; |
| final int srcBuffer[] = lineBuffer; |
| final int dstBuffer[] = dstBitmapScanline.lineBuffer; |
| |
| // the next two blocks are duplicated except for the missing shift operation if preShift == 0. |
| final int preShift0 = preShift[0]; |
| final int postShift0 = postShift[0]; |
| if (preShift0 != 0) { |
| for (int dstIndex = 0, tab = 0; tab < dstLength; tab++) { |
| final Weighttab weightTab = tabs[tab]; |
| final int weights = weightTab.weights.length; |
| |
| int sum = start; |
| for (int weightIndex = 0, srcIndex = weightTab.i0; weightIndex < weights && srcIndex < srcBuffer.length; weightIndex++) { |
| sum += weightTab.weights[weightIndex] * (srcBuffer[srcIndex++] >> preShift0); |
| } |
| |
| final int t = sum >> postShift0; |
| dstBuffer[dstIndex++] = t < 0 ? 0 : t > 255 ? 255 : t; |
| } |
| } else { |
| for (int dstIndex = 0, tab = 0; tab < dstLength; tab++) { |
| final Weighttab weightTab = tabs[tab]; |
| final int weights = weightTab.weights.length; |
| |
| int sum = start; |
| for (int weightIndex = 0, srcIndex = weightTab.i0; weightIndex < weights && srcIndex < srcBuffer.length; weightIndex++) { |
| sum += weightTab.weights[weightIndex] * srcBuffer[srcIndex++]; |
| } |
| |
| dstBuffer[dstIndex++] = sum >> postShift0; |
| } |
| } |
| } |
| |
| @Override |
| protected void accumulate(final int weight, final Scanline dst) { |
| final BitmapScanline dstBitmapScanline = (BitmapScanline) dst; |
| |
| final int srcBuffer[] = lineBuffer; |
| final int dstBuffer[] = dstBitmapScanline.lineBuffer; |
| |
| for (int b = 0; b < dstBuffer.length; b++) |
| dstBuffer[b] += weight * srcBuffer[b]; |
| } |
| |
| @Override |
| protected void shift(final int[] shift) { |
| final int shift0 = shift[0]; |
| final int half = 1 << shift0 - 1; |
| |
| final int srcBuffer[] = lineBuffer; |
| |
| for (int b = 0; b < srcBuffer.length; b++) { |
| final int pixel = srcBuffer[b] + half >> shift0; |
| srcBuffer[b] = pixel < 0 ? 0 : pixel > 255 ? 255 : pixel; |
| } |
| } |
| |
| @Override |
| protected void store(final int x, final int y) { |
| raster.setSamples(x, y, length, 1, 0, lineBuffer); |
| } |
| |
| } |