I've been struggling to an issue of saving an image into jpeg which loses quality. As a project for my degree, I'm making an app where i upload the images on facebook.
I have a nice colored image, for which i shuffle the pixel values to get a mapped image. Then I upload it onto the facebook. When, i download and move the pixels back to original image, it loses the quality too much.
Below are the original, mapped and retrieved images:
I've tried many strategies like using png files, which works. But, currently, whatever the image is, facebook converts it to jpeg. So, if i upload maskedimage.png to facebook, it converts it to .jpg and loses some of the pixel-correlation values, which doesnt end up giving me the right image to retrieve original.
I'm using PHP and facebook-php sdk.
Please suggest.
Thank you
-Kaur
You're stuck. JPEG is a lossy algorithm which depends on human vision characteristics to mask the inaccuracies. By scrambling the pixels you've changed the nature of the loss so that it's not invisible anymore.
This isn't primarily about JPEG being lossy; it's about Facebook forcing image recompression, even if you check "High quality" when uploading.
The best you can do is to double the source image resolution, and for solid colors, try to introduce noise. Details in this GD.SE question
Note that the trick of uploading images <100kb has no longer been working, since at least June 2012.
Related
We have a custom built CMS which allows for image uploads. In the CMS we have implemented
jCrop. When cropping an image (with GD in PHP), we are storing the original image name and crop image name in the database (MySQL), aswel as the original image and crop image on the server.
When we need an alternate crop, we use PHP to create another crop of the cropped image (and save it to the server). Because such an image has now been processed by GD twice, the result often looks bad.
A possible use case: in the CMS we manage persons. Each person can have an image. Since persons are usually shown in portrait mode, we let the user crop in portrait. On the website this works out fine, but on the mobile website, we actually need a square image. Hence we need two crops.
Lately we've been wondering how we could improve our crop workflow. Would an approach of only storing crop coordinates in the database work on the long term? What is a common approach of dealing with crops?
Thanks in advance!
I would use this approach:
Upload an image. Assign it an unique ID (i.e. an MD5 hash of the name).
Let the user crop it, store only the coordinates and image name in the db
Store the cropped image, give it a filename that is made for example out of the original file name plus the coordinates of the crop.
In this way you will be able to retrieve the cropped image only by knowing it's original name and the coordinates of the crop. In addition an exact duplicate of any crop would not be stored.
Example:
md5('image.jpg' . $crop->x0 . $crop->x1 . $crop->y0 . $crop->y1);
Would an approach of only storing crop coordinates in the database work on the long term?
Not if by that you mean you would also do the cropping each time the picture is requested. That puts unnecessary load on both your server (doing the actual cropping on-the-fly each time) and on the client as well (because there will be no caching of those dynamically generated crop images, unless you implement that on top of the whole thing).
Since persons are usually shown in portrait mode, we let the user crop in portrait. On the website this works out fine, but on the mobile website, we actually need a square image. Hence we need two crops.
Maybe a better approach would be what f.e. Facebook does in some places: Instead of cropping an image to be square server-side, the just have the client load the non-square version – and then let the client do the “cropping” by simply displaying the image as a positioned background image within a square element …
I currently have a website that aggregates images, the problem is those images are very large, and when I display them at smaller sizes, they still eat up a lot of computation.
I'm curious as to how to actually force reduced size/quality without just smooshing it into a <div> element.
Here is my site in question, you can see how 'laggy' it gets when you produce images:
http://newgameplus.nikuai.net/TEST/index.html
I was using timthumb.php to resize the images, but the host doesn't allow that script for some reason.
The best way to do this is to use some sort of image re-factoring service.
I have written my own one that uses ffmpeg and imagemagik to resize images on the fly and to generate arbitrarily sized thumbnails from videos. I memcache the results to make subsequent requests super snappy, and have some interesting additions such as automatic Point of Interest detection using Face Detection and Image Entropy, with the aim being "nice thumbnails, no matter the size"
An example of such a service is src.sencha.io - the documentation for this service is here but I have included the important bits below.
Specify Image Size
<img src='http://src.sencha.io/320/200/http://yourdomain.com/path/to/image.jpg'
alt='My constrained image'
width='320'
height='200' />
This will take your image (http://yourdomain.com/path/to/image.jpg) and run in through the resizing service, returning a 320x200 version of your image. You cannot set the gravity/point-of-interest using this service though (as far as I can tell).
You can also use this service to change formats, resize dataurls, do percentage resizes and use the resizing service to detect the width/height of the user agent requesting the image.
There are many such services available on the web.
I agree with slash: It depends on how the images are being resized. One thing I do for a site is use photoshop (or GIMP) to resize the image to the exact dimensions i need for the page i'm using the image for. Then i also include the same dimensions in the width-height attributes on the image itself.
Additionally, you can use your photo editing software to check the size of your image if you were to save it with a different file extension, and (specifically with jpeg and png files) photoshop will let you reduce the quality, which lowers file size and speeds up page loading.
Currently i am using gd to converting the image uploaded in jpg with
imagjpeg($data,NULL,85)
and storing it in a blob mysql field. Problem is the quality. Yes the quality is just awful. A screenshot of a window with some text inside becomes pretty hugly. (While with a game screenshot the quality is passable)
Should I use other lib than GD?
Should I use other gd format? (imagepng?)
ps. please note: this is not a duplicate.. i am not asking how to save an img to db
ps2. note that if i should change my currently format/method I have to convert something like 5000-6000 images already stored as jpg in my db
ps3. i use 85 for imagejpeg, can't use a higher value because the image size would grow more than the original version
ps4. I need to store image in db, please stay in topic
Thanks all
================================
REFORMULATING THE QUESTION
I save image (mostly software screenshots, sometime games screenshots) in BLOB field after doing an imagejpeg($resourceFromImageCreateFromString,NULL,85);
Problem I am experiencing is the image uploaded looks pretty bad in confront of the original even if it's the same size. (sometime it gets bigger because of 85)
Is the imagejpeg implementations that sucks?
ps. my simple upload script does the follow calls:
upload file
open it with "rb" (binary)
pass the data to imagecreatefromstring
pass the result to imagejpeg
Thanks again
Is there a special reason you want to store your image inside a BLOB?
What quality argument did you pass to imagejpeg()?
You can set the quality of your output with the 3rd parameter to imagejpeg(). The problem is that JPEG is not the best format for images with a lot of text - you have to choose between turning down the quality and getting a lot of artifacts in your image, or turning up the quality and having a large file size. You might consider using PNG instead.
my first recommendation would be to try saving it as a png as the quality is better.
my second recommendation is to try the quality parameter in imagejpeg($image, $filename, $quality).
recommendation #3 - I worked on a site that I had to rewrite the image storage system because they implemented just what you are doing, storing images as BLOBs in the database. Their system only had about 20K images in it and it was crashing weekly because the database could not handle the load.
The conversion process for 5-6K images should not take more than a couple hours no matter how large the images. When I converted my images to disk storage from db storage, I ran 1K images at a time and each run took 5-10 minutes.
Why do you re-code anyway if it already IS a jpeg? To save space? Well, but then you already have your answer, in part - to save space from jpg to jpg you have to save in lower quality.
You cannot specify quality with imagecopyresampled, with imagejpeg you can. Use a high(er) value for the quality parameter.
Please note that JPEG is a format optimized for storing FOTOS. Images with large areas of the same color, straight lines etc. are much better stored in a lossless format like PNG. Of course, if you have a screenshot taken from a screen with fotos as desk background you have elements of both - so choose your format according to what you want. If the foto-part is more important and you don't care as much about fonts and lines, go with jpeg. Of course JPEG can be just as good quality as PNG for screenshots as well, but then you miss out on most of its compression capabilities, you have to use a 90+% quality setting. At 100% JPEG too is lossless, but by then a PNG might actually be of smaller (file)size.
I'm developing a web-to-print, poster printing application.
I'm considering using PHP to crop user-uploaded images, and we will ultimately print the PHP-cropped image.
My concern is there will be a difference in 'quality' between the original user uploaded image, and image after it is cropped by PHP.
Will PHP affect the quality of the image when handling it? Or does it preserve the image's quality and simply crop the relevant area?
Many thanks,
BK
JPEG is lossy compression. A bit of oversimplification, but it works by analyzing pixels around other pixels to see how similar they are. Not every pixel is stored, and that means it isn't possible to simply chop bytes out of the image data to perform the crop. If you are outputting JPEG, you will be re-compressing an already compressed image, and you will have some loss in quality. However, if you crop the image and your output is a non-lossy format, then you will not have loss of quality.
To be clear, the loss of the quality isn't in the crop operation. It is in the way the image is compressed itself. If the source image is compressed with JPEG, quality has already been lost. When you crop that image, you aren't losing anything more, but if you were to output JPEG again afterwards, this would require a re-compression, and thus more loss.
So in the end, make your final output PNG or something non-lossy and you have nothing to worry about.
I am developing an iPhone camera app that uploads an image to Amazon S3 and that image is displayed on a website. When the iPhone takes a picture, it always saves the photo in an upright orientation, while the orientation used to correctly view the photo is saved in the image's EXIF data. So if I take a photo with the iPhone and open it in FireFox without processing the EXIF data, the image could be sideways or upside down.
My problem is that I don't know how to display the photo in it's correct orientation on the website. My current solution is to rotate the photo in the iPhone app, but I'd rather not do that. Is there anyway to respect the EXIF data when displaying on the web without pre-processing the image?
You have several options, listed in my order of preference.
Rotate the image on the camera.
Upload the data through Amazon EC2 and use program to read the exif and do the rotation
Run a program on your web server that proxies s3 and does the rotation.
Use some fancy Javascript and DHTML.
Option 3 might not be reliable across browsers, and I'm not sure of the performance. Option 2 would add unnecessary complexity. You might not want to do it, but unless you are planing on using the net for anything but storage, option 1 is best.
Rotating on the camera might be the best option, but if you rotate before storage and the image is a JPEG, rotation is a lossy operation -- so the image you store will immediately lose some quality.
Luckily, it doesn't have to be that way -- if instead of reading in the JPEG, rotating the image and then re-encoding as JPEG, there are ways to apply rotation directly to the file.
JPEG is stored as a series of 8x8 cells -- they can individually be rotated and rearranged without losing quality (90 degree increments) -- then you need to update the meta-data that has the size information.
Here's some C++ code you could try to port
http://eng.neologica.it/download/downloadIJGWin32.html
For .NET, my company (Atalasoft) provides an SDK that can do this.
Another option is reading the JPEG, rotating and then storing as PNG, but the file size will be much larger.