Reading PNG meta data on the web - php

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.

Related

Can I do server side processing of canvas using PHP

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/

What is the best way to send image file to server: as base64 or image file?

I have an app with REST on AngularJS/PHP(Yii);
I'm not good in backend.
I'm interesting what is the best way to upload a picture to server.
I'm using Angular Material directive and get image in base64 format.
Should I post image as base64?
Or it's better to convert it and what format?
Or maybe (It's not my opinion) to upload it from html form directly
to backend using Yii?
I think you trying to upload an image file from restangular,
Try the following code:
function upload($scope.image) {
var formData = new FormData();
formData.append($scope.image);
Restangular.one('/* your url*/').withHttpConfig({transformRequest:angular.identity})
.customPOST(formData, '', undefined, {'Content-Type': undefined}) }
by setting the content type undefined browser will automatically detect file type
that will handle your UI side. I have less idea about yii framework, but in following you can get the image file by using following type:
java : #ResponseBy : multipart/form-data,
php : $_file
I think its better to upload file using form-data.
If you plan to display those uploaded images on a website or mobile application, you can use ImageKit.io. Easy API to upload and you get an URL for displaying that image. It will take care of optimization and also provides URL-based parameters for resizing, cropping etc.
If you have a base64 data url representation of the file as you are saying, then you can convert that into a file Blob, add a name to it and upload the Blob as data file.

How to play MP3 format data in browser?

I am using php for server side scripting. In default I am using "audio" tag for playing audio files, Because my api call returns file path so it is easily handle.
for example my example look like this:
{
'id':123,
'question':'tell about your self?',
'audio':'/wdk/path/00fl.mp3'
}
so i can easily use this in audio tag.<audio src="www.abc.in/wdk/path/00fl.mp3" preload="auto">
But now i getting different format of API response. It returns data content instead of url. For example
{
'id':123,
'question':'tell about your self?',
'audio':'/wdk/path/MP3'
}
so now i need to make curl call again with content-type:audio/mpeg for getting data-content.It returns raw mp3 format data. So how can we play the audio file in browser? is any player there for convert mp3 format data to player data straightly? and i tried another way, but i could not able to store a mp3 format file in php.
can we create mp3 file using php? for ex:
$myfile = fopen("D:\xampp\htdocs\abc\testfile.mp3", "w");
$fwrite($myfile, $result);
my curl response like this:
ID3#TSSELavf56.15.102��8�Infora
!#%*,.0357<>#BEGIMPRTVY[adfhjmqsuxz|~��������������������������������������������������Lavc56.13$a5Cwc��8�"#�p7I<��Z���<ѣF�
��HP���.uN{P�! �{�����������]�D�DDwww��������"'����_���";�������=��B""�������
If you are getting the contents of the mp3 file, you can use data URI, the source is just encoded file contents:
echo '<audio src="data:audio/mpeg;base64,'.base64_encode($sound_text).'" autoplay="autoplay" controls ></audio>';
Data-URI
You could use data-URIs as #n-dru suggests in his answer, but you should be aware of a couple of things:
Base-64 increases the data size by 33%, and strings in JavaScript uses two bytes per char.
Some browsers limits the maximum data-URIs length (as there is a significant overhead decoding them)
Blob + ObjectURL
A better approach IMO, is to use Blobs and ObjectURLs. It's not without its own drawbacks though:
Require CORS fulfillment to load the data for the Blob (ie. your sample data must come from the same server as the page -or- the server must allow CORS usage)
The URL object must be prefixed in some browsers (incl. webkit)
The advantage is that the data can be loaded and used as a raw byte-buffer with no overhead in decoding nor bandwidth.
Example
This example loads the MP3 data (which would be the raw data you receive), then creates a Blob and an ObjectURL for the Blob. This can then be set as source for the audio element.
The example also shows how to handle the asynchronous nature of the various stages.
var audio = document.getElementById("audio");
audio.onload = function() {
// audio has loaded..
audio.play();
// continue from here (or the onerror event, not shown)
};
// load the url as raw data and create an ObjectURL:
loadRaw("/wdk/path/MP3", function(url) {
audio.src = url;
});
function loadRaw(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onerror = function() {console.log("Network error.")};
xhr.onload = function() {
if (xhr.status === 200) {
var blob = new Blob([xhr.response], {type: "audio/mpeg"}),
oURL = (URL || webkitURL).createObjectURL(blob);
callback(oURL);
}
else {console.log("Loading error:" + xhr.statusText)}
};
xhr.send();
}

read images and upload, after

What I'm trying to accomplish
[x] 1) User fills out form
[x] 2) User adds images to form through "drag & drop (html5)" or by "click to choose images"
and a preview is displayed on the page. (done)
Here it's easy to add code to trigger an upload of theese images to the server but I don't want that just yet.
[x] 3) Users clicks "add me & my desk" --> Create user account if doesn't already exist
[x] 4) Desk is added, and a connection to the right user is added as well.
[x] 5) Create a folder with the same name (id) as the desk_id.
::::THE QUESTION::::
6) -->> now I want to upload those dragged and dropped, or selected images to that folder.
:::::::::::::::::::
I've gotten this far with the information I found here: http://www.html5rocks.com/en/tutorials/file/dndfiles/ (the actual page really rocks!9
I know about this awesome solution: http://blueimp.github.com/jQuery-File-Upload/
But it's overkill for what I'm trying to do, and I happen to be so proud that I've got everything else working, and I really do think I'm so close.
words and expressions that keep coming up: read blob, check array blob, read from sandbox, canvas.toDataURL()
I feel that the answer is here: http://www.html5rocks.com/en/tutorials/file/xhr2/
AND / OR HERE http://www.html5rocks.com/en/tutorials/file/dndfiles/ Or HERE /
http://www.html5rocks.com/en/tutorials/file/filesystem/ (under "Duplicating user-selected files"), OR HERE http://robertnyman.com/2010/12/16/utilizing-the-html5-file-api-to-choose-upload-preview-and-see-progress-for-multiple-files/
You could say I'm at the next step after this: Preview an image before it is uploaded
but perhaps I could get a push in the right direction? :)
Of course I've had a look at these:
HTML5 Pre-resize images before uploading
facebook js api - HTML5 canvas upload as a photo
Currently displaying preview from DND files like this:
for (var i = 0, f; f = uppladdadeFiler[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb preview" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('listImages').insertBefore(span, null);
var span2 = document.createElement('span');
span2.innerHTML = ['<img class="thumb inside" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('huvudbilden').insertBefore(span2, null);
};
})(f);
$('#valdaBilder').show();
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
I will give you some inputs which I hope will lead you in the right direction. Please note that I am not providing an off-the-shelf working answer because of two reasons - 1. I am just too lazy:) and 2. from what I can see you are smart enough to figure it out once you get the gist of it... so here goes:
First thing to do is have a button named, say, 'Upload Files' and attach a fn to it like uploadFiles(). Now this function will look something like below:
function uploadFiles()
{
var file = files[0];
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState==4 && xhr.status==200)
alert(xhr.responseText);
};
xhr.open('POST', '/upload.php', true);
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
}
Ok, so the explanation:
var file = files[0];
The files object array should be something that you create in your drag and drop eventlistener functions, which will be file objects representing the files you dropped into the dropzone. Usually you create them so: files = event.dataTransfer.files; which creates a FileList object named files In the example I am only considering the first file in the dropzone - hence files[0]
I guess the rest of the code is pretty self-explanatory. One thing to note is:
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
As you can see we are sending out raw binary data content to the server. So the post operation is writing into the server stream with raw binary data of what the file contains. This is an important point because this affects how the server is able to read this posted data.
Server side upload.php:
I am just going to read the first 1000 bytes of the uploaded file and print it back into the client (which, based on the javascript code above, will alert it into the browser)
<?php
$streamHandle = fopen("php://input","rb");
$streamContent = fread($streamHandle,1000);
echo $streamContent;
?>
Many people get confused on how to read content at the server side and think about using $_POST, or $_FILES, but if you are sending data using X-FILE-NAME, then you have to read it by opening a handle to php://input which is the standard input stream of the running php process.
Once you have read the stream, it is only a matter of fwrite-ing it into a new file in whatever directory you want to.
Like I said, this is not a turn-key solution that you can just copy-paste into your particular code, but I hope this helps you in looking in the right direction for file uploads using HTML5's drag and drop and the file API provided by Javascript to support it.

Is that possible to display image thumbnail without uploading it to the server?

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.

Categories