18

I have just been told to send the thumbnail of an image using data URI. I have been searching it but all I found was that its basically a textual representation of a file and can be directly used in HTML. I could not really find how to make a data URI in Java. I have an input stream of a file. Can someone please shed some light on it and point me to a way to generate this?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Khizar
  • 2,288
  • 5
  • 32
  • 53

2 Answers2

21

E.G. for an image:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
    ImageIO.write(image, "png", baos);
} catch (IOException e) {
    e.printStackTrace();
}
String imageString = "data:image/png;base64," +
    Base64.getEncoder().encodeToString(bytes);

Example

Run the code below. If FF is the default browser, you might see something like this:

Data URI image in FF

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import java.util.Base64;

public class DataUriConverter {

    static String getImageAsString(BufferedImage image) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // serialize the image
        ImageIO.write(image, "png", baos);
        // convert the written image to a byte[]
        byte[] bytes = baos.toByteArray();
        System.out.println("bytes.length " + bytes.length);
        // THIS IS IT! Change the bytes to Base 64 Binary
        String data = Base64.getEncoder().encodeToString(bytes);
        // add the 'data URI prefix' before returning the image as string
        return "data:image/png;base64," + data;
    }

    static BufferedImage getImage() {
        int sz = 500;
        BufferedImage image = new BufferedImage(
                sz, sz, BufferedImage.TYPE_INT_ARGB);

        // paint the image..
        Graphics2D g = image.createGraphics();
        g.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(0,0,255,63));
        g.setStroke(new BasicStroke(1.5f));
        for (int ii = 0; ii < sz; ii += 5) {
            g.drawOval(ii, ii, sz - ii, sz - ii);
        }
        g.dispose();

        return image;
    }

    public static void main(String[] args) throws Exception {
        String imageString = getImageAsString(getImage());
        String htmlFrag = "<html><body><img src='%1s'></body></html>";
        String html = String.format(htmlFrag, imageString);

        // write the HTML
        File f = new File("image.html");
        FileWriter fw = new FileWriter(f);
        fw.write(html);
        fw.flush();
        fw.close();

        // display the HTML
        Desktop.getDesktop().open(f);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    While this seems is correct, I'll comment that the call to DatatypeConverter will fail in newer versions of Java. Replace with ```Base64.getEncoder().encodeToString``` to comply. – matsa Sep 08 '21 at 12:27
  • 1
    Right you are, @matsa! Thanks for the heads-up. I have edited the answer to use the `Base64` class. – Andrew Thompson Dec 11 '21 at 20:50
3

Here is my example.

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import javax.xml.bind.DatatypeConverter;

public class ToDataURI {

    public static void main(String[] args) throws IOException {

        // source file
        File file = new File("movie.mp4");

        // check content type of the file
        String contentType = Files.probeContentType(file.toPath());

        // read data as byte[]
        byte[] data = Files.readAllBytes(file.toPath());

        // convert byte[] to base64(java7)
        String base64str = DatatypeConverter.printBase64Binary(data);

        // convert byte[] to base64(java8)
        // String base64str = Base64.getEncoder().encodeToString(data);

        // cretate "data URI"
        StringBuilder sb = new StringBuilder();
        sb.append("data:");
        sb.append(contentType);
        sb.append(";base64,");
        sb.append(base64str);

        System.out.println(sb.toString());

    }
}

Processing flow

  1. Check file contentType
  2. Read file data into byte[]
  3. Convert byte[] data to base64
  4. Create "data URI" format

You can get like

data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21p....
riversun
  • 758
  • 8
  • 12