I've noticed the following behaviour in Chrome and Firefox on Ubuntu Linux and Windows 8:
A greyscale image containing text is perfectly legible when viewed in a picture editor, but browsers somehow make the greys much paler than the image is when viewed in them (Chrome, Firefox)
Does anybody have an idea if there is a way to stop this or control it, perhaps via Javascript, server headers, etc? Is there some sort of encoding in the images themselves which is not clearly setting the correct gray tone to use?
Not sure when this started happening, but this image is from a website that has perhaps a million such images, and there never used to be a problem.
The reason turns out to be connected with missing metadata stored in the png files which meant the images were not being assigned a correct default ICC colour profile. Older browsers didn't bother with colour profiles, which in this case meant they actually displayed the images "properly" in the past, but new browsers displayed faint images.
With pngs it is possible to set a single byte property in the image metadata which instructs image renderers to use the sRGB ICC image colour profile.
UPDATE:
Thanks to danack for pointing out the correct way of doing this withour resorting to using exec() as I did in my original fix:
$image->transformImageColorspace(Imagick::COLORSPACE_SRGB);
I should also note that contrary to what this page says the setImageColorspace() method does work as intended, as its function is not to actually make changes to the file colorspace, but only to set the colorspace that the image claims to be in (aka "sets the colorspace member of the Image structure" according to the ImageMagick API documentation). transformImageColorSpace() in contrast actually makes the required changes to make an image display as that colorspace.
Related
I want to know how to apply progressive image in my website.
I'm using Image intervention. I search some way to apply image intervention
but I did not understand. Like
$img = Image::make('public/foo.png');
$img->interlace();
the original image and image that interlace don't have difference.
Can anyone help me to understand progressive image and how to apply it using image itervention in my website?
As you can see in this illustration:
Interlacing (also known as interleaving) is a method of encoding a bitmap image such that a person who has partially received it sees a degraded copy of the entire image.
...
For example: Interlaced GIF is a GIF image that seems to arrive on your display like an image coming through a slowly opening Venetian blind. A fuzzy outline of an image is gradually replaced by seven successive waves of bit streams that fill in the missing lines until the image arrives at its full resolution.
~ Interlacing (bitmaps) on Wikipedia
In another word, you won't see any visual difference between two images unless you try to load them with a low-speed connection within a modern web browser.
(See: Firefox DevTools has now a network throttling tool to simulate slow connections)
And BTW, your code was correct. I guess you were just trying to see a difference between interlaced and non-interlaced images which you will not be able to as long as they are not huge and they'll load fast.
For better understanding:
Videos of SCTP vs TCP in progressive vs non-progressive
I'm trying to upload some photo from a mobile using jquery mobile and php but after uploading my photo it's always in landscape format even if my photo is in portrait format on my iphone !
So i can't know which one must be rotated or no .
Thanks
I had this same problem. My solution was a little quick and dirty but here you go:
Write a function to be called when the image loads, check to see if the image is going to rendered in landscape.
$(".imgTile").load(function(){
if(this.width>this.height){
$(this).css("transform","rotate(90deg)");
$(this).css("top",".7em");
$(this).css("left","-.5em");
}
}
A couple notes: I found I had to do some repositioning to get the rotated image to fit properly into the listview (hence the setting of top and left properties) so you may need to tweak this for your needs. Second, there are different css "transform" properties for different browsers, so you may need to set each to have cross browser support. Here's a guide on those properties http://www.w3schools.com/cssref/css3_pr_transform.asp
EDIT: I took some time and came up with a much more solid solution.
First, use php to read the exif tags:
$exif=exif_read_data("uploads/$fileExtension.jpg",0,true);
$orient=$exif["IFD0"]["Orientation"];
Some research into the EXIF standard reveals that the three cases that the iPhone will generate are:
1-- requires no rotation
3-- requires 180 deg. rotation
6-- required 90 deg. rotation
Then use php's shell_exec to run the following shell script, which uses imagemagick to destroy the EXIF headers, and physically rotates the image the specified amount:
#!/bin/bash
for i in $[filename]
do convert -rotate $[number of degrees] $i $i
done
mogrify -strip $[filename]
Now, the image will be correctly oriented everywhere, and browsers that do read EXIF headers won't show it any differently.
The only thing left to do is execute the script with the correct arguments based on the tag value.
Hope this helps!
I have a PHP photo sharing application in which user-uploaded images are resized into various thumb formats using ImageMagick.
As a seemingly "smart" way to save on file size, I am stripping exif info from these thumbs as follow:
$imagick = new Imagick($image);
$imagick->stripImage();
$imagick->writeImage($image);
This works. It does remove the EXIF info, where a thumbs of 30KB saves 12KB and becomes 18KB. A significant saving when showing many of such thumbs on a single page.
The problem however is that it works a little too well. The resulting images seem to lose a lot of color information and look "flat" compared to their non-stripped versions.
Based on my research so far, my theory is that one or both of the following is true:
Imagick throws away essential color profile information as part of the stripping process
Imagick recompresses the image upon saving it, losing quality
Regardless of the cause of the problem, I'm looking for a way to remove EXIF information in such a way that it does not affect the image quality or color itself.
Is this even possible?
Update:
Based on Gerald Schneider's answer, I tried enforcing the quality setting to 100% prior to "stripping" the image:
$imagick = new Imagick($image);
$imagick->setCompression(imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(100);
$imagick->stripImage();
$imagick->writeImage($image);
Unfortunately, the problem remains. Below is example output where despite setting the quality to 100%, images are still flattened.
Consider keeping the ICC profile (which causes richer colors) while removing all other EXIF data:
Extract the ICC profile
Strip EXIF data and image profile
Add the ICC profile back
In PHP + imagick:
$profiles = $img->getImageProfiles("icc", true);
$img->stripImage();
if(!empty($profiles))
$img->profileImage("icc", $profiles['icc']);
(Important note: using the ImageMagick 3.1.0 beta, the result I got from getImageProfiles() was slightly different from the documentation. I'd advise playing around with the parameters until you get an associative array with the actual profile(s).)
For command line ImageMagick:
convert image.jpg profile.icm
convert image.jpg -strip -profile profile.icm output.jpg
Images will get recompressed of course if you use ImageMagick, but at least colors stay intact.
Hope this helps.
Having made similar changes to MIME types in file headers that were incorrectly stored, I'd suggest you verify the length of the EXIF data via the standard tools, and then "Zero" the data manually using multibyte string functions.
EXIF can only be a maximum of 64KB in a JPEG file, however I'm not positive if it's exacly 64KB, so I would begin with this.
GIMP (another opensource image editor) also allows to remove EXIF, IPTC, XMP, thumbnail, ICC (color profile), etc meta data without loosing image/picture quality.
After opening the image in GIMP, Choose "Export" / "Export As" etc option, then select/unselect what meta data you want to remove/keep.
To keep original image quality you must select (tick mark) the option "Use quality settings from original image", which is shown under the "Quality" sliding-bar in top.
I usually like to keep ICC (save color profile meta data) option selected, to keep good color quality, with a colored photo.
Other options (Save EXIF, Save IPTC, Save XMP, Save thumbnail, etc) i usually unselect.
More info: here.
I have developed a photo sharing community site using CodeIgniter 1.7. Photos that are uploaded by members are automatically resized in a number of formats, for which I use the CodeIgniter Image Manipulation class. This class is built into the framework and basically a wrapper around multiple image manipulation libraries, such as GD, GD2, ImageMagick, and NETPBM. On my host, I can only make use of GD2, so that's where this question will be about.
On to my problem. Here is an example of a resized photo on my site. Note that the original was very large, over 3000px wide:
http://www.jungledragon.com/image/195/female_impala_close-up.html
Now, look at that same image, also resized, just a bit larger at Flickr:
http://www.flickr.com/photos/fledder/3763538865/in/set-72157621744113979
See the dramatic difference? I'm trying to bridge that huge gap. The first thing I did was to apply a sharpen filter to the images. You can see the result here:
Although still not perfect, it at least approaches the sharpness level of the Flickr image. The remaining problem is that the colors are washed away, as if their saturation is decreased. This happens before the sharpening filter already, so it must be in GD2.
This issue is vitally important to me, but I don't know where to look. I've found some .NET threads talking about chroma sub sampling but I don't know what to do with that information in my setup. I'm looking for any solution that works within the constraints of my setup.
Update: Hereby the original file, exactly as I uploaded it both to my site and Flickr:
http://www.jungledragon.com/img/DSC07275.jpg
Update 2: I'm shocked. In a good way. It took me a lot of pain to install ImageMagick but after switching to it (which was a matter of setting 'imagemagick' as the library to use at the Code Igniter image manipulation class, the result of the test image is as follow:
ImageMagick's resizing is doing it exactly as intended. The colors are preserved, and the sharpness is there. Yes, I disabled my custom sharpening routine since it is no longer needed due to ImageMagick. On top of that, the process is a lot faster and less memory hungry too. And here comes another great part: I cannot explain it, but I did absolutely nothing to tell ImageMagick to use a specific color profile, which was suggested by user #Alix. In my testing so far it looks like the color information is respected with or without an embedded profile. The output simply is a smaller version of the input. Is ImageMagick really that smart or am I dreaming?
I've managed to further test this with Imagick:
The left half of the image was processed with Imagick and the sRGB_IEC61966-2-1_no_black_scaling.icc color profile, the right half has no color profile associated and shows exactly the same if processed with Imagick or GD; here is the code I used:
header('Content-type: image/jpeg');
$image = new Imagick('/path/to/DSC07275.jpg');
if (($srgb = file_get_contents('http://www.color.org/sRGB_IEC61966-2-1_no_black_scaling.icc')) !== false)
{
$image->profileImage('icc', $srgb);
$image->setImageColorSpace(Imagick::COLORSPACE_SRGB);
}
$image->thumbnailImage(1024, 0);
echo $image;
Here is a comparison of the several sRGB profiles available on the color.org website:
It seems to me that the third profile produces the most vivid results, other than that I have no idea how one would make a definitive choice.
EDIT: Apparently, Imagick comes with a bundled sRGB profile, so you don't need to download the one from the Image Color Consortium website, the following code should handle all scenarios:
header('Content-type: image/jpeg');
$image = new Imagick('/path/to/DSC07275.jpg');
$version = $image->getVersion();
$profile = 'http://www.color.org/sRGB_IEC61966-2-1_no_black_scaling.icc';
if ((is_array($version) === true) && (array_key_exists('versionString', $version) === true))
{
$version = preg_replace('~ImageMagick ([^-]*).*~', '$1', $version['versionString']);
if (is_file(sprintf('/usr/share/ImageMagick-%s/config/sRGB.icm', $version)) === true)
{
$profile = sprintf('/usr/share/ImageMagick-%s/config/sRGB.icm', $version);
}
}
if (($srgb = file_get_contents($profile)) !== false)
{
$image->profileImage('icc', $srgb);
$image->setImageColorSpace(Imagick::COLORSPACE_SRGB);
}
$image->thumbnailImage(1024, 0);
echo $image;
Your original image has a Adobe RGB (1998) ICC profile attached. I think GD, not knowing about profiles, is interpreting the image data incorrectly. Here's a related PHP bug confirming this.
You would need to prepare the image with the correct profile, most likely sRGB.
If you have an application that can do that, try converting it to sRGB and re-uploading.
If you need a permanent server-side solution to the problem, I think you will need an image processing library that can deal with profiles. To be honest, I don't know how ImageMagick deals with these things, but at least it is familiar with the basic concept of colour profiles.
Related: Comparison of sRGB and Adobe RGB
I have a small bit of info to contribute to this thread. I'm a photographer and not a web developer so my technical knowledge is not great, however, I have been dealing with this issue so I hope this post will help someone else down the line.
I use an online photo sales tool that resamples all my images using GD. I was having issues with images looking way funky even when uploaded with proper sRGB conversion and ICC profiling attached, when viewing on my wide-gamut monitor.
What I found the problem to be is that GD strips all metadata and ICC profiles from the original files. Then the browsers, not seeing any profile, are not displaying them correctly. It's slight on a standard-gamut monitor but very obvious on wide-gamut.
If you're having problems with this, you can test my theory by using Firefox and changing a setting in about:config. Change the value of "gfx.color_management.mode" from the default of "2" to "1". This setting will force Firefox to assume any image without an ICC profile is sRGB and will display it as such. Images should then appear as you would expect and identical to Photoshop/Lightroom/etc. Why all browsers do not use this common-sense approach as their default is beyond me.
Unfortunately, my shopping cart is only setup to use PHP GD so I cannot get good results at this time. I would really like to see GD updated to leave ICC profiles attached or to have the option of adding a simple sRGB profile on export.
More info here:
http://www.gballard.net/psd/go_live_page_profile/embeddedJPEGprofiles.html#
Okay. So I have about 250,000 high resolution images. What I want to do is go through all of them and find ones that are corrupted. If you know what 4scrape is, then you know the nature of the images I.
Corrupted, to me, is the image is loaded into Firefox and it says
The image “such and such image” cannot be displayed, because it contains errors.
Now, I could select all of my 250,000 images (~150gb) and drag-n-drop them into Firefox. That would be bad though, because I don't think Mozilla designed Firefox to open 250,000 tabs. No, I need a way to programmatically check whether an image is corrupted.
Does anyone know a PHP or Python library which can do something along these lines? Or an existing piece of software for Windows?
I have already removed obviously corrupted images (such as ones that are 0 bytes) but I'm about 99.9% sure that there are more diseased images floating around in my throng of a collection.
An easy way would be to try loading and verifying the files with PIL (Python Imaging Library).
from PIL import Image
v_image = Image.open(file)
v_image.verify()
Catch the exceptions...
From the documentation:
im.verify()
Attempts to determine if the file is broken, without actually decoding the image data. If this method finds any problems, it raises suitable exceptions. This method only works on a newly opened image; if the image has already been loaded, the result is undefined. Also, if you need to load the image after using this method, you must reopen the image file.
i suggest you check out imagemagick for this: http://www.imagemagick.org/
there you have a tool called identify which you can either use in combination with a script/stdout or you can use the programming interface provided
In PHP, with exif_imagetype():
if (exif_imagetype($filename) === false)
{
unlink($filename); // image is corrupted
}
EDIT: Or you can try to fully load the image with ImageCreateFromString():
if (ImageCreateFromString(file_get_contents($filename)) === false)
{
unlink($filename); // image is corrupted
}
An image resource will be returned on
success. FALSE is returned if the
image type is unsupported, the data is
not in a recognized format, or the
image is corrupt and cannot be loaded.
If your exact requirements are that it show correctly in FireFox you may have a difficult time - the only way to be sure would be to link to the exact same image loading source code as FireFox.
Basic image corruption (file is incomplete) can be detected simply by trying to open the file using any number of image libraries.
However many images can fail to display simply because they stretch a part of the file format that the particular viewer you are using can't handle (GIF in particular has a lot of these edge cases, but you can find JPEG and the rare PNG file that can only be displayed in specific viewers). There are also some ugly JPEG edge cases where the file appears to be uncorrupted in viewer X, but in reality the file has been cut short and is only displaying correctly because very little information has been lost (FireFox can show some cut off JPEGs correctly [you get a grey bottom], but others result in FireFox seeming the load them half way and then display the error message instead of the partial image)
You could use imagemagick if it is available:
if you want to do a whole folder
identify "./myfolder/*" >log.txt 2>&1
if you want to just check a file:
identify myfile.jpg