Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Image Functions : imagesetpixel

imagesetpixel

Set a single pixel (PHP 4, PHP 5)
bool imagesetpixel ( resource image, int x, int y, int color )

imagesetpixel() draws a pixel at the specified coordinate.

Parameters

image

An image resource, returned by one of the image creation functions, such as imagecreatetruecolor().

x

x-coordinate

y

y-coordinate

color

A color identifier created with imagecolorallocate()

Return Values

Returns TRUE on success or FALSE on failure.

Examples

Example1021.imagesetpixel() example

A random drawing that ends with a regular picture.

<?php

$x
= 200;
$y = 200;

$gd = imagecreatetruecolor($x, $y);

$corners[0] = array('x' => 100, 'y' => 10);
$corners[1] = array('x' => 0, 'y' => 190);
$corners[2] = array('x' => 200, 'y' => 190);

$red = imagecolorallocate($gd, 255, 0, 0);

for (
$i = 0; $i < 100000; $i++) {
imagesetpixel($gd, round($x),round($y), $red);
$a = rand(0, 2);
$x = ($x + $corners[$a]['x']) / 2;
$y = ($y + $corners[$a]['y']) / 2;
}

header('Content-Type: image/png');
imagepng($gd);

?>

The above example will output something similar to:


Related Examples ( Source code ) » imagesetpixel





Code Examples / Notes » imagesetpixel

gusts kaksis

This code generate a simple colortable - not a very acurate one (it would be good to define fade of color - more fading)
<?php
set_time_limit(200);
/*
Custommize this to see some nice changes:
*/
$width = 360;   // degrees
$height = 18;   // byte
$offset = -60;    // offset of color hue
/*
Main programm:
Here comes transformations - width to degrees and height to intesity
*/
$w2deg = $width/360;
$h2byte = $height/255;
$byte2deg = 255/360;
$im = imagecreatetruecolor($width,$height);
for ($x = 0; $x < $width; $x ++){
 /*
 Transform X to degrees
 */
 $x_pos = $x/$w2deg;
 /*
 Intensity position (where max intensity is 255) on 360 degree scale.
 0 = red
 1 = green
 2 = blue
 */
 $rgb_pos[0] = sin(deg2rad($x_pos) - deg2rad($offset + 0));
 $rgb_pos[1] = sin(deg2rad($x_pos) - deg2rad($offset + 120));
 $rgb_pos[2] = sin(deg2rad($x_pos) - deg2rad($offset + 240));
 /*
 Calculate intesity at current point 0 - 255
 */
 $rgb_col[0] = 127 + 127 * $rgb_pos[0];
 $rgb_col[1] = 127 + 127 * $rgb_pos[1];
 $rgb_col[2] = 127 + 127 * $rgb_pos[2];
 /*
 White -> color -> Black loop
 */
 for ($y = 0; $y < $height; $y ++){
   /*
   Transform Y to intensity (-255 to 255)
   */
   $y_pos = -255 + ($y/$h2byte) * 2;
   $rgb_out[0] = $rgb_col[0] - $y_pos;
   $rgb_out[1] = $rgb_col[1] - $y_pos;
   $rgb_out[2] = $rgb_col[2] - $y_pos;
   /*
   If we go over 255 or under 0 we normalize it
   */
   foreach($rgb_out as $key => $col){
     if ($col > 255){
       $rgb_out[$key] = 255;
     } else if ($col < 0){
       $rgb_out[$key] = 0;
     }
   }
   /*
   Put a pixel
   */
   $col = imagecolorallocate($im,$rgb_out[0],$rgb_out[1],$rgb_out[2]);
   imagesetpixel($im,$x,$y,$col);
 }
}
/*
Test output
*/
imagejpeg($im,'colortable.jpg');
echo '<img src="colortable.jpg">';
?>


d

This code does generate a RGB-cube (with or without borders). Because its only rendering the visible pixels its clearly fast (approx 1 up to 2 seconds). With changing the $order-variable you can see the cube from different perspectives. Entering double or tribble values (like rrg or ggg) will give you other specs of single channels. Send any sugestions to my email.
<?php
$borders = true;
$order   = 'rgb';
set_time_limit(0);
$img = imageCreateTrueColor(510, 510);
$bg = imageColorAllocate($img, 255, 255, 255);
$black = imageColorAllocate($img, 255, 255, 255);
for ($r=0; $r<256; $r++) {
 for ($g=0; $g<256; $g++) {
   for ($b=0; $b<256; $b++) {
     $rN = ${$order{0}};
     $gN = ${$order{1}};
     $bN = ${$order{2}};
   
     $col = imageColorAllocate($img, $rN, $gN, $bN);
     imagesetpixel($img, $b+($r*0.5)+(255/4), $g+($r*0.5)+(255/4), $col);
     if ($r < 255 && $g > 0) break;
   }
 }
 
 if ($borders) {
   imagesetpixel($img, ($r*0.5+(255/4)), ($r*0.5)+(255/4),     $black);
   imagesetpixel($img, ($r*0.5)+255+(255/4), ($r*0.5)+(255/4), $black);
   imagesetpixel($img, ($r*0.5)+(255/4), ($r*0.5)+255+(255/4), $black);
 }
}
if ($borders) {
 imageline($img, 255/4, 255/4, 255+(255/4), 255/4, $black);
 imageline($img, 255/4, 255/4, 255/4, 255+(255/4), $black);
 imageline($img, 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
 imageline($img, 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5+(255/4), $black);
 imageline($img, 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
 imageline($img, 255*0.5 + 509*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
}
header("Content-Type: image/png");
imagepng($img);
imagedestroy($img);
?>


bpgordon

This code converts a block of text to an image so that each character in the block defines one pixel in the image and each line in the block (delimited by \n's) builds one whole row of pixels in the image.
Usage: Place a 0 to create a white pixel. Place a 1 to create a black pixel.
Example: Entering the following digits (including the line breaks) will create a 3x3 square with a 1-pixel white border.
00000
01110
01110
01110
00000
<?php
if (isset($_POST["sendtxt"])) {
header("Content-type: image/png");
$splitted = explode("\n", $_POST["sendtxt"]);
foreach ($splitted as $tcurkey => $curval) $tsplitted[$tcurkey] = rtrim($curval);
$splitted = $tsplitted; //referencing isn't working for some reason...
$image = imagecreate(strlen($splitted[1]), count($splitted));
$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); // don't delete this line
$black = imagecolorallocate($image, 0x00, 0x00, 0x00);
foreach($splitted as $curkey => $opelement) {
$subsplitten = preg_split("//", $opelement);
foreach($subsplitten as $subcurkey => $subopelement) {
if ($subopelement == "1" || $subopelement == ".") imagesetpixel($image, $subcurkey-1, $curkey, $black);
}
}
imagepng($image);
imagedestroy($image);
} else {
echo <<<end
<table width="1" border="0"><td>
<form method="post" action="#">
<textarea cols="30" rows="7" name="sendtxt"></textarea>
<input type="submit" value="render">
</form></td></table>
end; }
?>


dino

The example above diden't work, because of some errors.
This should work and it's also faster because there is only one 512*512 loop. (but it is still very slow)
<?
$filename="lena.raw";
$width=512;
$height=512;
$fp=fopen($filename, "r");
$contents=fread($fp,filesize($filename));
fclose($fp);
$image=imagecreate($width,$height);
// create greyscale palette because the image is limited to 256 colors
for ($i=0;$i<256;$i++){ ImageColorAllocate($image,$i,$i,$i);}
// This is slow, but probably the only way
for ($i=0;$i<512;$i++){
  for ($j=0;$j<512;$j++){    
  imagesetpixel ($image,$i,$j,ord($contents[$i+$j*512]));
  }
}
imagepng($image,"result.png");
imagedestroy($image);
echo "<img src=result.png></img>";
?>
--
Dino Patti


odindtdm.org

Just a simple implementation of the Bresenham algorythm (educational purpose....)
You can find more about this and many other tutorials for gfx there: http://brand107.home.comcast.net/pc-gpe/
<?php
/****************************************************
    Bresenham Line Algorythm PHP/GD implementation  
****************************************************/
function line($im,$x1,$y1,$x2,$y2,$color){

$deltax=abs($x2-$x1);
$deltay=abs($y2-$y1);
if ($deltax>$deltay) {
$numpixels=$deltax+1;
$d=(2*$deltay)-$deltax;
$dinc1=$deltay << 1; $dinc2=($deltay-$deltax) << 1;
$xinc1=1; $xinc2=1;
$yinc1=0; $yinc2=1;
} else {
$numpixels=$deltay+1;
$d=(2*$deltax)-$deltay;
$dinc1=$deltax << 1; $dinc2=($deltax-$deltay)<<1;
$xinc1=0; $xinc2=1;
$yinc1=1; $yinc2=1;
}
if ($x1>$x2) {
$xinc1=-$xinc1;
$xinc2=-$xinc2;
}
if ($y1>$y2) {
$yinc1=-$yinc1;
$yinc2=-$yinc2;
}
$x=$x1;
$y=$y1;
for ($i=0;$i<$numpixels;$i++) {
imagesetpixel($im,$x,$y,$color);
if ($d<0) {
 $d+=$dinc1;
 $x+=$xinc1;
 $y+=$yinc1;
} else {
 $d+=$dinc2;
 $x+=$xinc2;
 $y+=$yinc2;
}
}
return ;
}
?>


t. dekker

In reply to weitheism at gmail.com:
You should probably have used ImageAlphaBlending($image, false); in your early attempts. This way any paint/fill operation replaces the alpha value of the destination.


weitheism

I was looking for a way to actually DELETE pixels or squares or parts of an image from an image resource, and at first I thought imagesetpixel would do the trick. Unfortunately, it merely paints over that one pixel, and as far as I knew, php didn't have any native way of deleting sections out of your image - so this little method should take care of deleting rectangular parts of your pictures!
function deleteRectangle(&$oldImage,$leftX,$leftY,$rightX,$rightY)
{
// Since php has no native way of delete parts of images
// We have to divide the image into four different parts and then copy them manually to a new
// image

$xSize = imagesx($oldImage);
$ySize = imagesy($oldImage);

// Divides the image into four sections to copy
$imagesection = array();
$imagesection[] = array(0,0,$leftX,$ySize);
$imagesection[] = array($leftX,0,$rightX+1,$leftY);
$imagesection[] = array($leftX,$rightY+1,$rightX+1,$ySize);
$imagesection[] = array($rightX+1,0,$xSize,$ySize);

// Create the new, copied image
$newImage = imagecreatetruecolor($xSize,$ySize);
// Vital for transparency
imagesavealpha($newImage,true);

// Fills the background a transparent color
$transparentBackground = imagecolorallocatealpha($newImage,255,255,255,127);
imagefill($newImage,0,0,$transparentBackground);

// Copies each of the four imagesections into their respective old positions
for($i = 0;$i<count($imagesection);$i++)
imagecopyresampled($newImage,$oldImage, $imagesection[$i][0],$imagesection[$i][1], $imagesection[$i][0],$imagesection[$i][1], $imagesection[$i][2]-$imagesection[$i][0], $imagesection[$i][3]-$imagesection[$i][1], $imagesection[$i][2]-$imagesection[$i][0], $imagesection[$i][3]-$imagesection[$i][1]);

// Alternately you can cycle through each pixel in an image and see if that pixel is an the area
// but that could be more intensive
imagedestroy($oldImage);

// Sets the old image equal to the new, cleared image
$oldImage = $newImage;
}
It was made with a transparent background in mind, but you could easily change that by changeing imagecreatetruecolor to imagecreate and deleting the code that deals with transparency. Hope it helps!


brian vaughn php

I looked, but was unable to find any example code to watermark an image with a watermark that contained alpha transparency. So the following class does just that. As a parameter, it takes 2 image objects: the main image, and the watermark image (which can be a gif, png, whatever) - and optionally, an alpha setting (0-100% alpha for the watermark image). It then creates and returns a new image with the alpha-transparent watermark imposed, center-aligned, over the larger image.
<?php
class watermark{
function create_watermark( $dst_img, $watermark_img, $alpha = 100 ) {
$alpha /= 100; # convert 0-100% user-friendly alpha to decimal
# calculate our images dimensions
$dst_img_w = imagesx( $dst_img );
$dst_img_h = imagesy( $dst_img );
$watermark_img_w = imagesx( $watermark_img );
$watermark_img_h = imagesy( $watermark_img );

# create new image to hold merged changes
$return_img = imagecreatetruecolor( $dst_img_w, $dst_img_h );
# $return_img = imagecreate( $dst_img_w, $dst_img_h );

# determine center position coordinates
$dst_img_min_x = floor( ( $dst_img_w / 2 ) - ( $watermark_img_w / 2 ) );
$dst_img_max_x = ceil( ( $dst_img_w / 2 ) + ( $watermark_img_w / 2 ) );
$dst_img_min_y = floor( ( $dst_img_h / 2 ) - ( $watermark_img_h / 2 ) );
$dst_img_max_y = ceil( ( $dst_img_h / 2 ) + ( $watermark_img_h / 2 ) );

# walk through main image
for( $y = 0; $y < $dst_img_h; $y++ ) {
for( $x = 0; $x < $dst_img_w; $x++ ) {
$return_color = NULL;

# determine the correct pixel location within our watermark
$watermark_x = $x - $dst_img_min_x;
$watermark_y = $y - $dst_img_min_y;

# fetch color information for both of our images
$dst_rgb = imagecolorsforindex( $dst_img, imagecolorat( $dst_img, $x, $y ) );

# if our watermark has a non-transparent value at this pixel intersection
# and we're still within the bounds of the watermark image
if ( $watermark_x >= 0 && $watermark_x < $watermark_img_w &&
$watermark_y >= 0 && $watermark_y < $watermark_img_h ) {
$watermark_rbg = imagecolorsforindex( $watermark_img, imagecolorat( $watermark_img, $watermark_x, $watermark_y ) );

# using image alpha, and user specified alpha, calculate average
$watermark_alpha = round( ( ( 127 - $watermark_rbg['alpha'] ) / 127 ), 2 );
$watermark_alpha = $watermark_alpha * $alpha;

# calculate the color 'average' between the two - taking into account the specified alpha level
$avg_red = $this->get_ave_color( $dst_rgb['red'], $watermark_rbg['red'], $watermark_alpha );
$avg_green = $this->get_ave_color( $dst_rgb['green'], $watermark_rbg['green'], $watermark_alpha );
$avg_blue = $this->get_ave_color( $dst_rgb['blue'], $watermark_rbg['blue'], $watermark_alpha );

# calculate a color index value using the average RGB values we've determined
$return_color = $this->imagegetcolor( $return_img, $avg_red, $avg_green, $avg_blue );

# if we're not dealing with an average color here, then let's just copy over the main color
} else {
$return_color = imagecolorat( $dst_img, $x, $y );

} # END if watermark
# draw the appropriate color onto the return image
imagesetpixel( $return_img, $x, $y, $return_color );
} # END for each X pixel
} # END for each Y pixel

# return the resulting, watermarked image for display
return $return_img;
} # END create_watermark()

# average two colors given an alpha
function get_ave_color( $color_a, $color_b, $alpha ) {
return round( ( ( $color_a * ( 1 - $alpha ) ) + ( $color_b * $alpha ) ) );
} # END get_ave_color()

# return closest pallette-color match for RGB values
function imagegetcolor($im, $r, $g, $b) {
$c=imagecolorexact($im, $r, $g, $b);
if ($c!=-1) return $c;
$c=imagecolorallocate($im, $r, $g, $b);
if ($c!=-1) return $c;
return imagecolorclosest($im, $r, $g, $b);
} # EBD imagegetcolor()
} # END watermark API
?>


zehao dot chang

Here's my stab at the imagecreatefromtga function. I used code from send at mail dot 2aj dot net and others below as a basis, and added support for targa 16, targa 24 and targa 32. However, I only support uncompressed RBG data type as that's the only one I need. (I removed the return_array feature since you can simply use imagesx() and imagesy() to get the image size).
Please note that I have not tested this with a targa 16 since I don't have one handy at the moment.
<?php
function imagecreatefromtga( $filename )
{
$handle = fopen( $filename, 'rb' );
$data = fread( $handle, filesize( $filename ) );
fclose( $handle );
 
// Extract header information
$string_length = base_convert( bin2hex( substr($data,1,1) ), 16, 10 );
$data_type = base_convert( bin2hex( substr($data,2,1) ), 16, 10 );
$width = base_convert( bin2hex( strrev( substr($data,12,2) ) ), 16, 10 );
$height = base_convert( bin2hex( strrev( substr($data,14,2) ) ), 16, 10 );
$bits_per_pixel = base_convert( bin2hex( substr($data,16,1) ), 16, 10 );

// Currenly I'm only supporting RGB Data type
switch( $data_type ) // Header information taken from http://astronomy.swin.edu.au/~pbourke/dataformats/tga/
{
case 2: // Uncompressed RGB image
break;
case 0: // No attached image data
case 1: // Uncompressed color-mapped image
case 3: // Uncompressed black and white image
case 9: // Runlength encoded color-mapped image
case 10: // Runlength encoded RGB image
case 11: // Compressed black and white image
case 32: // Compressed color-mapped data, using Huffman, Delta, and runlength encoding
case 33: // Compressed color-mapped data, using Huffman, Delta, and runlength encoding.  4-pass quadtree-type process
default:
return NULL; // No support for any of these types
}

// Compute things we need from the header information
$pointer = 18 + $string_length;
$bytes_per_pixel = (int) $bits_per_pixel/8;
$x = 0;  $y = $height;

$image = imagecreatetruecolor($width, $height);
while ( $pointer < strlen($data) )
{
if( $bytes_per_pixel == 2 ) // TARGA 16 - ARRRRRGG GGGBBBBB
{
$low_byte = bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel)));
$high_byte = bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel)));
$r = base_convert( ($high_byte & 0x7C)>>2, 16, 10);
$g = base_convert( (($high_byte & 0x03)<<3) | (($low_byte & 0xE0)>>5), 16, 10);
$b = base_convert( $low_byte & 0x1F, 16, 10);
    imagesetpixel( $image, $x, $y, $r<<16 | $g<<8 | $b);
}
else if( $bytes_per_pixel == 3 ) // TARGA 24 - RRRRRRRR GGGGGGGG BBBBBBBB
{
    imagesetpixel( $image, $x, $y, base_convert( bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel))), 16, 10));
}
else if( $bytes_per_pixel == 4 ) // TARGA 32 - AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
{
    imagesetpixel( $image, $x, $y, base_convert( bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel-1))), 16, 10));
}

    if(++$x == $width)
{
$y--;
$x=0;
}
      $pointer += $bytes_per_pixel;
}
 
return $image;
}
?>


richard

Here is a function that takes an image ($im) and returns it with the contrast maximised...
<?php
function contrast($im) {
$brightness=0;
$maxb=0;
$minb=255;
$imagesize=getimagesize($im);
$w=$imagesize[0];
$h=$imagesize[1];
for ($x=0; $x<$w; $x++) {
for ($y=0; $y<$h; $y++) {
$rgb=imagecolorat($im, $x, $y);
$rgb=imagecolorsforindex($im, $rgb);
$grey=0.2125*$rgb['red']+
0.7154*$rgb['green']+
0.0721*$rgb['blue'];
$brightness+=$grey;
if ($grey>$maxb) $maxb=$grey;
if ($grey<$minb) $minb=$grey;
}
}
$brightness=$brightness/($w*$h);
$minb=$brightness/($brightness-$minb);
$maxb=(255-$brightness)/($maxb-$brightness);
$contrast=min($minb, $maxb);
for ($x=0; $x<$w; $x++) {
for ($y=0; $y<$h; $y++) {
$rgb=imagecolorat($im, $x, $y);
$rgb=imagecolorsforindex($im, $rgb);
imagesetpixel($im, $x, $y,
65536*floor(min($rgb['red']*$contrast, 255))+
256*floor(min($rgb['green']*$contrast, 255))+
floor(min($rgb['blue']*$contrast, 255)));
}
}
return ($im);
}
?>
An example of usage might be:
<?php
$imagefile="/path/filename";
$image=imagecreatefromjpeg($imagefile);
$image=contrast($image);
imagejpeg($image, $imagefile);
?>


chris

<?php
/*
An example combining the use of ImageColorAllocate, Imagesetpixel, Imagecopyresized and some basic Trig
By chris@drunkenpirates.co.uk
*/
Header("Content-type: image/png");
$height = 128;
$width = 128;
$imA = ImageCreate($width, $height);
$imB = ImageCreate($width*4, $height*4);
$bckA = ImageColorAllocate($imA, 0,0,0);
$bckB = ImageColorAllocate($imB, 0,0,0);
//GENERATE GRAY SCALE PALLETE
for($c=0;$c<256;$c++){
               ImageColorAllocate($imA, $c, $c, $c);
               }
//PRODUCE DATA
$m=rand(0,10);
for($c=0;$c<128;$c++){
               $s=  (sin( deg2rad($c*360*$m/128) )+1)*127;
               $col_arr[$c]=$s;
               }
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgA[$x][$y]=$col_arr[$x];
               }
       }
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgB[$x][$y]=$col_arr[$y];
               }
       }
//SET PIXELS
for($y=0;$y<$height;$y++){
       for($x=0;$x<$width;$x++){
               $imgC[$x][$y]=$imgA[$x][$y]+$imgB[$x][$y];
               $s=$imgC[$x][$y]/2;
               Imagesetpixel($imA,$x,$y,$s);
               }
       }
//RESIZE IMAGE FOR DISPLAY
Imagecopyresized ($imB, $imA, 0, 0, 0, 0, $width*4, $height*4, $width, $width);
ImagePNG($imB);
?>


Change Language


Follow Navioo On Twitter
gd_info
getimagesize
image_type_to_extension
image_type_to_mime_type
image2wbmp
imagealphablending
imageantialias
imagearc
imagechar
imagecharup
imagecolorallocate
imagecolorallocatealpha
imagecolorat
imagecolorclosest
imagecolorclosestalpha
imagecolorclosesthwb
imagecolordeallocate
imagecolorexact
imagecolorexactalpha
imagecolormatch
imagecolorresolve
imagecolorresolvealpha
imagecolorset
imagecolorsforindex
imagecolorstotal
imagecolortransparent
imageconvolution
imagecopy
imagecopymerge
imagecopymergegray
imagecopyresampled
imagecopyresized
imagecreate
imagecreatefromgd2
imagecreatefromgd2part
imagecreatefromgd
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromstring
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
imagecreatetruecolor
imagedashedline
imagedestroy
imageellipse
imagefill
imagefilledarc
imagefilledellipse
imagefilledpolygon
imagefilledrectangle
imagefilltoborder
imagefilter
imagefontheight
imagefontwidth
imageftbbox
imagefttext
imagegammacorrect
imagegd2
imagegd
imagegif
imagegrabscreen
imagegrabwindow
imageinterlace
imageistruecolor
imagejpeg
imagelayereffect
imageline
imageloadfont
imagepalettecopy
imagepng
imagepolygon
imagepsbbox
imagepsencodefont
imagepsextendfont
imagepsfreefont
imagepsloadfont
imagepsslantfont
imagepstext
imagerectangle
imagerotate
imagesavealpha
imagesetbrush
imagesetpixel
imagesetstyle
imagesetthickness
imagesettile
imagestring
imagestringup
imagesx
imagesy
imagetruecolortopalette
imagettfbbox
imagettftext
imagetypes
imagewbmp
imagexbm
iptcembed
iptcparse
jpeg2wbmp
png2wbmp
eXTReMe Tracker