Skip to content

Instantly share code, notes, and snippets.

@MidnightLightning
Created February 10, 2016 19:33
Show Gist options
  • Select an option

  • Save MidnightLightning/184c022d7474a2025386 to your computer and use it in GitHub Desktop.

Select an option

Save MidnightLightning/184c022d7474a2025386 to your computer and use it in GitHub Desktop.
Crosstitch converter
<?php
// Take an image and convert it into a crosstitch grid
function textImage($msg = "No message") {
$char_size = 3; # Which standard font size?
$char_height = 35; # How tall is a line?
$char_width = 7; # How wide is each character?
// Determine width based on string length
$width = strlen($msg)*$char_width+30;
// Create a blank image to draw on
$im = @imagecreatetruecolor($width, $char_height) or die("Cannot Initialize new GD image stream");
$bg = imagecolorallocate($im, 250, 230, 230);
imagefill($im, 0, 0, $bg);
$text_color = imagecolorallocate($im, 233, 14, 91);
// Write messgae
imagestring($im, 3, 15, 10, $msg, $text_color);
// Export the final image
header ("Content-type: image/png");
imagepng($im);
imagedestroy($im);
}
function showImage($im) {
# Export the final image
header ("Content-type: image/png");
imagepng($im);
imagedestroy($im);
exit;
}
if (!isset($_REQUEST['img']) && $_REQUEST['img'] == "") {
textImage("Must pass an 'img' value");
exit;
}
$source_file = $_GET['img']; // The filename of the source file.
if (isset($_GET['mask']) && $_GET['mask'] != "") {
$do_mask = TRUE;
$masked = explode(",", $_GET['mask']); // Show only a few colors?
} else {
$do_mask = FALSE;
}
$source = imagecreatefromgif($source_file);
if (!$source) {
// Failed to load
textImage("Failed to load source; make sure it is a GIF image.");
exit;
}
list($w_px, $h_px, $tmp) = getimagesize($source_file);
// The symbols are all 7x7px in dimension. With a 1px gridline between all cells, and a 3 pixel gridline between every tenth cell, each group of ten cells is 82 pixels wide. i.e.:
// -------|-------|-------|-------|-------|-------|-------|-------|-------|-------|||
$w_sets = floor($w_px/10);
$w_grid = $w_sets*82 + ($w_px-($w_sets*10))*8+1;
$h_sets = floor($h_px/10);
$h_grid = $h_sets*82 + ($h_px-($h_sets*10))*8;
//textImage("Source is $w_px x $h_px px, final will be $w_grid x $h_grid px.");
// Determine the number of colors of the final image
if ($do_mask) $mask = imagecreatefromgif("images/mask.gif");
$symbols = array("-1" => array("color" => "-1", "img" => $mask));
for ($x=0; $x<=$w_px; $x++) {
for ($y=0; $y<=$h_px; $y++) {
$rgb = imagecolorat($source, $x, $y);
$cdata = imagecolorsforindex($source, $rgb);
if ($cdata['alpha'] == 0) {
$symbol = findsymbol($rgb);
}
}
}
// Now all colors should be loaded into $symbols.
$color_count = count($symbols)-1;
$legend_w = 150; // How much space to allocate per color definition
$legend_h = 20;
$per_row = floor($w_grid/$legend_w);
$rows = ceil($color_count/$per_row);
$tot_h = $h_grid + 10 + $rows*$legend_h; // Add on to the bottom of the image the required space
$im = imagecreatetruecolor($w_grid, $tot_h); // New image for holding grid image
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
$gray = imagecolorallocate($im, 180, 180, 180);
imagefill($im, 2, 2, $white); // Make a white background
// Draw the grids
$x = 0;
$col = 0;
while ($x <= $w_grid) {
if ($col < 10) {
// Draw a thin line
imageline ($im, $x, 0, $x, $h_grid, $gray);
$col++;
$x += 8;
} else {
// Draw a thick line
imageline ($im, $x, 0, $x, $h_grid, $black);
imageline ($im, $x+1, 0, $x+1, $h_grid, $black);
imageline ($im, $x+2, 0, $x+2, $h_grid, $black);
$col = 1;
$x += 10;
}
}
$y = 0;
$row = 0;
while ($y <= $h_grid) {
if ($row < 10) {
// Draw a thin line
imageline ($im, 0, $y, $w_grid, $y, $gray);
$row++;
$y += 8;
} else {
// Draw a thick line
imageline ($im, 0, $y, $w_grid, $y, $black);
imageline ($im, 0, $y+1, $w_grid, $y+1, $black);
imageline ($im, 0, $y+2, $w_grid, $y+2, $black);
$row = 1;
$y += 10;
}
}
// Re-do the vertical thick lines, since they got painted over
$x = 80;
while ($x <= $w_grid) {
// Draw a thick line
imageline ($im, $x, 0, $x, $h_grid, $black);
imageline ($im, $x+1, 0, $x+1, $h_grid, $black);
imageline ($im, $x+2, 0, $x+2, $h_grid, $black);
$x += 82;
}
// Now go through and grab the colors from the source
for($x = 0; $x<= $w_px; $x++) {
for ($y = 0; $y< $h_px; $y++) {
// What is the color at this pixel of the source image
$rgb = imagecolorat($source, $x, $y);
$cdata = imagecolorsforindex($source, $rgb);
if ($cdata['alpha'] == 0) {
$symbol = findsymbol($rgb);
$dstx_tens = floor($x/10);
$dsty_tens = floor($y/10);
$dst_x = $dstx_tens*82 + ($x-$dstx_tens*10)*8+1;
$dst_y = $dsty_tens*82 + ($y-$dsty_tens*10)*8+1;
imagecopy($im, $symbol, $dst_x, $dst_y, 0, 0, 7, 7);
}
}
}
// Finally, show the legend on the bottom of the image.
$col = 0;
$row = 1;
for($x=1; $x<count($symbols); $x++) {
$color = $symbols[$x];
$dst_x = $col*$legend_w+10;
$dst_y = $h_grid + ($row-1)*$legend_h + 6;
// Show the symbol for this color
imagecopy($im, $color['img'], $dst_x, $dst_y, 0, 0, 7, 7);
imagerectangle($im, $dst_x-1, $dst_y-1, $dst_x+7, $dst_y+7, $gray);
// Draw the label after the symbol
$str = ": (#".$color['color'].") #".$color['str'];
imagestring($im, 2, $dst_x+10, $dst_y-4, $str, $black);
$col++;
if ($col >= $per_row) {
$col = 0;
$row++;
}
}
showImage($im);
function findsymbol($index) {
global $source;
global $symbols;
global $masked;
global $do_mask;
if ($index == "") { $index = 0; }
if ($do_mask == TRUE) {
// First check and see if this color is masked
if (!in_array($index, $masked)) {
// Not on the chosen list; show the mask image instead
return $symbols[-1]['img'];
}
}
foreach($symbols as $symbol) {
if ($symbol['color'] == $index) {
// Found the match
return $symbol['img'];
}
}
// If we get here, we haven't found a match. Therefore, this is a new color, make a symbol for it.
$next = count($symbols); // What's the next symbol?
$next_img = imagecreatefromgif("images/s".$next.".gif");
// Go through and replace colors
$color = imagecolorsforindex($source, $index);
$white = imagecolorallocate($next_img, $color['red'], $color['green'], $color['blue']);
//$black = imagecolorallocate($next_img, 255-$color['red'], 255-$color['green'], 255-$color['blue']);
if (($color['red']+$color['green']+$color['blue'])/3 < 100) {
$black = imagecolorallocate($next_img, 255, 255, 255);
} else {
$black = imagecolorallocate($next_img, 0, 0, 0);
}
for($x=0; $x<imagesx($next_img); $x++) {
for($y=0; $y<imagesy($next_img); $y++) {
$cur_color = imagecolorsforindex($next_img, imagecolorat($next_img, $x, $y));
if ($cur_color['red'] > 200 && $cur_color['green'] > 200 && $cur_color['blue'] > 200) {
imagesetpixel($next_img, $x, $y, $white);
} else {
imagesetpixel($next_img, $x, $y, $black);
}
}
}
$color_str = strtoupper(sprintf("%02s", dechex($color['red'])).sprintf("%02s", dechex($color['green'])).sprintf("%02s", dechex($color['blue'])));
$symbols[$next] = array("color" => $index, "img" => $next_img, "str" => $color_str);
return $next_img;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment