Magento resize() image quality: dirty white background - magento

I have a client who is seriously unhappy with the way their product thumbnails are rendering on Magento.
The dodgy appearance is noticeable on two accounts:
there is a dirty white background which has very light grey horizontal lines
and secondly there is ever so slight color loss (loses contrast and saturation).
I have removed ALL compression, set ALL quality to 100%, flushed image cache, experimented, broken, and fixed it all dozens of times, and nothing seems to work.
This version of Magento is ver. 1.4.2.0
Is anyone out here experiencing the same problems, and if so have you managed to fix it?

The problem has to do with the php function imagecopyresampled in the resize function inside lib/Varien/Image/Adapter/Gd2.php, there are some rounding issues that occur to make a smoothly resized image.
My solution is to simply change any very light grey pixels in the image to pure white after the image has been resized. To do so first copy lib/Varien/Image/Adapter/Gd2.php to app/code/local/Varien/Image/Adapter/Gd2.php
Next find the following code inside the resize function (around line 312)
// resample source image and copy it into new frame
imagecopyresampled(
$newImage,
$this->_imageHandler,
$dstX, $dstY,
$srcX, $srcY,
$dstWidth, $dstHeight,
$this->_imageSrcWidth, $this->_imageSrcHeight
);
Then add the following code underneath:
// Clean noise on white background images
if ($isTrueColor) {
$colorWhite = imagecolorallocate($newImage,255,255,255);
$processHeight = $dstHeight+$dstY;
$processWidth = $dstWidth+$dstX;
//Travel y axis
for($y=$dstY; $y<($processHeight); ++$y){
// Travel x axis
for($x=$dstX; $x<($processWidth); ++$x){
// Change pixel color
$colorat=imagecolorat($newImage, $x, $y);
$r = ($colorat >> 16) & 0xFF;
$g = ($colorat >> 8) & 0xFF;
$b = $colorat & 0xFF;
if(($r==253 && $g == 253 && $b ==253) || ($r==254 && $g == 254 && $b ==254)) {
imagesetpixel($newImage, $x, $y, $colorWhite);
}
}
}
}
Flush the images cache from the Cache management in Magento, and you should have nicer images for the new displays. Few things to note when implementing this, there is a small performance hit the first time you generate the images again, and images with shadows may have sharper edges as the very light greys have been removed.

try following example
echo Mage::helper('catalog/image')->init($product, 'small_image')->resize(180, 210)->setQuality(50);

You can put your own Gd2.php file in local (app/code/local/Varien/Image/Adapter/Gd2.php) and hard-wire the quality to 100%.
Quality is working for me so I have not done that.
You can also put an image convolution in there to sharpen your images, in that way you get the blur of a resize compensated for with a sharpen, e.g. put the following just inside the end of the 'resize' function:
$sharpenMatrix = array(array(-1,-1,-1),array(-1,24,-1),array(-1,-1,-1));
$divisor = 16;
$offset = 0;
imageconvolution($newImage, $sharpenMatrix, $divisor, $offset);

I had problems with images quality on one of projects. But the problem was not on back-end, but on the front-end. Images had bad quality because images width and height given in the CSS was not the same as the image file had.

quick grep shows that you are able to set this on product_image object
app/code/core/Mage/Catalog/Helper/Image.php:105: * Set image quality, values in percentage from 0 to 100
app/code/core/Mage/Catalog/Helper/Image.php:107: * #param int $quality
app/code/core/Mage/Catalog/Helper/Image.php:110: public function setQuality($quality)
app/code/core/Mage/Catalog/Helper/Image.php:112: $this->_getModel()->setQuality($quality);
app/code/core/Mage/Catalog/Model/Product/Image.php:38: protected $_quality = 90;
app/code/core/Mage/Catalog/Model/Product/Image.php:88: * Set image quality, values in percentage from 0 to 100
app/code/core/Mage/Catalog/Model/Product/Image.php:90: * #param int $quality
app/code/core/Mage/Catalog/Model/Product/Image.php:93: public function setQuality($quality)
app/code/core/Mage/Catalog/Model/Product/Image.php:95: $this->_quality = $quality;
app/code/core/Mage/Catalog/Model/Product/Image.php:100: * Get image quality
app/code/core/Mage/Catalog/Model/Product/Image.php:106: return $this->_quality;
app/code/core/Mage/Catalog/Model/Product/Image.php:331: 'quality' . $this->_quality
app/code/core/Mage/Catalog/Model/Product/Image.php:387: $this->_processor->quality($this->_quality);

I had the same issue with some of my images, later i realized that those images with lower resolution were getting distorted, try using an image more than 1100 X 1100 and it should work just fine !

Upload the images as PNG's. They may not be as small as JPG, but it allowed us to avoid some image quality issues created by Magento's resizing functionality.

Related

PHP crop image - wrong area

On the clientside I have a jQuery script which I use to select a square area on the picture.
I got x1, y1 and width, height parameters. They are sent correctly to the server.
I want to crop image to this selection and then convert to PNG (although I tried both imagejpg, imagepng functions)
The code is (I use laravel 4):
$file = Input::file('picture');
$filename = md5(microtime()).'.png';
$image = imagecreatefromstring(file_get_contents($file->getRealPath()));
$crop = imagecreatetruecolor(Input::get('width'), Input::get('height'));
imagecopy($crop, $image, 0, 0, (int)Input::get('x1'), (int)Input::get('y1'), Input::get('width'), Input::get('height'));
imagepng($crop, public_path().'/uploads/pictures/'.$filename);
It works perfectly when height > width of original image. When I try to crop wide images (width > height) I got wrong area and it seems like x1,y1 are wrong (although they're not). I got right width/height, but wrong section.
What's wrong with the code above?
Solved. The problem was that client side didn't take into account original image size, it was scaled with CSS

Reassembling a fragmented image

I have an image that has been broken in to parts, 64 rows by 64 columns. Each image is 256x256px. The images are all PNG. They are named "Image--.png" for example "Image-3-57". The rows and columns numbering start from 0 rather than 1.
How can I assemble this back in to one image? Ideally using BASH and tools (I'm a sysadmin) though PHP would be acceptable as well.
Well, it is not very complicated, if you want to use PHP. What you need is just a few image gunctions - imagecreate and imagecopy. If your PNG is semi transparent, you will also need imagefilledrectangle to create a transparent background.
In code below, I rely on fact, that all chunks are same size - so the pixel size must be able to be divided by the number of chunks.
<?php
$width = 256*64; //height of the big image, pixels
$height = 256*64;
$chunks_X = 64; //Number of chunks
$chunks_Y = 64; //Same for Y
$chuk_size_X = $width/$chunks_X; //Compute size of one chunk, will be needed in copying
$chuk_size_Y = $height/$chunks_Y;
$big = imagecreate($width, $height); //Create the big one
for($y=0; $y<$chunks_Y; $y++) {
for($x=0; $x<chunks_X; $x++) {
$chunk = imagecreatefrompng("Image-$x-$y.png");
imagecopy($big, $chunk,
$x*$chuk_size_X, //position where to place little image
$y*$chuk_size_Y,
0, //where to copy from on little image
0,
$chuk_size_X, //size of the copyed area - whole little image here
$chuk_size_Y,
);
imagedestroy($chunk); //Don't forget to clear memory
}
}
?>
This is just a draft. I'm not sure about all theese xs and ys as well as ather details. It is late and I'm tired.

IF image is too big, how do I reduce the size?

My Website
On the above link you can see that the middle news post has an image that is just too big.
The info for the news is taken out of a database so I'm not sure how to change the width of the image on only certain images. Ideally I'd like to have any image that is over 300px wide to be kept at 300px. This is what I have so far:
echo '<img src="media/'.$row['media1'].'" class="floatLeftClear" id="border">';
I tired adding width="300" to the above statement but that made ALL of the images become 300px which I don't want. I only want images bigger than 300px to be reduced to 300.
Can someone point me in the right direction please!
If you don't want to physically resize the images on the server, which would be the ideal solution, you can set the max-width property via CSS.
img {
max-width:300px;
}
Note that the property is not supported in IE6 and below.
The code helps to resizing the image. its resize the height and width depends upon the max width
function fixImgs(whichId, maxW) {
var pix=document.getElementById(whichId).getElementsByTagName('img');
for (i=0; i<pix.length; i++) {
w=pix[i].width;
h=pix[i].height;
if (w > maxW) {
f=1-((w - maxW) / w);
pix[i].width=w * f;
pix[i].height=h * f;
}
}
}
fixImgs('photos', 108); // ('element ID', maximum width)
But one thing the image size(KB) is not reduce. I hope its help to you .
Why not to add a special routine for news images layout, define max-size within it and call it for the related images?

Photoshop Action to fill image to make a certain ratio

I am looking to make a photoshop action (maybe this isn't possible, any other application recommendations would be helpful as well). I want to take a collection of photos and make them a certain aspect ration, ex: 4:3.
So I have an image that is 150px wide by 200px high. What I would like to happen is the image's canvas is made to be 267px wide, with the new area filled with a certain color.
So there are two possibilities I can think of:
1) Photoshop actions could do this, but I would have to pull current height, multiply by 1.333333 and then put that value in the width box of the canvas resize. Is it possible to have calculated values in Photoshop actions?
2) Some other application has this feature built in.
Any help is greatly appreciated.
Wow, I see now (after writing the answer) that this was asked a long time ago. . . oh well. This script does the trick.
This Photoshop script will resize any image's canvas so that it has a 4:5 aspect ratio. You can change the aspect ratio applied by changing arWidth and arHeight. The fill color will be set to the current background color. You could create an action to open a file, apply this script, then close the file to do a batch process.
Shutdown Photoshop.
Copy this javascript into a new file named "Resize Canvas.jsx" in Photoshop's Presets\Scripts folder.
Start Photoshop and in the File - Scripts menu it should appear.
#target photoshop
main ();
function main ()
{
if (app.documents.length < 1)
{
alert ("No document open to resize.");
return;
}
// These can be changed to create images with different aspect ratios.
var arHeight = 4;
var arWidth = 5;
// Apply the resize to Photoshop's active (selected) document.
var doc = app.activeDocument;
// Get the image size in pixels.
var pixelWidth = new UnitValue (doc.width, doc.width.type);
var pixelHeight = new UnitValue (doc.height, doc.height.type);
pixelWidth.convert ('px');
pixelHeight.convert ('px');
// Determine the target aspect ratio and the current aspect ratio of the image.
var targetAr = arWidth / arHeight;
var sourceAr = pixelWidth / pixelHeight;
// Start by setting the current dimensions.
var resizedWidth = pixelWidth;
var resizedHeight = pixelHeight;
// The source image aspect ratio determines which dimension, if any, needs to be changed.
if (sourceAr < targetAr)
resizedWidth = (arWidth * pixelHeight) / arHeight;
else
resizedHeight = (arHeight * pixelWidth) / arWidth;
// Apply the change to the image.
doc.resizeCanvas (resizedWidth, resizedHeight, AnchorPosition.MIDDLECENTER);
}
Mind that the accepted answer from #user268911 may not work for you if the source image has different pixels/inch than 72. Because the UnitValue.convert function works correctly only with 72 px/inch. To be sure the conversion is correct for ever pixel/inch value, set baseUnit property as follows:
...
var pixelWidth = new UnitValue (doc.width, doc.width.type);
pixelWidth.baseUnit = UnitValue (doc.width.baseUnit, "in");
var pixelHeight = new UnitValue (doc.height, doc.height.type);
pixelHeight.baseUnit = UnitValue (doc.height.baseUnit, "in");
...
For more details about the conversion see "Converting pixel and percentage values" section of the Adobe JavaScript Tools Guide.
What languages do you know? ImageMagick has command line tools that can do this, but you'd need to know a scripting language to get the values and calculate the new ones.
For .NET, my company's product, DotImage Photo, is free and can do this (need to know C# or VB.NET)

Codeigniter image manipulation class rotates image during resize

I'm using Codeigniter's image manipulation library to re-size an uploaded image to three sizes, small, normal and large.
The re-sizing is working great. However, if I'm resizing a vertical image, the library is rotating the image so it's horizontal.
These are the config settings I have in place:
$this->resize_config['image_library'] = 'gd2';
$this->resize_config['source_image'] = $this->file_data['full_path'];
$this->resize_config['maintain_ratio'] = TRUE;
// These change based on the type (small, normal, large)
$this->resize_config['new_image'] = './uploads/large/'.$this->new_file_name.'.jpg';
$this->resize_config['width'] = 432;
$this->resize_config['height'] = 288;
I'm not setting the master_dim property because the default it set to auto, which is what I want.
My assumption is that the library would take a vertical image, see that the height is greater than the width and translate the height/width config appropriately so the image remains vertical.
What is happening (apparently) is that the library is rotating the image when it is vertical and sizing it per the configuration.
This is the code in place I have to do the actual re-sizing:
log_message('debug', 'attempting '.$size.' photo resize');
$this->CI->load->library('image_lib');
$this->CI->image_lib->initialize($this->resize_config);
if ($this->CI->image_lib->resize())
{
$return_value = TRUE;
log_message('debug', $size.' photo resize successful');
}
else
{
$this->errors[] = $this->CI->image_lib->display_errors();
log_message('debug', $size.' photo resize failed');
}
$this->CI->image_lib->clear();
return $return_value;
EDIT
I think the problem may be from the upload library. When I get the image_height and image_width back from the upload, the width seems to be larger even though I uploaded a vertical image.
This is a portion of the code I'm using to upload the photo:
$this->upload_config['allowed_types'] = 'jpg|jpeg';
$this->upload_config['max_size'] = '2000';
$this->upload_config['max_width'] = '0';
$this->upload_config['max_height'] = '0';
$this->upload_config['upload_path'] = './uploads/working/';
$this->CI->load->library('upload', $this->upload_config);
if ($this->CI->upload->do_upload($this->posted_file))
{
$this->file_data = $this->CI->upload->data();
$return_value = TRUE;
log_message('debug', 'upload successful');
}
I added some logging to check the values:
$this->is_vertical = $this->file_data['image_height'] > $this->file_data['image_width'];
log_message('debug', 'image height:'.$this->file_data['image_height']);
log_message('debug', 'image width:'.$this->file_data['image_width']);
if ($this->is_vertical)
{
$this->resize_config['master_dim'] = 'height';
}
else
{
$this->resize_config['master_dim'] = 'width';
}
log_message('debug', 'master_dim setting:'.$this->resize_config['master_dim']);
These are the results of the log:
DEBUG - 2010-03-16 18:35:06 --> image height:1536
DEBUG - 2010-03-16 18:35:06 --> image width:2048
DEBUG - 2010-03-16 18:35:06 --> master_dim setting:width
Looking at the image in photoshop, these are the dimensions:
height: 2048
width: 1536
Anyone know what might be causing the upload library to do this?
I've never used this library, but having read the documentation, I wonder whether the master_dim property might help. If you set this to 'height' for vertical images that might keep them the right way up. You could just parse each image through a conditional to see if the image is vertically aligned and then only set this property if need be.
My other thought is about the maintain_ratio property. The documentation says that with this set to 'TRUE' it will resize as close to the target values as possible whilst maintaining the aspect ratio. I wonder if it thinks that rotating the image allows it to preserve this ratio more accurately? As an experiment, try setting this value to 'FALSE' for vertical images.
Ok - I decided not to trust photoshop and opened the images I was testing in quicktime and safari. I discovered that they were actually still horizontal.
So Codeigniter was operating exactly as expected.
I went back into photoshop, did a save for web on the test images, re-uploaded them and it worked as expected.
I then stripped out the extra code that I had added to test whether the image was vertical and the library works as I expected it would.
Now - I need to figure out how to prevent end users from doing this exact thing.
Thanks for taking the time to answer my question musoNic80. Hopefully someone else can learn from my mistakes here.

Resources