This solution worked for me on Magento 1.9.0.1.

To cut down file upload time and file size, I first suggested my client try uploading JPGs of quality 80, and see if that looked okay. For the first few, it seemed to be fine. After quite a few were uploaded, I noticed that the colours didn’t look that great, and the thumbnails didn’t look especially sharp.

I found a few articles suggesting that the problem was Gd2.

1. Gd2 fix

Take file /lib/Varien/Image/Adapter/Gd2.php and save it to /app/code/local/Varien/Image/Adapter/Gd2.php

I found these lines to be at line 147.

// set quality param for JPG file type
if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_JPEG)
{
  $functionParameters
[] = $this->quality(); }

I tried hard-coding “90” as the quality, but you can see the principle at work is “garbage in/garbage out”. If you put in an image with JPG quality 80%, when it’s resized, it will have 80% of 80% quality (well, I don’t know that for certain, but it seems pretty likely).

So I upped the quality of all my uploaded images to 90. If you want to try hard-coding the quality value, it looks like this:

 // set quality param for JPG file type
 if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_JPEG)
 {
    $functionParameters[] = 90;
 }

After saving, flush your catalog image cache (from System -> Cache Management in the Magento backend), then refresh your store and see if that sorts out your problem.

magento-flush-catalog-images-cache

2. Browser image resize

For me, I had a secondary problem that had more to do with my template set up encouraging the browser to resize images (and that badly). By changing the number of columns that the category view was displaying, I eliminated browser resize for category view. When the browser resized the images, they looked far, far worse and not sharp at all, compared to the resized images viewed by themselves. It’s worth checking to see if this is happening. In Chrome, I use right-click -> Inspect Element. When you hover your mouse over the img link, it will tell you the dimensions of the image as viewed as well as the dimensions of the image as it is naturally.

3. After resize, white backgrounds have grey noise / speckles / artifacts

Credit goes to jasuten for this solution. I’m copying and pasting most of your work to keep another copy online, for myself and any others who need this aid.

If your images have a white background, after resizing in JPG at less than 100% quality, they have faint lines, nearly white (#fefefe or #fdfdfd), that are visible from extreme angles on LCD screens.

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 377)

// 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. Two 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.

If you have other effective solutions, please let me know in the comments.