用PHP读写PGM(P5)图像文件

时间:2011-11-18 10:46:49

标签: php file pgm

在PHP中,可以使用 fread() fwrite()来完成简单的读写文件。 unpack() pack()运算符用于提取二进制信息。

问题是,如何在不使用任何其他PHP扩展/库的情况下在PHP中读写PGM(P5)图像?

3 个答案:

答案 0 :(得分:6)

根据灰色的最大值,您必须使用C*表示最多255的值,n*表示更高的值。

从数组读取/写入所有像素的示例类:

class PGM{
    public
        $magicNumber = '',
        $pixelArray = array(),
        $width = 0,
        $height = 0,
        $grayMax = 0,
        $createdBy = '';

    public function loadPGM($filename){
        $this->grayMax = $this->height = $this->width = $this->magicNumber = 0;
        $this->pixelArray = array();
        $fh = fopen($filename, 'rb');
        while($line = fgets($fh)){
            if(strpos($line, '#') === 0){
                continue;
            }
            if(!$this->grayMax){
                $arr = preg_split('/\s+/', trim($line));
                if($arr && !$this->magicNumber){
                    $this->magicNumber = array_shift($arr);
                    if($this->magicNumber != 'P5'){
                        throw new Exception("Unsupported PGM version");
                    }
                }
                if($arr && !$this->width)
                    $this->width = array_shift($arr);
                if($arr && !$this->height)
                    $this->height = array_shift($arr);
                if($arr && !$this->grayMax)
                    $this->grayMax = array_shift($arr);
            }else{
                $unpackMethod = ($this->grayMax > 255)?'n*':'C*';
                foreach(unpack($unpackMethod, $line) as $pixel){
                    $this->pixelArray[] = $pixel;
                }
            }
        }
        fclose($fh);
    }

    public function savePGM($filename){
        $fh = fopen($filename, 'wb');
        $this->magicNumber = 'P5';
        fwrite($fh, "{$this->magicNumber}\n");
        if($this->createdBy){
            fwrite($fh, "# {$this->createdBy}\n");
        }
        fwrite($fh, "{$this->width} {$this->height}\n");
        fwrite($fh, "{$this->grayMax}\n");
        $packMethod = ($this->grayMax > 255)?'n*':'C*';
        fwrite($fh, call_user_func_array('pack', array_merge(array($packMethod), $this->pixelArray)));  
        fclose($fh);
    }
}

您文件的测试用例:

$pgm = new PGM;
$pgm->loadPGM('a.pgm');
$pgm->createdBy = 'Created by IrfanView';
$pgm->savePGM('b.pgm');
echo (md5_file('a.pgm') == md5_file('b.pgm'))?'Images are identical':'Images are different';

答案 1 :(得分:0)

根据规格: Portable Gray Map

这看起来很简单。

你甚至不需要打包/解包,因为sscanf()应该处理大部分的ASCII到整数翻译。

将PGM转换为BMP的C program可能会给你一些指示。

答案 2 :(得分:0)

我编写了一个简单的函数将图像资源转换为PGM(便携式灰度图),以便将其提供给OCR程序。它的工作原理与其他图像输出功能一样,并将为您转换为灰度:

<?php
     function imagepgm($image, $filename = null)
    {
        $pgm = "P5 ".imagesx($image)." ".imagesy($image)." 255\n";
        for($y = 0; $y < imagesy($image); $y++)
        {
            for($x = 0; $x < imagesx($image); $x++)
            {
                $colors = imagecolorsforindex($image, imagecolorat($image, $x, $y));
                $pgm .= chr(0.3 * $colors["red"] + 0.59 * $colors["green"] + 0.11 * $colors["blue"]);
            }
        }
        if($filename != null)
        {
            $fp = fopen($filename, "w");
            fwrite($fp, $pgm);
            fclose($fp);
        }
        else
        {
            return $pgm;
        }
    }
?>