I created a PHP code to add color at specific pixel range for example x=0,y=0 to x=24, y=0. This creates a straight line on top left corner of the image towards y axis. Now beofre closing the image if I try to read the color from those position it returns me the color I added. But if i reopen the image and try to read the color from those pixels it is not giving me the exact color I added instead it give a color close to it. I am adding the piece of code which I used:
`$canvas = imagecreatefromjpeg('first_frame.jpg');
//create a random color
$rand = str_pad(dechex(rand(0x000000, 0xFFFFFF)), 6, 0, STR_PAD_LEFT);
$dec_color= hexdec($rand);
for ($i=0; $i < 24; $i++) {
imagerectangle($canvas,$i,0,0,0, $dec_color);
}
//read the image pixels add
for ($x=0; $x < 24 ; $x++) {
echo $new_color= imagecolorat($canvas, $x, 0);
echo '<br>';
}
$filename = 'test/'.time().'.jpg';
//store the image in dir
imagejpeg($canvas, $filename);
//destroy the opened image
imagedestroy($canvas);`
The above code gives me tha random generated color, adds it to the image and then reads those added colors. So this code gives me the expected added colors.
If i add the following code after the function imagedestroy($canvas), it gives me some other colors close to the one added.
`$dimg = imagecreatefromjpeg($filename);
for ($x=0; $x < 24 ; $x++) {
echo $new_color= imagecolorat($dimg, $x, 0);
echo '<br>';
}
`
I need to extract the exact color added to the image after the image is stored.
Added color and extracted colors are here
Thanks a lot for your help CBroe. So here is the complete code for getting the exact pixel color added in an image and it is unchanged after shared and retrieved via multiple social media platforms. This may help someone in future.
<?php
// load the image
$canvas = imagecreatefromjpeg('first_frame.jpg');
// create a random color
$rand = str_pad(dechex(rand(0x000000, 0xFFFFFF)), 6, 0, STR_PAD_LEFT);
$dec_color= hexdec($rand);
echo 'color created and added: '.$dec_color;
// add the new color to image
for ($i=0; $i < 24; $i++) {
imagesetpixel($canvas,$i,0,$dec_color);
}
// store the image and close the file opened
$filename = 'test/output.png';
imagepng($canvas, $filename);
imagedestroy($canvas);
// now read the same file stored and get the color ranges to be stored
$dimg = imagecreatefrompng($filename);
$extracted_color = array();
for ($x=0; $x < 24 ; $x++) {
$extracted_color[]= imagecolorat($dimg, $x, 0);
}
echo "<br>Retrieved colors:<pre>".print_r($extracted_color,1)."</pre>";
imagedestroy($dimg);
?>
I have multiple Images coming from an array (could be 3, could be 10) and I want to place them next to each other and if they don't fit anymore, place them in a new line.
I have written a foreach statement and I got it to work, so that they place into a new line if they don't fit in the current one and they also place next to each other.
But my problem is the spacing between the images, because as of now it's different for each image. Some have really wide space between them while others are overlapping.
Here's the function I wrote:
function createAwardsTable(pdflib $p, int $textStartLeft, array $arrInput) {
$awardImages = $arrInput['awards'];
$boxHeight = 50;
$x = $textStartLeft;
$y = 275;
foreach($awardImages as $awardImage) {
$image = $p->load_image("auto", $awardImage, "");
if ($image == 0) {
echo("Couldn't load $image: " . $p->get_errmsg());
exit(1);
}
$imagewidth = $p->info_image($image, "imagewidth", "");
if ($x > (565 - 20)) {
$y = 215;
$x = $textStartLeft;
}
$buf = "boxsize={" . $imagewidth . " " . $boxHeight . "} fitmethod=auto matchbox={name=awardimage}";
// $buf = "scale=1 matchbox={name=awardimage}";
$p->fit_image($image, $x, $y, $buf);
$awardWidth = $p->info_matchbox("awardimage", 1, "x2");
$x = ($x - 20) + $awardWidth;
}
}
And here's a picture of the result I get in my pdf:
I think your logic is fine so far.
$awardWidth = $p->info_matchbox("awardimage", 1, "x2");
$x = ($x - 20) + $awardWidth;
i think the new calculation of $x is just not quite right. If I understand your description correctly, then you simply want to output the next award image 20 pixels next to the previously placed image. If that's the case, then it's enough to use the matchbox to get the position of the placed image and then just add 20 px on top of it.
$awardX2 = $p->info_matchbox("awardimage", 1, "x2");
$x = $awardX2 + 20;
Maybe the problem also comes from the wrong name of $awardWidth. Info_matchbox() Returns you the X-position and not the width. If you want the width, then you should also get the x1 position and then calculate the difference. $width = $x2-$x1)
To select different parts of an image, I now load the image over and over again and crop to the part I want.
This is most probably not the most efficient way to do this, for I think I should be able to load the image one time in memory and then use it multiple times.
My current code:
$src = New Imagick();
for ($i = 0; $i < 4; $i++)
{
switch ($i)
{
case 0: $pos = [0,0]; break;
//...
}
$src->readImage('image.jpg');
$src->cropImage(100, 100, $pos[0], $pos[1]);
//...
}
Anyone knows a better way?
I am working on image manipulation script.
I want to change outline color of the pattern image, not fill up pattern with specific color.
I have tried different method of GD library. I could fill up color of the pattern but could not set outline color of the pattern.
Please let me know if any one has solution for the same.
Thanks in advance.
Try something like this:
// Draw a border
function drawBorder(&$img, &$color, $thickness = 1)
{
$x1 = 0;
$y1 = 0;
$x2 = ImageSX($img) - 1;
$y2 = ImageSY($img) - 1;
for($i = 0; $i < $thickness; $i++)
{
ImageRectangle($img, $x1++, $y1++, $x2--, $y2--, $color);
}
}
Credit where due
You can read about imagerectangle() on the PHP man page. The key point here is that $color must be "A color identifier created with imagecolorallocate()."
I'm trying to figure out a script that will generate a texture (which can then be multiplied by a grayscale image to "apply" it). So far my method involves seeding the RNG, then randomly generating a 8x8 matrix of integers in the range [0,3], then scaling up that matrix to a 256x256 image using some level of interpolation.
Here's an example output (seed value 24):
(source: adamhaskell.net)
On the left is the matrix scaled with nearest-neighbor interpolation. On the right is my attempt at bilinear interpolation. For the most part it seems okay, but then you get structures like near the middle-left where there are two diagonally-adjoining orange squares faced with two diagonally-adjoining red squares, andthe result is no interpolation for that area. Additionally, it's being treated more like a heatmap (as shown by the abundance of orange in the top-left corner) and that's causing more problems.
Here's the code I have for my "bilinear interpolation":
<?php
$matrix = Array();
srand(24);
$dim = 256;
$scale = 32;
for($y=0;$y<=$dim/$scale;$y++) for($x=0;$x<=$dim/$scale;$x++) $matrix[$y][$x] = rand(0,3);
$img = imagecreate($dim,$dim);
imagecolorallocate($img,255,255,255);
$cols = Array(
imagecolorallocate($img,128,0,0),
imagecolorallocate($img,128,64,32),
imagecolorallocate($img,128,128,0),
imagecolorallocate($img,64,64,64)
);
for($y=0;$y<$dim;$y++) {
for($x=0;$x<$dim;$x++) {
$xx = floor($x/$scale); $yy = floor($y/$scale);
$x2 = $x%$scale; $y2 = $y%$scale;
$col = $cols[round((
$matrix[$yy][$xx]*($scale-$x2)*($scale-$y2)
+ $matrix[$yy][$xx+1]*$x2*($scale-$y2)
+ $matrix[$yy+1][$xx]*($scale-$x2)*$y2
+ $matrix[$yy+1][$xx+1]*$x2*$y2
)/($scale*$scale))];
imagesetpixel($img,$x,$y,$col);
}
}
header("Content-Type: image/png");
imagepng($img);
exit;
In reality, this may be a bit of an XY Problem. What I'm specifically trying to do is generate "fur patterns" for creatures in a game I'm planning. In particular I want to be able to have it so that breeding mixes elements from the two parents (be it colour or elements of the pattern), so just having a random seed won't really cut it. Ideally I need some kind of vector-based approach, but I'm way out of my depth there so any help would be very much appreciated.
A couple things come to mind:
You are not interpolating the color values. To expand on zakinster's comment, you are interpolating the color indices, and then rounding to the nearest one. One effect of this is that you wind up with a swath of yellow (index 2) in between orange (index 1) and gray (index 3) areas. If you interpolated the color values instead, you would wind up with, perhaps, grayish orange?
You have more yellow and orange, and less red and gray in the final image. This is because of using round() to snap to a color index. Your calculation (before round()) may produce floats evenly distributed between 0 to 3, but rounding doesn't preserve it.
So, here are some suggestions:
If you are not limited to 4 colors, use more. Interpolate the color values (i.e. (128,0,0) mixed with (64,64,64) produces (91,32,32)) rather than the indices.
If you are limited to just those 4 colors, try some kind of dithering. A simple approach, with minimal changes to your code, would be to add some randomness to the color index that is chosen. So, instead of round(...), do something like this: say your calculation produces the value 1.7. Then, round to up to 2 with a 70% probability, and down to 1 the other 30%. This will blend the colors, but it may produce a very noisy image. If you are prepared to change your code more substantially, check out Floyd-Steinberg dithering.
I know it is old question, and answer from #markku-k is correct, anyway I have similar problem and here is my modified code for the question
several notices:
it produces 2 images in one, to show "original matrix" and result
it uses 8x8 matrix to produce result, but actual matrix is 10x10 to cover borders
it uses color to color index algorithm base on simple delta, it works ok for me
here is the code:
<?php
$matrix = array();
$dim = 256;
$scale = 32;
for($y=0; $y<=9; $y++)
{
$matrix[$y] = array();
for($x=0; $x<=9; $x++)
{
$same = false;
do
{
$matrix[$y][$x] = mt_rand(0, 3); // do not use rand function, mt_rand provide better results
if ( ($x>0) && ($y>0) ) // check for checkers siatuion, where no colors are preferable and produce 90 degree angles
{
$c1 = $matrix[$y-1][$x-1];
$c2 = $matrix[$y][$x];
$c3 = $matrix[$y-1][$x];
$c4 = $matrix[$y][$x-1];
$same = ( ($c1==$c2) && ($c3==$c4) );
}
} while ($same);
}
}
$img = imagecreate($dim*2 + 32*4, $dim + 32*2);
$colorsRGB = array(0x800000, 0x804020, 0x808000, 0x404040);
$cols = Array(
imagecolorallocate($img,128,0,0), // red
imagecolorallocate($img,128,64,32), // orange
imagecolorallocate($img,128,128,0), // yellow
imagecolorallocate($img,64,64,64), // gray
imagecolorallocate($img,0,0,0), // black, just to fill background
);
imagefilledrectangle($img, 0, 0, $dim*2 + 32*4 - 1, $dim + 32*2 - 1, $cols[4]);
function mulclr($color, $multiplicator)
{
return array(($color>>16) * $multiplicator, (($color>>8)&0xff) * $multiplicator, ($color&0xff) * $multiplicator);
}
function addclr($colorArray1, $colorArray2)
{
return array($colorArray1[0]+$colorArray2[0], $colorArray1[1]+$colorArray2[1], $colorArray1[2]+$colorArray2[2]);
}
function divclr($colorArray, $div)
{
return array($colorArray[0] / $div, $colorArray[1] / $div, $colorArray[2] / $div);
}
function findclridx($colorArray, $usedColors)
{
global $colorsRGB;
$minidx = $usedColors[0];
$mindelta = 255*3;
foreach ($colorsRGB as $idx => $rgb)
{
if (in_array($idx, $usedColors))
{
$delta = abs($colorArray[0] - ($rgb>>16)) + abs($colorArray[1] - (($rgb>>8)&0xff)) + abs($colorArray[2] - ($rgb&0xff));
if ($delta < $mindelta)
{
$minidx = $idx;
$mindelta = $delta;
}
}
}
return $minidx;
}
for($y=0; $y<($dim+64); $y++)
{
for($x=0; $x<($dim+64); $x++)
{
$xx = $x>>5;
$yy = $y>>5;
$x2 = ($x - ($xx<<5));
$y2 = ($y - ($yy<<5));
imagesetpixel($img, $x, $y, $cols[$matrix[$yy][$xx]]);
if ( ($xx>0) && ($yy>0) && ($xx<=8) && ($yy<=8) )
{
$color1 = $colorsRGB[$matrix[$yy][$xx]];
$color2 = $colorsRGB[$matrix[$yy][ ($xx+1) ]];
$color3 = $colorsRGB[$matrix[ ($yy+1) ][$xx]];
$color4 = $colorsRGB[$matrix[ ($yy+1) ][ ($xx+1) ]];
$usedColors = array_unique(array($matrix[$yy][$xx], $matrix[$yy][ ($xx+1) ], $matrix[ ($yy+1) ][$xx], $matrix[ ($yy+1) ][ ($xx+1) ]));
$a1 = mulclr($color1, ($scale-$x2)*($scale-$y2));
$a1 = addclr($a1, mulclr($color2, $x2*($scale-$y2)));
$a1 = addclr($a1, mulclr($color3, ($scale-$x2)*$y2));
$a1 = addclr($a1, mulclr($color4, $x2*$y2));
$a1 = divclr($a1, $scale*$scale);
$clrIdx = findclridx($a1, $usedColors);
$col = $cols[$clrIdx];
imagesetpixel($img, $dim+$x+32*2, $y, $col);
}
}
}
header("Content-Type: image/png");
imagepng($img);
exit;
here is sample result: