Display SVG in its ViewBox size - javascript

I am using the img-Tag to display SVG images which my users uplaoded to my Amazon S3 bucket.
<img src="http://testbucket.s3.amazonaws.com/mysvg.svg" />
The problem is that, once the image is loaded and shown, it's not the size it was constructed for. For example a test image is displayed with a size of 1920x1920px but its ViewBox is 0 0 128 128. However, I would like to display the image in the size of its ViewBox. In this case 128x128px.
The only idea I came up with is downloading the image with an ajax request and parse the ViewBox attribute out of the svg source. Than I adjust the size. However, I do not want to make any unnecessary http requests and I am looking for a solution to read the images ViewBox dimensions. I could use the <object>-Tag to load the image but since it's hosted on Amazon I get a cross domain issue and cannot read the svgs source. Even when adding CORS rules to my bucket.
Ideas?

You could try this approach :
Download the svg file with an Ajax request.
Parse the viewbox of that svg from the response.
Create a new Image();
Set the image's src to "data:image/svg+xml; charset =utf8,"+encodeURIComponent(the ajax response).
Set the image width/height from the viewBox infos you grabbed step 2 (via css or in its attributes).
That should work for all majors browsers supporting svg in <img>, and since you just appended the response string into the image src, you only make one single request to Amazon's servers.
So, e.g, it could give you a function like so :
function viewBoxedImgSVG(container, url){
//There might be a better way to parse it...
var parseViewBox = function(data){
var parsed = data.match(/viewBox="(.*?)."/);
if(parsed) return parsed[1].split(' ');
}
var xhr= new XMLHttpRequest();
xhr.onload = function(){
var img = new Image();
// responseText for IE, but doesn't support SMIL in img tag anyway
img.src = "data:image/svg+xml; charset=utf8,"+encodeURIComponent(xhr.responseText);
var vB = parseViewBox(xhr.responseText);
if(vB){
img.width = vB[2];
img.height = vB[3];
}
container.appendChild(img);
}
xhr.open('GET', url);
xhr.send();
}

I have a couple of suggestions:
I am not sure if this works - in general, or with AWS - but you could try doing an AJAX request with "Range" HTTP request header. The idea being that you only fetch the first few hundred bytes of the SVG file.
Assuming you are in control of the uploading, you could add the dimensions to the file name. Ie. "mysvg_128x128.svg" and parse the values from the name.

Related

JavaScript: Obtain the file-size of an image from the DOM element which loaded it [duplicate]

As part of a web app, once images have been downloaded and rendered on a web page, I need to determine an image's file size (kb) and resolution within the browser context (so I could, for example, display that info on the page. This needs to be done client-side, obviously. Must be able to be solved x-browser without an ActiveX control or Java applet (IE7+, FF3+, Safari 3+, IE6 nice to have), though it doesn't have to be the same solution per browser.
Ideally this would be done using system Javascript, but if I absolutely need a JQuery or similar library (or a tiny subset of it), that could be done.
Edit:
To get the current in-browser pixel size of a DOM element (in your case IMG elements) excluding the border and margin, you can use the clientWidth and clientHeight properties.
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Now to get the file size, now I can only think about the fileSize property that Internet Explorer exposes for document and IMG elements...
Edit 2: Something comes to my mind...
To get the size of a file hosted on the server, you could simply make an HEAD HTTP Request using Ajax. This kind of request is used to obtain metainformation about the url implied by the request without transferring any content of it in the response.
At the end of the HTTP Request, we have access to the response HTTP Headers, including the Content-Length which represents the size of the file in bytes.
A basic example using raw XHR:
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'img/test.jpg', true);
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 ) {
if ( xhr.status == 200 ) {
alert('Size in bytes: ' + xhr.getResponseHeader('Content-Length'));
} else {
alert('ERROR');
}
}
};
xhr.send(null);
Note: Keep in mind that when you do Ajax requests, you are restricted by the Same origin policy, which allows you to make requests only within the same domain.
Check a working proof of concept here.
Edit 3:
1.) About the Content-Length, I think that a size mismatch could happen for example if the server response is gzipped, you can do some tests to see if this happens on your server.
2.) For get the original dimensions of a image, you could create an IMG element programmatically, for example:
var img = document.createElement('img');
img.onload = function () { alert(img.width + ' x ' + img.height); };
img.src='http://sstatic.net/so/img/logo.png';
Check the uploaded image size using Javascript
<script type="text/javascript">
function check(){
var imgpath=document.getElementById('imgfile');
if (!imgpath.value==""){
var img=imgpath.files[0].size;
var imgsize=img/1024;
alert(imgsize);
}
}
</script>
Html code
<form method="post" enctype="multipart/form-data" onsubmit="return check();">
<input type="file" name="imgfile" id="imgfile"><br><input type="submit">
</form>
Getting the Original Dimensions of the Image
If you need to get the original image dimensions (not in the browser context), clientWidth and clientHeight properties do not work since they return incorrect values if the image is stretched/shrunk via css.
To get original image dimensions, use naturalHeight and naturalWidth properties.
var img = document.getElementById('imageId');
var width = img.naturalWidth;
var height = img.naturalHeight;
p.s. This does not answer the original question as the accepted answer does the job. This, instead, serves like addition to it.
How about this:
var imageUrl = 'https://cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg';
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open('GET', imageUrl, true);
xhr.responseType = 'blob';
xhr.onload = function()
{
blob = xhr.response;
console.log(blob, blob.size);
}
xhr.send();
http://qnimate.com/javascript-create-file-object-from-url/
due to Same Origin Policy, only work under same origin
Regarding the width and height:
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Regarding the filesize you can use performance
var size = performance.getEntriesByName(url)[0];
console.log(size.transferSize); // or decodedBodySize might differ if compression is used on server side
Service workers have access to header informations, including the Content-Length header.
Service workers are a bit complicated to understand, so I've built a small library called sw-get-headers.
Than you need to:
subscribe to the library's response event
identify the image's url among all the network requests
here you go, you can read the Content-Length header!
Note that your website needs to be on HTTPS to use Service Workers, the browser needs to be compatible with Service Workers and the images must be on the same origin as your page.
Most folks have answered how a downloaded image's dimensions can be known so I'll just try to answer other part of the question - knowing downloaded image's file-size.
You can do this using resource timing api. Very specifically transferSize, encodedBodySize and decodedBodySize properties can be used for the purpose.
Check out my answer here for code snippet and more information if you seek : JavaScript - Get size in bytes from HTML img src
You can use generic Image object to load source dynamically then measure it:
const img = new Image();
img.src = this.getUrlSource()
img.onload = ({target}) =>{
let width = target.width;
let height = target.height;
}
You can get the dimensions using getElement(...).width and ...height.
Since JavaScript can't access anything on the local disk for security reasons, you can't examine local files. This is also true for files in the browser's cache.
You really need a server which can process AJAX requests. On that server, install a service that downloads the image and saves the data stream in a dummy output which just counts the bytes. Note that you can't always rely on the Content-length header field since the image data might be encoded. Otherwise, it would be enough to send a HTTP HEAD request.
You can find dimension of an image on the page using something like
document.getElementById('someImage').width
file size, however, you will have to use something server-side
var img = new Image();
img.src = sYourFilePath;
var iSize = img.fileSize;
The only thing you can do is to upload the image to a server and check the image size and dimension using some server side language like C#.
Edit:
Your need can't be done using javascript only.

CORS is enabled but toDataURL still throws a warning

As the title says, I've enabled CORS for all of the images, but I'm still getting errors when trying to throw them onto a canvas and then extract that canvas (Chrome and FF). I ran a little sniffer on one of the images to test it out, and it seems to be in fact returning the correct headers:
Access-Control-Allow-Origin: *
Am I missing something?
You need to request CORS usage for the server, just add this attribute to the image tag:
<img crossOrigin="anonymous" ... />
or dynamically from JavaScript, use it as property (assuming img is created or obtained already):
var img = new Image;
img.onload = callback;
img.crossOrigin = ''; /// = anonymous
img.src = '...';
If you have multiple images to load you can use an image loader that supports cross-origin request (for example my YAIL loader where you can request all or individual images to be loaded using CORS).

How do you get the file size of an image on the web page with Javascript?

I'd like to be able to get the file size on an image on a webpage.
So let's say I have an image on the page (that has loaded) like this:
How do I call a function in Javascript (or, even better, jquery) to get the file size (not the dimensions) of the image?
It's important to note that I'm not using any inputs or having users upload the image, there's lots of SO answers on getting image sizes from browse buttons with the file API.
All I want to do is get the file size of any arbitrary image on the page based of it's id and src url.
Edit: I'm dealing with a keep-alive connection for some images so the Content-Length headers are not available.
You can't directly get the file size (or any data from it).
The only way is a bit dirty, because you have to do a XMLHTTPRequest (and it probably won't work with externals images, according to the "Cross Origin Resource Sharing"). But with the browser's cache, it should not cause another HTTP request.
var xhr = new XMLHttpRequest();
xhr.open("GET", "foo.png", true);
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = function() {
if(this.readyState == this.DONE) {
alert("Image size = " + this.response.byteLength + " bytes.");
}
};
xhr.send(null);
Here is a React version that worked for me, posting it in the event that it could save some time.
Form field
<input type="file"
name="file"
id="file"
multiple="multiple"
onChange={onChangeHandler}
className="fileUp" />
JSX
const onChangeHandler = event => {
console.log(event.target.files[0].size);
}
Old question but here is my take: I had the same issue but didn't want te rely on buffering to prevent my app from downloading the images twice (as the accepted answer does). What I ended up doing was fetch the file as a blob, read the file size, and use the blob as image source from there on. this was easily done with the URL.createObjectURL() function like so:
let img = new Image()
img.crossOrigin = "Anonymous"; // Helps with some cross-origin issues
fetch('foo.png')
.then(response => response.blob())
.then(blob => { img.src = URL.createObjectURL(blob); })
This looks a lot cleaner and perhaps it can still be useful for some.
Assuming you could use HTML5
Create a canvas
Put image in there
Grab the image data with .toDataURLHD()
Grab the base64 encoded string
Use some mad calculation to get the image size in bytes.
Have fun!
Maybe it's a lot easier to use a server side script, so it won't be HTML5-dependant

How to get image content (not url) from IMG element?

We are using the Eclipse SWT WebBrowser control to render HTML pages for our Java application. If the page contains an image, we want to get the image content. We can access the DOM to get the IMG element, but there doesn't seem to be a way to get the actual content (i.e. the bytes of the image) other than re-fetching the image using the image URL. (We can get the image URL via the 'src' attribute.) Is there any way to get the actual bytes of the image from the DOM?
I am not sure if this is what you are looking for, but basically you can just make a typed XHR (such as ArrayBuffer) to the image source (it should be cached, so no real hit by doing this). I am assume you are using an HTML5 compliant browser (or such that supports ArrayBuffer or the type you need). I am assuming the document has at least one image with a proper source, see Fiddle for working demo.
var img = document.querySelector('img'), xhr = new XMLHttpRequest();
xhr.open('GET', img.src, true);
xhr.responseType = 'arraybuffer';
xhr.addEventListener('load', handleBuffer, false);
xhr.send();
// Your image data ArrayBuffer, feel free to change the type.
function handleBuffer (data) {
var arryBuffer = data.target.response;
}
Sample Fiddle
Check out https://developer.mozilla.org/en-US/docs/Web/API/FileReader it will let you create base64 data urls, may not work depending on your browser versions.

Determining image file size + dimensions via Javascript?

As part of a web app, once images have been downloaded and rendered on a web page, I need to determine an image's file size (kb) and resolution within the browser context (so I could, for example, display that info on the page. This needs to be done client-side, obviously. Must be able to be solved x-browser without an ActiveX control or Java applet (IE7+, FF3+, Safari 3+, IE6 nice to have), though it doesn't have to be the same solution per browser.
Ideally this would be done using system Javascript, but if I absolutely need a JQuery or similar library (or a tiny subset of it), that could be done.
Edit:
To get the current in-browser pixel size of a DOM element (in your case IMG elements) excluding the border and margin, you can use the clientWidth and clientHeight properties.
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Now to get the file size, now I can only think about the fileSize property that Internet Explorer exposes for document and IMG elements...
Edit 2: Something comes to my mind...
To get the size of a file hosted on the server, you could simply make an HEAD HTTP Request using Ajax. This kind of request is used to obtain metainformation about the url implied by the request without transferring any content of it in the response.
At the end of the HTTP Request, we have access to the response HTTP Headers, including the Content-Length which represents the size of the file in bytes.
A basic example using raw XHR:
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'img/test.jpg', true);
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 ) {
if ( xhr.status == 200 ) {
alert('Size in bytes: ' + xhr.getResponseHeader('Content-Length'));
} else {
alert('ERROR');
}
}
};
xhr.send(null);
Note: Keep in mind that when you do Ajax requests, you are restricted by the Same origin policy, which allows you to make requests only within the same domain.
Check a working proof of concept here.
Edit 3:
1.) About the Content-Length, I think that a size mismatch could happen for example if the server response is gzipped, you can do some tests to see if this happens on your server.
2.) For get the original dimensions of a image, you could create an IMG element programmatically, for example:
var img = document.createElement('img');
img.onload = function () { alert(img.width + ' x ' + img.height); };
img.src='http://sstatic.net/so/img/logo.png';
Check the uploaded image size using Javascript
<script type="text/javascript">
function check(){
var imgpath=document.getElementById('imgfile');
if (!imgpath.value==""){
var img=imgpath.files[0].size;
var imgsize=img/1024;
alert(imgsize);
}
}
</script>
Html code
<form method="post" enctype="multipart/form-data" onsubmit="return check();">
<input type="file" name="imgfile" id="imgfile"><br><input type="submit">
</form>
Getting the Original Dimensions of the Image
If you need to get the original image dimensions (not in the browser context), clientWidth and clientHeight properties do not work since they return incorrect values if the image is stretched/shrunk via css.
To get original image dimensions, use naturalHeight and naturalWidth properties.
var img = document.getElementById('imageId');
var width = img.naturalWidth;
var height = img.naturalHeight;
p.s. This does not answer the original question as the accepted answer does the job. This, instead, serves like addition to it.
How about this:
var imageUrl = 'https://cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg';
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open('GET', imageUrl, true);
xhr.responseType = 'blob';
xhr.onload = function()
{
blob = xhr.response;
console.log(blob, blob.size);
}
xhr.send();
http://qnimate.com/javascript-create-file-object-from-url/
due to Same Origin Policy, only work under same origin
Regarding the width and height:
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Regarding the filesize you can use performance
var size = performance.getEntriesByName(url)[0];
console.log(size.transferSize); // or decodedBodySize might differ if compression is used on server side
Service workers have access to header informations, including the Content-Length header.
Service workers are a bit complicated to understand, so I've built a small library called sw-get-headers.
Than you need to:
subscribe to the library's response event
identify the image's url among all the network requests
here you go, you can read the Content-Length header!
Note that your website needs to be on HTTPS to use Service Workers, the browser needs to be compatible with Service Workers and the images must be on the same origin as your page.
Most folks have answered how a downloaded image's dimensions can be known so I'll just try to answer other part of the question - knowing downloaded image's file-size.
You can do this using resource timing api. Very specifically transferSize, encodedBodySize and decodedBodySize properties can be used for the purpose.
Check out my answer here for code snippet and more information if you seek : JavaScript - Get size in bytes from HTML img src
You can use generic Image object to load source dynamically then measure it:
const img = new Image();
img.src = this.getUrlSource()
img.onload = ({target}) =>{
let width = target.width;
let height = target.height;
}
You can get the dimensions using getElement(...).width and ...height.
Since JavaScript can't access anything on the local disk for security reasons, you can't examine local files. This is also true for files in the browser's cache.
You really need a server which can process AJAX requests. On that server, install a service that downloads the image and saves the data stream in a dummy output which just counts the bytes. Note that you can't always rely on the Content-length header field since the image data might be encoded. Otherwise, it would be enough to send a HTTP HEAD request.
You can find dimension of an image on the page using something like
document.getElementById('someImage').width
file size, however, you will have to use something server-side
var img = new Image();
img.src = sYourFilePath;
var iSize = img.fileSize;
The only thing you can do is to upload the image to a server and check the image size and dimension using some server side language like C#.
Edit:
Your need can't be done using javascript only.

Categories