如何在自定义CMS配置文件中使用ImageMagick检测EXIF方向并旋转图像?

时间:2017-02-01 22:49:57

标签: rotation orientation imagick exif

如何在我的配置文件中添加旋转功能,无法理解,在哪里添加以及如何添加,我的代码就在这里。这个来自cms的代码,它的工作,需要检测exif并添加自动旋转功能,如果图像方向错误:



# ImageMagick
   
    private function saveFileIM()
    {
        if($this->imShell) {
            $filename_orig = escapeshellarg($this->img['orig_filename']);
            $filename_dest = escapeshellarg($this->img['filename']);
        }
        
        do{
        
        // crop по указанным координатам и размерам
        if( ! empty($this->img['crop_width']) || ! empty($this->img['crop_height'])) {
            if($this->imShell) {
                // not implemented   
            } else {
                $this->im->cropImage($this->img['orig_width'], $this->img['orig_height'], $this->img['src_x'], $this->img['src_y']);
            }
        }
            
        // если пропорции будут сохранятся
        if($this->img['autofit'])
        {
            // указаны значения и высоты и ширины, обрезать изображение точно по размерам
            if( $this->img['height']<=0 && $this->img['width']<=0 ) {
                $this->error('no_th_size');
                break;
            }
            
            if($this->imShell)
            {
                if( ! $this->img['height'])
                {
                    // не указана высота thumbnail'a пропорциональное изображение по ширине
                    if(exec($this->imPath.'convert '.$filename_orig.' 
                            -resize '.$this->img['width'].'x
                            -quality '.$this->img['quality'].' '.$filename_dest))
                        $this->error('im_prop_w_err');
                }
                else if( ! $this->img['width'])
                {
                    // не указана ширина thumbnail'a пропорциональное изображение по высоте
                    if(exec($this->imPath.'convert '.$filename_orig.' 
                            -resize x'.$this->img['height'].'
                            -quality '.$this->img['quality'].' '.$filename_dest))
                        $this->error('im_prop_h_err');
                }         
                else
                {
                    if( $this->img['autofit_nocrop'] ) {
                        // not implemented
                    }

                    // проверяем какая сторона ужимается меньше всего
                    $nWidthDif = $this->img['width'] / $this->img['orig_width'];
                    $nHeightDif = $this->img['height'] / $this->img['orig_height'];
                    // сжимаем пропорционально по ширине или по высоте (по меньшему сжатию) сторону, коэф сжатия которой больше обрезаем
                    if($nWidthDif > $nHeightDif)
                    {
                        $this->cropHeight($nWidthDif, $this->img['crop_v']);
                        if(exec($this->imPath.'convert '.$filename_orig.' 
                                -resize '.$this->img['width'].'x
                                -quality '.$this->img['quality'].' '.$filename_dest))
                           $this->error('im_prop_h_err'); 
                    }
                    else                        
                    {
                        $this->cropWidth($nHeightDif, $this->img['crop_h']);
                        if(exec($this->imPath.'convert '.$filename_orig.' 
                                -resize x'.$this->img['height'].'
                                -quality '.$this->img['quality'].' '.$filename_dest))
                            $this->error('im_prop_w_err');
                    }
                    
                    // обрезка изображения до точного размера
                    if(exec($this->imPath.'convert '.$filename_dest.' 
                                -gravity '.$this->img['gravity'].'
                                -quality 100 
                                -crop '.$this->img['width'].'x'.$this->img['height'].'+0+0 +repage
                                '.$filename_dest))
                        $this->error('im_croping_err');
                }
            } else {
                if( ! $this->img['height']) {
                    if( !$this->im->thumbnailImage($this->img['width'], 0) )
                            $this->error('im_prop_w_err');
                } else if( ! $this->img['width']) {
                    if( ! $this->im->thumbnailImage(0, $this->img['height']) )
                            $this->error('im_prop_h_err');
                } else {
                    if( $this->img['autofit_nocrop'] )
                    {
                        if( ! empty($this->img['autofit_nocrop_bg'])) {
                            $bg_clr = $this->img['autofit_nocrop_bg']; // формат: 0xFFFFFF
                            //
                        }
                        if( ! $this->im->thumbnailImage($this->img['width'], $this->img['height'], true) )
                            $this->error('im_croping_err');
                    } else {
                        // фиксированной ширины и высоты, только center-center
                        if( ! $this->im->cropThumbnailImage($this->img['width'], $this->img['height']) )
                            $this->error('im_croping_err');
                        $this->im->setImagePage(0, 0, 0, 0); // фикс для gif
                    }
                }
            }
        }
        // ужимать не сохраняя пропорции
        else 
        {
            if($this->imShell)
            {
                if( ! $this->img['height'] && $this->img['width']>0)
                {
                  /* не указана высота  thumbnaila (выставляем высоту оригинального изображения) */  
                  if(exec($this->imPath.'convert '.$filename_orig.' 
                        -scale '.$this->img['width'].'x'.$this->img['orig_height'].'!
                        -quality '.$this->img['quality'].' '.$filename_dest))
                    $this->error('im_unprop_h_err'); 
                }                              
                else if( ! $this->img['width']&& $this->img['height']>0)
                {
                  /* не указана ширина thumbnaila (выставляем ширину оригинального изображения) */     
                  if(exec($this->imPath.'convert '.$filename_orig.'
                        -scale '.$this->img['orig_width'].'x'.$this->img['height'].'!
                        -quality '.$this->img['quality'].' '.$filename_dest))
                    $this->error('im_unprop_w_err');
                }                               
                else{
                  if(exec($this->imPath.'convert '.$filename_orig.' 
                        -scale '.$this->img['width'].'x'.$this->img['height'].'!
                        -quality '.$this->img['quality'].' '.$filename_dest))
                     $this->error('im_unprop_err');   
                }
            } else {
                if( ! $this->im->thumbnailImage($this->img['width'], $this->img['height']) )
                    $this->error('im_unprop_err'); 
            }
        } 
        
        } while(false);
                                           
        // нанесение watermark
        if($this->img['watermark'] && $this->img['watermark_src'])
        {
           $this->watermarkPrintIM();
        }
        
        // закругление углов
        if($this->img['round_corners'])
        {
            $this->roundCornersIM($this->img['filename'], $this->img['round_corners_color'], $this->img['round_corners_radius'], $this->img['round_corners_rate']);
        }

        if( ! $this->imShell) {
            $this->im->writeImage($this->img['filename']);
        }
        
        $this->clearOriginalImage();
     }
     
    /**
     * Приводим положение картинки к формату ImageMagick
     * @param mixed $vertical - положение по вертикали
     * @param mixed $horizontal - положение по горизонтали
     * @param mixed $pos
     */
    private function convertDimentionsIM($vertical, $horizontal, $pos = false)
    {
         if( ! empty($pos))
         {
             $i_w = $pos['i_w'];
             $i_h = $pos['i_h'];
             $t_w = $pos['t_w'];
             $t_h = $pos['t_h'];
             $paddingV = $pos['p_v'];
             $paddingH = $pos['p_h'];
             
             $x_right  = $i_w - $t_w - $paddingH;
             $x_center = round(($i_w - $t_w)/2);
             $y_center = round(($i_h - $t_h)/2);
             $y_bottom = $i_h - $t_h - $paddingV;
             
             $gravity = array(           
                'top-left'      => array($paddingH, $paddingV), // x - horizontal, y- vertical             
                'top-center'    => array($x_center, $paddingV),
                'top-right'     => array($x_right,  $paddingV),
                'center-left'   => array($paddingH, $y_center),
                'center-center' => array($x_center, $y_center),
                'center-right'  => array($x_right,  $y_center),
                'bottom-left'   => array($paddingH, $y_bottom),
                'bottom-center' => array($x_center, $y_bottom),
                'bottom-right'  => array($x_right,  $y_bottom),
             );
             return $gravity[$vertical.'-'.$horizontal];
         } else {
             $gravity = array(
                'top-left'      => array('NorthWest', IMagick::GRAVITY_NORTHWEST),
                'top-center'    => array('North',     IMagick::GRAVITY_NORTH),
                'top-right'     => array('NorthEast', IMagick::GRAVITY_NORTHEAST),
                'center-left'   => array('West',      IMagick::GRAVITY_WEST),
                'center-center' => array('Center',    IMagick::GRAVITY_CENTER),
                'center-right'  => array('East',      IMagick::GRAVITY_EAST),
                'bottom-left'   => array('SouthWest', IMagick::GRAVITY_SOUTHWEST),
                'bottom-center' => array('South',     IMagick::GRAVITY_SOUTH),
                'bottom-right'  => array('SouthEast', IMagick::GRAVITY_SOUTHEAST),
             );
             return $gravity[$vertical.'-'.$horizontal][ ($this->imShell ? 0 : 1) ];
         }
     }

    /**
     * Наносим watermark нa изображение с помощью Image Magick
     */
    private function watermarkPrintIM()
    {
        $sGravity = $this->convertDimentionsIM($this->img['watermark_pos_y'], $this->img['watermark_pos_x']);

        $sTmpWatermarkFile = $this->imTmpPath.'def_w_mark.png';
        
        // на основе изображения
        if(file_exists($this->img['watermark_src']))
        {
            /** 
             * если указано что wm надо ужимать вместе с картинкой
             * то получаем размеры загружаемого wm
             * и уменьшаем его пропорционально с основным изображением
             */
            if($this->imShell)
            {
                if($this->img['watermark_resizable'])
                {
                    $sParam = exec($this->imPath.'identify '.$this->img['watermark_src']);
                    $aParam = split(' ', $sParam);
                    $aSize  = split('x',$aParam[2]);
                    $nWMwidth  = intval($aSize[0] * $this->img['coef_width']);
                    $nWMheight = intval($aSize[1] * $this->img['coef_height']);
                    if( exec($this->imPath.'convert '.$this->img['watermark_src'].' -scale '.$nWMwidth.'x'.$nWMheight.' -quality '.$this->img['quality'].' '.$sTmpWatermarkFile) )
                        $this->error('im_wmresize_err');
                }
                
                // накладываем wm на thumbnail
                if( exec($this->imPath.'composite -dissolve 100 -gravity '.$sGravity.' -geometry +'.$this->img['watermark_padding_h'].'+'.$this->img['watermark_padding_v'].' '.$sTmpWatermarkFile.' '. $this->img['filename'].' '.$this->img['filename']) )
                    $this->error('im_wmadd_err');
                
                // накладываем wm на оригинал
                if($this->img['watermark_on_original'])
                {
                   if(exec($this->imPath.'composite -dissolve 100 -gravity '.$sGravity.' -geometry +'.$this->img['watermark_padding_h'].'+'.$this->img['watermark_padding_v'].' '. $this->img['watermark_src'] .' '. $this->img['orig_filename'].' '.$this->img['orig_filename']))
                        $this->error('im_wmorig_err');
                }
            } 
            else 
            {
                $wm = new Imagick($this->img['watermark_src']);
                $wmSize = array($wm->getImageWidth(), $wm->getImageHeight());
                if($this->img['watermark_resizable']) {
                    $wmSize[0] = intval($wmSize[0] * $this->img['coef_width']);  //width
                    $wmSize[1] = intval($wmSize[1] * $this->img['coef_height']); //height
                    $wm->thumbnailImage( $wmSize[1], $wmSize[0] );
                }

                // накладываем wm на thumbnail
                $aGravity = $this->convertDimentionsIM($this->img['watermark_pos_y'], $this->img['watermark_pos_x'],
                            array('t_w'=>$wmSize[0],'t_h'=>$wmSize[1],
                                  'i_w'=>$this->im->getImageWidth(),'i_h'=>$this->im->getImageHeight(),
                                  'p_v'=>$this->img['watermark_padding_v'], 'p_h'=>$this->img['watermark_padding_h']));
                
                // накладывает watermark на thumbnail
                if( ! $this->im->compositeImage( $wm, Imagick::COMPOSITE_OVER, $aGravity[0], $aGravity[1] ) )
                    $this->error('im_wmadd_err'); 
                
                // накладываем wm на оригинал
                if($this->img['watermark_on_original'])
                {                   
                   $imSrc = new Imagick($this->img['orig_filename']);
                   
                   $aGravitySrc = $this->convertDimentionsIM($this->img['watermark_pos_y'], $this->img['watermark_pos_x'],
                                array('t_w'=>$wmSize[0],'t_h'=>$wmSize[1],
                                      'i_w'=>$imSrc->getImageWidth(),'i_h'=>$imSrc->getImageHeight(),
                                      'p_v'=>$this->img['watermark_padding_v'], 'p_h'=>$this->img['watermark_padding_h']));

                   if( ! $imSrc->compositeImage( $wm, Imagick::COMPOSITE_OVER, $aGravitySrc[0], $aGravitySrc[1] ) )
                        $this->error('im_wmorig_err');                     
                   else {
                       $imSrc->writeImage( $this->img['orig_filename'] );
                   }
                   $imSrc->destroy();   
                } 
                
                $wm->destroy();            
            }
        }
        else // на основе текста
        {
            //задаем цвет шрифта wm в формате #ffffff
            $sText      = $this->img['watermark_src'];
            $sTextColor = $this->img['watermark_font_color'];
            $sFont      = $this->sFontDir.'/'.$this->img['watermark_font'];
            $nFontSize  = $this->img['watermark_font_size'];
            $nCoef = 1;
            if($this->img['watermark_resizable']) {
                // размер шрифта уменьшается пропорционально картинке
                $nCoef = ($this->img['coef_width']>$this->img['coef_height'] ? $this->img['coef_height'] : $this->img['coef_width']);
                $nFontSize = round($nCoef * $nFontSize);
            }

            if($this->imShell) 
            {       
                // создает изображение png из текста переданного как wm (размер шрифта не изменяется)
                if(exec($this->imPath.'convert -background "none"  -fill "'.$sTextColor.'" -font '.$sFont.' -pointsize '.($nFontSize).' label:"'.addslashes($sText).'" '.$sTmpWatermarkFile)) 
                    $this->error('im_wmorig_err'); 
                
                // накладывает watermark на thumbnail
                if(exec($this->imPath.'composite -dissolve 100 -gravity '.$sGravity.' -geometry +'.($this->img['watermark_padding_h'] * $nCoef).'+'.$this->img['watermark_padding_v']*$nCoef.' '.$sTmpWatermarkFile.' '.$this->img['filename'] .' '.$this->img['filename']))
                    $this->error('im_wmcreate_err');   

                // накладывает watermark на оригинал изображения
                if($this->img['watermark_on_original']) {
                   if(exec($this->imPath.'composite -dissolve 100 -gravity '.$sGravity.' -geometry +'.$this->img['watermark_padding_h'].'+'.$this->img['watermark_padding_v'].' '.$sTmpWatermarkFile.' '. $this->img['orig_filename'].' '.$this->img['orig_filename']))
                        $this->error('im_wmorig_err');
                }
            } 
            else 
            {
                $wmText = new ImagickDraw();
                $wmText->setGravity( IMagick::GRAVITY_CENTER );
                $wmText->setFont( $sFont );
                $wmText->setFontSize( $nFontSize );
                $wmText->setFillColor( $sTextColor ); 
                
                $wm = new Imagick();
                $wmTextProps = $wm->queryFontMetrics( $wmText, $sText );
                $wmW = intval( $wmTextProps['textWidth'] );
                $wmH = intval( $wmTextProps['textHeight'] );
                $wm->newImage( $wmW, $wmH, new ImagickPixel( 'transparent' ), 'png' );
                $wm->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
                $wm->annotateImage( $wmText, 0, 0, 0, $sText );
                
                $aGravity = $this->convertDimentionsIM($this->img['watermark_pos_y'], $this->img['watermark_pos_x'],
                            array('t_w'=>$wmW,'t_h'=>$wmH,
                                  'i_w'=>$this->im->getImageWidth(),'i_h'=>$this->im->getImageHeight(),
                                  'p_v'=>$this->img['watermark_padding_v'], 'p_h'=>$this->img['watermark_padding_h']));
                
                // накладывает watermark на thumbnail
                //$this->im->annotateImage( $wmText, $aGravity[0], $aGravity[1], 0, $sText );
                
                if( ! $this->im->compositeImage( $wm, Imagick::COMPOSITE_OVER, $aGravity[0], $aGravity[1] ) )
                    $this->error('im_wmcreate_err');   

                // накладывает watermark на оригинал изображения
                if($this->img['watermark_on_original'])
                {
                   $imSrc = new Imagick($this->img['orig_filename']);
                   
                   $aGravitySrc = $this->convertDimentionsIM($this->img['watermark_pos_y'], $this->img['watermark_pos_x'],
                                array('t_w'=>$wmW,'t_h'=>$wmH,
                                      'i_w'=>$imSrc->getImageWidth(),'i_h'=>$imSrc->getImageHeight(),
                                      'p_v'=>$this->img['watermark_padding_v'], 'p_h'=>$this->img['watermark_padding_h'] ));

                   if( ! $imSrc->compositeImage( $wm, Imagick::COMPOSITE_OVER, $aGravitySrc[0], $aGravitySrc[1] ) )
                        $this->error('im_wmorig_err'); 
                   else {
                       $imSrc->writeImage( $this->img['orig_filename'] );
                   }
                   $imSrc->destroy();
                }
                
                $wmText->destroy();
                $wm->destroy();
            }
        }
            
        // удаление временного файла с wm
        $this->img['orig_filename'] = $this->img['src'];
        if(file_exists($sTmpWatermarkFile)) {
            unlink($sTmpWatermarkFile);
        }
    }
    
    /**
     * Создание закругленных уголков с помощью Image Magick
     */ 
    private function roundCornersIM($filename, $cornercolor, $radius=5, $rate=5)
    {   
        // Если png/gif тогда углы прозрачные
        if($this->img['format'] == IMAGETYPE_GIF || $this->img['format'] == IMAGETYPE_PNG) {
            $cornercolor = false;
        }
        
        if($radius<=0) return false;
        if($radius > 100) $radius = 100;
        if($rate <=0) $rate = 5;
        else if($rate > 20) $rate = 20;
                
        $width  = $this->img['width'];
        $height = $this->img['height'];
        $radius = ($width<=$height)?((($width/100)*$radius)/2):((($height/100)*$radius)/2); 

        if($cornercolor === false)
        {
            $sOldName = $filename;
            $sNewName = $filename;
            if($this->img['format']!==IMAGETYPE_PNG) {
                $nLength  = strrpos($filename,'.');
                $sNewName = substr($filename,0,$nLength).'.png';
            }
            
            if($this->imShell)
            {
                // если углы прозрачные закругляем уголки без заливки цветом
                $cornercolor = 'transparent';
                if(exec($this->imPath.'convert "'.$sOldName.'" -border 0 -format "roundrectangle 0,0 %[fx:w],%[fx:h] '.$radius.','.$radius.'" info: > '.$this->imTmpPath.'tmp.mvg'))
                    $this->error('no_rouncorners');
                if(exec($this->imPath.'convert  "'.$sOldName.'" -border 0 -matte -channel RGBA -threshold -1 -background '.$cornercolor.' -fill none  -strokewidth 0 -draw "@'.$this->imTmpPath.'tmp.mvg"  '.$this->imTmpPath.'__overlay.png'))
                    $this->error('no_rouncorners');
                if(exec($this->imPath.'convert "'.$sOldName.'" -border 0 -matte -channel RGBA -threshold -1 -background '.$cornercolor.' -fill white  -strokewidth 0 -draw "@'.$this->imTmpPath.'tmp.mvg" '.$this->imTmpPath.'__mask.png '))
                    $this->error('no_rouncorners');
                 
                if(exec($this->imPath.'convert "'.$sOldName.'" -matte -bordercolor '.$cornercolor.'  -border 0 '.$this->imTmpPath.'__mask.png -compose DstIn -composite '.$this->imTmpPath.'__overlay.png -compose Over -composite  -quality 95 "'.$sNewName.'"  '))
                    $this->error('no_rouncorners');
                 
                if($sOldName != $sNewName) {
                    unlink($sOldName);
                    rename($sNewName, $sOldName);
                }   
                unlink($this->imTmpPath.'__mask.png'); 
                unlink($this->imTmpPath.'__overlay.png'); 
            } else {         
                $this->im->setImageFormat('png');
                $this->im->roundCorners($radius, $radius);
            }
        } 
        else
        {
            if($this->imShell)
            {
                // если углы не прозрачные закругляем уголки и заливаем из выставленным цветом 
                if(exec($this->imPath.'convert "'.$filename.'"  -border 0 -format "fill '.$cornercolor.' rectangle 0,0 %[fx:w],%[fx:h]" info: > '.$this->imTmpPath.'tmp.mvg'))
                    $this->error('no_rouncorners'); 
                if(exec( $this->imPath.'convert "'.$filename.'" -matte -channel RGBA -threshold -1 -draw "@'.$this->imTmpPath.'tmp.mvg" PNG:'.$this->imTmpPath.'__underlay.png'))
                   $this->error('no_rouncorners');
                if(exec($this->imPath.'convert '.$this->imTmpPath.'__underlay.png ( "'.$filename.'" ( +clone -threshold -1 -draw "fill black polygon 0,0 0,'.$radius.' '.$radius.',0 fill white circle '.$radius.','.$radius.' '.$radius.',0" ( +clone -flip ) -compose Multiply -composite ( +clone -flop ) -compose Multiply -composite -blur 1x1 ) +matte -compose CopyOpacity -composite ) -matte -compose over -composite "'.$filename.'"'))
                    $this->error('no_rouncorners');
                
                unlink($this->imTmpPath.'__underlay.png');
            } else {
                $this->im->setImageFormat('png');
                $this->im->roundCorners($radius, $radius);
//                $bg = new Imagick();
//                $bg->newImage($this->im->getImageWidth(), $this->im->getImageHeight(), new ImagickPixel($cornercolor));
//                $bg->compositeImage($this->im, Imagick::COMPOSITE_OVER, 0, 0);
//                $this->im->setImage($bg);
            }
        }
        
        if(file_exists($this->imTmpPath.'tmp.mvg')) {
            unlink($this->imTmpPath.'tmp.mvg'); 
        }
        
        $this->img['orig_filename'] = $this->img['src'];
        
        return $this->errors->no();
     }

    public function getErrors()
    {
        return $this->errors->show();
    }
           
    /**
    * Устанавливает лимит оперативной памяти
    * @param int $nSize - объем памяти в мегабайтах
    */
    public function setMemoryLimit($nSize)
    {
        $nSize = intval($nSize);
        if($nSize<=0) $nSize=1;
        ini_set('memory_limit', $nSize.'M');
    }

    /**
    * Указание пути к шрифтам
    * @param string путь к директории c файлами шрифтов
    */
    function setFontDir($sPath)
    {
        $this->sFontDir = $sPath;
    }

    function getAutofitResultSize($nWidth = false, $nHeight = false)
    {
        if( ! $nHeight) # не указана высота, возвращаем autofit-высоту
        {
          return intval( ($nWidth/$this->img['orig_width'])*$this->img['orig_height'] );
        }
        else if( ! $nWidth) # не указана ширина, возвращаем autofit-ширину
        {
          return intval( ($nHeight/$this->img['orig_height'])*$this->img['orig_width'] );
        }         
    }

    function getOriginalWidth()
    {
        return (int)$this->img['src_width'];
    }

    function getOriginalHeight()
    {
        return (int)$this->img['src_height'];
    }

}    
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

在此帖子中查看来自@orrd的回复:How to stop PHP iMagick auto-rotating images based on EXIF 'orientation' data

你必须找出把它放在哪里,因为我并不热衷于处理超过500行其他人的代码。

如果方向数据丢失或不正确,您可能仍会遇到问题。