I am creating a larger file with different pattern on canvas. Assuming the file size is 20,000 x 20,000 px. This is too much processing to be done on client side so I need to create the canvas and then make png from it which is then given as a download file.
The question is, Is there any way to do server side processing on <canvas> element in PHP. There is a node package called "canvas" but I am looking for something in PHP?
You'd have to convert your canvas to a Blob or a base64 string anyway if you want to send it to a server... and then process that on the server too and return it to the client. It really feels like unnecessary extra steps that hurt you more than they help you.
What I'd personally do in this scenario is convert the canvas to a Blob, create a stream from that Blob, and use StreamSaver.js to save it in a memory-efficient way. Does it improve processing time? No, but it's definitely better in terms of RAM usage. You could display a message to the user while it's generating.
function saveImage() {
message.innerText = 'Generating image...';
const start = performance.now();
const blob = canvas.toBlob(async function (blob) {
const fileStream = streamSaver.createWriteStream('test.png');
const readableStream = blob.stream();
await readableStream.pipeTo(fileStream);
const end = performance.now();
console.log(end - start);
message.innerText = 'Done!';
});
}
Fiddle for full example: https://jsfiddle.net/gp2xtbkn/
Related
I actually want to upload an image to a server.
To achieve this, i want the user just paste the image into chrome (the image is a print screen in fact), and then i post the stream to a php page, convert the stream as an image, and then upload it.
How can i achieve this web application ?
Today i have develop some differents parts :
I used this script, and i create the Upload.php page which gets the post variable and try to Create and image.
The problem i have, is that when i post the data, i only get a blob. I would like to get a base64 stream.
Can you help me ?
Thanks in advance.
I'm not sure why you are specifically looking for a "base 64 stream". If you are sending the Blob to your server via ajax, as far as your server is concerned, it's a file. Treat it no different than any other upload server-side. A Blob is a File without a name property. That's perhaps a bit overly-simplistic, but my point is that, again, this is really nothing more than a file as far as your server knows.
Assuming you are sending a multipart-encoded request, I'd like to point out that most user agents will set the filename property of the item's Content-Disposition header in the request to "blob" when the item you are uploading is a Blob instead of a file. It is possible to change this value in some browsers via the 3rd argument in FormData's append method, but I wouldn't rely on this just yet.
Also note that, if you are interested in a library that handles all of this already, I maintain, Fine Uploader which natively supports uploading images via paste in Chrome.
To answer this old question: Posting an image from clipboard with chrome is pretty much the same as posting a dropped file - except that the image/blob doesn't have the properties "name" and "lastModified".
var entry = items[i].webkitGetAsEntry();
if (!entry) entry = items[i].getAsFile();
if (entry instanceof Blob) /** CHROME pastet Bilder als Blob **/
{
entry.isFile = true;
entry.lastModifiedDate = new Date();
entry.name = ""+new Date().getTime()+"."+entry.type.split('/')[1];
}
if (entry.isFile)
{
//handle dropped file
}
A site I am working on has a lot of images that are pulled from a database. The dimensions of the images are not consistent and I am trying to display them in uniformly sized boxes (divs). I do not know the dimensions of any of the images but I can retrieve them with:
document.getElementById( myImage ).width
document.getElementById( myImage ).height
After this I do my tests to see how to resize images to fit the uniform boxes. Finally I set the effects with:
document.getElementById( myImage ).width = theNewWidth
document.getElementById( myImage ).height = theNewHeight
This function is only called once per image by using onload="resizingFunction( imgId );" in the img tag. It takes about 1-2 seconds for every image in the database to complete this function and the function is never run for any of those images again. Despite never running again, the site runs significantly slower if I use this function. After googling I tried adding:
document.getElementById( myImage ).removeAttribute("width")
document.getElementById( myImage ).removeAttribute("height")
Before setting the new width and height. This did improve the speed but it is still slower than if I had not resized the images. Again, just for clarification, each image is resized one time after it has been loaded but for some reason this still slows down the site.
Images are created by being PHP echoed into JavaScript. This is necessary because they need information from the database (PHP), and the JavaScript places them inside the correct box (div). Here is the creation of image code:
echo "\t\t\tdocument.getElementById('gBox".$i."').innerHTML = '<img onload=\"image_applyToGrid(".$i.");\" id=\"img".$i."\" style=\"left:0; top:0;\" src=\"'+gBoxes[".$i."].imgPath+'\"/>';\n";
Here is the image resizing function that images call once onload:
function image_applyToGrid(inId) {
inIdImage = document.getElementById("img"+inId);
var imgW = inIdImage.width;
var imgH = inIdImage.height;
if (imgW > imgH) {
var proportions = imgW/imgH;
imgH = gridUnit;
imgW = gridUnit*proportions;
inIdImage.style.left = -((imgW-gridUnit)>>1)+"px";
}
else {
var proportions = imgH/imgW;
imgW = gridUnit;
imgH = gridUnit*proportions;
inIdImage.style.top = -((imgH-gridUnit)>>1)+"px";
}
inIdImage.removeAttribute("width");
inIdImage.removeAttribute("height");
inIdImage.width = imgW;
inIdImage.height = imgH;
}
Resizing images with Javascript is generally not an ideal approach. You are consuming all of the bandwidth to send the full size images across the web and then scaling them down. A better way would be to pull the images from your image store and resize them server side. Then store the result in a server side cache so you can provide all of your client requests with the optimized images. No need to over think the concept of cache here, in this case it could be as simple as a directory or a new column in your database. (FWIW, I prefer not to store binary data in databases but that's probably another discussion)
See: http://www.white-hat-web-design.co.uk/blog/resizing-images-with-php/
The images are probably much too large. I would suggest preparing the images for web use. Google "optimizing images for web" for some ideas on how to do this.
It's bad practice to take full-size images and load the entire image at different dimensions. Consider having thumbnails generated and placed on the page.
If you have a 2500x2500 image that you're just setting the height and width to 500x500, the entire 2500x2500 image is still having to be loaded.
I've recently written a Python module that writes meta tags and values to PNG images using PIL, with the intent to have a webpage read the tags and sort the images accordingly (I'm not interested in the default stuff like Camera Type, I attach tags like "CarModel" if I've just been to a rally for example.
Does anyone recommend a way of reading the PNG meta? I'm using PHP at the moment (http://stackoverflow.com/questions/2190236/how-can-i-read-png-metadata-from-php at the bottom) which is great for the reason that it only pics up the tags I've added, but annoying as I can't figure away of building a neat array with the data for many pictures. Can javascript do this?
Sorry If I've been rubbish at explaining, but I'll re-explain if needs be.
you should have a look at the following php function - exif_read_data
PS: javascript can't do that as far as I know
i had a similar task. I had to write physical dimensions and additional metadata to PNG files. I have found some solutions and combined it into one small library.
png-metadata
it could read and write PNG metadata. it could be used on client and server side.
May be it will help somebody.
Here how you can read PNG metadata in the Browser:
function loadFileAsBlob(url){
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status === 200) {
resolve(this.response);
// myBlob is now the blob that the object URL pointed to.
}else{
reject(this.response);
}
};
xhr.send();
})
};
const blob = await loadFileAsBlob('1000ppcm.png');
metadata = readMetadataB(blob);
Here is a link to a Javascript library that claims to be able to read image metadata:
http://blog.nihilogic.dk/2008/08/imageinfo-reading-image-metadata-with.html
The nihilogic Javascript libraries are indeed very useful for client-side EXIF reading and parsing; but that only applies to JPEG images, as the metadata is supported only in the JPEG and TIFF format (and the TIFF format only supported natively by Safari browser).
PNG can include metadata but not in the form of IPTC or EXIF fields as JPEG or TIFF formats allow.
I want let user to upload images to server add some info (like description, tags) about each image.I use Uploadify to upload multiple images.
I wonder if it is possible to show thumbnails of the images (while the user enters the additional info about each image) before the images are actually uploaded to the server.
I want user to have the following experience:
Select multiple image files
Immediately after that enter additional information about each image while seeing images thumbnails
Press Upload Files button to upload images to server, and go to drink coffee...
I found this script, but I think it also uploads the file before displaying the image thumbnail.
I would appreciate any help !
If you could enforce an HTML 5 capable browser you could use the file-api
Example: http://html5demos.com/file-api
Sure it is possible. Use the FileReader object to get a data URL (or use File.url if you are sure the Client implements it.) and assign it to an new Image()object. Then you can insert the image into DOM.
As an alternative to the standard-based HTML5 APIs, you can use a plugin such as Flash or Browserplus.
There is actually a ready-made application which might do exactly what you want. It's called Plupload. You can upload your files / images using a variety of "runtimes", and do client-side image resizing before uploading. I guess you can hook a thumbnail preview somewhere in there, in certain runtimes.
Otherwise, you can try building what you want from scratch, using the HTML5 / Gears / BrowserPlus / etc. APIs.
I'm pretty sure flash and java can both do it. Flash would require certain (obvious) security precautions (ie, you can do this for any file, it must be selected by the user).
Meanwhile java would show a security popup.
Xavier posted this solution on another thread, and I tried to improove it to work with multiple file inputs. I hope it helps.
$("body").on('change', 'input:file', function(e){
for (var i = 0; i < e.originalEvent.srcElement.files.length; i++) {
var file = e.originalEvent.srcElement.files[i];
var img = document.createElement("img");
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
}
img.width = "50";
reader.readAsDataURL(file);
if($(this).next().hasClass('image_place')){
$(this).next('.image_place').html('').append(img);
}else {
$(this).after('<div class="image_place"></div>');
$(this).next('.image_place').append(img);
}
}
});
It scans all file inputs in the document body and reads the image using the FileReader api. If it finds any images, it creates a div called "image_place" where he puts the image. If there's already a image inside, the script replaces the image.
I am looking to build an app similar to santayourself (facebook application) a screenshot below
The application will accept a photo and then the users can move it with controls for zoom and rotate and moving image right, left, up and down. Then once the face is as required then the user can click save to save the image on the server (php, apache, linux).
Any recommendations on how to go about this project? I guess a javascript solution will be better. Any suggestions welcome.
javascript AND php GD-library would do it - most of the things described above can be done w javascript alone. The fastest way to do this would be to have the santa mask done w a transparent png absolutely placed over a simalarly placed client photo that is however placed in a div the same size as the mask with overflow set to hidden. Since the client phot is absolute within the div it can be moved around and its size can be manipulated by the user through some mechanism as shown above. However - rotation will be a bitch and here you will have to use php gd-library or image majik (personally i would dump rotation). This is a simple-ish job but time consuming - the user-interface to image manipulation is tricky tho. If the output for this is for print-from-screen i would not bother w further server-side manipulation, but rather just store the image to mask positional relationship (1/2 kb) of data...
yep. javascript is the way to go about interactive things like this. I can see this easily being done with a simple script and some PNGs (though you might have to do something creative for the rotation). PHP would only be needed for saving.
EDIT: Actually, now that I think of it, a HTML 5 canvas approach would be best. It's got lots of transformation and pixel-manipulation methods, and can even save the image client-side! Remember, though that HTML 5 is not supported in all browsers (basically everything except IE).
(HTML 5 Canvas Spec)
The drawImage method is what you're looking for:
(I quote from spec)
void drawImage(in HTMLImageElement image, in float dx, in float dy, in optional float dw, in float dh);
So, your HTML would have a canvas element that draws the user's picture:
<canvas id="canvasElement" width="xx px" height="xx px">
<!-- What to display in browsers that don't support canvas -->
<p>Your browser doesn't support canvas</p>
</canvas>
Then, your javascript:
var view;
var context;
var userPhoto=new Image;
userPhoto.src="uploaded.jpg";
// Update these with UI settings
var position = {x:x, y:y};
var scale;
var rotation;
function init() {
// Run this once at the loading of your page
view = document.getElementById("canvasElement");
context = view.getContext("2d");
}
function update() {
// Run this every time you want the picture size, position, rotation updated
context.clearRect(0, 0, view.width, view.height);
// Scale X and Y
context.scale( scale, scale );
// Rotate (convert degrees to radians)
context.rotate( rotation / 3.14159 * 180 )
// Draw the image at X and Y
context.drawImage( userPhoto, position.x, position.y )
}
HTML 5 Canvas is very powerful, so there's tons of other things you can do to your image if you go this direction. However, another viable solution would be to use flash, which is supported everywhere — but I recommend HTML 5 as it is the way of the future (Steve Jobs: Thoughts on Flash).
Have a look at the jCrop library (jQuery), you may be able to tweak it enough to do what you want to do.
http://deepliquid.com/content/Jcrop.html (they obviously supply a few demos)