?

Log in

No account? Create an account
Previous Entry Поделиться Next Entry
BMP в GD
devpreview
Недавно делал тестовое задание для нового места работы. Там в том числе требовалось изменить размер изображения - естественно, я решил использовать Imagick. Но мне пришёл ответ, мол, а нельзя ли то же самое, но только с GD? Да не вопрос!
Ниже представляю часть класса для обработки изображения (см. подкат).

  // Обработать файлы изображения
  private function ProcessImage($path)
  {
    global $config;
    if($this->iid == false)
      return false;
    // Изменям размеры изображений
    $pathBigImage = $config['images']['path'] . 'img' . $this->iid . '_big.png';
    $pathSmallImage = $config['images']['path'] . 'img' . $this->iid . '_small.png';
    // Выбираем библиотеку
    switch($config['images']['library'])
    {
      case 'Imagick':
        if(!$this->ResizeImageImagick($path, $pathBigImage, $config['images']['size']['big']['width'], $config['images']['size']['big']['height'], $config['images']['background']))
          return false;
        if(!$this->ResizeImageImagick($path, $pathSmallImage, $config['images']['size']['small']['width'], $config['images']['size']['small']['height'], $config['images']['background']))
          return false;
        break;
      case 'GD':
      default:
        if(!$this->ResizeImageGD($path, $pathBigImage, $config['images']['size']['big']['width'], $config['images']['size']['big']['height'], $config['images']['background']))
          return false;
        if(!$this->ResizeImageGD($path, $pathSmallImage, $config['images']['size']['small']['width'], $config['images']['size']['small']['height'], $config['images']['background']))
          return false;
    }
    // Получаем инфо о размере файла
    $this->size = filesize($pathBigImage);
    return true;
  }

  // Ресайз изображения с помощью GD
  private function ResizeImageGD($inputFile, $outputFile, $width = 100, $height = 100, $background = '#ffffff')
  {
    $imageSize = getimagesize($inputFile);
    switch($imageSize['mime'])
    {
      case 'image/jpeg':
      case 'image/pjpeg':
        $im = imagecreatefromjpeg($inputFile);
        break;
      case 'image/gif':
        $im = imagecreatefromgif($inputFile);
        break;
      case 'image/png':
      case 'image/x-png':
        $im = imagecreatefrompng($inputFile);
        break;
      case 'image/bmp':
        $im = $this->imagecreatefrombmp($inputFile);
        break;
      default:
        return false;
    }

    $k1 = $width / imagesx($im);
    $k2 = $height / imagesy($im);
    $k = $k1 > $k2 ? $k2:$k1;

    $w = intval(imagesx($im) * $k);
    $h = intval(imagesy($im) * $k);

    $iWidth = $width - $w;
    if($iWidth%2 && $width > 0)
      $left = ($iWidth - 1) / 2;
    else
      $left = $iWidth / 2;

    $iHeight = $height - $h;
    if($iHeight%2 && $height > 0)
      $top = ($iHeight - 1) / 2;
    else
      $top = $iHeight / 2;

    $im_ = imagecreatetruecolor($width, $height);
    $c = $this->html2rgb($background);
    $bg = imagecolorallocate($im_, $c[0], $c[1], $c[2]);
    imagefilledrectangle($im_, 0, 0, $width, $height, $bg);
    imagecopyresampled($im_, $im, $left, $top, 0, 0, $w, $h, imagesx($im), imagesy($im));

    //header('Content-type: image/png');
    ob_start();
    imagepng($im_);
    $image = ob_get_contents();
    ob_end_clean();

    $fh = fopen($outputFile, 'a+');
    fwrite($fh, $image);
    fclose($fh);

    imagedestroy($im);
    imagedestroy($im_);
    return true;
  }

  // Ресайз изображения с помощью Imagick
  private function ResizeImageImagick($inputFile, $outputFile, $width = 100, $height = 100, $background = '#ffffff')
  {
      $image = new Imagick($inputFile);
    $image->adaptiveResizeImage($width, $height, true);
    $image->setImageFormat('png');
    $image->setImageBackgroundColor($background);
    $iHeight = $height - $image->getImageHeight();
    if($iHeight%2 && $height > 0)
      $top = 0 - ($iHeight - 1) / 2;
    else
      $top = 0 - $iHeight / 2;
    $iWidth = $width - $image->getImageWidth();
    if($iWidth%2 && $width > 0)
      $left = 0 - ($iWidth - 1) / 2;
    else
      $left = 0 - $iWidth / 2;
    $image->extentImage($width, $height, $left, $top);
    $image->writeImage($outputFile);
    $image->clear();
    $image->destroy();
    return true;
  }

  // Конвертировать из BMP в GD
  private function ConvertBMP2GD($src, $dest = false)
  {
    if(!($src_f = fopen($src, 'rb')))
    {
      return false;
    }
    if(!($dest_f = fopen($dest, 'wb')))
    {
      return false;
    }
    $header = unpack('vtype/Vsize/v2reserved/Voffset', fread($src_f, 14));
    $info = unpack('Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vimportant', fread($src_f, 40));

    extract($info);
    extract($header);

    if($type != 0x4D42)
    {
      // signature "BM"
      return false;
    }

    $palette_size = $offset - 54;
    $ncolor = $palette_size / 4;
    $gd_header = '';

    // true-color vs. palette
    $gd_header .= ($palette_size == 0) ? "\xFF\xFE" : "\xFF\xFF";
    $gd_header .= pack('n2', $width, $height);
    $gd_header .= ($palette_size == 0) ? "\x01" : "\x00";
    if($palette_size)
    {
      $gd_header .= pack('n', $ncolor);
    }

    // no transparency
    $gd_header .= "\xFF\xFF\xFF\xFF";

    fwrite($dest_f, $gd_header);

    if($palette_size)
    {
      $palette = fread($src_f, $palette_size);
      $gd_palette = '';
      $j = 0;
      while($j < $palette_size)
      {
        $b = $palette{$j++};
        $g = $palette{$j++};
        $r = $palette{$j++};
        $a = $palette{$j++};
        $gd_palette .= $r . $g . $b . $a;
      }
      $gd_palette .= str_repeat("\x00\x00\x00\x00", 256 - $ncolor);
      fwrite($dest_f, $gd_palette);
    }

    $scan_line_size = (($bits * $width) + 7) >> 3;
    $scan_line_align = ($scan_line_size & 0x03) ? 4 - ($scan_line_size & 0x03) : 0;

    for($i = 0, $l = $height - 1; $i < $height; $i++, $l--)
    {
      // BMP stores scan lines starting from bottom
      fseek($src_f, $offset + (($scan_line_size + $scan_line_align) * $l));
      $scan_line = fread($src_f, $scan_line_size);
      if($bits == 24)
      {
        $gd_scan_line = '';
        $j = 0;
        while($j < $scan_line_size)
        {
          $b = $scan_line{$j++};
          $g = $scan_line{$j++};
          $r = $scan_line{$j++};
          $gd_scan_line .= "\x00" . $r . $g . $b;
        }
      }
      elseif($bits == 8)
      {
        $gd_scan_line = $scan_line;
      }
      elseif($bits == 4)
      {
        $gd_scan_line = '';
        $j = 0;
        while($j < $scan_line_size)
        {
          $byte = ord($scan_line{$j++});
          $p1 = chr($byte >> 4);
          $p2 = chr($byte & 0x0F);
          $gd_scan_line .= $p1 . $p2;
        }
        $gd_scan_line = substr($gd_scan_line, 0, $width);
      }
      elseif($bits == 1)
      {
        $gd_scan_line = '';
        $j = 0;
        while($j < $scan_line_size)
        {
          $byte = ord($scan_line{$j++});
          $p1 = chr((int) (($byte & 0x80) != 0));
          $p2 = chr((int) (($byte & 0x40) != 0));
          $p3 = chr((int) (($byte & 0x20) != 0));
          $p4 = chr((int) (($byte & 0x10) != 0));
          $p5 = chr((int) (($byte & 0x08) != 0));
          $p6 = chr((int) (($byte & 0x04) != 0));
          $p7 = chr((int) (($byte & 0x02) != 0));
          $p8 = chr((int) (($byte & 0x01) != 0));
          $gd_scan_line .= $p1 . $p2 . $p3 . $p4 . $p5 . $p6 . $p7 . $p8;
        }
        $gd_scan_line = substr($gd_scan_line, 0, $width);
      }
      fwrite($dest_f, $gd_scan_line);
    }
    fclose($src_f);
    fclose($dest_f);
    return true;
  }

  // Создать GD-объект из BMP
  private function imagecreatefrombmp($filename)
  {
    global $config;
    $tmp_name = tempnam($config['images']['path'], 'GD');
    if($this->ConvertBMP2GD($filename, $tmp_name))
    {
      $img = imagecreatefromgd($tmp_name);
      unlink($tmp_name);
      return $img;
    }
    return false;
  }

  // Конвертировать код цвета из HTML в RGB
  private function html2rgb($color)
  {
    if ($color[0] == '#')
      $color = substr($color, 1);
    if (strlen($color) == 6)
    list($r, $g, $b) = array($color[0].$color[1],
                             $color[2].$color[3],
                             $color[4].$color[5]);
    elseif(strlen($color) == 3)
      list($r, $g, $b) = array($color[0].$color[0], $color[1].$color[1], $color[2].$color[2]);
    else
      return false;
    $r = hexdec($r); $g = hexdec($g); $b = hexdec($b);
    return array($r, $g, $b);
  }
}
 

  • 1
Под кат может уберешь? в ленте километр занимает :(

  • 1