Placeholder Image

ADN Informatique

Consultant Ingénierie Informatique

Saguenay (Jonquière), Québec, Canada. Tél: (581) 683-9887 Téléc: (581) 221-0874

Placeholder Picture

Retour

Building PNG Images

2008-09-18 10:26:31 (ID: 86, Parent: 0, Type: post)
Did you ever try to build a png image (with a programming language, not an image editor)?  A lot of code sample are available on the internet.  But most if not all are using libpng or some high level libraries like gd.

But what happend if you can't install libraries on the system where you're working?  Ever thing about building an image from scratch?  Here is what I do in PHP.

This isn't the most performant code, but at least it generate a valid PNG image without any non standard libraries.   (Some one could say that zlib or crc are php external libs.. but I haven't see any php distribution whitout them in a while!)

<?php
/*
* Title: PNG Image Generation
* Author: Jean-Luc Cyr
* Date: 2008-09-17
* License: GNU GPL2
* Description: Generate a simple PNG image
* directly in PHP without using external libs
* like GD.
*/

header("content-type: image/png");

function long2string($long)
{
$string = chr(($long&0xFF000000)>>24).
chr(($long&0xFF0000)>>16).
chr(($long&0xFF00)>>8).
chr(($long&0xFF)>>0);
return $string;
} // long2string()
function build_png($matrix, $w, $h)
{
////////////////////////////////////////////////////////////////
//PNG Header
$image = chr(0x89).chr(0x50).chr(0x4E).chr(0x47);
$image .= chr(0x0D).chr(0x0A).chr(0x1A).chr(0x0A);

////////////////////////////////////////////////////////////////
//Header Chunk

//Chunk type
$chunk = "IHDR";
//Chunk data
//Width
$data = long2string($w);
//Height
$data .= long2string($h);
//Depth
$data .= chr(8); //Bits per sample
//Color Type
$data .= chr(2); //RGB
//Compression method
$data .= chr(0);
//Filter method
$data .= chr(0);
//Interlaced method
$data .= chr(0);

$crc = crc32($chunk.$data);
//Add length at start
$chunk = long2string(strlen($data)).$chunk.$data;
//Add CRC at the end
//Dump chunk
$chunk = $chunk.long2string($crc);
$image .= $chunk;

////////////////////////////////////////////////////////////////
//Data Chunk

//Chunk type
$chunk = "IDAT";
//Data (2x2 rgb 8bits)
$s = 3; //samples per pixels
#$matrix  ="\0\0\0\0\0\0\0\0\0";
#$matrix .="\0\0\0\0\0\0\0\0\0";
#$matrix .="\0\0\0\0\0\0\0\0\0";
// No filter so add 0 to beginning of each scan line
$datas = '';
for($c=0; $c<$h; $c++)
$datas .= "\0". substr($matrix,$c*($w*$s),($w*$s));
// Compress Data
#$zdata = gzencode($data,9,FORCE_DEFLATE);
#$zdata = gzdeflate($data,0);
$zdata = gzcompress($datas,0);
// Calculate CRC
$crc = crc32($chunk.$zdata);
// Add length at start
$l = strlen($zdata);
$chunk = long2string($l).$chunk.$zdata;
// Add CRC at the end
$chunk = $chunk.long2string($crc);
$image .= $chunk;

////////////////////////////////////////////////////////////////
//End Chunk

// Chunk type
$chunk = "IEND";
// Data
$data = "";
// Calculate CRC
$crc = crc32($chunk);
// Add length at start
$chunk = long2string(strlen($data)).$chunk.$data;
// Add CRC at the end
$chunk = $chunk.long2string($crc);
$image .= $chunk;

// Send out the image
echo $image;die();
} // build_png()
////////////////////////////////////////////////////////////////
// Demo code

// Build a simple image matrix
// 256 x 256 x 8rgb

$w=256; // width
$h=256; // height
$s=3;   // 3 x 8 bits samples per pixel (8bits rgb)
for($x=0; $x<$h; $x++)
for($y=0; $y<$w; $y++)
//    for($z=0; $z<$s; $z++) //Ordered R G B
$matrix .=
chr( ( (($y/64)<1) && (($y/64)>0) )?$x:0 ). // R
chr( ( (($y/64)<2) && (($y/64)>1) )?$x:0 ). // G
chr( ( (($y/64)<3) && (($y/64)>2) )?$x:0 ); // B

build_png($matrix,$w,$h);
die();

////////////////////////////////////////////////////////////////
// Hex dump image for debugging

for ($x=0; $x<strlen($image); $x++) {
printf("%02X ",ord($image[$x]));
if ((($x+1)%16)==0)
printf("<br/>");
}

Document Informatif

ADN Informatique

2015

Rev. 1

Jean-Luc Cyr