Reputation: 5045
How can I get the size of the newly created new Image()
in bytes if this image's src
is base64
data image?
I have such coffeescript code:
# This string is received after some original image preprocessing
base64String = "data:image/jpeg;base64......"
newImageObj = new Image()
newImageObj.src = base64String
newImageObj.onload = ->
console.log "Resized image width is " + this.width
console.log "New file size in bytes is " + newImageObj.fileSize
The output is always like this:
Resized image width is 500
New file size in bytes is undefined
This newImageObj.fileSize
is always undefined
.
Upvotes: 13
Views: 44866
Reputation: 817
Here is the algorithm to find file size from base64 string:
base64String = "data:image/jpeg;base64......";
var stringLength = base64String.length - 'data:image/png;base64,'.length;
var sizeInBytes = 4 * Math.ceil((stringLength / 3))*0.5624896334383812;
var sizeInKb=sizeInBytes/1000;
Upvotes: 35
Reputation: 21
You can refer to this example and see how base64 decoding works:
I have also attached the reference to base64 table. Base64 index table
Decoding->base64 string : QWJoaXNoZWs=
First, you need to split the string character by character. Thus, you got 12 groups: Q W J o a X N o Z W s =
Each group (character) is a Base64 character that has its own index, and now your task is to convert groups to indices. To do this, by mapping values from the Base64 Characters Table replace each character by its index (if you cannot find an index for a specific group, just discard it). All in all, you should get the following indices: 16 22 9 40 26 23 13 40 25 22 44
At this step you should convert each group from decimal to binary. So find corresponding decimal values in the ASCII table and make sure you get the following binary values: 00010000 00010110 00001001 00101000 00011010 00010111 00001101 00101000 00011001 00010110 00101100
Now remove the prefix “00” (two zeros) in front of each group: 010000 010110 001001 101000 011010 010111 001101 101000 011001 010110 101100
There you have a simple concatenation of previous groups (that is, glue all the binary values together and get an 66-character string): 010000010110001001101000011010010111001101101000011001010110101100
Then, divide the resulting string into groups so that each one has 8 characters (if the last group has less than 8 characters, you must discard it). Now you have 8 groups of eight-bit bytes: 01000001 01100010 01101000 01101001 01110011 01101000 01100101 01101011
Once again using the ASCII table, convert all binary values into their ASCII characters: A b h i s h e k
The final chord, concatenate all ASCII characters to get the result string: Abhishek
Thus,
Size of original string(in bytes) = floor(6n/8) – padding
Size of base64 string(in bytes) = ceil(8n/6) + padding
When decoding from base64
int paddingCount = (base64Data.endsWith("==")) ? 2 :(base64Data.endsWith("=")) ? 1 : 0;
double dataSize = floor(base64Data.length() * 3 / 4) - paddingCount;
When encoding to base64
int paddingCount = 3 - (stringToEncode.length()) % 3;
double dataSize = ceil(stringToEncode.length() * 4 / 3) + paddingCount;
Upvotes: 2
Reputation: 1642
const img = 'data:image/png;base64,aBdiVBORw0fKGgoAAA';
const buffer = Buffer.from(img.substring(img.indexOf(',') + 1));
console.log("Byte length: " + buffer.length);
console.log("MB: " + buffer.length / 1e+6);
Upvotes: -2
Reputation: 18551
You can take advantage of the inner workings of fetch
for that:
const url = 'data:image/jpeg;base64...'
const resp = await fetch(url)
const size = +resp.headers.get('Content-Length')
Upvotes: -1
Reputation: 6035
I'm a little late to the question here, and maybe I'm wrong but...
Looking at your code above, it looks like you are defining a function and using arrow notation to return the answer. However, there are TWO lines following the arrow, and they aren't grouped in any way, so... the arrow notation is returning the value of onload() to the first log() only. So "this" actually has a value. But the second log() is a new command altogether, right? It's not being returned from onload(). So newImageObj is undefined.
Or maybe it's a coffeescript syntax, I'm not familiar with it. Would this fix it?
newImageObj = new Image()
newImageObj.src = base64String
newImageObj.onload = ->
{
console.log "Resized image width is " + this.width
console.log "New file size in bytes is " + newImageObj.fileSize
}
Upvotes: 0
Reputation: 831
I'd personally use something like this to do the above, which will work correctly in the case that the data isn't formatted correctly (eg, an '=' missing, which usually gets decoded correctly anyway)
new Buffer(base64String, 'base64').length
Upvotes: 7