
- Drop me a line! Contact me here.
Image Mosaics with GD
We have kept the colour channels seperate in the database. This helps speed things up a little later on. In general it is always preferable to work on colour channels seperately, it makes things go a little faster and produces nicer results.
Now we have a bank of tiles to use we can set about making our first mosaic. We need to select a relatively small image file. If we're using 32*32 pixel tiles, then a 64*64 source file will generate a mosaic image that is 2048*2048 pixels square. Thats a large image file, and requires a lot of memory to generate.
Once we have the source image open we need to open a blank canvas to copy our tiles to.
$s is the size of our tile images.
The pixel colour processing stage is very similar to the code that was used to calculate the pixel colour averages in the first stage of the mosaic process. We select a pixel, then calculate the value of each colour channel. Once we have these we can then go to the database and select the closest matching tile image.
Calculating the nearest colour is a matter of subtracting the channel value in the database from our extracted channel value, and adding up the absolute values for each of the three channels.
Taking the absolute value of the difference between two numbers gives you the difference between the two values. If there is a large difference you will have a large integer, if there is a small difference you will have a small integer. Adding together the differences between each channel gives you the overall difference in colour between the tile image and the source pixel. By finding the tile with the smallest difference you can find which image will most closely represent the pixel colour of the source.
Each source pixel colour is copied into $rgbCache to save having to calculate the same pixel colour twice.
Now we have a bank of tiles to use we can set about making our first mosaic. We need to select a relatively small image file. If we're using 32*32 pixel tiles, then a 64*64 source file will generate a mosaic image that is 2048*2048 pixels square. Thats a large image file, and requires a lot of memory to generate.
<?php
$mosaic = "mosaic.jpg";
$image = imagecreatefromjpeg($mosaic);
?>
Once we have the source image open we need to open a blank canvas to copy our tiles to.
<?php
$output = imagecreatetruecolor((imagesx($image)*$s), (imagesy($image)*$s));
?>
$s is the size of our tile images.
<?php
for ($y=0;$y<imagesy($image);$y++) {
for ($x=0;$x<imagesx($image);$x++) {
//Process pixel colour
}
}
?>
The pixel colour processing stage is very similar to the code that was used to calculate the pixel colour averages in the first stage of the mosaic process. We select a pixel, then calculate the value of each colour channel. Once we have these we can then go to the database and select the closest matching tile image.
Calculating the nearest colour is a matter of subtracting the channel value in the database from our extracted channel value, and adding up the absolute values for each of the three channels.
Taking the absolute value of the difference between two numbers gives you the difference between the two values. If there is a large difference you will have a large integer, if there is a small difference you will have a small integer. Adding together the differences between each channel gives you the overall difference in colour between the tile image and the source pixel. By finding the tile with the smallest difference you can find which image will most closely represent the pixel colour of the source.
<?php
$rgb = imagecolorat($image,$x,$y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
if ($rgbCache[$rgb] == "") {
$sql = "select * from sourceimage order by abs(".$r."-rVal) + abs(".$g."-gVal) + abs(".$b."-bVal) limit 1";
$result = mysql_query($sql,$databaseLink);
$record = mysql_fetch_object($result);
$rgbCache[$rgb] = $record->filename;
}
?>
Each source pixel colour is copied into $rgbCache to save having to calculate the same pixel colour twice.
<?php
$tile = imagecreatefromjpeg("tiles/".$rgbCache[$rgb]);
imagecopy($output,$tile,$x*$s,$y*$s,0,0,$s,$s);
?>
Comments
Comments are not currently being accepted for this article.
Sidebar
Published:
17/01/2007
Views:
2597
Author:
Chris Neale
Labels:
Print:
- © Ooer.com Chris Neale 2007
- PHPGD.com
- Powered by PHP
- Database by MySQL
- DB Queries: 9
- DB Time: 0.0672 seconds
