/* * 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. */ /* $Id$ */ package com.tom_roush.pdfbox.filter.ccitt; import com.tom_roush.pdfbox.io.IOUtils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * Tests the CCITT Fax G3 1D decoder. */ public class TestCCITTFaxG31DDecodeInputStream extends AbstractCCITTFaxTestCase { private static final boolean DEBUG = false; private static final String EOL = "000000000001"; private static final String RTC = EOL + EOL + EOL + EOL + EOL + EOL; /** * Tests the decoder with naked bits (no EOL, no alignment, nothing). * @throws IOException if an I/O error occurs */ public void testDecoderNaked() throws IOException { //Test data: 24x3 pixels encoded byte[] data = fromBinary("10011" + "000101" + "10011" + "00110101" + "011" + "10011" + "0000111" + "00110101" + "010" + "000111" + "010" + "0010111" + "000000"); assertStandardDecodingResult(data); } /** * Tests the decoder with EOLs. * @throws IOException if an I/O error occurs */ public void testDecoderWithEOL() throws IOException { //Test data: 24x3 pixels encoded byte[] data = fromBinary("10011" + "000101" + "10011" + EOL + "00110101" + "011" + "10011" + "0000111" + EOL + "00110101" + "010" + "000111" + "010" + "0010111" + "000000" + EOL); assertStandardDecodingResult(data); } /** * Tests the decoder with RTC and byte alignment. * @throws IOException if an I/O error occurs */ public void testDecoderAlignedWithRTC() throws IOException { //Test data: 24x3 pixels encoded byte[] data = fromBinary("1001100010110011" + EOL + "00110101011100110000111" + "0" + EOL + "001101010100001110100010111000000" + "00000" + RTC); assertStandardDecodingResult(data); } /** * Tests the decoder with an initial EOL. * @throws IOException if an I/O error occurs */ public void testDecoderInitialEOL() throws IOException { //Test data: 24x3 pixels encoded byte[] data = fromBinary("000" + EOL + "1001100010110011" + EOL + "00110101011100110000111" + EOL + "001101010100001110100010111000000"); assertStandardDecodingResult(data); } private void assertStandardDecodingResult(byte[] data) throws IOException { int columns = 24; byte[] decoded = decode(data, columns); if (DEBUG) { dumpBitmap(decoded, columns); System.out.println(PackedBitArray.toBitString(decoded)); } assertEquals(9, decoded.length); assertEquals("000000001111111100000000" + "111100000000111111111111" + "101000000000000000000000", toBitString(decoded)); } /** * Tests the decoder with a restriction in the number of rows. * @throws IOException if an I/O error occurs */ public void testDecoderRowsRestriction() throws IOException { //Test data: 24x3 pixels encoded byte[] data = fromBinary("10011" + "000101" + "10011" + "00110101" + "011" + "10011" + "0000111" + "00110101" + "010" + "000111" + "010" + "0010111" + "000000"); int columns = 24; int rows = 2; //We actually have data for three rows. Just checking the restriction. CCITTFaxG31DDecodeInputStream decoder = new CCITTFaxG31DDecodeInputStream( new ByteArrayInputStream(data), columns, rows, false); byte[] decoded = IOUtils.toByteArray(decoder); decoder.close(); if (DEBUG) { dumpBitmap(decoded, columns); System.out.println(PackedBitArray.toBitString(decoded)); } assertEquals(6, decoded.length); assertEquals("000000001111111100000000" + "111100000000111111111111", toBitString(decoded)); } /** * Tests the decoder with white lines. * @throws IOException if an I/O error occurs */ public void testDecoderWhiteLines() throws IOException { //Test data: 1728x3 pixels encoded (all white) byte[] data = fromBinary(EOL + "010011011" + "00110101" //EOL + w1728 (make-up) + w0 + EOL + "010011011" + "00110101" + EOL + "010011011" + "00110101" + RTC); int columns = 1728; byte[] decoded = decode(data, columns); if (DEBUG) { dumpBitmap(decoded, columns); } assertEquals(columns * 3 / 8, decoded.length); } /** * Decodes a byte buffer. * @param data the data * @param columns the number of columns * @return the decoded bits/pixels * @throws IOException if an I/O error occurs */ public static byte[] decode(byte[] data, int columns) throws IOException { CCITTFaxG31DDecodeInputStream decoder = new CCITTFaxG31DDecodeInputStream( new ByteArrayInputStream(data), columns, false); byte[] decoded = IOUtils.toByteArray(decoder); decoder.close(); return decoded; } private byte[] fromBinary(String binary) { ByteArrayOutputStream baout = new ByteArrayOutputStream(); int pos = 0; while (pos < binary.length() - 8) { int v = Integer.parseInt(binary.substring(pos, pos + 8), 2); baout.write(v & 0xFF); pos += 8; } int rest = binary.length() - pos; if (rest > 0) { String f = binary.substring(pos) + "00000000".substring(rest); baout.write(Integer.parseInt(f, 2)); } return baout.toByteArray(); } }