Merge pull request #3 from TouchInstinct/black_pixels_fix

Black pixels fix
This commit is contained in:
Alex Urzhumtcev 2016-10-26 12:21:30 +03:00 committed by GitHub
commit 2571a51c7e
9 changed files with 966 additions and 1311 deletions

View File

@ -1,7 +1,7 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion "23.0.2"
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
minSdkVersion 14
@ -17,7 +17,7 @@ android {
}
dependencies {
provided 'com.android.support:appcompat-v7:24.2.1'
provided 'com.android.support:appcompat-v7:25.0.0'
compile('com.github.chrisbanes:PhotoView:1.3.0') {
exclude group: 'com.android.support', module: 'support-v4'
}

File diff suppressed because it is too large Load Diff

View File

@ -54,9 +54,7 @@ import com.sun.pdfview.font.PDFFont;
*/
public class PDFParser extends BaseWatchable {
/**
* emit a file of DCT stream data.
*/
/** emit a file of DCT stream data. */
public final static String DEBUG_DCTDECODE_DATA = "debugdctdecode";
static final boolean RELEASE = true;
static final int PDF_CMDS_RANGE1_MIN = 1;
@ -78,13 +76,11 @@ public class PDFParser extends BaseWatchable {
private boolean resend = false;
private Tok tok;
private boolean catchexceptions; // Indicates state of BX...EX
/**
* a weak reference to the page we render into. For the page
/** a weak reference to the page we render into. For the page
* to remain available, some other code must retain a strong reference to it.
*/
private WeakReference pageRef;
/**
* the actual command, for use within a singe iteration. Note that
/** the actual command, for use within a singe iteration. Note that
* this must be released at the end of each iteration to assure the
* page can be collected if not in use
*/
@ -92,7 +88,7 @@ public class PDFParser extends BaseWatchable {
// ---- result variables
byte[] stream;
HashMap<String, PDFObject> resources;
// public static int debuglevel = 4000;
// public static int debuglevel = 4000;
// TODO [FHe]: changed for debugging
public static int debuglevel = -1;
@ -125,7 +121,7 @@ public class PDFParser extends BaseWatchable {
* on to a PDFParser.
*/
public PDFParser(PDFPage cmds, byte[] stream,
HashMap<String, PDFObject> resources) {
HashMap<String, PDFObject> resources) {
super();
this.pageRef = new WeakReference<PDFPage>(cmds);
@ -141,76 +137,43 @@ public class PDFParser extends BaseWatchable {
/////////////////////////////////////////////////////////////////
// B E G I N R E A D E R S E C T I O N
/////////////////////////////////////////////////////////////////
/**
* a token from a PDF Stream
*/
static class Tok {
/**
* begin bracket &lt;
*/
/** begin bracket &lt; */
public static final int BRKB = 11;
/**
* end bracket &gt;
*/
/** end bracket &gt; */
public static final int BRKE = 10;
/**
* begin array [
*/
/** begin array [ */
public static final int ARYB = 9;
/**
* end array ]
*/
/** end array ] */
public static final int ARYE = 8;
/**
* String (, readString looks for trailing )
*/
/** String (, readString looks for trailing ) */
public static final int STR = 7;
/**
* begin brace {
*/
/** begin brace { */
public static final int BRCB = 5;
/**
* end brace }
*/
/** end brace } */
public static final int BRCE = 4;
/**
* number
*/
/** number */
public static final int NUM = 3;
/**
* keyword
*/
/** keyword */
public static final int CMD = 2;
/**
* name (begins with /)
*/
/** name (begins with /) */
public static final int NAME = 1;
/**
* unknown token
*/
/** unknown token */
public static final int UNK = 0;
/**
* end of stream
*/
/** end of stream */
public static final int EOF = -1;
/**
* the string value of a STR, NAME, or CMD token
*/
/** the string value of a STR, NAME, or CMD token */
public String name;
/**
* the value of a NUM token
*/
/** the value of a NUM token */
public double value;
/**
* the type of the token
*/
/** the type of the token */
public int type;
/**
* a printable representation of the token
*/
/** a printable representation of the token */
@Override
public String toString() {
if (type == NUM) {
@ -409,7 +372,7 @@ public class PDFParser extends BaseWatchable {
* character, which has already been read, and end with a balanced ')'
* character. A '\' character starts an escape sequence of up
* to three octal digits.</p>
* <p/>
*
* <p>Parenthesis must be enclosed by a balanced set of parenthesis,
* so a string may enclose balanced parenthesis.</p>
*
@ -421,7 +384,7 @@ public class PDFParser extends BaseWatchable {
int parenLevel = 0;
final StringBuffer sb = new StringBuffer();
for (int to = stream_.length; loc < to; ) {
for (int to = stream_.length; loc < to;) {
int c = stream_[loc++];
if (c == ')') {
if (parenLevel-- == 0) {
@ -462,7 +425,7 @@ public class PDFParser extends BaseWatchable {
* character, which has already been read, and end with a '>'
* character. Each byte in the array is made up of two hex characters,
* the first being the high-order bit.
* <p/>
*
* We translate the byte arrays into char arrays by combining two bytes
* into a character, and then translate the character array into a string.
* [JK FIXME this is probably a really bad idea!]
@ -477,7 +440,7 @@ public class PDFParser extends BaseWatchable {
char w = (char) 0;
// read individual bytes and format into a character array
for (int to = stream_.length; (loc < to) && (stream_[loc] != '>'); ) {
for (int to = stream_.length; (loc < to) && (stream_[loc] != '>');) {
final char c = (char) stream_[loc];
byte b = (byte) 0;
@ -515,7 +478,6 @@ public class PDFParser extends BaseWatchable {
/////////////////////////////////////////////////////////////////
// B E G I N P A R S E R S E C T I O N
/////////////////////////////////////////////////////////////////
/**
* Called to prepare for some iterations
*/
@ -543,16 +505,16 @@ public class PDFParser extends BaseWatchable {
/**
* parse the stream. commands are added to the PDFPage initialized
* in the constructor as they are encountered.
* <p/>
* <p>
* Page numbers in comments refer to the Adobe PDF specification.<br>
* commands are listed in PDF spec 32000-1:2008 in Table A.1
*
* @return <ul><li>Watchable.RUNNING when there are commands to be processed
* <li>Watchable.COMPLETED when the page is done and all
* the commands have been processed
* <li>Watchable.STOPPED if the page we are rendering into is
* no longer available
* </ul>
* <li>Watchable.COMPLETED when the page is done and all
* the commands have been processed
* <li>Watchable.STOPPED if the page we are rendering into is
* no longer available
* </ul>
*/
public int iterate() throws Exception {
// make sure the page is still available, and create the reference
@ -700,7 +662,7 @@ public class PDFParser extends BaseWatchable {
path = new Path();
break;
case 'f':
// the fall-through is intended!
// the fall-through is intended!
case 'F':
// fill the path (close/not close identical)
cmds.addPath(path, PDFShapeCmd.FILL | clip);
@ -990,11 +952,11 @@ public class PDFParser extends BaseWatchable {
break;
case 'Q' + ('q' << 8):
processQCmd();
// 'q'-cmd
// push the parser state
parserStates.push((ParserState) state.clone());
// push graphics state
cmds.addPush();
// 'q'-cmd
// push the parser state
parserStates.push((ParserState) state.clone());
// push graphics state
cmds.addPush();
break;
default:
if (catchexceptions) {
@ -1063,7 +1025,6 @@ public class PDFParser extends BaseWatchable {
path = null;
cmds = null;
}
boolean errorwritten = false;
public void dumpStreamToError() {
@ -1107,12 +1068,10 @@ public class PDFParser extends BaseWatchable {
/////////////////////////////////////////////////////////////////
// H E L P E R S
/////////////////////////////////////////////////////////////////
/**
* get a property from a named dictionary in the resources of this
* content stream.
*
* @param name the name of the property in the dictionary
* @param name the name of the property in the dictionary
* @param inDict the name of the dictionary in the resources
* @return the value of the property in the dictionary
*/
@ -1133,7 +1092,6 @@ public class PDFParser extends BaseWatchable {
* Insert a PDF object into the command stream. The object must
* either be an Image or a Form, which is a set of PDF commands
* in a stream.
*
* @param obj the object to insert, an Image or a Form.
*/
private void doXObject(PDFObject obj) throws IOException {
@ -1153,9 +1111,8 @@ public class PDFParser extends BaseWatchable {
/**
* Parse image data into a Java BufferedImage and add the image
* command to the page.
*
* @param obj contains the image data, and a dictionary describing
* the width, height and color space of the image.
* the width, height and color space of the image.
*/
private void doImage(PDFObject obj) throws IOException {
cmds.addImage(PDFImage.createImage(obj, resources));
@ -1165,9 +1122,8 @@ public class PDFParser extends BaseWatchable {
* Inject a stream of PDF commands onto the page. Optimized to cache
* a parsed stream of commands, so that each Form object only needs
* to be parsed once.
*
* @param obj a stream containing the PDF commands, a transformation
* matrix, bounding box, and resources.
* matrix, bounding box, and resources.
*/
private void doForm(PDFObject obj) throws IOException {
// check to see if we've already parsed this sucker
@ -1230,7 +1186,6 @@ public class PDFParser extends BaseWatchable {
//
// return patternSpace.getPaint(pattern, components, resources);
// }
/**
* Parse the next object out of the PDF stream. This could be a
* Double, a String, a HashMap (dictionary), Object[] array, or
@ -1243,13 +1198,13 @@ public class PDFParser extends BaseWatchable {
case Tok.NUM:
return new Double(tok.value);
case Tok.STR:
// the fall-through is intended!
// the fall-through is intended!
case Tok.NAME:
return tok.name;
case Tok.BRKB: {
final HashMap<String, PDFObject> hm = new HashMap<String, PDFObject>();
String name = null;
for (Object obj = null; (obj = parseObject()) != null; ) {
for (Object obj = null; (obj = parseObject()) != null;) {
if (name == null) {
name = (String) obj;
} else {
@ -1265,7 +1220,7 @@ public class PDFParser extends BaseWatchable {
case Tok.ARYB: {
// build an array
final ArrayList<Object> ary = new ArrayList<Object>();
for (Object obj = null; (obj = parseObject()) != null; ) {
for (Object obj = null; (obj = parseObject()) != null;) {
ary.add(obj);
}
if (tok.type != Tok.ARYE) {
@ -1396,7 +1351,6 @@ public class PDFParser extends BaseWatchable {
/**
* add graphics state commands contained within a dictionary.
*
* @param name the resource name of the graphics state dictionary
*/
private void setGSState(String name) throws IOException {
@ -1454,15 +1408,11 @@ public class PDFParser extends BaseWatchable {
/**
* pop a single float value off the stack.
*
* @return the float value of the top of the stack
* @throws PDFParseException if the value on the top of the stack
* isn't a number
* isn't a number
*/
private float popFloat() throws PDFParseException {
if (stack.isEmpty()) {
return 0;
}
Object obj = stack.pop();
if (obj instanceof Double) {
return ((Double) obj).floatValue();
@ -1475,11 +1425,10 @@ public class PDFParser extends BaseWatchable {
* pop an array of float values off the stack. This is equivalent
* to filling an array from end to front by popping values off the
* stack.
*
* @param count the number of numbers to pop off the stack
* @return an array of length <tt>count</tt>
* @throws PDFParseException if any of the values popped off the
* stack are not numbers.
* stack are not numbers.
*/
private float[] popFloat(int count) throws PDFParseException {
float[] ary = new float[count];
@ -1491,7 +1440,6 @@ public class PDFParser extends BaseWatchable {
/**
* pop a single integer value off the stack.
*
* @return the integer value of the top of the stack
* @throws PDFParseException if the top of the stack isn't a number.
*/
@ -1508,11 +1456,10 @@ public class PDFParser extends BaseWatchable {
* pop an array of integer values off the stack. This is equivalent
* to filling an array from end to front by popping values off the
* stack.
*
* @param count the number of numbers to pop off the stack
* @return an array of length <tt>count</tt>
* @throws PDFParseException if any of the values popped off the
* stack are not numbers.
* stack are not numbers.
*/
private float[] popFloatArray() throws PDFParseException {
Object obj = stack.pop();
@ -1533,10 +1480,9 @@ public class PDFParser extends BaseWatchable {
/**
* pop a String off the stack.
*
* @return the String from the top of the stack
* @throws PDFParseException if the top of the stack is not a NAME
* or STR.
* or STR.
*/
private String popString() throws PDFParseException {
Object obj = stack.pop();
@ -1549,10 +1495,9 @@ public class PDFParser extends BaseWatchable {
/**
* pop a PDFObject off the stack.
*
* @return the PDFObject from the top of the stack
* @throws PDFParseException if the top of the stack does not contain
* a PDFObject.
* a PDFObject.
*/
private PDFObject popObject() throws PDFParseException {
Object obj = stack.pop();
@ -1564,10 +1509,9 @@ public class PDFParser extends BaseWatchable {
/**
* pop an array off the stack
*
* @return the array of objects that is the top element of the stack
* @throws PDFParseException if the top element of the stack does not
* contain an array.
* contain an array.
*/
private Object[] popArray() throws PDFParseException {
Object obj = stack.pop();
@ -1584,17 +1528,11 @@ public class PDFParser extends BaseWatchable {
*/
class ParserState implements Cloneable {
/**
* the fill color space
*/
/** the fill color space */
PDFColorSpace fillCS;
/**
* the stroke color space
*/
/** the stroke color space */
PDFColorSpace strokeCS;
/**
* the text paramters
*/
/** the text paramters */
PDFTextFormat textFormat;
/**

View File

@ -1,60 +0,0 @@
/*
* $Id: CalRGBColor.java,v 1.2 2007/12/20 18:33:34 rbair Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.sun.pdfview.colorspace;
import android.graphics.Color;
public class ICCIColorSpace extends PDFColorSpace {
public ICCIColorSpace() {
}
/**
* get the number of components (3)
*/
@Override public int getNumComponents() {
return 3;
}
@Override public int toColor(float[] fcomp) {
return Color.rgb((int)(fcomp[0]*255),(int)(fcomp[1]*255),(int)(fcomp[2]*255));
}
@Override public int toColor(int[] icomp) {
return Color.rgb(icomp[0],icomp[1],icomp[2]);
}
/**
* get the type of this color space (TYPE_RGB)
*/
@Override public int getType() {
return COLORSPACE_GRAY;
}
@Override
public String getName() {
return "RGB";
}
}

View File

@ -28,186 +28,187 @@ import com.sun.pdfview.PDFPaint;
import com.sun.pdfview.PDFParseException;
import com.sun.pdfview.function.PDFFunction;
/**
* A color space that can convert a set of color components into
* PDFPaint.
*
* @author Mike Wessler
*/
public abstract class PDFColorSpace {
/** the name of the device-dependent gray color space */
public static final int COLORSPACE_GRAY = 0;
/** the name of the device-dependent gray color space */
public static final int COLORSPACE_GRAY = 0;
/** the name of the device-dependent RGB color space */
public static final int COLORSPACE_RGB = 1;
/** the name of the device-dependent RGB color space */
public static final int COLORSPACE_RGB = 1;
/** the name of the device-dependent CMYK color space */
public static final int COLORSPACE_CMYK = 2;
/** the name of the device-dependent CMYK color space */
public static final int COLORSPACE_CMYK = 2;
/** the name of the pattern color space */
public static final int COLORSPACE_PATTERN = 3;
/** the name of the pattern color space */
public static final int COLORSPACE_PATTERN = 3;
public static final int COLORSPACE_INDEXED = 4;
public static final int COLORSPACE_INDEXED = 4;
public static final int COLORSPACE_ALTERNATE = 5;
public static final int COLORSPACE_ALTERNATE = 5;
/** the device-dependent color spaces */
// private static PDFColorSpace graySpace =
// new PDFColorSpace(ColorSpace.getInstance(ColorSpace.CS_GRAY));
private static PDFColorSpace rgbSpace = new RGBColorSpace();
private static PDFColorSpace cmykSpace = new CMYKColorSpace();
/** the device-dependent color spaces */
// private static PDFColorSpace graySpace =
// new PDFColorSpace(ColorSpace.getInstance(ColorSpace.CS_GRAY));
private static PDFColorSpace rgbSpace = new RGBColorSpace();
private static PDFColorSpace cmykSpace = new CMYKColorSpace();
private static PDFColorSpace icciSpace = new ICCIColorSpace();
/** the pattern space */
private static PDFColorSpace patternSpace = new RGBColorSpace(); // TODO [FHe]
/** the pattern space */
private static PDFColorSpace patternSpace = new RGBColorSpace(); // TODO [FHe]
/** graySpace and the gamma correction for it. */
private static PDFColorSpace graySpace = new GrayColorSpace();
/** graySpace and the gamma correction for it. */
private static PDFColorSpace graySpace = new GrayColorSpace();
/**
* create a PDFColorSpace based on a Java ColorSpace
*
* @param cs the Java ColorSpace
*/
protected PDFColorSpace() {
}
/**
* Get a color space by name
*
* @param name the name of one of the device-dependent color spaces
*/
public static PDFColorSpace getColorSpace(int name) {
switch (name) {
case COLORSPACE_GRAY:
return graySpace;
case COLORSPACE_RGB:
return rgbSpace;
case COLORSPACE_CMYK:
return cmykSpace;
case COLORSPACE_PATTERN:
return patternSpace;
default:
throw new IllegalArgumentException("Unknown Color Space name: " + name);
}
}
/**
* Get a color space specified in a PDFObject
*
* @param csobj the PDFObject with the colorspace information
*/
public static PDFColorSpace getColorSpace(PDFObject csobj, Map resources) throws IOException {
String name;
PDFObject colorSpaces = null;
if (resources != null) {
colorSpaces = (PDFObject) resources.get("ColorSpace");
/**
* create a PDFColorSpace based on a Java ColorSpace
* @param cs the Java ColorSpace
*/
protected PDFColorSpace() {
}
if (csobj.getType() == PDFObject.NAME) {
name = csobj.getStringValue();
/**
* Get a color space by name
*
* @param name the name of one of the device-dependent color spaces
*/
public static PDFColorSpace getColorSpace(int name) {
switch (name) {
case COLORSPACE_GRAY:
return graySpace;
if (name.equals("DeviceGray") || name.equals("G")) {
return getColorSpace(COLORSPACE_GRAY);
} else if (name.equals("DeviceRGB") || name.equals("RGB")) {
return getColorSpace(COLORSPACE_RGB);
} else if (name.equals("DeviceCMYK") || name.equals("CMYK")) {
return getColorSpace(COLORSPACE_CMYK);
} else if (name.equals("Pattern")) {
return getColorSpace(COLORSPACE_PATTERN);
} else if (colorSpaces != null) {
csobj = (PDFObject) colorSpaces.getDictRef(name);
}
case COLORSPACE_RGB:
return rgbSpace;
case COLORSPACE_CMYK:
return cmykSpace;
case COLORSPACE_PATTERN:
return patternSpace;
default:
throw new IllegalArgumentException("Unknown Color Space name: " +
name);
}
}
if (csobj == null) {
return null;
} else if (csobj.getCache() != null) {
return (PDFColorSpace) csobj.getCache();
/**
* Get a color space specified in a PDFObject
*
* @param csobj the PDFObject with the colorspace information
*/
public static PDFColorSpace getColorSpace(PDFObject csobj, Map resources)
throws IOException {
String name;
PDFObject colorSpaces = null;
if (resources != null) {
colorSpaces = (PDFObject) resources.get("ColorSpace");
}
if (csobj.getType() == PDFObject.NAME) {
name = csobj.getStringValue();
if (name.equals("DeviceGray") || name.equals("G")) {
return getColorSpace(COLORSPACE_GRAY);
} else if (name.equals("DeviceRGB") || name.equals("RGB")) {
return getColorSpace(COLORSPACE_RGB);
} else if (name.equals("DeviceCMYK") || name.equals("CMYK")) {
return getColorSpace(COLORSPACE_CMYK);
} else if (name.equals("Pattern")) {
return getColorSpace(COLORSPACE_PATTERN);
} else if (colorSpaces != null) {
csobj = (PDFObject) colorSpaces.getDictRef(name);
}
}
if (csobj == null) {
return null;
} else if (csobj.getCache() != null) {
return (PDFColorSpace) csobj.getCache();
}
PDFColorSpace value = null;
// csobj is [/name <<dict>>]
PDFObject[] ary = csobj.getArray();
name = ary[0].getStringValue();
if (name.equals("CalGray")) {
value = graySpace; // TODO [FHe]
} else if (name.equals("CalRGB")) {
value = rgbSpace; // TODO [FHe]
} else if (name.equals("Lab")) {
value = rgbSpace; // TODO [FHe]
} else if (name.equals("ICCBased")) {
value = rgbSpace; // TODO [FHe]
} else if (name.equals("Separation") || name.equals("DeviceN")) {
PDFColorSpace alternate = getColorSpace(ary[2], resources);
PDFFunction function = PDFFunction.getFunction(ary[3]);
value = new AlternateColorSpace(alternate, function);
} else if (name.equals("Indexed") || name.equals("I")) {
/**
* 4.5.5 [/Indexed baseColor hival lookup]
*/
PDFColorSpace refspace = getColorSpace(ary[1], resources);
// number of indices= ary[2], data is in ary[3];
int count = ary[2].getIntValue();
value = new IndexedColor(refspace, count, ary[3]);
} else if (name.equals("Pattern")) {
return rgbSpace; // TODO [FHe]
} else {
throw new PDFParseException("Unknown color space: " + name +
" with " + ary[1]);
}
csobj.setCache(value);
return value;
}
PDFColorSpace value = null;
/**
* get the number of components expected in the getPaint command
*/
public abstract int getNumComponents();
// csobj is [/name <<dict>>]
PDFObject[] ary = csobj.getArray();
name = ary[0].getStringValue();
if (name.equals("CalGray")) {
value = graySpace; // TODO [FHe]
} else if (name.equals("CalRGB")) {
value = rgbSpace; // TODO [FHe]
} else if (name.equals("Lab")) {
value = rgbSpace; // TODO [FHe]
} else if (name.equals("ICCBased")) {
value = rgbSpace;//icciSpace; // TODO [FHe]
} else if (name.equals("Separation") || name.equals("DeviceN")) {
PDFColorSpace alternate = getColorSpace(ary[2], resources);
PDFFunction function = PDFFunction.getFunction(ary[3]);
value = new AlternateColorSpace(alternate, function);
} else if (name.equals("Indexed") || name.equals("I")) {
/**
* 4.5.5 [/Indexed baseColor hival lookup]
*/
PDFColorSpace refspace = getColorSpace(ary[1], resources);
// number of indices= ary[2], data is in ary[3];
int count = ary[2].getIntValue();
value = new IndexedColor(refspace, count, ary[3]);
} else if (name.equals("Pattern")) {
return rgbSpace; // TODO [FHe]
} else {
throw new PDFParseException("Unknown color space: " + name +
" with " + ary[1]);
/**
* get the PDFPaint representing the color described by the
* given color components
* @param components the color components corresponding to the given
* colorspace
* @return a PDFPaint object representing the closest Color to the
* given components.
*/
public PDFPaint getPaint(float[] components) {
return PDFPaint.getColorPaint(toColor(components));
}
public PDFPaint getFillPaint(float[] components) {
return PDFPaint.getPaint(toColor(components));
}
csobj.setCache(value);
/**
* get the type of this color space
*/
public abstract int getType();
/**
* get the name of this color space
*/
public abstract String getName();
return value;
}
public abstract int toColor(float[] fcomp);
public abstract int toColor(int[] icomp);
@Override
public String toString() {
return "ColorSpace["+getName()+"]";
}
/**
* get the number of components expected in the getPaint command
*/
public abstract int getNumComponents();
/**
* get the PDFPaint representing the color described by the
* given color components
*
* @param components the color components corresponding to the given
* colorspace
* @return a PDFPaint object representing the closest Color to the
* given components.
*/
public PDFPaint getPaint(float[] components) {
return PDFPaint.getColorPaint(toColor(components));
}
public PDFPaint getFillPaint(float[] components) {
return PDFPaint.getPaint(toColor(components));
}
/**
* get the type of this color space
*/
public abstract int getType();
/**
* get the name of this color space
*/
public abstract String getName();
public abstract int toColor(float[] fcomp);
public abstract int toColor(int[] icomp);
@Override public String toString() {
return "ColorSpace[" + getName() + "]";
}
}

View File

@ -21,13 +21,19 @@
package com.sun.pdfview.decode;
import java.io.IOException;
import java.nio.IntBuffer;
import net.sf.andpdf.nio.ByteBuffer;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.util.Log;
import com.sun.pdfview.PDFObject;
import com.sun.pdfview.PDFParseException;
import net.sf.andpdf.nio.ByteBuffer;
import com.sun.pdfview.colorspace.PDFColorSpace;
/**
* decode a DCT encoded array into a byte array. This class uses Java's
@ -37,49 +43,52 @@ import net.sf.andpdf.nio.ByteBuffer;
*/
public class DCTDecode {
/**
* decode an array of bytes in DCT format.
* <p>
* DCT is the format used by JPEG images, so this class simply
* loads the DCT-format bytes as an image, then reads the bytes out
* of the image to create the array. Unfortunately, their most
* likely use is to get turned BACK into an image, so this isn't
* terribly efficient... but is is general... don't hit, please.
* <p>
* The DCT-encoded stream may have 1, 3 or 4 samples per pixel, depending
* on the colorspace of the image. In decoding, we look for the colorspace
* in the stream object's dictionary to decide how to decode this image.
* If no colorspace is present, we guess 3 samples per pixel.
*
* @param dict the stream dictionary
* @param buf the DCT-encoded buffer
* @param params the parameters to the decoder (ignored)
* @return the decoded buffer
*/
protected static ByteBuffer decode(PDFObject dict, ByteBuffer buf, PDFObject params) throws PDFParseException {
// System.out.println("DCTDecode image info: "+params);
buf.rewind();
/**
* decode an array of bytes in DCT format.
* <p>
* DCT is the format used by JPEG images, so this class simply
* loads the DCT-format bytes as an image, then reads the bytes out
* of the image to create the array. Unfortunately, their most
* likely use is to get turned BACK into an image, so this isn't
* terribly efficient... but is is general... don't hit, please.
* <p>
* The DCT-encoded stream may have 1, 3 or 4 samples per pixel, depending
* on the colorspace of the image. In decoding, we look for the colorspace
* in the stream object's dictionary to decide how to decode this image.
* If no colorspace is present, we guess 3 samples per pixel.
*
* @param dict the stream dictionary
* @param buf the DCT-encoded buffer
* @param params the parameters to the decoder (ignored)
* @return the decoded buffer
*/
protected static ByteBuffer decode(PDFObject dict, ByteBuffer buf,
PDFObject params) throws PDFParseException
{
// System.out.println("DCTDecode image info: "+params);
buf.rewind();
// copy the data into a byte array required by createimage
byte[] ary = new byte[buf.remaining()];
buf.get(ary);
// copy the data into a byte array required by createimage
byte[] ary = new byte[buf.remaining()];
buf.get(ary);
Bitmap img = BitmapFactory.decodeByteArray(ary, 0, ary.length);
Bitmap img = BitmapFactory.decodeByteArray(ary, 0, ary.length);
if (img == null) throw new PDFParseException("could not decode image of compressed size " + ary.length);
Config conf = img.getConfig();
Log.e("ANDPDF.dctdecode", "decoded image type" + conf);
int size = 4 * img.getWidth() * img.getHeight();
if (conf == Config.RGB_565) {
size = 2 * img.getWidth() * img.getHeight();
if (img == null)
throw new PDFParseException("could not decode image of compressed size "+ary.length);
Config conf = img.getConfig();
Log.e("ANDPDF.dctdecode", "decoded image type"+conf);
int size = 4*img.getWidth()*img.getHeight();
if (conf == Config.RGB_565)
size = 2*img.getWidth()*img.getHeight();
// TODO [FHe]: else ... what do we get for gray? Config.ALPHA_8?
java.nio.ByteBuffer byteBuf = java.nio.ByteBuffer.allocate(size);
img.copyPixelsToBuffer(byteBuf);
ByteBuffer result = ByteBuffer.fromNIO(byteBuf);
result.rewind();
return result;
}
// TODO [FHe]: else ... what do we get for gray? Config.ALPHA_8?
java.nio.ByteBuffer byteBuf = java.nio.ByteBuffer.allocate(size);
img.copyPixelsToBuffer(byteBuf);
ByteBuffer result = ByteBuffer.fromNIO(byteBuf);
result.rewind();
return result;
}
}

View File

@ -1,22 +1,17 @@
package net.sf.andpdf.pdfviewer;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@ -25,7 +20,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -43,7 +37,6 @@ import net.sf.andpdf.nio.ByteBuffer;
import net.sf.andpdf.refs.HardReference;
import java.io.IOException;
import java.util.Locale;
import uk.co.senab.photoview.PhotoViewAttacher;
@ -64,8 +57,6 @@ public class PdfViewerFragment extends Fragment {
public static final boolean DEFAULTANTIALIAS = true;
public static final boolean DEFAULTUSEFONTSUBSTITUTION = false;
public static final String DIALOG_FRAGMENT_TAG_MARK = "DIALOG_FRAGMENT";
private GraphView mGraphView;
private PDFFile mPdfFile;
public static byte[] byteArray;
@ -221,13 +212,6 @@ public class PdfViewerFragment extends Fragment {
}
}
private void gotoPage() {
if (mPdfFile != null) {
final Bundle bundle = new Bundle();
showDialogFragment(new GoToPageDialogFragment(), bundle);
}
}
/**
* Hides device keyboard that is showing over {@link Activity}.
* Do NOT use it if keyboard is over {@link android.app.Dialog} - it won't work as they have different {@link Activity#getWindow()}.
@ -241,78 +225,11 @@ public class PdfViewerFragment extends Fragment {
getActivity().getWindow().getDecorView().requestFocus();
}
public class GoToPageDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
LayoutInflater factory = LayoutInflater.from(getActivity());
final View pagenumView = factory.inflate(R.layout.dialog_pagenumber, null);
final EditText edPagenum = (EditText) pagenumView.findViewById(R.id.pagenum_edit);
edPagenum.setText(String.format(Locale.getDefault(), "%d", mPage));
edPagenum.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event == null || (event.getAction() == 1)) {
// Hide the keyboard
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edPagenum.getWindowToken(), 0);
}
return true;
}
});
return new AlertDialog.Builder(getActivity())
//.setIcon(R.drawable.icon)
.setTitle("Jump to page")
.setView(pagenumView)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String strPagenum = edPagenum.getText().toString();
int pageNum = mPage;
try {
pageNum = Integer.parseInt(strPagenum);
} catch (NumberFormatException ignore) {
}
if ((pageNum != mPage) && (pageNum >= 1) && (pageNum <= mPdfFile.getNumPages())) {
mPage = pageNum;
mGraphView.bZoomOut.setEnabled(true);
mGraphView.bZoomIn.setEnabled(true);
progress = ProgressDialog.show(getActivity(), "Loading", "Loading PDF Page " + mPage, true, true);
startRenderThread(mPage);
}
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
})
.create();
}
}
public void showDialogFragment(@NonNull final DialogFragment dialogFragment, @Nullable final Bundle bundle) {
if (getFragmentManager().getFragments() != null) {
for (final Fragment fragment : getFragmentManager().getFragments()) {
// to fix bug with opening fragment several times on fast clicking
if (fragment != null && fragment.getClass() == dialogFragment.getClass()) {
return;
}
}
}
if (bundle != null) {
dialogFragment.setArguments(bundle);
}
dialogFragment.show(getFragmentManager(), dialogFragment.getClass().getName() + ";" + DIALOG_FRAGMENT_TAG_MARK);
}
private class GraphView extends FrameLayout {
public Bitmap mBi;
public ImageView pdfZoomedImageView;
public PhotoViewAttacher photoViewAttacher;
ImageButton bZoomOut;
ImageButton bZoomIn;
public GraphView(Context context) {
super(context);
@ -366,70 +283,64 @@ public class PdfViewerFragment extends Fragment {
// TODO: refactor
private void showPage(final int page) {
// on some Android getWidth() and getHeight() returns 0, so we need to wait until UI is ready
mGraphView.post(new Runnable() {
@Override
public void run() {
try {
// free memory from previous page
mGraphView.setPageBitmap(null);
mGraphView.updateImage();
try {
// free memory from previous page
mGraphView.setPageBitmap(null);
mGraphView.updateImage();
// Only load the page if it's a different page (i.e. not just changing the zoom level)
if (mPdfPage == null || mPdfPage.getPageNumber() != page) {
mPdfPage = mPdfFile.getPage(page, true);
}
// Only load the page if it's a different page (i.e. not just changing the zoom level)
if (mPdfPage == null || mPdfPage.getPageNumber() != page) {
mPdfPage = mPdfFile.getPage(page, true);
}
final int scale = 3;
final int scale = 3;
double width = mPdfPage.getWidth() * scale;
double height = mPdfPage.getHeight() * scale;
double width = mPdfPage.getWidth() * scale;
double height = mPdfPage.getHeight() * scale;
int maxWidthToPopulate = mGraphView.getWidth();
int maxHeightToPopulate = mGraphView.getHeight();
int maxWidthToPopulate = mGraphView.getWidth();
int maxHeightToPopulate = mGraphView.getHeight();
int calculatedWidth;
int calculatedHeight;
final double widthRatio = width / maxWidthToPopulate;
final double heightRatio = height / maxHeightToPopulate;
if (width < maxWidthToPopulate && height < maxHeightToPopulate) {
if (widthRatio > heightRatio) {
calculatedWidth = (int) (width / widthRatio);
calculatedHeight = (int) (height / widthRatio);
} else {
calculatedWidth = (int) (width / heightRatio);
calculatedHeight = (int) (height / heightRatio);
}
int calculatedWidth;
int calculatedHeight;
final double widthRatio = width / maxWidthToPopulate;
final double heightRatio = height / maxHeightToPopulate;
if (width < maxWidthToPopulate && height < maxHeightToPopulate) {
if (widthRatio > heightRatio) {
calculatedWidth = (int) (width / widthRatio);
calculatedHeight = (int) (height / widthRatio);
} else {
calculatedWidth = (int) (width / heightRatio);
calculatedHeight = (int) (height / heightRatio);
}
} else {
if (widthRatio > 1 && heightRatio > 1) {
if (widthRatio > heightRatio) {
calculatedHeight = (int) (height / widthRatio);
calculatedWidth = (int) (width / widthRatio);
} else {
if (widthRatio > 1 && heightRatio > 1) {
if (widthRatio > heightRatio) {
calculatedHeight = (int) (height / widthRatio);
calculatedWidth = (int) (width / widthRatio);
} else {
calculatedHeight = (int) (height / heightRatio);
calculatedWidth = (int) (width / heightRatio);
}
} else {
if (widthRatio > heightRatio) {
calculatedHeight = (int) (height / widthRatio);
calculatedWidth = (int) (width / widthRatio);
} else {
calculatedHeight = (int) (height / heightRatio);
calculatedWidth = (int) (width / heightRatio);
}
}
calculatedHeight = (int) (height / heightRatio);
calculatedWidth = (int) (width / heightRatio);
}
} else {
if (widthRatio > heightRatio) {
calculatedHeight = (int) (height / widthRatio);
calculatedWidth = (int) (width / widthRatio);
} else {
calculatedHeight = (int) (height / heightRatio);
calculatedWidth = (int) (width / heightRatio);
}
final Bitmap bitmap = mPdfPage.getImage(calculatedWidth, calculatedHeight, null, true, true);
mGraphView.setPageBitmap(bitmap);
mGraphView.updateImage();
} catch (Throwable e) {
Log.e(TAG, e.getMessage(), e);
}
}
});
final Bitmap bitmap = mPdfPage.getImage(calculatedWidth, calculatedHeight, null, true, true);
mGraphView.setPageBitmap(bitmap);
mGraphView.updateImage();
} catch (Throwable e) {
Log.e(TAG, e.getMessage(), e);
}
hideProgressBar();
}
private void hideProgressBar() {

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2012 Jason Polites
*
* Licensed 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 net.sf.andpdf.utils;
import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;
public class MathUtils {
public static float distance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
public static float distance(PointF p1, PointF p2) {
float x = p1.x - p2.x;
float y = p1.y - p2.y;
return FloatMath.sqrt(x * x + y * y);
}
public static float distance(float x1, float y1, float x2, float y2) {
float x = x1 - x2;
float y = y1 - y2;
return FloatMath.sqrt(x * x + y * y);
}
public static void midpoint(MotionEvent event, PointF point) {
float x1 = event.getX(0);
float y1 = event.getY(0);
float x2 = event.getX(1);
float y2 = event.getY(1);
midpoint(x1, y1, x2, y2, point);
}
public static void midpoint(float x1, float y1, float x2, float y2, PointF point) {
point.x = (x1 + x2) / 2.0f;
point.y = (y1 + y2) / 2.0f;
}
/**
* Rotates p1 around p2 by angle degrees.
*
* @param p1
* @param p2
* @param angle
*/
public void rotate(PointF p1, PointF p2, float angle) {
float px = p1.x;
float py = p1.y;
float ox = p2.x;
float oy = p2.y;
p1.x = (FloatMath.cos(angle) * (px - ox) - FloatMath.sin(angle) * (py - oy) + ox);
p1.y = (FloatMath.sin(angle) * (px - ox) + FloatMath.cos(angle) * (py - oy) + oy);
}
public static float angle(PointF p1, PointF p2) {
return angle(p1.x, p1.y, p2.x, p2.y);
}
public static float angle(float x1, float y1, float x2, float y2) {
return (float) Math.atan2(y2 - y1, x2 - x1);
}
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2012 Jason Polites
*
* Licensed 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 net.sf.andpdf.utils;
import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;
public class VectorF {
public float angle;
public float length;
public final PointF start = new PointF();
public final PointF end = new PointF();
public void calculateEndPoint() {
end.x = FloatMath.cos(angle) * length + start.x;
end.y = FloatMath.sin(angle) * length + start.y;
}
public void setStart(PointF p) {
this.start.x = p.x;
this.start.y = p.y;
}
public void setEnd(PointF p) {
this.end.x = p.x;
this.end.y = p.y;
}
public void set(MotionEvent event) {
this.start.x = event.getX(0);
this.start.y = event.getY(0);
this.end.x = event.getX(1);
this.end.y = event.getY(1);
}
public float calculateLength() {
length = MathUtils.distance(start, end);
return length;
}
public float calculateAngle() {
angle = MathUtils.angle(start, end);
return angle;
}
}