6

I have a PHP file that makes an image. I have PHP configured to report errors on the screen. When I run the file in the PHP file in Firefox 23, it returns the Image cannot be displayed because it contains errors.

How can I find out what particular error is at fault in the image?

Here is the code:

<?php
    $tfont[] = 'cylburn-webfont.ttf';

    $cryptinstall = "./cryptographp.fct.php";
    include $cryptinstall;

    error_reporting(E_ALL ^ E_NOTICE);
    srand((double)microtime()*1000000);

    if ($_GET[$_GET['sn']] == "")
        unset ($_GET['sn']);

    session_start();

    include('getcaptcha.php');
    $question = getcaptcha();
    $questionLen = strlen($question);
    $cryptwidth  = 25 * $questionLen;

    $cryptinstall2 = "./cryptographp.cfg.php";
    include $cryptinstall;

    $cryptwidth = 900;
    $cryptheight = 200;

    // CrÈation du cryptogramme temporaire
    $imgtmp = imagecreatetruecolor($cryptwidth, $cryptheight);
    $blank  = imagecolorallocate($imgtmp, 255, 255, 255);
    $black   = imagecolorallocate($imgtmp, 0, 0, 0);
    imagefill($imgtmp, 0, 0, $blank);

    $word = '';
    $x = 10;
    $pair = rand(0, 1);
    $charnb = rand($charnbmin, $charnbmax);


    for ($i=0; $i<= $questionLen; $i++) {
         $tword[$i]['font'] =  $tfont[array_rand($tfont, 1)];
         $tword[$i]['angle'] = (rand(1, 2) == 1) ? rand(0, $charanglemax) : rand(360-$charanglemax, 360);

         $tword[$i]['element'] = str_split($question)[$i-1];

         $tword[$i]['size'] = rand($charsizemin, $charsizemax);
         $tword[$i]['y'] = ($charup ? ($cryptheight/2) + rand(0, ($cryptheight/5)) : ($cryptheight/1.5));
         $word .= $tword[$i]['element'];

         $lafont = "fonts/" . $tword[$i]['font'];
         imagettftext($imgtmp, $tword[$i]['size'], $tword[$i]['angle'], $x, $tword[$i]['y'], $black, $lafont, $tword[$i]['element']);

         $x += $charspace;
     }

    // Calculate horizontal racadrage temporary cryptogram
    $xbegin = 0;
    $x = 0;
    while (($x<$cryptwidth)and(!$xbegin)) {
        $y = 0;
        while (($y<$cryptheight) and (!$xbegin)) {
            if (imagecolorat($imgtmp, $x, $y) != $blank)
                $xbegin = $x;
            $y++;
        }
        $x++;
    }

    $xend = 0;
    $x = $cryptwidth-1;
    while (($x>0) and (!$xend)) {
        $y = 0;
        while (($y<$cryptheight)and(!$xend)) {
            if (imagecolorat($imgtmp, $x, $y) != $blank)
                $xend = $x;
            $y++;
        }
        $x--;
    }

    $xvariation = round(($cryptwidth/2)-(($xend-$xbegin)/2));
    imagedestroy ($imgtmp);

    // Create the final cryptogram
    // Create the background
    $img = imagecreatetruecolor($cryptwidth, $cryptheight);

    if ($bgimg and is_dir($bgimg)) {
        $dh  = opendir($bgimg);
        while (false !== ($filename = readdir($dh)))
            if(eregi(".[gif|jpg|png]$", $filename))
                $files[] = $filename;
                closedir($dh);
                $bgimg = $bgimg . '/' . $files[array_rand($files, 1)];
    }

    if ($bgimg) {
        list($getwidth, $getheight, $gettype, $getattr) = getimagesize($bgimg);
            $imgread = imagecreatefrompng($bgimg); break;
            imagecopyresized($img, $imgread, 0, 0, 0, 0, $cryptwidth, $cryptheight, $getwidth, $getheight);
            imagedestroy ($imgread);
        }
        else {
            $bg = imagecolorallocate($img, $bgR, $bgG, $bgB);
            imagefill($img, 0, 0, $bg);
            if ($bgclear)
                imagecolortransparent($img, $bg);
        }


    function ecriture()
    {
        // CrÈation de l'Ècriture
        global  $img, $ink, $charR, $charG, $charB, $charclear, $xvariation, $charnb, $charcolorrnd, $charcolorrndlevel, $tword, $charspace;
        $ink = imagecolorallocatealpha($img, $charR, $charG, $charB, $charclear);

        global $question;
        global $questionLen;

        $x = $xvariation;
        for ($i=1; $i<$questionLen; $i++) {

            if ($charcolorrnd) {   // Choisit des couleurs au hasard
                $ok = false;
                do {
                    $rndcolor = 0;
                    switch ($charcolorrndlevel) {
                        case 1 :
                            if ($rndcolor<200)
                                $ok = true; break; // tres sombre

                        default : $ok = true;
                    }
                } while (!$ok);

                $rndink = imagecolorallocatealpha($img, $rndR, $rndG, $rndB, $charclear);
            }

            $lafont = "fonts/" . $tword[$i]['font'];
            imagettftext($img, $tword[$i]['size'], $tword[$i]['angle'], $x, $tword[$i]['y'], $charcolorrnd ? $rndink : $ink, $lafont, $tword[$i]['element']);

            $x += $charspace;
        }
    }


    // Fonction permettant de dÈterminer la couleur du bruit et la forme du pinceau
    function noisecolor()
    {
        global $img, $noisecolorchar, $ink, $bg, $brushsize;
        switch ($noisecolorchar) {
            case 1  : $noisecol = $ink; break;
            case 2  : $noisecol = $bg; break;
            case 3  :
            default : $noisecol = imagecolorallocate ($img, 0, 0, 0); break;
        }

        if ($brushsize and $brushsize>1 and function_exists('imagesetbrush')) {
            $brush = imagecreatetruecolor($brushsize, $brushsize);
            imagefill($brush, 0, 0, $noisecol);
            imagesetbrush($img, $brush);
            $noisecol = IMG_COLOR_BRUSHED;
        }
        return $noisecol;
    }


    //Adding noise: points, lines and circles random
    function bruit()
    {
        global $noisepxmin, $noisepxmax, $noiselinemin, $noiselinemax, $nbcirclemin, $nbcirclemax, $img, $cryptwidth, $cryptheight;
        $nbpx = rand($noisepxmin, $noisepxmax);
        $nbline = rand($noiselinemin, $noiselinemax);
        for ($i=1; $i<$nbpx; $i++)
            imagesetpixel($img, rand(0, $cryptwidth-1), rand(0, $cryptheight-1), noisecolor());
            for ($i=1; $i<=$nbline; $i++)
                imageline($img, rand(0, $cryptwidth-1), rand(0, $cryptheight-1), rand(0, $cryptwidth-1), rand(0, $cryptheight-1), noisecolor());
    }


    if ($noiseup) {
        ecriture();
        bruit();
    }
    else {
        bruit();
        ecriture();
    }


    // Create the frame
    if ($bgframe) {
       $framecol = imagecolorallocate($img, ($bgR*3 + $charR)/4, ($bgG*3 + $charG)/4, ($bgB*3 + $charB)/4);
       imagerectangle($img, 0, 0, $cryptwidth-1, $cryptheight-1, $framecol);
    }


    // Transformations supplÈmentaires: Grayscale et Brouillage
    // VÈrifie si la fonction existe dans la version PHP installÈe
    if ($cryptgrayscal)
        imagefilter($img, IMG_FILTER_GRAYSCALE);
    if ($cryptgaussianblur)
        imagefilter($img, IMG_FILTER_GAUSSIAN_BLUR);

    /* If I comment out these lines, then the file runs fine, but
       of course it does not return an image.
    header("Content-type: image/png"); // This is the only header(...) that is
                                       // included in the file. I am requesting
                                       // the file directly with the URL.
    imagepng($img);

    imagedestroy ($img);
    unset ($word, $tword);
    unset ($_SESSION['cryptreload']); */
?>

If I comment out the header("content-type: image/png"), it gets rid of the error, but it returns nonsense to the browser that looks like this:

Enter image description here

(All this said, I am less interested in fixing this particular image file than in understanding how to go about debugging errors/unexpected behavior in image-creation files. I want to learn how to fix problematic image-generating files on my own.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bernie2436
  • 22,841
  • 49
  • 151
  • 244

10 Answers10

2

First make sure that no part of your code before the header() command outputs anything.

If you have any includes before your header, make sure you don't finish your PHP code with ?> because sometimes this generates a byte.

Finally try wrapping your includes inside of ob_start(); and ob_end_clean(); as this will make sure that no random bytes are cast to the output due to any other reasons (I had this happen once).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kostas
  • 21
  • 3
1

Comment out the header() so it just sends back data and not image/png.

Gerben Jacobs
  • 4,515
  • 3
  • 34
  • 56
  • Thanks for the suggestion. See my edit above. But my real question is how can I find out WHAT the error is? It is hard for me to know how to go about debugging if firefox just spits out "there is a mysterious error" and I don't know where to look to fix it. – bernie2436 Sep 02 '13 at 09:20
  • Okay, so it's not a PHP error you have (unless you have errors turned off) and you have an problem with the data that makes up the image. – Gerben Jacobs Sep 02 '13 at 09:22
  • Can you explain how you know that? What is it about commenting out the header and then seeing that it returned garbled images that made that clear to you? – bernie2436 Sep 02 '13 at 09:25
  • Well because else you'd get a PHP error. Now you get PNG-data, so PHP thinks the script went fine (which it probably did) but the PNG-data is messed up, i.e. "cannot display image" – Gerben Jacobs Sep 02 '13 at 09:28
1

Perhaps your PHP script messed up your images. Logical errors can't be reported, you have to find it by yourself. To turn on regular error reporting, check out this link: How do I enable error reporting in PHP?

To enable error logging Where does PHP store the error log? (PHP 5, Apache, FastCGI, and cPanel)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

In an ASP.NET Core application you may be tempted to put picture files in a folder called Images under the solution, but you need to put them in the wwwroot/images folder:

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • Six years after it was posed, you added the ASP.NET Core tag to this PHP question. And after that, .NET Core answers started to be added (two so far). Can you add an explanation in comments to the *question* (not here)? It is not at all clear why that was appropriate. – Peter Mortensen Nov 05 '21 at 21:22
0

Read your PHP error log and you will find out the exact error. Most probably PHP is throwing a warning. That's the reason you are seeing this error in your browser.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Maximus
  • 2,906
  • 4
  • 35
  • 55
0

That's a trick question, isn't it?

Your script contains the line

echo('here!'); //prints here to the screen

This will prepend the ASCII string "here" to the PNG data stream, thus ruining the image.

Hint: If you download the result of your script (using e.g. wget, or simply "Save page" in Firefox), and open the file in an editor, you'll quickly see the problem.

sleske
  • 81,358
  • 34
  • 189
  • 227
  • 1
    not intended as a trick! That was a debugging step I forgot to remove. There are still problems w/ the image – bernie2436 Sep 02 '13 at 21:33
0

I hope this might save a hour for someone troubleshooting .NET Core applications on Linux:

In my case it wasn't actually the issue with the image. The problem was a server-side uppercase directory/file name. In the Windows file system filename, case doesn't matter while the Linux file system is case-sensitive.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dmitry
  • 41
  • 2
0

Here's an answer from a thread at support.mozilla.org that may help others who come across this question:

I have discovered that a very common reason for this is that the image type does not match the file extension. This causes the webserver to report the wrong mime-type. For example, if you take a photoshop image, rename it to a .jpg file, and put it on a webserver, it will not load in Firefox.

If you are working on troubleshooting this issue, try downloading the file and verifying that the file type matches the jpg. I fixed this for a client today who took a .psd file, renamed it to .jpg, uploaded it to a webserver, and wondered why it wouldn't load in Firefox.

waldyrious
  • 3,683
  • 4
  • 33
  • 41
0

For my case, it was Visual Studio's fault for the error. I started to add the image to the code via the img tag, and Visual Studio guided me through it with IntelliSense I guess. The funny thing is, it added the wrong path. This is what it added in for me:

<img src="~/images/home-couple.jpg" />

Where it should have been:

<img src="images/home-couple.jpg" />

The location of the images folder is right under wwwroot. This is an ASP.NET Core web application.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
CaptainGenesisX
  • 328
  • 3
  • 10
0

Before the header line insert this function ob_clean(); like in the example:

$image = file_get_contents($imageFilePath);

ob_clean(); // <-DON'T FORGET THIS LINE

header('Content-type: image/jpeg'); //jpeg, png, bmp...
header("Content-Disposition: filename=".basename($imageFilePath)); 
echo $image;

ob_clean() is used to clean (erase) the output buffer. So, if there is something else echoed beofre the header, it will be erased;

Teo Mihaila
  • 134
  • 1
  • 2
  • 18