Size comparison of compressed JSON and original PNG image

This page demonstrates how to deal with binary data in JSON. It puts a PNG image into a JSON file, which is compressed. It demonstrates the size of the PNG and the compressed JSON file, then it reads back in the compressed JSON file and demonstrates recovery of the PNG image.

Here is a small PNG image:

use warnings;
use strict;
use JSON;
use FindBin '$Bin';

# Test file

my $file = "$Bin/tantei-san.png";
my $file_size = -s $file;
print "Size of $file is $file_size.\n";

# Read in file

open my $in, "<:raw", $file or die $!;
my $bytes = read ($in, my $data, -s $file);
if ($bytes != $file_size) {
    die "Bad no. of bytes $bytes should be $file_size";
close $in or die $!;

# Make JSON & print it to a file.

my $json_data = $data;
$json_data =~ s/(.)/sprintf ("%02X", ord ($1))/ge;
my $json = { png => $json_data };
my $outfile = 'out.json.gz';
open my $out, ">:gzip", $outfile or die $!;
print $out to_json ($json);
close $out or die $!;
print "Size of $outfile is ", -s $outfile, ".\n";

# Check it all worked by reading it back in again.

open my $inagain, "<:gzip", $outfile or die $!;
my $json2 = '';
while (<$inagain>) {
    $json2 .= $_;
my $png = from_json ($json2);
my $pngdata = $png->{png};
$pngdata =~ s/([0-9A-F]{2})/chr (hex ($1))/eg;
if ($pngdata eq $data) {
    print "OK\n";
else {
    print "mismatch\n";


This prints out

Size of tantei-san.png is 2942.
Size of out.json.gz is 3009.

Copyright © Ben Bullock 2009-2023. All rights reserved. For comments, questions, and corrections, please email Ben Bullock ( or use the discussion group at Google Groups. / Privacy / Disclaimer