Skip to content

Commit

Permalink
Fixed bugs in scrollview and upgraded piccolo to 3.0
Browse files Browse the repository at this point in the history
git-svn-id: https://tesseract-ocr.googlecode.com/svn/trunk@1026 d0cd1f9f-072b-0410-8dd7-cf729c803f20
  • Loading branch information
theraysmith@gmail.com committed Jan 29, 2014
1 parent ad14984 commit 99e1f05
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 346 deletions.
6 changes: 3 additions & 3 deletions java/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ SCROLLVIEW_CLASSES = \
com/google/scrollview/ScrollView.class

SCROLLVIEW_LIBS = \
$(srcdir)/piccolo-1.2.jar \
$(srcdir)/piccolox-1.2.jar
$(srcdir)/piccolo2d-core-3.0.jar \
$(srcdir)/piccolo2d-extras-3.0.jar

CLASSPATH = $(srcdir)/piccolo-1.2.jar:$(srcdir)/piccolox-1.2.jar
CLASSPATH = $(srcdir)/piccolo2d-core-3.0.jar:$(srcdir)/piccolo2d-extras-3.0.jar

ScrollView.jar : $(SCROLLVIEW_CLASSES)
$(JAR) cf $@ com/google/scrollview/*.class \
Expand Down
43 changes: 11 additions & 32 deletions java/com/google/scrollview/ScrollView.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.google.scrollview.events.SVEvent;
import com.google.scrollview.ui.SVImageHandler;
import com.google.scrollview.ui.SVWindow;
import org.piccolo2d.nodes.PImage;

import java.io.BufferedReader;
import java.io.IOException;
Expand All @@ -23,7 +24,6 @@
import java.util.ArrayList;
import java.util.regex.Pattern;


/**
* The ScrollView class is the main class which gets started from the command
* line. It sets up LUA and handles the network processing.
Expand Down Expand Up @@ -115,29 +115,10 @@ private static void IOLoop() {
first = !first;
}
assert first;
} else if (SVImageHandler.getReadImageData() == false) {
// If we are currently not transmitting an image, process this
// normally.
} else {
// Process this normally.
processInput(inputLine);
}
// We are still transmitting image data, but there seems to be some
// command at the
// end of the message attached as well. Thus, we have to split it
// accordingly and
// first generate the image and afterwards process the remaining
// message.
else if (inputLine.length() >
SVImageHandler.getMissingRemainingBytes()) {
String luaCmd = inputLine.substring(
SVImageHandler.getMissingRemainingBytes());
String imgData = inputLine.substring(0,
SVImageHandler.getMissingRemainingBytes());
SVImageHandler.parseData(imgData);
processInput(luaCmd);
} else { // We are still in the middle of image data and have not
// reached the end yet.
SVImageHandler.parseData(inputLine);
}
}
}
// Some connection error
Expand Down Expand Up @@ -228,6 +209,9 @@ private static void parseArguments(String argList,

/** Executes the LUA command parsed as parameter. */
private static void processInput(String inputLine) {
if (inputLine == null) {
return;
}
// Execute a function encoded as a LUA statement! Yuk!
if (inputLine.charAt(0) == 'w') {
// This is a method call on a window. Parse it.
Expand Down Expand Up @@ -298,11 +282,6 @@ private static void processInput(String inputLine) {
} else if (func.equals("drawText")) {
windows.get(windowID).drawText(intList.get(0), intList.get(1),
stringList.get(0));
} else if (func.equals("openImage")) {
windows.get(windowID).openImage(stringList.get(0));
} else if (func.equals("drawImage")) {
windows.get(windowID).drawImage(stringList.get(0),
intList.get(0), intList.get(1));
} else if (func.equals("addMenuBarItem")) {
if (boolList.size() > 0) {
windows.get(windowID).addMenuBarItem(stringList.get(0),
Expand Down Expand Up @@ -337,12 +316,12 @@ private static void processInput(String inputLine) {
} else if (func.equals("zoomRectangle")) {
windows.get(windowID).zoomRectangle(intList.get(0), intList.get(1),
intList.get(2), intList.get(3));
} else if (func.equals("createImage")) {
windows.get(windowID).createImage(stringList.get(0), intList.get(0),
intList.get(1), intList.get(2));
} else if (func.equals("readImage")) {
PImage image = SVImageHandler.readImage(intList.get(2), in);
windows.get(windowID).drawImage(image, intList.get(0), intList.get(1));
} else if (func.equals("drawImage")) {
windows.get(windowID).drawImage(stringList.get(0),
intList.get(0), intList.get(1));
PImage image = new PImage(stringList.get(0));
windows.get(windowID).drawImage(image, intList.get(0), intList.get(1));
} else if (func.equals("destroy")) {
windows.get(windowID).destroy();
}
Expand Down
10 changes: 5 additions & 5 deletions java/com/google/scrollview/events/SVEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@

import javax.swing.Timer;

import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.nodes.PPath;
import org.piccolo2d.PCamera;
import org.piccolo2d.PNode;
import org.piccolo2d.event.PBasicInputEventHandler;
import org.piccolo2d.event.PInputEvent;
import org.piccolo2d.nodes.PPath;

/**
* The ScrollViewEventHandler takes care of any events which might happen on the
Expand Down
233 changes: 37 additions & 196 deletions java/com/google/scrollview/ui/SVImageHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2007 Google Inc. All Rights Reserved.
//
//
// 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
Expand All @@ -10,219 +10,60 @@

package com.google.scrollview.ui;

import edu.umd.cs.piccolo.nodes.PImage;
import org.piccolo2d.nodes.PImage;

import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.xml.bind.DatatypeConverter;

/**
* The ScrollViewImageHandler is a helper class which takes care of image
* processing. It is used to construct an Image from the message-stream and
* basically consists of a number of utility functions to process the input
* stream.
*
*
* @author wanke@google.com
*/
public class SVImageHandler {
/**
* Stores a mapping from the name of the string to its actual image. It
* enables us to re-use images without having to load or transmit them again
*/
static HashMap<String, PImage> images = new HashMap<String, PImage>();

/** A global flag stating whether we are currently expecting Image data */
static boolean readImageData = false;

// TODO(wanke) Consider moving all this into an SVImage class.
/** These are all values belonging to the image which is currently being read */
static String imageName = null; // Image name
static int bytesRead = 0; // Nr. of bytes already read
static int bpp = 0; // Bit depth
static int pictureArray[]; // The array holding the actual image

static int bytePerPixel = 0; // # of used bytes to transmit a pixel (32 bpp
// -> 7 BPP)
static int width = 0;
static int height = 0;

/* All methods are static, so we forbid to construct SVImageHandler objects */
private SVImageHandler() {
}

/**
* Takes a binary input string (consisting of '0' and '1' characters) and
* converts it to an integer representation usable as image data.
* Reads size bytes from the stream in and interprets it as an image file,
* encoded as png, and then text-encoded as base 64, returning the decoded
* bitmap.
*
* @param size The size of the image file.
* @param in The input stream from which to read the bytes.
*/
private static int[] processBinaryImage(String inputLine) {
int BLACK = 0;
int WHITE = Integer.MAX_VALUE;

int[] imgData = new int[inputLine.length()];

for (int i = 0; i < inputLine.length(); i++) {
if (inputLine.charAt(i) == '0') {
imgData[i] = WHITE;
} else if (inputLine.charAt(i) == '1') {
imgData[i] = BLACK;
} // BLACK is default anyway
else { // Something is wrong: We did get unexpected data
System.out.println("Error: unexpected non-image-data: ("
+ SVImageHandler.bytesRead + "," + inputLine.length() + ","
+ (SVImageHandler.height * SVImageHandler.width) + ")");
System.exit(1);
public static PImage readImage(int size, BufferedReader in) {
char[] charbuffer = new char[size];
int numRead = 0;
while (numRead < size) {
int newRead = -1;
try {
newRead = in.read(charbuffer, numRead, size - numRead);
} catch (IOException e) {
System.out.println("Failed to read image data from socket" + e.getMessage());
}
if (newRead < 0) {
return null;
}
numRead += newRead;
}
return imgData;
}

/**
* Takes an input string with pixel depth of 8 (represented by 2 bytes in
* hexadecimal format, e.g. FF for white) and converts it to an
* integer representation usable as image data
*/
private static int[] processGrayImage(String inputLine) {
int[] imgData = new int[inputLine.length() / 2];
// Note: This is really inefficient, splitting it 2-byte-arrays in one pass
// would be wa faster than substring everytime.
for (int i = 0; i < inputLine.length(); i +=2) {
String s = inputLine.substring(i, i+1);
imgData[i] = Integer.parseInt(s, 16);
}

return imgData;
}

/**
* Takes an input string with pixel depth of 32 (represented by HTML-like
* colors in hexadecimal format, e.g. #00FF00 for green) and converts it to an
* integer representation usable as image data
*/
private static int[] process32bppImage(String inputLine) {

String[] strData = inputLine.split("#");
int[] imgData = new int[strData.length - 1];

for (int i = 1; i < strData.length; i++) {
imgData[i - 1] = Integer.parseInt(strData[i], 16);
}

return imgData;
}

/**
* Called when all image data is transmitted. Generates the actual image used
* by java and puts it into the images-hashmap.
*/
private static void closeImage() {

BufferedImage bi = null;
if (bpp == 1) {
bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
} else if (bpp == 8) {
bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
} else if (bpp == 32) {
bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
} else {
System.out.println("Unsupported Image Type: " + bpp + " bpp");
System.exit(1);
}

bi.setRGB(0, 0, width, height, pictureArray, 0, width);

PImage img = new PImage(bi);

images.put(imageName, img);

imageName = null;
readImageData = false;

System.out.println("(server, #Bytes:" + bytesRead + ") Image Completed");

bytesRead = 0;
bpp = 0;
}

/** Starts creation of a new image. */
public static void createImage(String name, int width, int height,
int bitsPerPixel) {
// Create buffered image that does not support transparency
bpp = bitsPerPixel;
if (bpp == 1) {
bytePerPixel = 1;
} else if (bpp == 8) {
bytePerPixel = 2;
} else if (bpp == 32) {
bytePerPixel = 7;
} else {
throw new IllegalArgumentException(
"bpp should be 1 (binary), 8 (gray) or 32 (argb), is " + bpp);
}
if (imageName != null) {
throw new IllegalArgumentException("Image " + imageName + " already opened!");
}
else {
imageName = name;
bytesRead = 0;
readImageData = true;
SVImageHandler.height = height;
SVImageHandler.width = width;
pictureArray = new int[width * height];
}

System.out.println("Processing Image with " + bpp + " bpp, size " + width + "x" + height);
}

/**
* Opens an Image from location. This means the image does not have to be
* actually transfered over the network. Thus, it is a lot faster than using
* the createImage method.
*
* @param location The (local) location from where to open the file. This is
* also the internal name associated with the image (if you want to draw it).
*/
public static void openImage(String location) {
PImage img = new PImage(location);
images.put(location, img);
}

/** Find the image corresponding to a given name */
public static PImage getImage(String name) {
return images.get(name);
}

/**
* Gets called while currently reading image data. Decides, how to process it
* (which image type, whether all data is there).
*/
public static void parseData(String inputLine) {
int[] data = null;

if (bpp == 1) {
data = processBinaryImage(inputLine);
} else if (bpp == 8) {
data = processGrayImage(inputLine);
} else if (bpp == 32) {
data = process32bppImage(inputLine);
} else {
System.out.println("Unsupported Bit Type: " + bpp);
}

System.arraycopy(data, 0, pictureArray, bytesRead, data.length);
bytesRead += data.length;

// We have read all image data - close the image
if (bytesRead == (height * width)) {
closeImage();
// Convert the character data to binary.
byte[] binarydata = DatatypeConverter.parseBase64Binary(new String(charbuffer));
// Convert the binary data to a byte stream and parse to image.
ByteArrayInputStream byteStream = new ByteArrayInputStream(binarydata);
try {
PImage img = new PImage(ImageIO.read(byteStream));
return img;
} catch (IOException e) {
System.out.println("Failed to decode image data from socket" + e.getMessage());
}
}

/** Returns whether we a currently reading image data or not */
public static boolean getReadImageData() {
return readImageData;
}

/** Computes how many bytes of the image data are still missing */
public static int getMissingRemainingBytes() {
return (height * width * bytePerPixel) - bytesRead;
return null;
}
}
Loading

0 comments on commit 99e1f05

Please sign in to comment.