mirror of
https://github.com/zxing/zxing.git
synced 2024-11-10 04:54:04 -08:00
Various improvements to decode speed and efficiency of J2ME client
git-svn-id: https://zxing.googlecode.com/svn/trunk@257 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
4abc8aecec
commit
8c03ed9301
|
@ -37,7 +37,7 @@ final class AdvancedMultimediaManager {
|
|||
|
||||
private static final int NO_ZOOM = 100;
|
||||
private static final int MAX_ZOOM = 200;
|
||||
private static final long FOCUS_TIME_MS = 1000L;
|
||||
private static final long FOCUS_TIME_MS = 750L;
|
||||
|
||||
private AdvancedMultimediaManager() {
|
||||
// do nothing
|
||||
|
|
|
@ -117,19 +117,27 @@ public final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapS
|
|||
}
|
||||
|
||||
/**
|
||||
* Extracts luminance from a pixel from this source. By default, the source is assumed to use RGB,
|
||||
* so this implementation computes luminance is a function of a red, green and blue components as
|
||||
* follows:
|
||||
*
|
||||
* <code>Y = 0.299R + 0.587G + 0.114B</code>
|
||||
*
|
||||
* where R, G, and B are values in [0,1].
|
||||
* An optimized approximation of a more proper conversion from RGB to luminance which
|
||||
* only uses shifts. See BufferedImageMonochromeBitmapSource for an original version.
|
||||
*/
|
||||
private static int computeRGBLuminance(int pixel) {
|
||||
// Coefficients add up to 1024 to make the divide into a fast shift
|
||||
return (306 * ((pixel >> 16) & 0xFF) +
|
||||
601 * ((pixel >> 8) & 0xFF) +
|
||||
117 * (pixel & 0xFF)) >> 10;
|
||||
// Instead of multiplying by 306, 601, 117, we multiply by 256, 512, 256, so that
|
||||
// the multiplies can be implemented as shifts.
|
||||
//
|
||||
// Really, it's:
|
||||
//
|
||||
// return ((((pixel >> 16) & 0xFF) << 8) +
|
||||
// (((pixel >> 8) & 0xFF) << 9) +
|
||||
// (( pixel & 0xFF) << 8)) >> 10;
|
||||
//
|
||||
// That is, we're replacing the coefficients in the original with powers of two,
|
||||
// which can be implemented as shifts, even though changing the coefficients slightly
|
||||
// corrupts the conversion. Not significant for our purposes.
|
||||
//
|
||||
// But we can get even cleverer and eliminate a few shifts:
|
||||
return (((pixel & 0x00FF0000) >> 8) +
|
||||
((pixel & 0x0000FF00) << 1) +
|
||||
((pixel & 0x000000FF) << 8)) >> 10;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,56 +28,64 @@ import javax.microedition.media.Player;
|
|||
import javax.microedition.media.control.VideoControl;
|
||||
|
||||
/**
|
||||
* Thread which does the work of capturing a frame and decoding it.
|
||||
*
|
||||
* @author Sean Owen (srowen@google.com)
|
||||
*/
|
||||
final class SnapshotThread extends Thread {
|
||||
|
||||
private static SnapshotThread currentThread;
|
||||
|
||||
private final ZXingMIDlet zXingMIDlet;
|
||||
private final Object waitLock;
|
||||
private boolean done;
|
||||
|
||||
private SnapshotThread(ZXingMIDlet zXingMIDlet) {
|
||||
SnapshotThread(ZXingMIDlet zXingMIDlet) {
|
||||
this.zXingMIDlet = zXingMIDlet;
|
||||
waitLock = new Object();
|
||||
done = false;
|
||||
}
|
||||
|
||||
static synchronized void startThread(ZXingMIDlet zXingMIDlet) {
|
||||
if (currentThread == null) {
|
||||
currentThread = new SnapshotThread(zXingMIDlet);
|
||||
currentThread.start();
|
||||
void continueRun() {
|
||||
synchronized (waitLock) {
|
||||
waitLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForSignal() {
|
||||
synchronized (waitLock) {
|
||||
try {
|
||||
waitLock.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
done = true;
|
||||
continueRun();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Player player = zXingMIDlet.getPlayer();
|
||||
try {
|
||||
AdvancedMultimediaManager.setFocus(player);
|
||||
do {
|
||||
waitForSignal();
|
||||
try {
|
||||
player.stop();
|
||||
AdvancedMultimediaManager.setFocus(player);
|
||||
byte[] snapshot = takeSnapshot();
|
||||
Image capturedImage = Image.createImage(snapshot, 0, snapshot.length);
|
||||
MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
|
||||
Reader reader = new MultiFormatReader();
|
||||
Result result = reader.decode(source);
|
||||
zXingMIDlet.handleDecodedText(result.getText());
|
||||
} catch (ReaderException re) {
|
||||
// Show a friendlier message on a mere failure to read the barcode
|
||||
zXingMIDlet.showError("Sorry, no barcode was found.");
|
||||
} catch (MediaException me) {
|
||||
// continue
|
||||
zXingMIDlet.showError(me);
|
||||
} catch (RuntimeException re) {
|
||||
zXingMIDlet.showError(re);
|
||||
}
|
||||
byte[] snapshot = takeSnapshot();
|
||||
Image capturedImage = Image.createImage(snapshot, 0, snapshot.length);
|
||||
MonochromeBitmapSource source = new LCDUIImageMonochromeBitmapSource(capturedImage);
|
||||
Reader reader = new MultiFormatReader();
|
||||
Result result = reader.decode(source);
|
||||
zXingMIDlet.handleDecodedText(result.getText());
|
||||
} catch (ReaderException re) {
|
||||
// Show a friendlier message on a mere failure to read the barcode
|
||||
zXingMIDlet.showError("Sorry, no barcode was found.");
|
||||
} catch (MediaException me) {
|
||||
zXingMIDlet.showError(me);
|
||||
} catch (RuntimeException re) {
|
||||
zXingMIDlet.showError(re);
|
||||
} finally {
|
||||
try {
|
||||
player.start();
|
||||
} catch (MediaException me) {
|
||||
// continue
|
||||
}
|
||||
currentThread = null;
|
||||
}
|
||||
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
private byte[] takeSnapshot() throws MediaException {
|
||||
|
|
|
@ -23,6 +23,9 @@ import javax.microedition.lcdui.Displayable;
|
|||
import javax.microedition.lcdui.Graphics;
|
||||
|
||||
/**
|
||||
* The main {@link Canvas} onto which the camera's field of view is painted.
|
||||
* This class manages decoding via {@link SnapshotThread}.
|
||||
*
|
||||
* @author Sean Owen (srowen@google.com)
|
||||
*/
|
||||
final class VideoCanvas extends Canvas implements CommandListener {
|
||||
|
@ -30,11 +33,14 @@ final class VideoCanvas extends Canvas implements CommandListener {
|
|||
private static final Command exit = new Command("Exit", Command.EXIT, 1);
|
||||
|
||||
private final ZXingMIDlet zXingMIDlet;
|
||||
private final SnapshotThread snapshotThread;
|
||||
|
||||
VideoCanvas(ZXingMIDlet zXingMIDlet) {
|
||||
this.zXingMIDlet = zXingMIDlet;
|
||||
addCommand(exit);
|
||||
setCommandListener(this);
|
||||
snapshotThread = new SnapshotThread(zXingMIDlet);
|
||||
snapshotThread.start();
|
||||
}
|
||||
|
||||
protected void paint(Graphics graphics) {
|
||||
|
@ -44,12 +50,16 @@ final class VideoCanvas extends Canvas implements CommandListener {
|
|||
protected void keyPressed(int keyCode) {
|
||||
// Any valid game key will trigger a capture
|
||||
if (getGameAction(keyCode) != 0) {
|
||||
SnapshotThread.startThread(zXingMIDlet);
|
||||
snapshotThread.continueRun();
|
||||
} else {
|
||||
super.keyPressed(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void commandAction(Command command, Displayable displayable) {
|
||||
if (command.getCommandType() == Command.EXIT || command.getCommandType() == Command.STOP) {
|
||||
int type = command.getCommandType();
|
||||
if (type == Command.EXIT || type == Command.STOP || type == Command.BACK || type == Command.CANCEL) {
|
||||
snapshotThread.stop();
|
||||
zXingMIDlet.stop();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue