From 13d97af6894dde9e6d156904a30d8882354f7cfb Mon Sep 17 00:00:00 2001 From: "srowen@gmail.com" Date: Tue, 23 Apr 2013 08:11:46 +0000 Subject: [PATCH] Try to support data: URIs git-svn-id: https://zxing.googlecode.com/svn/trunk@2682 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- .../zxing/client/j2se/DecodeWorker.java | 22 +----- .../google/zxing/client/j2se/GUIRunner.java | 5 +- .../google/zxing/client/j2se/ImageReader.java | 75 +++++++++++++++++++ .../com/google/zxing/web/DecodeServlet.java | 29 ++++++- 4 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 javase/src/com/google/zxing/client/j2se/ImageReader.java diff --git a/javase/src/com/google/zxing/client/j2se/DecodeWorker.java b/javase/src/com/google/zxing/client/j2se/DecodeWorker.java index b8b2aef6e..24a9d5f1a 100644 --- a/javase/src/com/google/zxing/client/j2se/DecodeWorker.java +++ b/javase/src/com/google/zxing/client/j2se/DecodeWorker.java @@ -137,16 +137,7 @@ final class DecodeWorker implements Callable { } private Result decode(URI uri, Map hints) throws IOException { - BufferedImage image; - try { - image = ImageIO.read(uri.toURL()); - } catch (IllegalArgumentException ignored) { - throw new FileNotFoundException("Resource not found: " + uri); - } - if (image == null) { - System.err.println(uri.toString() + ": Could not load image"); - return null; - } + BufferedImage image = ImageReader.readImage(uri); try { LuminanceSource source; if (config.getCrop() == null) { @@ -183,16 +174,7 @@ final class DecodeWorker implements Callable { } private Result[] decodeMulti(URI uri, Map hints) throws IOException { - BufferedImage image; - try { - image = ImageIO.read(uri.toURL()); - } catch (IllegalArgumentException ignored) { - throw new FileNotFoundException("Resource not found: " + uri); - } - if (image == null) { - System.err.println(uri.toString() + ": Could not load image"); - return null; - } + BufferedImage image = ImageReader.readImage(uri); try { LuminanceSource source; if (config.getCrop() == null) { diff --git a/javase/src/com/google/zxing/client/j2se/GUIRunner.java b/javase/src/com/google/zxing/client/j2se/GUIRunner.java index 9df1f6f8b..0e67f1b38 100644 --- a/javase/src/com/google/zxing/client/j2se/GUIRunner.java +++ b/javase/src/com/google/zxing/client/j2se/GUIRunner.java @@ -87,13 +87,10 @@ public final class GUIRunner extends JFrame { private static String getDecodeText(File file) { BufferedImage image; try { - image = ImageIO.read(file); + image = ImageReader.readImage(file); } catch (IOException ioe) { return ioe.toString(); } - if (image == null) { - return "Could not decode image"; - } LuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result; diff --git a/javase/src/com/google/zxing/client/j2se/ImageReader.java b/javase/src/com/google/zxing/client/j2se/ImageReader.java new file mode 100644 index 000000000..e06bd7d7f --- /dev/null +++ b/javase/src/com/google/zxing/client/j2se/ImageReader.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013 ZXing authors + * + * 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 com.google.zxing.client.j2se; + +import javax.imageio.ImageIO; +import javax.xml.bind.DatatypeConverter; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URLDecoder; + +/** + * Encapsulates reading URIs as images. + * + * @author Sean Owen + */ +public final class ImageReader { + + private static final String BASE64TOKEN = "base64,"; + + private ImageReader() { + } + + public static BufferedImage readImage(URI uri) throws IOException { + if ("data".equals(uri.getScheme())) { + return readDataURIImage(uri); + } + BufferedImage result; + try { + result = ImageIO.read(uri.toURL()); + } catch (IllegalArgumentException iae) { + throw new IOException("Resource not found: " + uri, iae); + } + if (result == null) { + throw new IOException("Could not load " + uri); + } + return result; + } + + public static BufferedImage readDataURIImage(URI uri) throws IOException { + String uriString = uri.toString(); + if (!uriString.startsWith("data:image/")) { + throw new IOException("Unsupported data URI MIME type"); + } + int base64Start = uriString.indexOf(BASE64TOKEN); + if (base64Start < 0) { + throw new IOException("Unsupported data URI encoding"); + } + String base64DataEncoded = uriString.substring(base64Start + BASE64TOKEN.length()); + String base64Data = URLDecoder.decode(base64DataEncoded, "UTF-8"); + byte[] imageBytes = DatatypeConverter.parseBase64Binary(base64Data); + return ImageIO.read(new ByteArrayInputStream(imageBytes)); + } + + public static BufferedImage readImage(File file) throws IOException { + return readImage(file.toURI()); + } + +} diff --git a/zxingorg/src/com/google/zxing/web/DecodeServlet.java b/zxingorg/src/com/google/zxing/web/DecodeServlet.java index 3138e0d56..5a235912c 100644 --- a/zxingorg/src/com/google/zxing/web/DecodeServlet.java +++ b/zxingorg/src/com/google/zxing/web/DecodeServlet.java @@ -28,6 +28,7 @@ import com.google.zxing.Reader; import com.google.zxing.ReaderException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; +import com.google.zxing.client.j2se.ImageReader; import com.google.zxing.common.GlobalHistogramBinarizer; import com.google.zxing.common.HybridBinarizer; @@ -126,13 +127,30 @@ public final class DecodeServlet extends HttpServlet { imageURIString = "http://" + imageURIString; } - URL imageURL; + URI imageURI; try { - imageURL = new URI(imageURIString).toURL(); + imageURI = new URI(imageURIString); } catch (URISyntaxException ignored) { log.info("URI was not valid: " + imageURIString); response.sendRedirect("badurl.jspx"); return; + } + + // Shortcut for data URI + if ("data".equals(imageURI.getScheme())) { + try { + BufferedImage image = ImageReader.readDataURIImage(imageURI); + processImage(image, request, response); + } catch (IOException ioe) { + log.info(ioe.toString()); + response.sendRedirect("badurl.jspx"); + return; + } + } + + URL imageURL; + try { + imageURL = imageURI.toURL(); } catch (MalformedURLException ignored) { log.info("URI was not valid: " + imageURIString); response.sendRedirect("badurl.jspx"); @@ -289,6 +307,13 @@ public final class DecodeServlet extends HttpServlet { response.sendRedirect("badimage.jspx"); return; } + + processImage(image, request, response); + } + + private static void processImage(BufferedImage image, + ServletRequest request, + HttpServletResponse response) throws IOException, ServletException { Reader reader = new MultiFormatReader(); LuminanceSource source = new BufferedImageLuminanceSource(image);