I've tried everything i know for the last 3 days, but can't figure it out, so i hope someone could help me on this one.
I want to get multiple records from a database. In the database is for every single record the link to a thumbnail, x-coordinate and an y-coordinate specified.
The image (a map of a building) must be created starting with an empty map of a building (plattegrond.jpg). Then, multiple thumbnails must be added which contains numbers (see image below) on the coordinated specified in the database. When all the thumbnails are added, it must be saved as something like Project1.jpg or whatever.
$emptymap = "plattegrond.jpg"; // this is a map of a building
$newmap = "Project1.jpg"; // this must be the new map with the images
header('Content-type: image/jpeg');
$im = #imagecreatefromjpeg('maps/'.$emptymap) or die("Cannot Initialize new GD image stream");
$im2 = #imagecreatefromjpeg('thumbnails/'.$linkToThumbnail);
imagecopy($im, $im2, $xcoord, $ycoord, 0, 0, imagesx($im2), imagesy($im2));
imagejpeg($im, 'maps/'.$newmap, 100);
imagedestroy($im);
imagedestroy($im2);
The thumbnails already exists and are all small images saved as 1.jpg, 2.jpg, 3.jpg, etc.
So, in summary:
How do i put multiple images with coordinates, which are specified in a database , on that single image?
All suggestions are welcome!
This is a preview of a map with a single thumbnail:
With the help of Darren his link, i managed to figure it out, finaly! I can sleep again :)
<?php
$coords = array
(
array("2","100","200"),
array("3","200","100"),
array("4","250","30"),
array("5","134","90")
);
$arrlength = count($coords);
$map = "Project2.jpg";
for($x = 0; $x < $arrlength; $x++) {
addThumb($map, $coords[$x][0], $coords[$x][1], $coords[$x][2]);
}
function addThumb($map, $thumb, $xcoord, $ycoord)
{
$thumb .= ".jpg";
$imMap = imagecreatefromjpeg('maps/'.$map);
$imThumb = imagecreatefromjpeg('thumbnails/'.$thumb);
imagecopy($imMap, $imThumb, $xcoord, $ycoord, 0, 0, imagesx($imThumb), imagesy($imThumb));
imagejpeg($imMap, 'maps/'.$map, 100);
imagedestroy($imMap);
imagedestroy($imThumb);
}
?>
Related
I have removed my original question as I have managed to partially get this working, what I have is 7 images,
https://dl.dropboxusercontent.com/u/58586640/layer1.png
https://dl.dropboxusercontent.com/u/58586640/layer2.png
https://dl.dropboxusercontent.com/u/58586640/layer3.png
https://dl.dropboxusercontent.com/u/58586640/layer4.png
https://dl.dropboxusercontent.com/u/58586640/layer5.png
https://dl.dropboxusercontent.com/u/58586640/layer6.png
https://dl.dropboxusercontent.com/u/58586640/layer7.png
Each of these images when placed over the top of each other should create one image that slots together perfectly.
The current result i have is,
https://dl.dropboxusercontent.com/u/58586640/Screen%20Shot%202013-12-11%20at%2018.31.57.png
As you can see it works nearly perfectly but 2 of the layers are either not being copied or are not getting the alphas saved correctly. I am not sure what I am doing wrong, as all the other layers seem to working fine, the images that are coming in as black are,
https://dl.dropboxusercontent.com/u/58586640/layer3.png https://dl.dropboxusercontent.com/u/58586640/layer4.png
Here is my current code,
<?php
$images = array('img/layer1.png', 'img/layer2.png', 'img/layer3.png', 'img/layer4.png', 'img/layer5.png', 'img/layer6.png', 'img/layer7.png');
// foreach($images as $i) {
// var_dump(file_exists($i));
// }
// Allocate new image
$img = imagecreatetruecolor(704, 469);
// Make alpha channels work
imagealphablending($img, true);
imagesavealpha($img, true);
foreach($images as $fn) {
// Load image
$cur = imagecreatefrompng($fn);
imagealphablending($cur, true);
imagesavealpha($cur, true);
// Copy over image
imagecopy($img, $cur, 0,0,0,0, 704, 469);
// Free memory
imagedestroy($cur);
}
header('Content-Type: image/png');
imagepng($img);
As you can see I have checked to make sure that the files exist, and they do so it must be GD problem, anyone have ideas?
Funny I did exactly this yesterday here's how I did it using a static background layer and a QR code which is generated prior to the combine.
$template = imagecreatefrompng("./images/asset_barcode_template.png");
//QR created fine assemble final image
$qrimage = imagecreatefrompng($this->qrfilename);
//final image assembled just fine
imagecopy($template, $qrimage, 230, 6, 0, 0, 106, 106);
imagepng($template,$filename,0,PNG_NO_FILTER);
First question, so sorry if I do something wrong!
My issue is, I have a product catalog, which displays up to 18 thumbnails, each approx 6kb, in a product catalog. Each of the thumbnails calls a script get_db_image which searches for and returns the image relating to the product. Simple, so far. The issue only arises when approx 3 or 4 requests are made at the same time for a product catalog page, each user is expecting 18 thumbnails and details to be returned, but when they all do it at the same time I get out of memory errors and sometimes the server crashes. I've stripped down the code that retrieves and displays the image, and the hosting people have raised the memory limit to 256M, but it's all to no avail. As far as I can tell I'm destroying the images I've created and the virtual memory goes back to zero split seconds after the requests are made, but at the peak all the memory is being utilised, hence the crashes, so the only thing I can think off doing is getting, displaying and destroying each image before I start the next one, but I don't know how to go about that, but maybe there is a better solution? Please help, pulling my hair out and I don't have a lot to waste!
// executes the query searching for the image
$res = execPDORetRes($query, $vars);
// if there is no image, load a default
if(sizeof($res) == 0)
{
$query_parts = explode(" ", $query);
$query = "select * from ".$query_parts[3]." where id = :id";
$vars = array(':id-int' => 1);
$res = execPDORetRes($query, $vars);
}
$data = $res[0];
// create the image from the DB
$img = imagecreatefromstring($data[$name]);
$type = "image/pjpeg";
Header( "Content-type: image/pjpeg");
$width = imagesx($img);
$height = imagesy($img);
// if the image is too big
if($size_w != $width || $size_h != $height)
{
// set widths and heights
if ($width <= $size_w)
{
$new_w = $width;
$new_h = $height;
}
else
{
$new_w = $size_w;
$new_h = $size_h;
}
// create a new image of the specified width and height
$new_img = imagecreatetruecolor($new_w,$new_h);
// resize the original
imagecopyresized($new_img,$img,0,0,0,0,$new_w,$new_h,$width,$height);
// determine image type and send it to the client
imagejpeg($new_img,"","80");
// clear the image from memory
imagedestroy($new_img);
imagedestroy($img);
unset($width, $height, $new_h, $new_w, $new_img, $img);
}
else
{
// if the image is smaller than or the right size
// determine image type and send it to the client
imagejpeg($img,"","80");
// clear the image from memory
imagedestroy($img);
unset($width, $height, $img);
}
ob_flush();
Thanks for the help.
I think you should generate your thumbnails in advance if you want to this it this way.
This means you should have your normal product images under e.g. "public/images/products/main" and then your thumbs under "public/images/products/thumbs" and then store in the database your paths to the product images and your thumbs.
This approach is better then creating them on the fly.
Otherwise you could just scale them down with css, if bandwidth is not a problem, but I guess it is.
You can even keep your thumbs script and check in the db if a thumbnail exists, if it does not, call your script: generate thumb, save thumb, update db. The next time a user comes and you need to display this thumbnail, it will already be there.
256 megabytes should be plenty. Nothing in your code looks bad and you're even using unset. I recommend debugging with Xdebug and WinCacheGrind, they can produce in-depth logs...
i want to make a picture upload in frame and save both image and frame as a single image ,main thing is whatever the size of image in frame,it should be appear exactly same in a final resulting image after merging.
Here is part of my code:
$imgframe = $_GET['imgframe'];
$imgphoto = $_GET['imgphoto'];
$imgwidth = $_GET['imgwidth'];
$imgheight = $_GET['imgheight'];
$imgleft = substr($_GET['imgleft'],0,-2);
$imgtop = substr($_GET['imgtop'],0, -2);
$src = imagecreatefromjpeg($imgphoto);//'image.jpg'
$dest = imagecreatefrompng($imgframe);//clip_image002.png
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopyresampled(
$dest, $src, $imgleft, $imgtop, $imgleft, $imgtop,
$imgwidth, $imgheight, $imgwidth, $imgheight
);
As per your comment below the question, you are using the wrong function.
The PHP manual page for imagecopymerge states that it copies a part of an image onto another. It states that you can specify the origin coordinates, width and height of the region to copy from the source, and the coordinates in the destination in which to place that region.
In other words, it takes a rectangular area of a given size from the source image and puts it on top of the destination, at the given location. It does NOT ask for the size of the region into which you are copying it, only the location. Therefore, it does not resize the copied region, but copies it pixel-for-pixel.
The function you actually need is imagecopyresampled, which allows you to specify the size of the destination region, and will smoothly scale the source region to fit.
EDIT
You are still having a problem because you are using the same coordinates and the same dimensions in the source and the destination parameters. Same dimensions == no resizing.
$imgframe = $_GET['imgframe'];
$imgphoto = $_GET['imgphoto'];
// I am assuming these specify the area of the imgphoto which
// should be placed in the frame?
$imgwidth = $_GET['imgwidth'];
$imgheight = $_GET['imgheight'];
$imgleft = substr($_GET['imgleft'],0,-2);
$imgtop = substr($_GET['imgtop'],0, -2);
// now you also need to get the size of the frame so that
// you can resize the photo correctly:
$frameSize = getimagesize($imgframe);
$src = imagecreatefromjpeg($imgphoto);//'image.jpg'
$dest = imagecreatefrompng($imgframe);//clip_image002.png
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopyresampled(
$dest, $src,
0, 0, // these two specify where in the DESTINATION you want to place the source. You might want these to be offset by the width of the frame
$imgleft, $imgtop, // the origin of area of the source you want to copy
$frameSize[0], $frameSize[1], // These specify the size of the area that you want to copy IN TO (i.e., the size in the destination), again you might want to reduce these to take into account the width of the frame
$imgwidth, $imgheight // the size of the area to copy FROM
);
I am trying to replicate the functionality that Dribbble.com does with detecting the predominant colors in an Image. In the image below you can see a screenshot from Dribbble.com that shows the 8 predominant colors in the image to the left. Here is the actual page in the image http://dribbble.com/shots/528033-Fresh-Easy?list=following
I need to be able to do this in PHP, once I get the colors I need I will save them to a database so the processing does not need to be run on every page load.
After some research on how to get these colors out of an Image, some people said you simply examine an image pixel by pixel and then save the colors that occur the most. Other say there is more to it and that getting the colors that exist the most frequent won't give the desired affect. They say you need to Quantize the image/colors (I am lost at this point).
In the image below the Dribble shot below is a Javascript library that does the same thing, that page can be viewed here http://lokeshdhakar.com/projects/color-thief/
Viewing the source of that page I can see there is a Javascript file named quantize.js and the results are really good. So I am hoping to be able to do what that Javascript library does but with PHP and GD/ImageMagick
I had found this function that will return the colors and count in an Image with PHP but the results are different from the Javascript version above and the Dribble results
/**
* Returns the colors of the image in an array, ordered in descending order, where the keys are the colors, and the values are the count of the color.
*
* #return array
*/
function Get_Color()
{
if (isset($this->image))
{
$PREVIEW_WIDTH = 150; //WE HAVE TO RESIZE THE IMAGE, BECAUSE WE ONLY NEED THE MOST SIGNIFICANT COLORS.
$PREVIEW_HEIGHT = 150;
$size = GetImageSize($this->image);
$scale=1;
if ($size[0]>0)
$scale = min($PREVIEW_WIDTH/$size[0], $PREVIEW_HEIGHT/$size[1]);
if ($scale < 1)
{
$width = floor($scale*$size[0]);
$height = floor($scale*$size[1]);
}
else
{
$width = $size[0];
$height = $size[1];
}
$image_resized = imagecreatetruecolor($width, $height);
if ($size[2]==1)
$image_orig=imagecreatefromgif($this->image);
if ($size[2]==2)
$image_orig=imagecreatefromjpeg($this->image);
if ($size[2]==3)
$image_orig=imagecreatefrompng($this->image);
imagecopyresampled($image_resized, $image_orig, 0, 0, 0, 0, $width, $height, $size[0], $size[1]); //WE NEED NEAREST NEIGHBOR RESIZING, BECAUSE IT DOESN'T ALTER THE COLORS
$im = $image_resized;
$imgWidth = imagesx($im);
$imgHeight = imagesy($im);
for ($y=0; $y < $imgHeight; $y++)
{
for ($x=0; $x < $imgWidth; $x++)
{
$index = imagecolorat($im,$x,$y);
$Colors = imagecolorsforindex($im,$index);
$Colors['red']=intval((($Colors['red'])+15)/32)*32; //ROUND THE COLORS, TO REDUCE THE NUMBER OF COLORS, SO THE WON'T BE ANY NEARLY DUPLICATE COLORS!
$Colors['green']=intval((($Colors['green'])+15)/32)*32;
$Colors['blue']=intval((($Colors['blue'])+15)/32)*32;
if ($Colors['red']>=256)
$Colors['red']=240;
if ($Colors['green']>=256)
$Colors['green']=240;
if ($Colors['blue']>=256)
$Colors['blue']=240;
$hexarray[]=substr("0".dechex($Colors['red']),-2).substr("0".dechex($Colors['green']),-2).substr("0".dechex($Colors['blue']),-2);
}
}
$hexarray=array_count_values($hexarray);
natsort($hexarray);
$hexarray=array_reverse($hexarray,true);
return $hexarray;
}
else die("You must enter a filename! (\$image parameter)");
}
So I am asking if anyone knows how I can do such a task with PHP? Possibly something exist already that you know of or any tips to put me a step closer to doing this would be appreciated
Here's exactly what you're looking for in PHP: https://github.com/thephpleague/color-extractor
Example :
use League\ColorExtractor\Palette;
$palette = Palette::fromFilename('some/image.png');
$topEightColors = $palette->getMostUsedColors(8);
This is my simple method to get the main color of an image
$image=imagecreatefromjpeg('image.jpg');
$thumb=imagecreatetruecolor(1,1);
imagecopyresampled($thumb,$image,0,0,0,0,1,1,imagesx($image),imagesy($image));
$mainColor=strtoupper(dechex(imagecolorat($thumb,0,0)));
echo $mainColor;
You need to scale down the picture and you will get the main colors of the picture. If you need 4 colors in the pallet, scale it down to about 8x8, 6 colors to about 12x8 and so on...
imagecopyresized for scaled down image then check every pixels and store them in array imagecolorat($image,px,py)
Try this out
<?php
// EXAMPLE PICTURE
$url='https://www.nordoff-robbins.org.uk/sites/default/files/google.jpg';
//var_dump(getColorPallet($url));
echoColors(getColorPallet($url));
function echoColors($pallet){ // OUTPUT COLORSBAR
foreach ($pallet as $key=>$val)
echo '<div style="display:inline-block;width:50px;height:20px;background:#'.$val.'"> </div>';
}
function getColorPallet($imageURL, $palletSize=[16,8]){ // GET PALLET FROM IMAGE PLAY WITH INPUT PALLET SIZE
// SIMPLE CHECK INPUT VALUES
if(!$imageURL) return false;
// IN THIS EXEMPLE WE CREATE PALLET FROM JPG IMAGE
$img = imagecreatefromjpeg($imageURL);
// SCALE DOWN IMAGE
$imgSizes=getimagesize($imageURL);
$resizedImg=imagecreatetruecolor($palletSize[0],$palletSize[1]);
imagecopyresized($resizedImg, $img , 0, 0 , 0, 0, $palletSize[0], $palletSize[1], $imgSizes[0], $imgSizes[1]);
imagedestroy($img);
//CHECK IMAGE
/*header("Content-type: image/png");
imagepng($resizedImg);
die();*/
//GET COLORS IN ARRAY
$colors=[];
for($i=0;$i<$palletSize[1];$i++)
for($j=0;$j<$palletSize[0];$j++)
$colors[]=dechex(imagecolorat($resizedImg,$j,$i));
imagedestroy($resizedImg);
//REMOVE DUPLICATES
$colors= array_unique($colors);
return $colors;
}
?>
Works perfect for me.
The page you linked to has a link to the source code on GitHub so if you want to know exactly how they are doing you could replicate their source in PHP.
The big difference between how they are doing it and how you are doing it, is that they are using clustering to find the color. Instead of rounding the color when they store it, they are storing all of the raw colors in an array. Then they loop through this array until they find a cluster that has the highest ratio of points in the cluster to number of colors in the cluster. The center point of this is the most common color. The palette is then defined by the next highest sets of clusters, with some logic to prevent near complete overlap of the clusters.
Try this: http://www.coolphptools.com/color_extract
Works with JPEG and PNG.
And best!: no hustle with composer, just require_once
require_once 'colorextract/colors.inc.php';
$ex=new GetMostCommonColors();
$num_results=20;
$reduce_brightness=1;
$reduce_gradients=1;
$delta=24;
$colors=$ex->Get_Color( 'image.png', $num_results, $reduce_brightness, $reduce_gradients, $delta);
print_r($colors);
give you something like this:
Array (
[3060a8] => 0.55827380952381
[f0a848] => 0.19791666666667
[000000] => 0.069642857142857
[483018] => 0.02047619047619
[786018] => 0.01827380952381
[183060] => 0.01797619047619
[4878a8] => 0.016011904761905
[181800] => 0.015119047619048
[a87830] => 0.014345238095238
[a8c0d8] => 0.011904761904762
[6090c0] => 0.01172619047619
[d89030] => 0.011011904761905
[90a8d8] => 0.0071428571428571
[ffffff] => 0.0070238095238095
[604830] => 0.006547619047619
[f0f0f0] => 0.0063095238095238
[d8d8f0] => 0.005297619047619
[c0d8d8] => 0.0044047619047619
[f0f0ff] => 0.00041666666666667
[181830] => 0.00011904761904762 )
I tried it with different images and it seems reliable.
The idea of getting the predominant colors of the image is a bit tricky, because for example the most frequent pixel color could be so widely scattered in the image that it is not perceived as a predominant color at all.
I think an algorithm like Color coherence vector will be good enough to overcome this issue, because it clusters the colors into coherent and incoherent (which is quite intuitive), and then you can use them to discard those false positive predominant colors.
I see it is an easy algorithm to implement, this tutorial Image Retrieval: Color Coherence Vector describes describes its steps with examples of how it works and there is even a matlab implementation mentioned at the end of it.
I have a Unix bash shell script with ImageMagick called dominantcolor that may do what you want. See my scripts web site at http://www.fmwconcepts.com/imagemagick/index.php. You an run it from PHP exec(). See my pointers for use on my home page.
Input:
dominantcolor -n 6 -p all -s save plate.png
count,hexcolor
586,#5ECADC
520,#AFA85D
469,#3C3126
462,#B9C8BB
258,#488A70
205,#B06928
The -n 6 is the desired number of colors in the color quantization. The -p all means print all counts and colors for the resulting 6 colors. The -s save indictates to save a swatch image.
Colors below are shown with the dominant color on the left and decreasing count colors towards the right according to the list above.
I am currently working on an application that needs to analyse a number of images and figure out what color they're closest to.
Therefore I found a code snippet that does exactly that:
function analyzeImageColors($im, $xCount =3, $yCount =3)
{
//get dimensions for image
$imWidth =imagesx($im);
$imHeight =imagesy($im);
//find out the dimensions of the blocks we're going to make
$blockWidth =round($imWidth/$xCount);
$blockHeight =round($imHeight/$yCount);
//now get the image colors...
for($x =0; $x<$xCount; $x++) { //cycle through the x-axis
for ($y =0; $y<$yCount; $y++) { //cycle through the y-axis
//this is the start x and y points to make the block from
$blockStartX =($x*$blockWidth);
$blockStartY =($y*$blockHeight);
//create the image we'll use for the block
$block =imagecreatetruecolor(1, 1);
//We'll put the section of the image we want to get a color for into the block
imagecopyresampled($block, $im, 0, 0, $blockStartX, $blockStartY, 1, 1, $blockWidth, $blockHeight );
//the palette is where I'll get my color from for this block
imagetruecolortopalette($block, true, 1);
//I create a variable called eyeDropper to get the color information
$eyeDropper =imagecolorat($block, 0, 0);
$palette =imagecolorsforindex($block, $eyeDropper);
$colorArray[$x][$y]['r'] =$palette['red'];
$colorArray[$x][$y]['g'] =$palette['green'];
$colorArray[$x][$y]['b'] =$palette['blue'];
//get the rgb value too
$hex =sprintf("%02X%02X%02X", $colorArray[$x][$y]['r'], $colorArray[$x][$y]['g'], $colorArray[$x][$y]['b']);
$colorArray[$x][$y]['rgbHex'] =$hex;
//destroy the block
imagedestroy($block);
}
}
//destroy the source image
imagedestroy($im);
return $colorArray;
}
Problem is that whenever I provide an image with transparency, GDLib consinders the transparency to be black, thus producing a wrong (much darker) output than is really the case.
For example this icon where the white area around the arrow is actually transparent:
example http://img651.imageshack.us/img651/995/screenshot20100122at113.png
Can anyone tell me how to work around this?
You need imageColorTransparent(). http://www.php.net/imagecolortransparent
Transparency is a property of the image, not of a color. So use something like $transparent = imagecolortransparent($im) to see if there is any transparency on your image, then just ignore that color in your $colorArray or have some other way to identify the transparent color in the return from your function. That all depends on how you're using the returned data.
--M