Jump to content

[SOLVED] Interesting problem with merging images


aspacecodyssey

Recommended Posts

Hi -- first time poster here. Couldn't find an issue quite like this one by searching the forums, and I'm certainly R-ingTFM.

 

I'm using jQuery cycle http://malsup.com/jquery/cycle/ to power a "create your own backpack" application for a client's website. Essentially, the concept is as follows: each piece of a backpack is a separate .png image, all the same dimensions, where the actual "piece" is placed inside the transparent area in its proper location. These pieces are overlayed atop one another the create the effect of the user being able to pick and choose the color of each piece.

 

My issue is this: I want the user to be able to then save the created bag. This is how far I am: The URLs of the "current" images in the cycle are being passed to hidden form fields. When you hit the "Submit" button, those fields should be and are properly passed into the process of merging them. There's where I'm having an issue. There aren't a set amount of "pieces" for each different bag, so the amount of items in the array of images is also not finite. Essentially, I just want to take all of the images and lay them on top of one another to create one image. Here's the code for the page:

 

<?php
session_start();
if(!isset($_SESSION["user"])) {
header("location:index.php");
}

$page = 'Design Your Own Bag';
$bag = $_GET['bag'];
include 'header.php';
?>

		First, choose a bag style below. Then knock yourself out (colloquially speaking).<br />
		<br />
		<ul id="linenav">
			<li><a href="?bag=10586s"><img src="images/design/lines/10586s_t.png" width="145" height="145" alt="" /></a></li>
			<li><a href="?bag=10602"><img src="images/design/lines/10602_t.png" width="145" height="145" alt="" /></a></li>
			<li><a href="?bag=10702"><img src="images/design/lines/10702_t.png" width="145" height="145" alt="" /></a></li>
			<li><a href="?bag=10576mb"><img src="images/design/lines/10576mb_t.png" width="145" height="145" alt="" /></a></li>
			<li><a href="?bag=10120m"><img src="images/design/lines/10120m_t.png" width="145" height="145" alt="" /></a></li>
			<li><a href="?bag=10505" class="last"><img src="images/design/lines/10505_t.png" width="145" height="145" alt="" /></a></li>
		</ul>
		<div id="load"></div>
		<div id="design-wrap" class="hide">
			<div id="linecycle">
			<?php
			if (isset($bag)) {
			if ($bag=='10586s' || $bag=='10702' || $bag=='10602' || $bag=='10576mb' || $bag=='10120m' || $bag=='10505') {
				switch ($bag) {
					case '10505':
						$options = array('Front-Top Panel' => 'ft', 'Front-Bottom Panel' => 'fb', 'Top/Sides' => 'top', 'Trim' => 'trim', 'Handle' => 'handle');
					break;
					case '10602':
						$options = array('Body' => 'body', 'Trim' => 'trim', 'Front Panel' => 'fp', 'Pocket Panel' => 'pp', 'Handle' => 'handle');
					break;
					case '10702':
						$options = array('Body' => 'body', 'Trim' => 'trim', 'Panel' => 'p', 'Handle' => 'handle');
					break;
					case '10576mb':
						$options = array('Body' => 'body', 'Trim' => 'trim', 'Front Panel' => 'fp', 'Pocket Panel' => 'pp', 'Handle' => 'handle');
					break;
					case '10120m':
						$options = array('Flap' => 'flap', 'Body' => 'body', 'High Trim' => 'ht', 'Low Trim' => 'lt');
					break;
					case '10586s':
						$options = array('Body' => 'body', 'Panel' => 'p', 'Front Panel' => 'fp', 'High Trim' => 'ht', 'Low Trim' => 'lt');
					break;
					default:
						echo '<img class="hidden" src="images/load.gif" alt="" />';
					break;
				}
				unset($value);

				$count = count($options);
				$backpat = implode(array_slice($options, 0, 1));
				echo "\n";?>

				<div class="patternacc <?php echo 'n'.$count; ?>">
						<?php foreach($options as $call => $part) { echo "\n"; ?>
					<a href="#"><?php echo $call; ?></a>
					<div>
						<ul class="patternnav" id="pn-<?php echo $bag.'-'.$part; ?>">
							<?php include 'patternnav.php'; ?>

						</ul>
					</div>
						<?php } echo "\n"; ?>
				</div>

				<div class="lineimg">
					<img class="topimg" src="images/design/lines/<?php echo $bag; ?>.png" width="455" height="455" alt="" />
						<?php foreach($options as $call => $part) { echo "\n"; ?>
					<div id="pc-<?php echo $bag.'-'.$part; ?>">
						<?php
						if ($part == $backpat) {
							$bagpath = '';
							$partpath = '';
							$ext = '.gif';
						} else {
							$bagpath = $bag.'/';
							$partpath = $part.'/';
							$ext = '.png';
						}
						include 'patterncycle.php';
						?>

					</div>
						<?php } ?>

				</div>
				<div class="clear"></div>
				<div id="savebag">
					To save your bag, click the “Save Bag” button below. Then show it to all your friends!<br />
					<br />
					<form method="post" action="testpost.php">
						<div class="hidden">
						<?php $i = 1; foreach($options as $call => $part) { ?>
<textarea id="output<?php echo $bag.$part; ?>" rows="" cols="" name="<?php echo 'part'.$i; ?>"></textarea>
						<?php $i = $i + 1; } ?>

						</div>
						<p><input type="submit" name="submit" id="savebag-btn" value="Save Bag" /></p>
					</form>
				</div>
			<?php } else {
				echo '<META HTTP-EQUIV="Refresh" Content="0; URL=partner-design.php">'; exit;
			}
			}
			?>

			</div>
		</div>
<?php include 'footer.php'; ?>

 

And here is the process code:

 

<?php
if (isset($_POST['submit']))
{
$postcount = count($_POST);
$postcount = $postcount - 1;

$partarr = array();
for ($i = 1; $i <= $postcount; $i++)
{
	$part = 'part'.$i;
	$part = $_POST[$part];
	$partarr[$i] = $part;
}

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

$imgBuf = array ();
$iOut = imagecreatetruecolor("455","455");
foreach ($partarr as $link)
{
	switch(substr($link,strrpos ($link,".")+1))
	{
		case 'png': $iTmp = imagecreatefrompng($link); break;
		case 'gif': $iTmp = imagecreatefromgif($link); break;
	array_push ($imgBuf,$iTmp);
	}
}

for ($j = 1; $j <= $postcount; $j++)
{
	imagecopy ($iOut,$imgBuf[$j],0,0,0,0,imagesx($imgBuf[$j]),imagesy($imgBuf[$j]));
	imagedestroy ($imgBuf[$j]);
}
imagepng($iOut);
}
?>

 

 

Link to comment
Share on other sites

I'm not sure what the problem is from preventing your method from working, but instead of using gd to combine images, I would just do it client side. Here is what I would do:

 

<?php
// $url_array is an array holding the url's for the images to combine

foreach ( $url_array as $url ) {
       echo '<div style="background-image: url(\'' . $url . '\'); width: 100px; height: 100px;">';
}
foreach ( $url_array as $url  ) {
       echo '</div>';
}
?>

Link to comment
Share on other sites

Working Code Example:

 

<?php
$url_array[] = "http://us.i1.yimg.com/us.yimg.com/i/us/av/logo.gif";
$url_array[] = "http://www.google.com/intl/en_ALL/images/logo.gif";
$url_array[] = "http://l.yimg.com/a/i/ww/beta/y3.gif";


foreach ( $url_array as $url  ) {
       echo '<div style="background-image: url(\'' . $url . '\'); width: 1000px; height: 1000px;">';
}
foreach ( $url_array as $url  ) {
       echo '</div>';
}
?>

Link to comment
Share on other sites

Here: http://www.topzipco.com/

 

I've set up a test user/pass:

 

User: test

Pass: passwd123

 

From there, click on "Design Your Own Bag", choose a bag, and test it out. Inside the page itself, I'm already doing what that solution would accomplish -- namely, overlaying the images to create the illusion of one single image. What I need to do now is to actually merge them into one image for real, so that the user can save that image. I'm just getting a black, blank image right now. I've changed it slightly in testing, so here's where I'm at:

 

<?php
if (isset($_POST['submit']))
{
$postcount = count($_POST); // COUNTS THE AMOUNT OF POST VARIABLES
$postcount = $postcount - 2; // DECREASES BY TWO FOR NEXT STEP

$partover = $_POST['partover']; // PULLS IN ONE EXTRA IMAGE (THE TOP LINE DRAWING OF THE BACKPACK)

$partarr = array();
for ($i = 1; $i <= $postcount; $i++)
{
	$part = 'part'.$i;
	$part = $_POST[$part];
	$partarr[$i] = $part;
}
	$partarr[$i] = $partover; // NOW WE HAVE THE URL'S OF THE IMAGES IN AN ARRAY

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

$imgBuf = array ();
$iOut = imagecreatetruecolor("455","455");
foreach ($partarr as $link)
{
	switch(substr($link,strrpos ($link,".")+1))
	{
		case 'png': $iTmp = imagecreatefrompng($link); break;
		case 'gif': $iTmp = imagecreatefromgif($link); break;
	array_push ($imgBuf,$iTmp);
	}
}

for ($j = 1; $j <= $postcount; $j++)
{
	imagecopy ($iOut,$imgBuf[$j],0,0,0,0,imagesx($imgBuf[$j]),imagesy($imgBuf[$j]));
	imagedestroy ($imgBuf[$j]);
}
imagepng($iOut);
}
?>

Link to comment
Share on other sites

I feel like this might be closer -- still not working though.

 

<?php
if (isset($_POST['submit']))
{
$postcount = count($_POST); // COUNTS THE AMOUNT OF POST VARIABLES
$postcount = $postcount - 2; // DECREASES BY TWO FOR NEXT STEP

$partover = $_POST['partover']; // PULLS IN ONE EXTRA IMAGE (THE TOP LINE DRAWING OF THE BACKPACK)

$partarr = array();
for ($i = 1; $i <= $postcount; $i++)
{
	$part = 'part'.$i;
	$part = $_POST[$part];
	$partarr[$i] = $part;
}
	$partarr[$i] = $partover; // NOW WE HAVE THE URL'S OF THE IMAGES IN AN ARRAY

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

$iOut = imagecreatetruecolor("455","455");
foreach ($partarr as $link)
{
	switch(substr($link,strrpos ($link,".")+1))
	{
		case 'png': $iTmp = imagecreatefrompng($link); break;
		case 'gif': $iTmp = imagecreatefromgif($link); break;
	}
	imagecopy($iOut,$iTmp,0,0,0,0,455,455);
	imagedestroy ($iTmp);
}

imagepng($iOut);
}
?>

Link to comment
Share on other sites

I didn't read through your code, but I once wrote a simple function to merge two or more PNG images. Have a look:

 

<?php
//function merge_png() takes two or more URLs or paths to PNG files as arguments, and merges the PNGs
function merge_png() {
//check and store arguments
if (func_num_args() < 2) {
	trigger_error('Wrong parameter count for merge_png()', E_USER_ERROR);
	return false;
}
$args = func_get_args();
//set image width and height
$w = 80;
$h = 100;
//create blank, fully transparent canvas
$im = imagecreatetruecolor($w, $h);
imagesavealpha($im, true);
$trans_color = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $trans_color);
//merge PNGs
foreach($args as $url) {
	$dest_im = imagecreatefrompng(str_replace(' ', '%20', $url));
	imagecopy($im, $dest_im, 0, 0, 0, 0, $w, $h);
}
//output final image
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
return true;
}
//usage
//image credits goes to the creator
merge_png(
'http://www.anitaria.com/images/avatars/equips/Mid Tone.png',
'http://www.anitaria.com/images/avatars/equips/Glasses.png'
);
?>

 

Would be easy to make it take an array instead of several arguments.

Link to comment
Share on other sites

I tried it, first testing without trying to implement the array on top of it, i.e.:

 

<?php
//function merge_png() takes two or more URLs or paths to PNG files as arguments, and merges the PNGs
function merge_png() {
   //check and store arguments
   if (func_num_args() < 2) {
	trigger_error('Wrong parameter count for merge_png()', E_USER_ERROR);
	return false;
   }
   $args = func_get_args();
   //set image width and height
   $w = 455;
   $h = 455;
   //create blank, fully transparent canvas
   $im = imagecreatetruecolor($w, $h);
   imagesavealpha($im, true);
   $trans_color = imagecolorallocatealpha($im, 0, 0, 0, 127);
   imagefill($im, 0, 0, $trans_color);
   //merge PNGs
foreach($args as $url) {
	$dest_im = imagecreatefrompng(str_replace(' ', '%20', $url));
	imagecopy($im, $dest_im, 0, 0, 0, 0, $w, $h);
}
//output final image
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
return true;
}
//usage
//image credits goes to the creator
merge_png(
'http://www.topzipco.com/images/design/patterns/10586s/fp/pattern00-11.png',
'http://www.topzipco.com/images/design/patterns/10586s/ht/pattern00-115.png',
'http://www.topzipco.com/images/design/patterns/10586s/lt/pattern00-1795.png',
'http://www.topzipco.com/images/design/patterns/10586s/p/pattern00-469.png',
'http://www.topzipco.com/images/design/lines/10586s.png'
);
?>

 

I'm so lost here. This seems like it should work.

Link to comment
Share on other sites

Huh -- yeah, it does work actually. It's the host I'm using -- I tested it on a different server, and it worked. Damn. Wonder if the original code will work there, too.

 

Okay, so follow-up. It does seem like it should be a simple task to use an array instead of a list of images, but how would I do that? I'm really overthinking it.

Link to comment
Share on other sites

If allow_url_fopen is Off in the server settings, imagecreatefrompng() won't allow URLs. Could be your problem. Here's the modified function that takes an array:

 

<?php
//function merge_png() takes an array of URLs or paths to PNG files, and merges the PNGs
function merge_png($pngs) {
if (!is_array($pngs)) {
	trigger_error('Argument passed to merge_png() must be an array', E_USER_ERROR);
	return false;
}
//set image width and height
$w = 455;
$h = 455;
//create blank, fully transparent canvas
$im = imagecreatetruecolor($w, $h);
imagesavealpha($im, true);
$trans_color = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $trans_color);
//merge PNGs
foreach($pngs as $url) {
	$dest_im = imagecreatefrompng(str_replace(' ', '%20', $url));
	imagecopy($im, $dest_im, 0, 0, 0, 0, $w, $h);
}
//output final image
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
return true;
}
?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.