Smallest Data Uri Image Possible For a Transparent Image

Smallest data URI image possible for a transparent image

After playing around with different transparent GIFs, some are unstable and cause CSS glitches. For example, if you have an <img> and you use the tiniest transparent GIF possible, it works fine, however, if you then want your transparent GIF to have a background-image, then this is impossible. For some reason, some GIFs such as the following prevent CSS backgrounds (in some browsers).

Shorter (but unstable - 74 bytes)

data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==

I would advise using the slightly longer and more stable version as follows:

⇊ Stable ⇊ (but slightly longer - 78 bytes)

data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7

As another tip, don't omit image/gif as one comment suggests. This will break in several browsers.

How to create the smallest possible transparent png/gif of a given size in PHP?

Considering that the image will be transparent and nothing will appear on it you don't need it to be lossless. This means you can use a color palette of single color which will create a index for this color and use the index for all pixels in the image. To create index palette PNG you should use the imagetruecolortopalette() function in your code: http://php.net/manual/en/function.imagetruecolortopalette.php

You can also set the image compression level to highest.

function createTransparentDataURI($w = 1, $h = 1) {
//...
//create image palette with one color, the dithering (the second argument) doesn't matter here
imagetruecolortopalette($img, false, 1);
imagepng($img, null, 9); //set the compression level to highest
//...
}

This reduced the data length of image 1016x312 from 1308 to 133 bytes, which is almost by factor of ten.

By converting the binary data to base64 you can see with naked eye that there is room to compress that too:

iVBORw0KGgoAAAANSUhEUgAAA/gAAAE4AQMAAADVYspJAAAAA1BMVEUEAgSVKDOdAAAAPUlEQVR42u3BAQ0AAADCoPdPbQ8HFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/BicAAABWZX81AAAAABJRU5ErkJggg==

where the multiple "A"s are

You can enable the http's server gzip compression, to compress this response further more.

GIF wouldn't do better as it's size in my test was 910 bytes.

smallest filesize for transparent single pixel image

Checkout this blank.gif file (43 bytes). Less than 49 :D

Blank image encoded as data-uri

I looked into it and the smallest possible transparent GIF image, encoded as a data-uri, was this:

data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==

which is what I'm using now.

What's the smallest image format for randomly sized uniformly coloured images?

You can possibly achieve what you want with a specially-crafted GIF file.

The GIF format allows you to specify "logical screen width" and "logical screen height" values in the "Logical Screen Descriptor" section at the start of the file, which define the size of the image.

However, you don't actually need to encode the pixels for the entire image, and any pixels which are not encoded are considered transparent. Instead, the GIF file contains one or more "Image Descriptor" sections, which encodes the pixels for a sub-region of the image. This is used for compressing GIF animations (only the sub-regions of the image that change compared to the previous frame need to be encoded) but it can also be used for single-frame images. So what you can do is just output a single Image Descriptor encoding a 1x1 transparent pixel region of the image, and set the logical screen width and height values your desired image size, to create a uniformly transparent GIF image of arbitrary size, for a fixed file size (42 bytes).

You just need to modify bytes 6-9 (for the width) and bytes 10-13 (for the height) of this transparent 1x1 pixel GIF. Note that GIF uses little-endian byte order.

Here is an example file, a 1024 x 1024 pixel transparent GIF image.

This file loads up correctly for me as a 1k by 1k transparent image in the GIMP image editor, but some file viewers seem to base the image size on the size of the image descriptors and display it as 1x1 pixels, which is wrong AFAIK. You'll have to test whether your server reads them correctly.

CSS transparent background image using data:

That's called the The data URI scheme

Use the Data URI Kitchen to convert just about anything to data uri's. Link:
http://software.hixie.ch/utilities/cgi/data/data

Using an image file vs data URI in the CSS

I don't think you will gain much... and if it is a file image, the browser can cache it. I wouldn't bother doing it with CSS unless you have a real need for it.

Transparent PNG can't be displayed but is downloadable

Testing this same demo in Safari, it will work correctly. In Firefox and Chrome it does not. Data URIs are best used for small images — they add a ~30% size penalty to the data they store, and a significant amount of extra processing is required to display them. Browsers including Chrome impose limits on the supported length of Data URIs for this reason, see https://stackoverflow.com/a/41755526/1314762 for details on those limits.

The topmost and bottommost coordinates of the visible image in a transparent PNG

You can get the pixels from an image using the method described in this question:
How to use JavaScript or jQuery to read a pixel of an image when user clicks it?

var img = new Image();
img.src = 'image.jpg';
var context = document.getElementById('canvas').getContext('2d');
context.drawImage(img, 0, 0);
data = context.getImageData(x, y, 1, 1).data;

Then loop through the array of pixels and check for the threshold value you are looking for. 0 being fully transparent and 255 being fully opaque.

This question might be a help aswell on how to access the specific color channel:
getPixel from HTML Canvas?

You will want to look at pix[i+3] which in the linked example holds the alpha channel.

Your current pixel position is simply calculated by using the current loop iteration and dividing it by your width which gives you the current height.

For example your image is 200x50 px. You hit a not fully transparent pixel at loop iteration 534, 534/200 = 2 so your are 2 pixels down at the Y axis and then get the remainder with 534 mod 200. So you know how far "in" your at the X axis.



Related Topics



Leave a reply



Submit