These are functions intended to be used with the JSI image format, an image type designed for manual editing, using JavaScript to display it. Further information can be found in the JavaScript thread here;
/*****[ By Richard Moyer - v1.1 ]**************************************************************************
Takes a raw image and converts it into a JSI or xJSI image based on $format. If $file is specified,
then this function will output to it instead of returning the converted image. Returns false if the
raw image does not exist, or the $file cannot be opened/written to.
- $image = Raw image to be converted.
- $format = Set to 1 to convert the image into xJSI format.
- $file = The file, if specified, to save the image into. instead of returning it.
$trans_threshold = 114; // What transparency pixels are seen as transparent at (0 would convert all pixels to transparent, 64 would convert pixels that are 50% transparent into transparent, 127 would convert only truly 100% transparent pixels into the transparent color).
$maxpalette = 1296; // Maximum palette a JSI image can have. Do not change this.
$csize = ($format != 1) ? 3: 6; // The size of the HTML colors. JSI uses only 3 characters to represent color.
$width = @imagesx($image);
$height = @imagesy($image);
if (!$width || !$height || $width == 0 || $height == 0 || ($file != "" && !$fh = @fopen($file,'wb'))) return false;
// Set the variables used...
$colors = array();
$colors_used = array();
$transparent = "";
$guts = array();
// Figures out all of the used colors, storing the number into $colors_used, and the location data into $colors.
// Also sets the $guts of the image, which is used later for the actual palette locations for each pixel.
for ($y=0;$y<$height;$y++) {
$guts[$y] = array();
for ($x=0;$x<$width;$x++) {
$guts[$y][$x] = "";
$temp = imagecolorsforindex($image,imagecolorat($image,$x,$y));
if ($temp['alpha'] >= $trans_threshold) $temp2 = 'trans';
else {
$temp2 = strtoupper(str_pad(base_convert($temp['red'],10,16),2,"0",STR_PAD_LEFT).str_pad(base_convert($temp['green'],10,16),2,"0",STR_PAD_LEFT).str_pad(base_convert($temp['blue'],10,16),2,"0",STR_PAD_LEFT));
if ($format == 0) $temp2 = substr($temp2,0,1).substr($temp2,2,1).substr($temp2,4,1);
}
if (!isset($colors[$temp2])) {
$colors[$temp2] = array();
$colors_used[$temp2] = 0;
}
$colors[$temp2][] = $x.",".$y;
$colors_used[$temp2]++;
}
}
ksort($colors);
asort($colors_used,SORT_NUMERIC);
// Minimize palette for JSI images, in case the image has more than $maxpalette colors. xJSI doesn't need to be reduced.
$offs = 1;
$use = "";
while ($format == 0 && count($colors) > $maxpalette) {
$offs = ($use == "") ? 1: ($offs+1);
$use = "";
foreach ($colors_used as $key => $value) {
if ($use == "" && $key != "trans") {
$acceptable = ",";
$use = $key;
$rgb = array(base_convert(substr($use,0,1),16,10),base_convert(substr($use,1,1),16,10),base_convert(substr($use,2,1),16,10));
}
else if ($key != "trans") {
$rgb = array(abs(base_convert(substr($use,0,1),16,10)-base_convert(substr($key,0,1),16,10)),abs(base_convert(substr($use,1,1),16,10)-base_convert(substr($key,1,1),16,10)),abs(base_convert(substr($use,2,1),16,10)-base_convert(substr($key,2,1),16,10)));
if ($rgb[0] <= $offs && $rgb[1] <= $offs && $rgb[2] <= $offs) {
foreach ($colors[$use] as $key2 => $value2) {
$colors[$key][] = $value2;
$colors_used[$key]++;
}
unset($colors[$use],$colors_used[$use]);
$use = "";
break;
}
}
}
}
// If there was any transparent color set, then find a usable palette color for it that won't conflict with the
// rest of the used palette.
if (isset($colors['trans'])) {
$count = 0;
$temp = str_repeat("0",$csize);
$stop = str_repeat("F",$csize);
while (isset($colors[$temp]) && $temp != $stop) {
$count++;
$temp = str_pad(base_convert($count,10,16),$csize,"0",STR_PAD_LEFT);
}
if ($temp != $stop) $transparent = $temp;
}
// Now create the image from the details we've already set above.
$zoom = ($format != 1) ? "1": "1-e1.0"; // The version is stored beside the zoom in the first entry of the image. JSI images won't work with xJSI, and vice versa.
$palette = "";
$guts = "";
$count = 0;
foreach ($colors as $key => $value) {
if ($key == "trans") $key = $transparent;
$palette .= $key;
foreach ($value as $key2 => $value2) {
$temp = explode(",",$value2);
$guts[$temp[1]][$temp[0]] = ($format != 1) ? str_pad(strtoupper(base_convert($count,10,36)),2,"0",STR_PAD_LEFT): strtoupper(base_convert($count,10,36));
}
$count++;
}
// Implode the $guts...
foreach ($guts as $key => $value) {
ksort($guts[$key],SORT_NUMERIC);
$guts[$key] = ($format != 1) ? implode("",$guts[$key]): implode(",",$guts[$key]);
}
ksort($guts,SORT_NUMERIC);
$guts = ($format != 1) ? implode("\t",$guts): implode("/",$guts); // JSI rows are separated by a tab, xJSI by a forward slash.
// If $file was specified, we already opened the $fh in the if statement near the top, and checked it's openability.
if ($file != "") {
if (!fwrite($fh,$res)) return false;
fclose($fh);
return true;
}
return $res;
}
Convert an xJSI or JSI image to a raw GD image;
PHP Code:
function imagecreatefromjsi($image="") {
/*****[ By Richard Moyer - v1.0 ]**************************************************************************
Takes a JSI or xJSI image and converts it to a raw format, returning it. If $image is a file, it
will load the image from there. Returns false if the JSI image is incorrectly formatted, or the JSI
image is of an unsupported version.
- $image = The text of the JSI image to be converted, or the path to the file to use.
// Define the extension functions we'll need for converting and verification.
if (!function_exists("JSIonlyHex")) {
function JSIonlyHex($inp) {
return preg_replace("/[^0-9a-f]/i","",$inp);
}
function JSIhex($a) {
$a = strtolower($a);
$set = "abcdef0123456789";
$result = "#";
for ($i=0;$i<strlen($a);$i++) {
if (strpos($set,substr($a,$i,1)) !== false) {
$result .= substr($a,$i,1);
}
if (strlen($result) >= 7) break;
}
while (strlen($result) < 7) {
$result .= "0";
}
$result = strtoupper($result);
return $result;
}
function JSIhex2rgb($col="#000000") {
$col = JSIhex($col);
$newr = base_convert("0x".substr($col,1,2),16,10);
$newg = base_convert("0x".substr($col,3,2),16,10);
$newb = base_convert("0x".substr($col,5,2),16,10);
return array($newr,$newg,$newb);
}
}
if ($image == "") return false;
// Check if $image is a file, and load it if so.
if (is_file($image)) $image = @file_get_contents($image);
// Run some verification.
$x = explode("\t\t",$image);
if (count($x) != 4) return false;
$format = 3;
$zoom = explode("-",$x[0]);
if (isset($zoom[1]) && substr($zoom[1],0,3) != "e1.") return false;
if (isset($zoom[1])) $format = 6;
$zoom = floor(abs($zoom[0]));
if ($zoom < 1) $zoom = 1;
if ($zoom > 99) $zoom = 99;
$transparent = JSIonlyHex($x[1]);
if (strlen($transparent) != 3 && strlen($transparent) != 6) $inv = "";
if (strlen($transparent) == 3) $transparent = substr($transparent,0,1).substr($transparent,0,1).substr($transparent,1,1).substr($transparent,1,1).substr($transparent,2,1).substr($transparent,2,1);
$temp = ($format == 3) ? explode("\t",$x[3]): explode("/",$x[3]);
if ($format == 3) $temp2 = (strlen($temp[0])/2);
else {
$temp2 = explode(",",$temp[0]);
$temp2 = count($temp2);
}
// Create our base image.
$img = imagecreatetruecolor(($temp2*$zoom),(count($temp)*$zoom));
// Define transparent color if it exists.
if ($transparent != "") {
$transparent = JSIhex2rgb(JSIhex($transparent));
$transparent = imagecolorallocate($img,$transparent[0],$transparent[1],$transparent[2]);
imagecolortransparent($img,$transparent);
}