1

我使用 PHP 和 GD 库创建了自己的自定义蜘蛛图生成器。基本上,用户回答一系列问题,并根据问题的答案生成蜘蛛图。

总的来说,一切都很好。生成的图表在数学上是准确的(不过,测验需要完全改写),而且它似乎运行得足够快。但是,我注意到,当我尝试从 Firefox(Snowleopard 上的版本 15.0.1)保存图像时,图像本身无法打开。从任何其他浏览器保存图像会生成可以在任何图像编辑器中打开的工作图像。

我发现特别有趣的是它何时破裂。我会看看我是否可以准确地解释这一点。

完整的工作版本是 [不再在这里],这里是图表本身的处理和生成所涉及的所有相关代码位:

chart.php(处理 POST 数据)

$r = 300; //Radius
//Processing of information passed from the previous form yields an array $cargs
//$cargs contains key value pairs. Values are of type float with a range 0-$r

$chart = new Chart($r); //Generates Canvas and Circle
$chart->generate($cargs); //Generates Polygon based on $cargs

header("Content-type: image/png");
imagesavealpha($chart->image, true);
imagepng($chart->image);
imagedestroy($chart->image);
?>

SS_Chart.php(图表对象)

class Chart
{
    public $radius;
    public $diameter;
    public $image;

    private $_labels;
    private $_values;
    private $_n;

    public function Chart($r=300)
    {
        $this->radius = $r;
        $this->diameter = 2*$r;
        $this->image = $this->_get_transparent_canvas($this->diameter, $this->diameter);
        $this->_draw_circle();
    }
    public function generate($arr)
    {
        if(count($arr)>2)
        {
            $red = imagecolorallocate($this->image, 255, 0, 0);
            $this->_n = count($arr);
            $this->_labels = array_keys($arr);
            $this->_values = array_values($arr);

            $coors = array();
            for($i=0;$i<$this->_n;$i++)
            {
                //Generate coordinates....
            }
            imagefilledpolygon($this->image, $coors, $this->_n, $red);
        }
        else
            trigger_error('Number of $key=>$value pairs in arguments must be 3 or greater', E_USER_ERROR);
    }
    private function _get_transparent_canvas($w, $h)
    {
        $canvas = imagecreatetruecolor($w, $h);
        imagealphablending($canvas, true);
        $transparent = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
        imagefill($canvas, 0, 0, $transparent);

        return $canvas;
    }
    private function _draw_circle()
    {
        $white = imagecolorallocate($this->image, 255, 255, 255);
        imagearc($this->image, $this->radius, $this->radius, $this->diameter, $this->diameter,  0, 360, $white);
    }
}

有趣的地方在于:当$chart->generate($cargs);在 chart.php 中注释掉时,Firefox 将根据尺寸生成一个可工作且可编辑的透明 png,以及一个白色圆圈。

但是,如果我注释掉public function generateSS_Chart.php 中的所有内容并保持未$chart->generate($cargs);注释(基本上会导致方法运行,但实际上不执行任何操作),则无法再打开生成的 png。

这怎么可能??

除了这里和那里的奇怪论坛描述了让 Firefox 与 GD 库合作的一些困难之外,我在这个问题上没有找到太多的东西,但这是我第一次遇到这样的事情。

  • 如果我的代码有问题,那么这个问题不会在所有浏览器中普遍存在吗?
  • 这是否与范围界定以及主要 GD 函数在对象中使用的事实有更多关系?
  • 此外,这个问题是否会发生在其他人身上?
  • 有没有人遇到过这样的问题?
  • 这甚至是一个已知问题吗?

这实际上更像是一个好奇心,而不是一个真正的“问题”,但任何对此事的洞察力将不胜感激。

4

2 回答 2

2

查看该保存图像的来源

<br />
<b>Fatal error</b>:  Number of $key=>$value pairs in arguments must be 3 or greater in <b>/home/mattmaio/public_html/dev/assets/classes/SS_Chart.php</b> on line <b>38</b><br />

当您将其保存在 Firefox 中时,fireox 不会保存您看到的内容。它的作用是 - 它在保存时发出另一个 GET 请求。

GET http://dev.mattmaiorano.com/chart.php HTTP/1.1
Host: dev.mattmaiorano.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://dev.mattmaiorano.com/chart.php

显然,所有 POST 数据都丢失了,因此出现了错误。我不确定你评论的事情,但我想就是这样。

于 2012-10-03T15:01:39.437 回答
1

我在这里看到 2 个问题

  • 保存
  • 破圈

保存

你应该做的是保存图像,然后用readfile这种方式输出它,文件不必重新生成,它也适用于 Firefox

不必一直生成图像也有助于节省带宽

示例代码

$r = 300; // $cargs
$tempDir = "xxx";
session_start();

__flush($tempDir);

if (isset($_POST) || ! isset($_SESSION['file'])) {
    $_SESSION['file'] = $tempDir . DIRECTORY_SEPARATOR . sha1(serialize($_POST)) . ".png";
}

header("Content-type: image/png");
$file = $_SESSION['file'];

if (file_exists($file)) {
    readfile($file);
} else {
    $chart = new Chart($r); // Generates Canvas and Circle
    $chart->generate(array("A" => array(40,50),"B" => array(20,240),"C" => array(60,60),"D" => array(240,20),"E" => array(50,40),"F" => array(10,10))); // Generates

    imagesavealpha($chart->image, true);
    imagepng($chart->image, $file);
    imagedestroy($chart->image);
}

破圈

破碎的圆圈has nothing to do with Firefox..在我的初步调查中,当我使用自己的变量运行您的代码时,它生成了以下图像..

在此处输入图像描述

问题

从上图中,green制造商显示了虚线。当以下情况属实时,我必须发现此错误:

画布宽度 = 圆直径

您这样称呼它的代码是哪种形式:

imagearc($this->image, $this->radius, $this->radius, $this->diameter, $this->diameter, 0, 360, $white);

解决方案

你应该做的是用这样的东西稍微减小圆的直径

  imagearc($this->image, $this->radius, $this->radius, ceil(0.9 * $this->diameter), ceil(0.9 * $this->diameter), 0, 360, $white);

你会得到一个完美的圆圈

在此处输入图像描述

使用的代码

$r = 300; // $cargs
$tempDir = "xxx";
session_start();

__flush($tempDir);

if (isset($_POST) || ! isset($_SESSION['file'])) {
    $_SESSION['file'] = $tempDir . DIRECTORY_SEPARATOR . sha1(serialize($_POST)) . ".png";
}

header("Content-type: image/png");
$file = $_SESSION['file'];

if (file_exists($file)) {
    readfile($file);
} else {
    $chart = new Chart($r); // Generates Canvas and Circle
    $chart->generate(array("A" => array(40,50),"B" => array(20,240),"C" => array(60,60),"D" => array(240,20),"E" => array(50,40),"F" => array(10,10))); // Generates

    imagesavealpha($chart->image, true);
    imagepng($chart->image, $file);
    imagedestroy($chart->image);
}

function __flush($tempDir) {
    $expire = 300; // 5mins
    $iterator = new DirectoryIterator($tempDir);
    foreach ( $iterator as $fileinfo ) {

        if ($fileinfo->isDot())
            continue;

        if ((time() - $fileinfo->getMTime()) > $expire) {
            @unlink($iterator->getPath());
        }
    }
}


class Chart {
    public $radius;
    public $diameter;
    public $image;
    private $_labels;
    private $_values;
    private $_n;

    public function Chart($r = 300) {
        $this->radius = $r;
        $this->diameter = 2 * $r;
        $this->image = $this->_get_transparent_canvas($this->diameter, $this->diameter);
        $this->_draw_circle();
    }

    public function generate($arr) {
        if (count($arr) > 2) {
            $red = imagecolorallocate($this->image, 255, 0, 0);
            $this->_n = count($arr);
            $this->_labels = array_keys($arr);
            $this->_values = array_values($arr);

            $coors = array();
            foreach ( $this->_values as $key => $value ) {
                $coors = array_merge($coors, $value);
            }
            imagefilledpolygon($this->image, $coors, $this->_n, $red);
        } else
            trigger_error('Number of $key=>$value pairs in arguments must be 3 or greater', E_USER_ERROR);
    }

    private function _get_transparent_canvas($w, $h) {
        $canvas = imagecreatetruecolor($w, $h);
        imagealphablending($canvas, true);
        $transparent = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
        imagefill($canvas, 0, 0, $transparent);

        return $canvas;
    }

    private function _draw_circle() {
        $white = imagecolorallocate($this->image, 255, 255, 255);
        imagearc($this->image, $this->radius, $this->radius, ceil(0.9 * $this->diameter), ceil(0.9 * $this->diameter), 0, 360, $white);
        // imagearc($this->image, $this->radius, $this->radius,
    // $this->diameterCycle, $this->diameterCycle, 0, 360, $white);
    }
}
于 2012-10-05T11:33:00.703 回答