Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jpedal.io.filter.ccitt.CCITT1D Maven / Gradle / Ivy
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2016 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---------------
* CCITT1D.java
* ---------------
*/
package org.jpedal.io.filter.ccitt;
import java.util.BitSet;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;
/**
* implement 1D CCITT decoding
*/
public class CCITT1D implements CCITTDecoder{
/**
* values set in PdfObject
*/
boolean BlackIs1,isByteAligned;
int columns = 1728;
byte[] data;
int bitReached;
private static final int EOL = -1;
private static final boolean debug = false;
boolean isWhite = true;
private boolean isTerminating;
private boolean isEndOfLine;
private boolean EOS;
private int cRTC;
int width;
int height;
private int line;
BitSet out;
private BitSet inputBits;
int outPtr;
private int bytesNeeded;
int scanlineStride;
private int inputBitCount;
// ---------- BLACK --------------
private static final int[][][] b = {
{{3, 2, 0},{2, 3, 0}},
{{2, 1, 0},{3, 4, 0}},
{ //b4
{3, 5, 0},
{2, 6, 0}
},
//b5
{
{3, 7, 0}
},
//b6
{
{5, 8, 0},
{4, 9, 0}
},
//b7
{
{4, 10, 0},
{5, 11, 0},
{7, 12, 0}
},
//b8
{
{4, 13, 0},
{7, 14, 0}
},
//b9
{
{24, 15, 0}
},
//b10
{
{55, 0, 0},
{23, 16, 0},
{24, 17, 0},
{8, 18, 0},
{15, 64, 1}
},
//b11
{
{103, 19, 0},
{104, 20, 0},
{108, 21, 0},
{55, 22, 0},
{40, 23, 0},
{23, 24, 0},
{24, 25, 0},
{8, 1792, 1},
{12, 1856, 1},
{13, 1920, 1}
},
//b12
{
{202, 26, 0},
{203, 27, 0},
{204, 28, 0},
{205, 29, 0},
{104, 30, 0},
{105, 31, 0},
{106, 32, 0},
{107, 33, 0},
{210, 34, 0},
{211, 35, 0},
{212, 36, 0},
{213, 37, 0},
{214, 38, 0},
{215, 39, 0},
{108, 40, 0},
{109, 41, 0},
{218, 42, 0},
{219, 43, 0},
{84, 44, 0},
{85, 45, 0},
{86, 46, 0},
{87, 47, 0},
{100, 48, 0},
{101, 49, 0},
{82, 50, 0},
{83, 51, 0},
{36, 52, 0},
{55, 53, 0},
{56, 54, 0},
{39, 55, 0},
{40, 56, 0},
{88, 57, 0},
{89, 58, 0},
{43, 59, 0},
{44, 60, 0},
{90, 61, 0},
{102, 62, 0},
{103, 63, 0},
{200, 128, 1},
{201, 192, 1},
{91, 256, 1},
{51, 320, 1},
{52, 384, 1},
{53, 448, 1},
{1, EOL, 1},
{18, 1984, 1},
{19, 2048, 1},
{20, 2112, 1},
{21, 2176, 1},
{22, 2240, 1},
{23, 2304, 1},
{28, 2368, 1},
{29, 2432, 1},
{30, 2496, 1},
{31, 2560, 1}
},
//b13
{
{108, 512, 1},
{109, 576, 1},
{74, 640, 1},
{75, 704, 1},
{76, 768, 1},
{77, 832, 1},
{114, 896, 1},
{115, 960, 1},
{116, 1024, 1},
{117, 1088, 1},
{118, 1152, 1},
{119, 1216, 1},
{82, 1280, 1},
{83, 1344, 1},
{84, 1408, 1},
{85, 1472, 1},
{90, 1536, 1},
{91, 1600, 1},
{100, 1664, 1},
{101, 1728, 1}
}};
// ---------- WHITE --------------
private static final int[][][] w = {{
{7, 2, 0},
{8, 3, 0},
{11, 4, 0},
{12, 5, 0},
{14, 6, 0},
{15, 7, 0}},
//b5
{
{19, 8, 0},
{20, 9, 0},
{7, 10, 0},
{8, 11, 0},
{27, 64, 1},
{18, 128, 1}
},
//b6
{
{7, 1, 0},
{8, 12, 0},
{3, 13, 0},
{52, 14, 0},
{53, 15, 0},
{42, 16, 0},
{43, 17, 0},
{23, 192, 1},
{24, 1664, 1}
},
//w7
{
{39, 18, 0},
{12, 19, 0},
{8, 20, 0},
{23, 21, 0},
{3, 22, 0},
{4, 23, 0},
{40, 24, 0},
{43, 25, 0},
{19, 26, 0},
{36, 27, 0},
{24, 28, 0},
{55, 256, 1}
},
//w8
{
{53, 0, 0},
{2, 29, 0},
{3, 30, 0},
{26, 31, 0},
{27, 32, 0},
{18, 33, 0},
{19, 34, 0},
{20, 35, 0},
{21, 36, 0},
{22, 37, 0},
{23, 38, 0},
{40, 39, 0},
{41, 40, 0},
{42, 41, 0},
{43, 42, 0},
{44, 43, 0},
{45, 44, 0},
{4, 45, 0},
{5, 46, 0},
{10, 47, 0},
{11, 48, 0},
{82, 49, 0},
{83, 50, 0},
{84, 51, 0},
{85, 52, 0},
{36, 53, 0},
{37, 54, 0},
{88, 55, 0},
{89, 56, 0},
{90, 57, 0},
{91, 58, 0},
{74, 59, 0},
{75, 60, 0},
{50, 61, 0},
{51, 62, 0},
{52, 63, 0},
{54, 320, 1},
{55, 384, 1},
{100, 448, 1},
{101, 512, 1},
{104, 576, 1},
{103, 640, 1}
},
//w9
{
{204, 704, 1},
{205, 768, 1},
{210, 832, 1},
{211, 896, 1},
{212, 960, 1},
{213, 1024, 1},
{214, 1088, 1},
{215, 1152, 1},
{216, 1216, 1},
{217, 1280, 1},
{218, 1344, 1},
{219, 1408, 1},
{152, 1472, 1},
{153, 1536, 1},
{154, 1600, 1},
{155, 1728, 1}
},
//w10
{
},
//w11
{
{8, 1792, 1},
{12, 1856, 1},
{13, 1920, 1}
},
//w12
{
{1, EOL, 1},
{18, 1984, 1},
{19, 2048, 1},
{20, 2112, 1},
{21, 2176, 1},
{22, 2240, 1},
{23, 2304, 1},
{28, 2368, 1},
{29, 2432, 1},
{30, 2496, 1},
{31, 2560, 1}
}};
public CCITT1D(final byte[] rawData, final int width, int height, final PdfObject DecodeParms){
this.data=rawData;
this.bitReached = 0;
columns=width; //default if not set (in theory should be the same if set)
//and any values from PDFobject
if(DecodeParms!=null){
BlackIs1 = DecodeParms.getBoolean(PdfDictionary.BlackIs1);
final int columnsSet = DecodeParms.getInt(PdfDictionary.Columns);
if(columnsSet!=-1) {
columns = columnsSet;
}
final int rowsSet = DecodeParms.getInt(PdfDictionary.Rows);
if(rowsSet>0) //allow for value set to 0 which is impossible! (see abacus/aba_Dossier)
{
height = rowsSet;
}
isByteAligned = DecodeParms.getBoolean(PdfDictionary.EncodedByteAlign);
if(debug) {
System.out.println("BlackIs1=" + BlackIs1 + "\ncolumnsSet=" + columnsSet + "\nisByteAligned=" + isByteAligned + "\nrowsSet=" + rowsSet);
}
}
//and other values which might use defaults set from PdfObject
this.width = columns;
this.height=height;
scanlineStride=(columns + 7) >> 3;
bytesNeeded= (height * scanlineStride);
out=new BitSet(bytesNeeded<<3);
//number of bits in raw compressed data
inputBitCount=data.length<<3;
//raw data bits to read for codewords
inputBits =fromByteArray(data, inputBitCount);
}
CCITT1D() {}
@Override
public byte[] decode(){
moveToEOLMarker();
//read all the tokens and find sub values until End Of Stream
decode1DRun();
//put output bits together into byte[] we return
//put it all together
final byte[] buffer= createOutputFromBitset();
//by default blackIs1 is false so black pixels do not need to be set
// invert image if needed -
// ultimately will be quicker to add into decode
//k==0 seems to be reverse of others
if (BlackIs1) {
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (byte) (255 - buffer[i]); //invert all bytes
}
}
return buffer;
}
byte[] createOutputFromBitset() {
final byte[] output = new byte[bytesNeeded];
//assemble all tokens into a decompressed output data block
int bytePtr = 0,bitPtr = 7,mask;
byte entry = 0;
for(int j=0;j0){
if(pixelIsWhite){
out.set(outPtr, (outPtr + pixelCount), true);
}
outPtr += pixelCount;
}
}
}
private int getCodeWord() {
int pixelCount=0,itemFound = -1,maskAdj = 0;
/*
* look for valid value starting at 2 bits
*
* starting with 2 bits (4 for white)
* look at next pixels until we find a valid value for next codeword
*/
int startBitLength=2,endBit=14,code=0,bits=0;
if(isWhite){ //no values for 2,3 in this case
startBitLength=4;
endBit=13;
}
//loop to find the valid keys by checking next bit value against tables
for(int bitLength =startBitLength; bitLength inputBitCount){
EOS = true;
}
return pixelCount;
}
private int processCodeWord(final int itemFound, final int code, final int bits) {
int pixelCount;
final boolean isT;
//values in the table
if(isWhite){
pixelCount=w[bits-4][itemFound][1];
isT=w[bits-4][itemFound][2]==0;
}else{
pixelCount=b[bits-2][itemFound][1];
isT=b[bits-2][itemFound][2]==0;
}
if(isT) {
isTerminating = true;
}
if(pixelCount ==-1){
if(line != 0){
LogWriter.writeLog("EOF marker encountered but not EOL yet!");
// pixelCount = width - line;
}
line = 0;
isWhite = true;
isTerminating = false;
}
if (pixelCount != -1) {
line += pixelCount;
if(line==width){
if(isT){
line = 0;
isEndOfLine = true;
}
}else if(line>width){
line = 0;
isEndOfLine = true;
}
}
if(bits ==12 && code ==1){
cRTC++;
if(cRTC==6){
EOS = true;
}
}else{
cRTC = 0;
}
if(cRTC!=6 && isEndOfLine && isByteAligned){
//get bits over 8 and align to byte boundary
final int iPart = (bitReached)%8;
final int iDrop = 8-(iPart);
if(iPart>0){
bitReached += iDrop;
}
}
return pixelCount;
}
//2D version
int get1DBits(final int bitsToGet) {
return get1DBits(bitsToGet,false);
}
private int get1DBits(final int bitsToGet, final boolean is1D) {
int tmp = 0;
int maskAdj=0;
if(is1D && bitsToGet>8) {
maskAdj++;
}
int mask;
for(int y=0;y< bitsToGet;y++){
if(inputBits.get(y+ bitReached)){
mask = 1 << (bitsToGet -y-1-maskAdj);
tmp |= mask;
}
}
return tmp;
}
private static int checkTables(final int possCode, final int bitLength, final boolean isWhite) {
int itemFound=-1;
final int[][] table;
if(isWhite){
table=w[bitLength-4];
}else{
table=b[bitLength-2];
}
final int size=table.length;
for(int z=0; z< size;z++){
if(possCode== table[z][0]){
itemFound=z;
z=size;
}
}
return itemFound;
}
private static BitSet fromByteArray(final byte[] bytes, final int bitsNeeded) {
int bitSetPtr = 0,value;
byte tmp;
final BitSet bits = new BitSet(bitsNeeded);
for (final byte aByte : bytes) {
tmp = aByte;
for (int z = 7; z >= 0; z--) {
value = (tmp & (1 << z));
if (value >= 1) {
bits.set(bitSetPtr, true);
}
bitSetPtr++;
}
}
return bits;
}
private void moveToEOLMarker(){
boolean isEOL = false, bit;
int i = 0;
while(!isEOL){
isEOL = true;
for(i=0;i<12;i++){
bit=inputBits.get(i + bitReached);
if(i==11){
if(!bit){
isEOL = false;
}
}else{
if(bit){
isEOL = false;
}
}
}
bitReached++;
// if EOL not found in the first 10 bits assume that
// there is no EOL at the start od the line and start
// at 0
if(bitReached > 26){
bitReached = 0;
return;
}
}
bitReached = bitReached + i - 1;
}
}