2014年5月29日 星期四

拼圖生產器(三)

還是想不到解決黑線的方法;只好用最耗時的方式處理。是這樣的:

1) 掃瞄已裁出來的圖片
2) 當像素是綠色,亦即是要保留的像素時,檢查其上下左右的像素是否為黑
3) 若是黑色的話,則把它收成青色
4) 直至掃瞄完成
5) 之後重新掃瞄一次
6) 把綠色及青色像素,按照片的像素保留
7) 其餘的以透明色代替

以下是拼圖生產器的 PHP 代碼:
<?php
//----------------------------------------------------------------------------------------
//  Jigsaw Puzzle Creator: Create Puzzle Mask
//----------------------------------------------------------------------------------------
//  Written by Pacess HO
//  Copyright 2014 Hotaru Production.  All rights reserved.
//----------------------------------------------------------------------------------------

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

//----------------------------------------------------------------------------------------
$directory = "./puzzles/";
$filename = "Sita.jpg";
$width = 800;
$height = 600;

$columns = 4;
$rows = 4;

//----------------------------------------------------------------------------------------
if (isset($_GET["image"]))  {
 $filename = $_GET["image"];
 $filePath = $directory.$filename;

 //  Get image dimension
 list($width, $height) = getimagesize($filePath);
}

if (isset($_GET["width"]))  {$width = $_GET["width"];}
if (isset($_GET["height"]))  {$height = $_GET["height"];}

if (isset($_GET["column"]))  {$columns = $_GET["column"];}
if (isset($_GET["row"]))  {$rows = $_GET["row"];}

//----------------------------------------------------------------------------------------
$pieceWidth = $width/$columns;
$pieceHeight = $height/$rows;

$maskImage = imagecreatetruecolor($width, $height);
$oddColor = imagecolorallocate($maskImage, 255, 250, 200);
$evenColor = imagecolorallocate($maskImage, 255, 200, 200);
$borderColor = imagecolorallocate($maskImage, 0, 0, 100);

//----------------------------------------------------------------------------------------
//  Draw grid blocks
$angle = rand();
$sinWidth = $pieceWidth*0.02;
$sinHeight = $pieceHeight*0.02;

$ratio = 160;
$angleStep = 180/$pieceWidth;
for ($y=1; $y<$rows; $y++)  {
 for ($x=0; $x<$width; $x++)  {

  $radians = ($angle%360)*0.0174532925;

  $drawX = $x;
  $drawY = ($y*$pieceHeight)+(sin($radians)*$sinHeight);
  imageline($maskImage, $drawX, $drawY, $drawX, $drawY, $borderColor);

  $angle += $angleStep;
 }
}

$angleStep = 180/$pieceHeight;
for ($x=1; $x<$columns; $x++)  {
 for ($y=0; $y<$height; $y++)  {

  $radians = ($angle%360)*0.0174532925;

  $drawX = ($x*$pieceWidth)+(sin($radians)*$sinWidth);
  $drawY = $y;
  imageline($maskImage, $drawX, $drawY, $drawX, $drawY, $borderColor);

  $angle += $angleStep;
 }
}

//  Fill blocks
for ($y=0; $y<$rows; $y++)  {
 for ($x=0; $x<$columns; $x++)  {

  $drawX = ($x*$pieceWidth)+($pieceWidth*0.5);
  $drawY = ($y*$pieceHeight)+($pieceHeight*0.5);

  $shouldDraw = ($x+$y)&1;
  if ($shouldDraw == 0)  {
   imagefill($maskImage, $drawX, $drawY, $evenColor);
  }  else  {
   imagefill($maskImage, $drawX, $drawY, $oddColor);
  }
 }
}

//----------------------------------------------------------------------------------------
//  Draw male/female
$diameterX = $pieceWidth*0.3;
$diameterY = $pieceHeight*0.3;
$offsetX = ($diameterX*0.3);
$offsetY = ($diameterY*0.3);
for ($y=0; $y<$rows; $y++)  {
 for ($x=0; $x<$columns; $x++)  {

  $shouldDraw = ($x+$y)&1;

  if ($x != 0)  {
   $value = $pieceHeight/20;
   $randomValue = rand(-$value, $value);
   $drawY = ($y*$pieceHeight)+($pieceHeight*0.5)+$randomValue;
   if ($shouldDraw == 0)  {
    $drawX = ($x*$pieceWidth)-$offsetX;
   }  else  {
    $drawX = ($x*$pieceWidth)+$offsetX;
   }
   imagefilledellipse($maskImage, $drawX, $drawY, $diameterX, $diameterY, $evenColor);
  }

  if ($y != 0)  {
   $value = $pieceWidth/20;
   $randomValue = rand(-$value, $value);
   $drawX = ($x*$pieceWidth)+($pieceWidth*0.5)+$randomValue;
   if ($shouldDraw == 0)  {
    $drawY = ($y*$pieceHeight)+$offsetY;
   }  else  {
    $drawY = ($y*$pieceHeight)-$offsetY;
   }
   imagefilledellipse($maskImage, $drawX, $drawY, $diameterX, $diameterY, $oddColor);
  }
 }
}

//----------------------------------------------------------------------------------------
//  Save mask as PNG
$pathParts = pathinfo($filename);
$outputPath = $pathParts["filename"]."_mask.png";
$saveResult = imagepng($maskImage, $directory.$outputPath);

//----------------------------------------------------------------------------------------
//  Create puzzle pieces
mkdir($directory.$pathParts["filename"], 0777, true);
$photoImage = imagecreatefromjpeg($filePath);

$top = 0;
for ($y=0; $y<$rows; $y++)  {

 $left = 0;
 for ($x=0; $x<$columns; $x++)  {

  $cropX1 = $left-$diameterX;
  $cropX2 = $left+$diameterX+$pieceWidth;
  $cropY1 = $top-$diameterY;
  $cropY2 = $top+$diameterY+$pieceHeight;

  if ($cropX1 < 0)  {$cropX1 = 0;}
  if ($cropY1 < 0)  {$cropY1 = 0;}

  //  Copy image to a new buffer
  $cropWidth = $cropX2-$cropX1+1;
  $cropHeight = $cropY2-$cropY1+1;
  $cropImage = imagecreatetruecolor($cropWidth, $cropHeight);

  imagealphablending($cropImage, false);
  imagesavealpha($cropImage, true);
  $transparentColor = imagecolorallocatealpha($cropImage, 0, 0, 0, 127);

  imagecopy($cropImage, $maskImage, 0, 0, $cropX1, $cropY1, $cropWidth, $cropHeight);

  //  Fill piece to cropping color
  $drawX = ($cropWidth*0.5);
  $drawY = ($cropHeight*0.5);
  $cropColor = imagecolorallocate($cropImage, 255, 0, 255);
  imagefill($cropImage, $drawX, $drawY, $cropColor);

  //  Fill the black border
  $sourceY = $cropY1;
  $cropBorderColor = imagecolorallocate($cropImage, 0, 255, 255);
  for ($pieceY=0; $pieceY<$cropHeight; $pieceY++)  {

   $sourceX = $cropX1;
   for ($pieceX=0; $pieceX<$cropWidth; $pieceX++)  {

    $maskColor = imagecolorat($cropImage, $pieceX, $pieceY);
    if ($maskColor != 0xff00ff)  {continue;}

    if ($pieceX > 0)  {
     $maskColor = imagecolorat($cropImage, $pieceX-1, $pieceY);
     if ($maskColor == 0x000064)  {imagesetpixel($cropImage, $pieceX-1, $pieceY, $cropBorderColor);}
    }

    if ($pieceY < ($cropWidth-1))  {
     $maskColor = imagecolorat($cropImage, $pieceX+1, $pieceY);
     if ($maskColor == 0x000064)  {imagesetpixel($cropImage, $pieceX+1, $pieceY, $cropBorderColor);}
    }

    if ($pieceY > 0)  {
     $maskColor = imagecolorat($cropImage, $pieceX, $pieceY-1);
     if ($maskColor == 0x000064)  {imagesetpixel($cropImage, $pieceX, $pieceY-1, $cropBorderColor);}
    }

    if ($pieceY < ($cropHeight-1))  {
     $maskColor = imagecolorat($cropImage, $pieceX, $pieceY+1);
     if ($maskColor == 0x000064)  {imagesetpixel($cropImage, $pieceX, $pieceY+1, $cropBorderColor);}
    }
   }
  }

  //  Replace mask pixel by image pixel
  $sourceY = $cropY1;
  for ($pieceY=0; $pieceY<$cropHeight; $pieceY++)  {

   $sourceX = $cropX1;
   for ($pieceX=0; $pieceX<$cropWidth; $pieceX++)  {

    $maskColor = imagecolorat($cropImage, $pieceX, $pieceY);

    if ($maskColor == 0xff00ff || $maskColor == 0x00ffff)  {

     //  Body
     $color = imagecolorat($photoImage, $sourceX, $sourceY);
     imagesetpixel($cropImage, $pieceX, $pieceY, $color);
    }  else  {

     //  Transparent
     imagesetpixel($cropImage, $pieceX, $pieceY, $transparentColor);
    }

    $sourceX++;
   }
   $sourceY++;
  }
  imagepng($cropImage, $directory.$pathParts["filename"]."/".$pathParts["filename"]."_piece_".$x."_".$y.".png");
  imagedestroy($cropImage);

  $left += $pieceWidth;
 }
 $top += $pieceHeight;
}

imagedestroy($photoImage);
imagedestroy($maskImage);

//----------------------------------------------------------------------------------------
//  Upload error
$pieceCount = $rows*$columns;
$resultArray = array(
 "result"=>0,
 "saveResult"=>$saveResult,
 "outputPath"=>$outputPath,
 "pieceCount"=>$pieceCount);
echo(json_encode($resultArray));

?>