Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 940d46fe50ddb7fbec93679e5d8c0a3d7073d629 Nicholas C. Zakas committed Oct 26, 2009
2 .gitignore
@@ -0,0 +1,2 @@
+build/
+nbproject/
31 README
@@ -0,0 +1,31 @@
+DataURI
+=======
+
+Copyright (c) 2009 Nicholas C. Zakas. All rights reserved.
+
+About
+-----
+
+DataURI is a small program/library to make creation of data URIs for web
+content quick and easy.
+
+License
+-------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
8 ant.properties
@@ -0,0 +1,8 @@
+src.dir = src
+lib.dir = lib
+doc.dir = doc
+build.dir = build
+product.name = datauri
+version.number = 0.0.1
+jar.name = ${product.name}-${version.number}.jar
+dist.package.name = ${product.name}-${version.number}
64 build.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<project name="DataURI" default="build.jar" basedir=".">
+
+ <target name="clean" depends="-load.properties">
+ <delete dir="${build.dir}" quiet="true"/>
+ </target>
+
+ <target name="-load.properties">
+ <property file="ant.properties"/>
+ </target>
+
+ <target name="-init" depends="-load.properties">
+ <mkdir dir="${build.dir}"/>
+ </target>
+
+ <target name="build.classes" depends="-init">
+ <mkdir dir="${build.dir}/classes"/>
+ <javac srcdir="${src.dir}"
+ destdir="${build.dir}/classes"
+ includes="**/*.java"
+ deprecation="off"
+ debug="on"
+ source="1.4">
+ <classpath>
+ <pathelement location="${lib.dir}/jargs-1.0.jar"/>
+ <pathelement location="${lib.dir}/commons-codec-1.4.jar" />
+ </classpath>
+ </javac>
+ </target>
+
+ <target name="build.jar" depends="build.classes">
+ <mkdir dir="${build.dir}/jar"/>
+ <unjar src="${lib.dir}/jargs-1.0.jar" dest="${build.dir}/jar"/>
+ <unjar src="${lib.dir}/commons-codec-1.4.jar" dest="${build.dir}/jar"/>
+ <copy todir="${build.dir}/jar">
+ <fileset dir="${build.dir}/classes" includes="**/*.class"/>
+ </copy>
+ <jar destfile="${build.dir}/${jar.name}" basedir="${build.dir}/jar">
+ <manifest>
+ <attribute name="Main-Class" value="net.nczonline.web.datauri.DataURI"/>
+ </manifest>
+ </jar>
+ </target>
+
+ <target name="build.dist.package" depends="build.jar">
+ <mkdir dir="${build.dir}/${dist.package.name}"/>
+ <mkdir dir="${build.dir}/${dist.package.name}/build"/>
+ <copy file="${build.dir}/${jar.name}" todir="${build.dir}/${dist.package.name}/build"/>
+ <copy todir="${build.dir}/${dist.package.name}">
+ <fileset dir=".">
+ <include name="ant.properties"/>
+ <include name="build.xml"/>
+ <include name="doc/**/*"/>
+ <include name="lib/**/*"/>
+ <include name="src/**/*"/>
+ <exclude name="**/.git"/>
+ </fileset>
+ </copy>
+ <zip destfile="${build.dir}/${dist.package.name}.zip"
+ basedir="${build.dir}"
+ includes="${dist.package.name}/**/*"/>
+ </target>
+
+</project>
BIN lib/commons-codec-1.4.jar
Binary file not shown.
BIN lib/jargs-1.0.jar
Binary file not shown.
159 src/net/nczonline/web/datauri/DataURI.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009 Nicholas C. Zakas. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package net.nczonline.web.datauri;
+
+import jargs.gnu.CmdLineParser;
+import java.io.*;
+import java.nio.charset.Charset;
+
+/*
+ * This file heavily inspired and based on YUI Compressor.
+ * http://github.com/yui/yuicompressor
+ */
+
+public class DataURI {
+
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+
+ //default settings
+ boolean verbose = false;
+ String charset = null;
+ String outputFilename = null;
+ Writer out = null;
+ Reader in = null;
+ String mimeType = null;
+ String inputCharset = null;
+
+
+ //initialize command line parser
+ CmdLineParser parser = new CmdLineParser();
+ CmdLineParser.Option verboseOpt = parser.addBooleanOption('v', "verbose");
+ CmdLineParser.Option mimeTypeOpt = parser.addStringOption('m', "mime");
+ CmdLineParser.Option helpOpt = parser.addBooleanOption('h', "help");
+ CmdLineParser.Option charsetOpt = parser.addStringOption("charset");
+ CmdLineParser.Option outputFilenameOpt = parser.addStringOption('o', "output");
+
+ try {
+
+ //parse the arguments
+ parser.parse(args);
+
+ //figure out if the help option has been executed
+ Boolean help = (Boolean) parser.getOptionValue(helpOpt);
+ if (help != null && help.booleanValue()) {
+ usage();
+ System.exit(0);
+ }
+
+ //determine boolean options
+ verbose = parser.getOptionValue(verboseOpt) != null;
+
+ //check for charset
+ charset = (String) parser.getOptionValue(charsetOpt);
+
+ //check for MIME type
+ mimeType = (String) parser.getOptionValue(mimeTypeOpt);
+
+ //get the file arguments
+ String[] fileArgs = parser.getRemainingArgs();
+
+ //need to have at least one file
+ if (fileArgs.length == 0){
+ System.err.println("No files specified.");
+ System.exit(1);
+ }
+
+ String inputFilename = fileArgs[0];
+ //inputCharset = DataURIGenerator.getCharset(inputFilename, charset);
+
+// if (DataURIGenerator.isImageFile(inputFilename)){
+// if (verbose){
+// System.err.println("[INFO] Image file detecting, not using specified charset.");
+// }
+// in = new InputStreamReader(new FileInputStream(inputFilename));
+// } else {
+// in = new InputStreamReader(new FileInputStream(inputFilename), inputCharset);
+// }
+
+
+ //get output filename
+ outputFilename = (String) parser.getOptionValue(outputFilenameOpt);
+
+ if (outputFilename == null) {
+ if (charset == null){
+ out = new OutputStreamWriter(System.out);
+ } else {
+ out = new OutputStreamWriter(System.out, charset);
+ }
+ } else {
+ if (verbose){
+ System.err.println("[INFO] Output file is '" + (new File(outputFilename)).getAbsolutePath() + "'");
+ }
+ out = new OutputStreamWriter(new FileOutputStream(outputFilename), charset);
+ }
+
+
+
+ //close just in case out is the same as in
+ //in.close(); in = null;
+
+ //generate
+ DataURIGenerator.generate(new File(inputFilename), out, mimeType, charset, verbose);
+ } catch (CmdLineParser.OptionException e) {
+ usage();
+ System.exit(1);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.err.println(e.getMessage());
+ System.exit(1);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Outputs help information to the console.
+ */
+ private static void usage() {
+ System.out.println(
+ "\nUsage: java -jar combiner-x.y.z.jar [options] [input files]\n\n"
+
+ + "Global Options\n"
+ + " -h, --help Displays this information.\n"
+ + " --charset <charset> Read the input file and write data URI using <charset>.\n"
+ + " -v, --verbose Display informational messages and warnings.\n"
+ + " -m, --mime <type> Mime type to encode into the data URI.\n"
+ + " -o <file> Place the output into <file>. Defaults to stdout.");
+ }
+}
223 src/net/nczonline/web/datauri/DataURIGenerator.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2009 Nicholas C. Zakas. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package net.nczonline.web.datauri;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.HashMap;
+import org.apache.commons.codec.binary.Base64;
+import java.awt.image. BufferedImage;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import javax.imageio.ImageIO;
+
+
+public class DataURIGenerator {
+
+
+ private static HashMap imageTypes = new HashMap();
+ private static HashMap textTypes = new HashMap();
+
+ static {
+ imageTypes.put("gif", "image/gif");
+ imageTypes.put("jpg", "image/jpeg");
+ imageTypes.put("png", "image/png");
+ imageTypes.put("jpeg", "image/jpeg");
+
+ textTypes.put("htm", "text/html");
+ textTypes.put("html", "text/html");
+ textTypes.put("xml", "application/xml");
+ textTypes.put("xhtml", "application/xhtml+xml");
+ textTypes.put("js", "application/x-javascript");
+ textTypes.put("css", "text/css");
+ textTypes.put("txt", "text/plain");
+ }
+
+
+ public static void generate(File file, Writer out, boolean verbose) throws IOException, UnsupportedCharsetException {
+ generate(file, out, null, verbose);
+ }
+
+ public static void generate(File file, Writer out, String mimeType, boolean verbose) throws IOException, UnsupportedCharsetException {
+ generate(file, out, null, null, verbose);
+ }
+
+ public static void generate(File file, Writer out, String mimeType, String charset, boolean verbose) throws IOException, UnsupportedCharsetException {
+ //if (isImageFile(file.getName())){
+ // generateImage(file, out, mimeType, verbose);
+ //} else {
+ // generateText(file, out, mimeType, charset, verbose);
+ //}
+ generateDataURI(file, out, getMimeType(file.getName(), mimeType, verbose), getCharset(file.getName(), charset, verbose), verbose);
+ }
+
+ private static void generateImage(File file, Writer out, String mimeType, boolean verbose) throws IOException {
+
+ //have to read images in using ImageIO to avoid encoding issues
+ String imageType = getImageType(file.getName());
+ BufferedImage image = ImageIO.read(file);
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ ImageIO.write(image, imageType, bytes);
+ bytes.flush();
+ byte[] rawBytes = bytes.toByteArray();
+ bytes.close();
+
+ if (verbose){
+ System.err.println("[INFO] Image is of type '" + imageType + "'.");
+ }
+
+ generateDataURI(rawBytes, out, getMimeType(file.getName(), mimeType, verbose), null, verbose);
+ }
+
+
+ private static void generateDataURI(File file, Writer out, String mimeType, String charset, boolean verbose) throws IOException{
+
+ //read the bytes from the file
+ InputStream in = new FileInputStream(file);
+ byte[] bytes = new byte[(int) file.length()];
+ in.read(bytes);
+ in.close();
+
+ //actually write
+ generateDataURI(bytes, out, mimeType, charset, verbose);
+ }
+
+ private static void generateDataURI(byte[] bytes, Writer out, String mimeType, String charset, boolean verbose) throws IOException {
+ //create the output
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("data:");
+
+ //add MIME type
+ buffer.append(mimeType);
+
+ //add charset if necessary
+ if (charset != null){
+ buffer.append(";charset=" + charset);
+ }
+
+ //output base64-encoding
+ buffer.append(";base64,");
+ buffer.append(new String(Base64.encodeBase64(bytes)));
+
+ //output to writer
+ out.write(buffer.toString());
+ }
+
+ /**
+ * Determines if the given filename represents an image file.
+ * @param filename The filename to check.
+ * @return True if the filename represents an image, false if not.
+ */
+ private static boolean isImageFile(String filename){
+ return imageTypes.containsKey(getFileType(filename));
+ }
+
+ /**
+ * Retrieves the extension for the filename.
+ * @param filename The filename to get the extension from.
+ * @return All characters after the final "." in the filename.
+ */
+ private static String getFileType(String filename){
+ String type = "";
+
+ int idx = filename.lastIndexOf('.');
+ if (idx >= 0 && idx < filename.length() - 1) {
+ type = filename.substring(idx + 1);
+ }
+
+ return type;
+ }
+
+ private static String getImageType(String filename){
+ String type = getFileType(filename);
+ if (type.equals("gif")){
+ return "GIF";
+ } else if (type.equals("jpeg") || type.equals("jpg")){
+ return "JPEG";
+ } else {
+ return "PNG";
+ }
+ }
+
+ private static String getMimeType(String filename, String mimeType, boolean verbose) throws IOException {
+ if (mimeType == null){
+
+ String type = getFileType(filename);
+
+ //if it's an image type, don't use a charset
+ if (imageTypes.containsKey(type)){
+ mimeType = (String) imageTypes.get(type);
+ } else if (textTypes.containsKey(type)){
+ mimeType = (String) textTypes.get(type);
+ } else {
+ throw new IOException("No MIME type provided and MIME type couldn't be automatically determined.");
+ }
+
+ if (verbose){
+ System.err.println("[INFO] No MIME type provided, defaulting to '" + mimeType + "'.");
+ }
+ }
+
+ return mimeType;
+ }
+
+ private static String getCharset(String filename, String charset, boolean verbose) {
+ if (charset != null){
+
+ if (Charset.isSupported(charset)){
+
+ if (isImageFile(filename)){
+ if (verbose){
+ System.err.println("[INFO] Image file detected, skipping charset '" + charset + "'.");
+ }
+ charset = null;
+ } else {
+ if (verbose){
+ System.err.println("[INFO] Using charset '" + charset + "'.");
+ }
+ }
+
+
+ } else {
+ charset = null;
+ if (verbose){
+ System.err.println("[INFO] Charset '" + charset + "' is invalid, skipping.");
+ }
+ }
+
+ } else {
+ if (verbose){
+ System.err.println("[INFO] Charset not specified, skipping.");
+ }
+ }
+
+ return charset;
+ }
+
+}

0 comments on commit 940d46f

Please sign in to comment.