站三界导航
首页 PHP代码PHP 实现基于 JPEG 所采用的 DCT 压缩图片算法的样例代码

PHP 实现基于 JPEG 所采用的 DCT 压缩图片算法的样例代码

  • PHP代码
  • 来源:站三界导航
  • 53阅读
  • 2023-05-16

有损压缩是为了减小数据的大小,但同时也可能会影响到图像的质量。为了解决这个问题,JPEG 标准提供了一种有损压缩方法,被称作“基于离散余弦变换(DCT)的压缩”。这种压缩方法将图像分成 8x8 的块,对每一个块分别进行 DCT 变换,然后保留变换系数中的高频成分并舍弃低频成分,最后再将这些系数进行压缩。

下面是 PHP 实现基于 JPEG 所采用的 DCT 压缩算法的样例代码。


// 压缩图像并保存到文件
function compressImage($srcFile, $dstFile, $quality) {
  // 加载源图像
  $imgInfo = getimagesize($srcFile);
  switch ($imgInfo[2]) {
    case IMAGETYPE_JPEG:
      $srcImg = imagecreatefromjpeg($srcFile);
      break;
    case IMAGETYPE_PNG:
      $srcImg = imagecreatefrompng($srcFile);
      break;
    default:
      throw new Exception('Unsupported image type');
  }

  // 获取源图像的宽度和高度
  $srcWidth = $imgInfo[0];
  $srcHeight = $imgInfo[1];

  // 计算目标图像的宽度和高度(必须是 8 的倍数)
  $dstWidth = ceil($srcWidth / 8) * 8;
  $dstHeight = ceil($srcHeight / 8) * 8;

  // 创建目标图像
  $dstImg = imagecreatetruecolor($dstWidth, $dstHeight);

  // 将源图像复制到目标图像中,并进行缩放(比例不变)
  imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $dstWidth, $dstHeight, $srcWidth, $srcHeight);

  // 将彩色图像转换为灰度图像
  imagefilter($dstImg, IMG_FILTER_GRAYSCALE);

  // 进行 DCT 变换,并且舍弃低频成分
  for ($y = 0; $y < $dstHeight; $y += 8) {
    for ($x = 0; $x < $dstWidth; $x += 8) {
      // 获取块数据
      $data = [];
      for ($i = 0; $i < 8; $i++) {
        for ($j = 0; $j < 8; $j++) {
          $data[$i][$j] = imagecolorat($dstImg, $x + $j, $y + $i);
        }
      }

      // 进行 DCT 变换
      $data = applyDCT($data);

      // 舍弃低频成分,只保留高频成分
      for ($i = 0; $i < 8; $i++) {
        for ($j = 0; $j < 8; $j++) {
          if ($i >= 4 || $j >= 4) {
            $data[$i][$j] = 0;
          }
        }
      }

      // 进行 IDCT 反变换
      $data = applyIDCT($data);

      // 设置块数据
      for ($i = 0; $i < 8; $i++) {
        for ($j = 0; $j < 8; $j++) {
          $color = intval($data[$i][$j]);
          imagesetpixel($dstImg, $x + $j, $y + $i, $color);
        }
      }
    }
  }

  // 将目标图像保存到文件中
  switch ($imgInfo[2]) {
    case IMAGETYPE_JPEG:
      imagejpeg($dstImg, $dstFile, $quality);
      break;
    case IMAGETYPE_PNG:
      imagepng($dstImg, $dstFile);
      break;
    default:
      throw new Exception('Unsupported image type');
  }

  // 释放内存
  imagedestroy($srcImg);
  imagedestroy($dstImg);
}

// 应用 DCT 变换
function applyDCT($data) {
  $result = [];
  for ($u = 0; $u < 8; $u++) {
    for ($v = 0; $v < 8; $v++) {
      $sum = 0;
      for ($i = 0; $i < 8; $i++) {
        for ($j = 0; $j < 8; $j++) {
          $cos1 = cos((2 * $i + 1) * $u * pi() / 16);
          $cos2 = cos((2 * $j + 1) * $v * pi() / 16);
          $sum += ($data[$i][$j] - 128) * $cos1 * $cos2;
        }
      }
      $sum *= (c($u) * c($v)) / 4;
      $result[$u][$v] = $sum;
    }
  }
  return $result;
}

// 应用 IDCT 反变换
function applyIDCT($data) {
  $result = [];
  for ($i = 0; $i < 8; $i++) {
    for ($j = 0; $j < 8; $j++) {
      $sum = 0;
      for ($u = 0; $u < 8; $u++) {
        for ($v = 0; $v < 8; $v++) {
          $cos1 = cos((2 * $i + 1) * $u * pi() / 16);
          $cos2 = cos((2 * $j + 1) * $v * pi() / 16);
          if ($u == 0) {
            $cu = 1 / sqrt(2);
          } else {
            $cu = 1;
          }
          if ($v == 0) {
            $cv = 1 / sqrt(2);
          } else {
            $cv = 1;
          }
          $sum += $cu * $cv * $data[$u][$v] * $cos1 * $cos2;
        }
      }
      $sum /= 4;
      $sum += 128;
      if ($sum < 0) {
        $sum = 0;
      }
      if ($sum > 255) 
$sum = 255;
      }
      $result[$i][$j] = $sum;
    }
  }
  return $result;
}

// 计算 DCT 变换系数
function c($x) {
  if ($x == 0) {
    return 1 / sqrt(2);
  } else {
    return 1;
  }
}


这是一个简单的基于 JPEG 的 DCT 压缩算法实现。该代码首先读取图像文件,将其缩放并转换为灰度图像,然后按照 8x8 的块进行 DCT 变换,保留高频成分并舍弃低频成分,最后再应用 IDCT 反变换将图像恢复到原始质量,并保存到文件中。


需要注意的是,这只是一个演示性的实现,实际上 JPEG 标准中采用的还有一些其他的技巧来进一步提高压缩比和图像质量,如色彩空间转换、预测编码等。


这个方法用于压缩图像并保存到文件。您需要将该代码保存为 PHP 文件(例如 compress.php),然后在页面中调用该文件并传递所需参数。以下是一个简单的示例:

// 调用 compressImage 函数压缩图像并保存到文件
$srcFile = 'source.jpg';   // 源图像文件路径
$dstFile = 'compressed.jpg';  // 压缩后的文件路径
$quality = 75;   // 压缩质量(0-100)

compressImage($srcFile, $dstFile, $quality);

// 输出压缩后的图像
echo '<img src="' . $dstFile . '">';
在上面的示例中,我们调用 compressImage 函数来进行图像的压缩,其中 $srcFile 是要压缩的源图像文件路径,$dstFile 是压缩后的文件路径,$quality 是压缩质量,取值范围为 0 到 100。

当函数完成后,会生成压缩后的图像并保存到指定的文件路径中,然后我们以输出 <img> 标签的形式展示压缩后的图像。

请注意,由于该代码仅供演示用途,因此未做任何安全检查或错误处理。在实际使用时,您需要添加必要的验证和错误处理来确保代码的正确性和安全性。

本文结束
本文来自投稿,不代表站三界导航立场,如若转载,请注明出处:https://www.zhansanjie.com/article/details/43003.html

版权声明:

1、本文系转载,版权归原作者所有,旨在传递信息,不代表看本站的观点和立场。

2、本站仅提供信息发布平台,不承担相关法律责任。

3、若侵犯您的版权或隐私,请联系本站管理员删除。

4、本文由会员转载自互联网,如果您是文章原创作者,请联系本站注明您的版权信息。

分享
站三界导航
本站声明:本站严格遵守国家相关法律规定,非正规网站一概不予收录。本站所有资料取之于互联网,任何公司或个人参考使用本资料请自辨真伪、后果自负,站三界导航不承担任何责任。在此特别感谢您对站三界导航的支持与厚爱。