Image file size from data URI in JavaScript - javascript

I am not sure it's even possible but - can I get the image file size from data URI?
For example, let's say there is an IMG element where src goes:
src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...
Based on the src, can I get the image file size by using plain JavaScript? (without server request)

If you want file size, simply decode your base64 string and check the length.
var src ="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP/// yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
var base64str = src.substr(22);
var decoded = atob(base64str);
console.log("FileSize: " + decoded.length);

If you're okay with a (very good) estimate, the file size is 75% of the size of the base64 string. The true size is no larger than this estimate, and, at most, two bytes smaller.
If you want to write one line and be done with it, use atob() and check the length, as in the other answers.
If you want an exact answer with maximum performance (in the case of gigantic files or millions of files or both), use the estimate but account for the padding to get the exact size:
let base64Length = src.length - (src.indexOf(',') + 1);
let padding = (src.charAt(src.length - 2) === '=') ? 2 : ((src.charAt(src.length - 1) === '=') ? 1 : 0);
let fileSize = base64Length * 0.75 - padding;
This avoids parsing the entire string, and is entirely overkill unless you're hunting for microoptimizations or are short on memory.

Your best option is to calculate the length of the base64 string itself.
What is a base64 length in bytes?
You have to convert the base64 string to a normal string using atob() and then check it length, it will return a value that you can say is close to the actual size of the image. Also you don't need the data:image/jpeg;base64, part from the data URI to check the size.

This is a universal solution for all types of base64 strings based on Daniel Trans's code.
var src ="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP/// yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
var base64str = src.split('base64,')[1];
var decoded = atob(base64str);
console.log("FileSize: " + decoded.length);

The other solutions make use of atob, which has now been deprecated. Here is an up-to-date example, using Buffer instead.
const src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...";
const base64str = src.split('base64,')[1]; //remove the image type metadata.
const imageFile = Buffer.from(base64str, 'base64'); //encode image into bytes
console.log('FileSize: ' + imageFile.length);

Related

How can I convert from a Javascript Buffer to a String only containing 0 and 1

So I currently am trying to implement the huffman alg and it works fine for decoding and encoding. However, I store the encoded data as follows.
The result of the encoding function is a list containing many strings made up of 0 and 1 and all are varying length.
If i'd safe them in a normal txt file it would take up more space, if Id store them how they are in a binary file it could be that for example an 'e' which would have the code 101 would be stored in a full 8 bits looking like '00000101' which is wasteful and wont take up less storage then the original txt file. I took all the strings in the list and put them into one string and split it into equal parts of length 8 to store them more effectively.
However if I wanna read the data now, instead of 0 and 1 I get utf-8 chars, even some escape characters.
I'm reading the file with fs.readFileSync("./encoded.bin", "binary"); but javascript then thinks it's a buffer already and converts it to a string and it gets all weird... Any solutions or ideas to convert it back to 0 and 1?
I also tried to switch the "binary" in fs.readFileSync("./encoded.bin", "binary"); to a "utf-8" which helped with not crashing my terminal but still is "#��C��Ʃ��Ԧ�y�Kf�g��<�e�t"
To clarify, my goal in the end is to read out the massive string of binary data which would look like this "00011001000101001010" and actually get this into a string...
You can convert a String of 1s and 0s to the numerical representation of a byte using Number.parseInt(str, 2) and to convert it back, you can use nr.toString(2).
The entire process will look something like this:
const original = '0000010100000111';
// Split the string in 8 char long substrings
const stringBytes = original.match(/.{8}/g);
// Convert the 8 char long strings to numerical byte representations
const numBytes = stringBytes.map((s) => Number.parseInt(s, 2));
// Convert the numbers to an ArrayBuffer
const buffer = Uint8Array.from(numBytes);
// Write to file
// Read from file and reverse the process
const decoded = [...buffer].map((b) => b.toString(2).padStart(8, '0')).join('');
console.log('original', original, 'decoded', decoded, 'same', original === decoded);
var binary = fs.readFileSync("./binary.bin");
binary = [...binary].map((b) => b.toString(2).padStart(8, "0")).join("");
console.log(binary);
//Output will be like 010000111011010

Image to data uri without base64

I have image as base64 data URI but want to convert it to Data URI without base64 (in my case image size doesn't matter) - how to do it? This is what I try so far
let imgB64="Qk3KAAAAAAAAAD4AAAAoAAAAHQAAACMAAAABAAEAAAAAAIwAAADDDgAAww4AAAAAAAAAAAAAAAAAAP///wD//f/4//B/+P/tv/j/nc/4/n3z+P39/fjx+Px45uUzuJddz8h3vd/wd73f8He93/BvvN/wX78f8D+f3/BOZz/wdfr/8Hv9//B7+f/we+X/8Hvd//B73f/we93/8GTd/nBfUniQP4+m6L/f3tjP396489/eeP3f2fj+X9f4/5/P+P/Pv/j/8n/4//3/+A";
let imgStr=atob(imgB64); // decode base 64 to str
let bytes=Uint8Array.from(imgStr, c => c.charCodeAt(0)); // string to bytes
picB64.src='data:image;base64,'+imgB64 // this works
pic.src='data:image;text/plain,'+encodeURIComponent(bytes); // this not work :(
<div>This works</div> <img id="picB64">
<div>This not works</div> <img id="pic">
Here is example showing that this is possible (probably partially broken but works)
<img src=data:image;text/plain,BMv%0A%00%00%00%00%00%00x%00%00%00(%00%00%00%40%00%00%00%40%00%00%00%01%00%04%00%00%00%00%00%00%00%00%00%C3%84%0E%00%00%C3%84%0E%00%00%00%00%00%00%00%00%00%00%00%00%00%00%2B%C2%81%C3%BC%00%08%1F%C3%8D%00%08Zr%00%C3%BC%C3%BA%C3%BC%00%5E%5E%5E%00%119%C2%B9%00%08%C2%93%0B%00%C2%AB%C2%AB%C2%AB%00%00%C3%BF%00%00%00%C3%BF%00%00%00%C3%BF%C3%BC%00%C3%BC%C3%BF%C2%AB%00%C2%AB%C3%BF%00%00%00%C3%BF%00%00%00%C3%BF%00%00%00%00%00%02%00%03%01%03%00%01%01%02%03%03%03%02%03%03%02%00%03%01%01%01%03%03%03%02%03%01%02%02%01%02%01%00%00%00%01%03%00%00%02%00%02%01%02%00%02%01%03%03%01%01%02%01%01%02%00%01%02%02%03%00%01%02%03%00%01%01%01%01%03%01%02%01%01%02%03%02%02%03%00%00%00%02%01%01%02%01%02%01%00%03%00%02%02%03%01%03%01%02%02%02%02%00%01%01%02%00%00%03%00%02%01%01%03%03%03%03%01%03%02%01%00%00%01%02%02%01%00%00%01%03%03%00%00%00%03%00%01%01%01%01%01%02%00%02%00%03%03%03%00%02%02%03%01%02%01%02%00%01%01%03%02%01%02%00%00%00%00%00%01%00%01%02%02%01%01%03%03%02%02%02%01%02%03%02%00%00%03%00%03%00%01%03%01%01%02%02%03%02%03%03%03%02%03%03%02%01%03%02%03%01%00%02%03%03%00%02%02%01%02%02%01%02%02%03%03%01%00%01%03%03%03%01%01%01%01%01%00%03%02%00%00%00%02%01%01%02%00%02%02%01%02%03%03%00%03%02%00%02%02%01%00%03%00%00%03%01%03%03%01%02%00%02%03%01%01%01%03%00%00%03%02%03%00%01%02%03%03%02%03%02%02%01%01%01%00%03%03%03%03%01%02%03%02%03%00%00%01%01%01%00%02%00%02%01%03%01%00%02%02%03%02%01%02%01%01%01%01%03%00%01%03%03%00%03%02%01%02%00%01%01%01%00%00%03%01%00%03%01%01%01%01%02%01%02%00%03%03%00%00%01%00%00%03%02%03%02%00%03%02%03%03%01%03%00%01%01%00%01%01%02%00%00%02%02%01%00%00%00%03%02%00%02%02%00%02%03%03%01%02%01%01%00%01%00%03%03%00%01%01%00%03%01%03%01%02%01%00%02%01%01%01%00%02%02%03%02%01%00%00%00%03%02%00%03%00%00%00%02%03%00%00%01%03%02%01%02%02%03%01%00%00%01%01%02%03%03%03%00%01%00%01%00%03%02%02%02%00%00%03%02%02%03%00%00%02%02%01%03%01%02%01%02%03%03%03%01%00%01%02%02%01%02%03%00%03%01%03%01%02%00%01%00%03%03%03%02%01%01%02%03%03%01%01%02%03%01%01%03%02%01%01%01%00%01%00%00%03%01%00%02%02%03%02%00%02%01%03%00%00%02%02%03%03%01%02%00%00%00%03%01%03%02%02%01%02%02%03%03%03%01%01%00%00%03%03%01%00%01%03%03%02%03%03%02%00%02%00%02%00%02%00%02%00%00%01%01%00%02%03%03%03%01%00%01%03%01%01%00%03%02%02%00%02%02%02%01%00%00%02%01%03%02%01%01%00%03%02%01%01%01%02%02%02%02%02%00%01%01%02%00%00%03%02%02%00%02%03%00%01%00%01%03%01%02%03%02%00%03%01%01%00%03%00%03%02%02%03%00%03%01%03%02%01%02%00%01%01%02%00%00%00%02%03%03%01%03%03%02%01%01%01%00%02%01%01%01%01%03%01%02%01%02%03%01%02%02%02%00%02%01%00%00%01%00%02%00%00%02%00%00%01%03%01%02%02%01%03%01%03%02%02%03%00%02%03%03%01%00%03%00%00%01%03%03%03%02%01%02%00%01%03%02%02%02%01%00%02%03%01%01%02%02%01%02%03%03%01%00%01%02%03%00%00%02%02%02%03%01%03%02%03%03%00%00%02%01%02%00%00%01%03%02%00%01%01%01%01%00%01%01%00%00%02%02%02%03%00%02%00%00%01%01%01%01%03%03%01%03%01%03%03%02%03%01%00%03%02%01%01%00%03%03%03%01%00%02%01%02%03%01%02%03%03%01%00%01%03%02%00%00%03%01%03%03%02%03%01%02%02%00%00%03%02%03%00%03%03%02%00%01%03%03%03%00%01%00%00%00%03%02%00%02%01%01%03%01%01%01%01%01%02%02%00%00%00%01%02%00%03%01%03%03%03%03%01%00%01%03%02%00%02%00%00%02%00%02%00%02%01%03%03%01%02%01%02%01%03%00%03%01%00%03%01%03%03%02%03%01%01%01%00%03%03%03%01%03%03%01%01%01%03%01%03%02%00%02%00%01%02%00%03%02%01%00%00%01%02%01%00%02%02%01%00%01%03%01%03%01%03%00%02%02%02%01%00%03%02%01%02%03%02%00%00%02%03%01%01%01%01%00%03%03%02%03%03%02%01%00%01%03%01%01%00%00%03%00%03%03%01%00%02%02%01%00%02%02%02%00%02%00%01%03%02%01%02%01%01%03%01%01%02%01%00%00%00%02%02%03%01%02%01%02%03%01%02%03%01%00%02%02%01%02%03%00%03%01%01%00%01%00%00%03%03%03%00%02%03%01%01%00%03%02%01%02%02%00%00%01%02%02%02%03%02%00%02%00%01%00%03%02%02%03%01%01%01%03%03%03%03%02%02%02%01%01%02%01%02%00%00%00%02%00%01%02%00%00%02%02%02%02%01%02%02%02%02%01%03%03%01%01%01%00%03%03%00%00%00%01%01%02%00%00%00%03%01%00%01%03%03%01%03%02%02%02%01%00%00%03%00%03%00%01%01%02%03%02%03%02%01%01%01%01%00%02%03%03%03%03%03%01%00%01%03%03%01%02%01%01%01%02%02%00%03%00%01%00%00%02%01%02%02%00%00%00%00%02%00%03%01%01%01%00%01%03%02%01%00%03%02%02%00%01%02%03%03%02%03%01%02%00%02%01%01%03%01%00%01%03%01%02%00%02%00%03%03%00%02%03%00%02%02%01%01%00%02%03%01%03%03%03%00%00%00%01%00%00%00%03%03%02%00%01%03%03%00%03%02%03%02%03%02%03%03%03%00%00%01%03%00%01%00%02%00%03%00%00%00%01%03%01%02%00%03%03%00%02%03%00%03%01%02%02%02%03%03%01%01%01%01%01%01%00%00%03%03%01%01%00%01%03%00%02%02%00%00%01%01%01%00%00%02%03%00%01%02%03%00%03%02%02%03%01%02%03%02%01%01%02%01%00%00%01%01%01%00%02%02%00%02%00%00%02%01%00%02%03%00%00%01%01%02%02%02%00%02%03%03%00%02%02%00%03%01%03%03%01%00%01%03%03%03%03%01%01%03%02%03%00%00%01%02%03%01%02%02%02%03%03%03%02%03%02%01%01%02%03%03%03%02%00%03%00%02%00%02%01%02%03%02%00%00%01%02%03%03%02%03%00%01%00%02%03%03%03%02%03%01%00%00%01%00%00%01%03%02%03%00%02%02%00%02%03%00%02%03%01%00%01%03%03%02%02%02%01%03%02%03%00%00%01%03%01%00%03%01%01%03%02%00%01%03%03%01%02%01%03%00%01%01%01%02%02%01%02%00%01%03%03%02%02%02%01%02%02%02%00%03%01%00%03%01%00%03%00%01%03%03%02%02%02%03%02%02%00%03%03%01%03%00%01%02%03%00%03%02%00%02%03%02%02%00%01%01%03%01%00%02%02%03%02%02%00%00%03%01%03%01%03%00%02%00%03%01%03%01%01%00%00%02%01%03%02%03%03%03%03%01%00%01%02%03%00%01%00%00%01%03%02%02%01%01%01%03%02%00%03%03%00%01%02%03%01%00%02%02%01%00%03%01%02%02%02%01%01%01%01%02%01%01%01%03%01%00%03%02%00%03%01%02%01%03%00%00%03%03%01%00%03%00%01%03%00%01%03%01%00%00%01%00%01%01%03%00%00%03%02%00%02%00%00%02%01%01%02%00%02%02%03%03%02%00%02%01%02%02%03%03%01%02%00%00%00%00%01%00%01%03%00%01%03%00%03%02%02%00%00%01%03%02%00%00%02%00%00%02%03%00%02%03%02%01%01%02%01%02%00%02%03%02%01%03%02%01%02%01%01%02%02%01%00%03%03%00%03%01%01%03%02%03%01%03%02%02%02%03%02%00%01%00%02%02%03%03%01%03%00%00%00%02%03%03%00%00%00%00%01%00%03%03%00%00%00%00%02%00%00%01%00%00%01%02%01%00%00%03%00%02%01%03%01%01%00%01%02%01%01%03%00%01%00%00%01%00%00%03%03%00%03%00%01%02%01%01%00%02%02%01%02%01%01%00%00%01%02%00%00%03%03%01%01%02%02%01%03%03%00%00%02%02%01%00%00%01%01%03%01%01%03%02%00%03%03%00%00%00%03%02%01%00%00%02%03%03%00%02%03%03%01%01%03%00%03%01%02%03%01%01%02%00%03%01%00%03%01%00%01%03%01%03%01%03%01%03%01%00%00%02%02%00%02%00%03%02%00%01%02%01%03%02%02%02%01%01%00%03%00%03%03%01%00%03%00%02%01%00%03%03%00%01%03%03%01%00%01%01%03%03%02%03%00%00%01%01%00%00%01%02%03%00%00%01%03%00%02%00%01%01%01%03%01%00%03%01%03%01%03%02%03%00%01%00%02%03%03%01%02%00%00%02%02%02%02%03%01%03%01%00%01%00%02%00%00%03%03%00%00%00%02%01%02%00%02%00%02%03%02%03%00%03%02%01%03%03%01%00%00%01%01%03%00%03%00%00%02%00 >
It's definitely possible to render image without base64 encoding.
Here is it:
//function for convert byte array to hex
function toHexString(byteArray) {
return Array.from(byteArray, function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('%')
}
//image in base64
var imgB64="Qk3KAAAAAAAAAD4AAAAoAAAAHQAAACMAAAABAAEAAAAAAIwAAADDDgAAww4AAAAAAAAAAAAAAAAAAP///wD//f/4//B/+P/tv/j/nc/4/n3z+P39/fjx+Px45uUzuJddz8h3vd/wd73f8He93/BvvN/wX78f8D+f3/BOZz/wdfr/8Hv9//B7+f/we+X/8Hvd//B73f/we93/8GTd/nBfUniQP4+m6L/f3tjP396489/eeP3f2fj+X9f4/5/P+P/Pv/j/8n/4//3/+A";
//base64 to string
var imgStr=atob(imgB64);
//make byte array
var bytes=Uint8Array.from(imgStr, c => c.charCodeAt(0));
//transform input array into hex array
var hexBytes = "data:image,%" + toHexString(bytes);
//set image to element
document.getElementById("pic").src = hexBytes;
<html>
<head>
<title>Sample</title>
</head>
<body>
<img id="pic">
</body>
</html>
Unfortunately, the content of a data-uri is either textual or base64 encoded binary data.
From MDN Data URLs
Data URLs are composed of four parts: a prefix (data:), a MIME type indicating the type of data, an optional base64 token if non-textual, and the data itself:
data:[<mediatype>][;base64],<data>
The mediatype is a MIME type string, such as 'image/jpeg' for a JPEG image file. If omitted, defaults to text/plain;charset=US-ASCII
If the data is textual, you can simply embed the text (using the appropriate entities or escapes based on the enclosing document's type). Otherwise, you can specify base64 to embed base64-encoded binary data. You can find more info on MIME types here and here.
To use binary data with a data-uri requires binary data be base64 encoded. Sorry
UPDATE
It seems that you have come across a "work-around", although this allows you to use url encoded text within the data-uri, it is goung to be even larger than the base64 encoding.
Base 64 encodes 3 bytes on binary data in to 4 bytes of ASCII. Resulting in a (approximately) 33% increase in size. URL Encoding a single byte will result in 3 characters resulting in a 200% increase in size.
This increase in size is exactly what you are trying to avoid though.

How to determine file size from a string in ES?

Is there a way to get the size of a file based on a string?
Is it:
var size = value.length / 1024;
console.log("File is " + size + " megabytes");
I'm posting to a server and sometimes it doesn't go through so I'm guessing there may be a post limit and I'd like to get the file size of the string before trying to post and show a message if the size is too large.
You're looking for the equivalent of Buffer.byteLength in ActionScript:
Returns the actual byte length of a string. This is not the same as String.prototype.length since that returns the number of characters in a string.

Split Long Filename string in two Lines with Adobe Javascript

I am newbie using Javascript in Adobe. I have written script that catch the file name and add it as a title in the document, but problem is it doesn't split in 2 lines long file names. So long text file names are out of the page border.
For example file name is
"This is a text that I need to split in two lines How to write the script in order to split the long text and fit in the page"
This is just a sample. What I need to edit? And is it possible?
var trFileName = this.documentFileName.replace(/.*\/|\.pdf$/ig,""); //remove .pdf extension
var pageAmount = this.numPages; //define how many pages are there
this.addWatermarkFromText({
cText: trFileName,
nStart: 0,
nEnd: pageAmount,
nFontSize: 18,
aColor: color.blue,
cFont: "Helvetica-Bold",
nTextAlign: app.constants.align.center,
nHorizAlign: app.constants.align.center,
nVertAlign: app.constants.align.top,
//nHorizValue: -25,
nVertValue: -87.87
})
So looking at the documentation for Acrobat the quick way to do this is to add and use the bPercentage: -1 property which ought to scale the watermark to fit the page with a max of 100%. Obviously, the longer the text, the smaller the the typesize, but it ought to only scale when needed.
The big problem here is "how big is too big?" Since most fonts are not fixed-width. So if you do not have some function to check the size of the type in that font, you would need to set up a temp image, set the type, then measure the dimensions of the image, then decide how much to break the text.
The worst case for English though is probably going to be an endless string of W, so if you want to hard code the font size and some reasonable character limit, you can get a reasonable max character count by counting how many Ws it takes to go out of bounds.
Once you have that number you can split the string.
One way to split a string is to use substring:
var cDisplayText = trFilename;
var nMaxChars = 10;
var cAdobeNewline = '\r';
var cLineBreakChar = '-';
if (cDisplayText.length > nMaxChars && cDisplayText.length > 0) {
cDisplayText = cDisplayText.substring(0, nMaxChars)
+ cLineBreakChar
+ cAdobeNewline
+ cDisplayText.substring(nMaxChars);
}
And then replace cText: trFileName, with cText: cDisplayText,
I have not tested this and my javascript has atrophied a little, but the idea is to test the string length and insert a hyphen and a line break.
This (obviously) does not account for case where there is more than 1 line break required.

How to extract pixel information from PNG using javascript (getImageData alternatives)

I am trying to get pixel data from PNG images for processing. The current way is by using canvas.drawImage followed canvas.getImageData (example here). I am looking for alternatives.
The problem with the current approach is that browsers modify pixel values influenced by alpha, as discussed here and here.
This question has been asked before, but no satisfactory answers are available.
The only way to do this without using canvas and getImageData() is to load the PNG file as a binary typed array and parse the file in code "manually".
Prerequisites:
For this you need the PNG specification which you can find here.
You need to know how to use typed arrays (for this a DataView is the most suitable view).
PNG files are chunk based and you will need to know how to parse chunks
A typical chunk based file has a four byte header called a FourCC identifier, followed by the size and misc. data depending on the file format definition.
Then chunks are placed right after this containing often a FOURCC (or four character code) and then the size of the chunk without the chunk header. In principle:
MAGIC FOURCC
SIZE/MISC - depending on definition
...
CHK1 - Chunk FourCC
SIZE - unsigned long
.... data
CHK2
SIZE
.... data
This format principle came originally from the Commodore Amiga platform and EA/IFF (Interleaved File Format) back in mid 80's.
But in modern days some vendors has extended or vary the chunk format, so for PNG chunks it will actually look like this:
Header (always 8 bytes and the same byte values):
‰PNG (first byte is 0x89, see specs for reason)
CR + LF 0x0C0A
EOC + LF 0x1A0A
Chunks:
SIZE (4 bytes, may be 0 (f.ex. IEND). Excl. chunk header and crc)
FOURCC (4 bytes, ie. "IHDR", "IDAT")
[...data] (length: SIZE x bytes)
CRC32 (4 bytes representing the CRC-32 checksum of the data)
(see the referenced specification link above for details).
And the byte-order (endianess) for PNG is always big-endian ("network" order).
This makes it easy to parse through the file supporting only some (or all) chunks. For PNG you would need to support at least (source):
IHDR must be the first chunk; it contains (in this order) the image's width, height, bit depth and color type.
IDAT contains the image, which may be split between multiple IDAT chunks. Such splitting increases the file size slightly, but makes it easier to stream the PNG. The IDAT chunk contains the actual image data, which is the output stream of the compression algorithm.
IEND marks the file end.
If you intend to support palette (color indexed) files you would also need to support the PLTE chunk. When you parse the IHDR chunk you will be able to see what color format is used (type 2 for RGB data, or 6 for RGBA and so on).
Parsing is itself easy so your biggest challenge would be supporting things like ICC profiles (when present in the iCCP chunk) to adjust the image color data. A typical chunk is the gamma chunk (gAMA) which contains a single gamma value you can apply to convert the data to linear format so that it displays correctly when display gamma is applied (there are also other special chunks related to colors).
The second biggest challenge would be the decompression which uses INFLATE. You can use a project such as PAKO zlib port to do this job for you and this port has performance close to native zlib. In addition to that, if you want to do error checking on the data (recommended) CRC-32 checking should also be supported.
For security reason you should always check that fields contain the data they're suppose to as well as that reserved space are initialized with either 0 or the defined data.
Hope this helps!
Example chunk parser: (note: won't run in IE).
function pngParser(buffer) {
var view = new DataView(buffer),
len = buffer.byteLength,
magic1, magic2,
chunks = [],
size, fourCC, crc, offset,
pos = 0; // current offset in buffer ("file")
// check header
magic1 = view.getUint32(pos); pos += 4;
magic2 = view.getUint32(pos); pos += 4;
if (magic1 === 0x89504E47 && magic2 === 0x0D0A1A0A) {
// parse chunks
while (pos < len) {
// chunk header
size = view.getUint32(pos);
fourCC = getFourCC(view.getUint32(pos + 4));
// data offset
offset = pos + 8;
pos = offset + size;
// crc
crc = view.getUint32(pos);
pos += 4;
// store chunk
chunks.push({
fourCC: fourCC,
size: size,
offset: offset,
crc: crc
})
}
return {chunks: chunks}
}
else {
return {error: "Not a PNG file."}
}
function getFourCC(int) {
var c = String.fromCharCode;
return c(int >>> 24) + c(int >>> 16 & 0xff) + c(int >>> 8 & 0xff) + c(int & 0xff);
}
}
// USAGE: ------------------------------------------------
fetch("//i.imgur.com/GP6Q3v8.png")
.then(function(resp) {return resp.arrayBuffer()}).then(function(buffer) {
var info = pngParser(buffer);
// parse each chunk here...
for (var i = 0, chunks = info.chunks, chunk; chunk = chunks[i++];) {
out("CHUNK : " + chunk.fourCC);
out("SIZE : " + chunk.size + " bytes");
out("OFFSET: " + chunk.offset + " bytes");
out("CRC : 0x" + (chunk.crc>>>0).toString(16).toUpperCase());
out("-------------------------------");
}
function out(txt) {document.getElementById("out").innerHTML += txt + "<br>"}
});
body {font: 14px monospace}
<pre id="out"></pre>
From here you can extract the IHDR to find image size and color type, then IDAT chunk(s) to deflate (PNG uses filters per scanline which do complicate things a bit, as well as a interlace mode, see specs) and your almost done ;)

Categories

Resources