How to create grid based on luma numbers - php

I have 555 photos in a directory. They get scanned and given a number from 1 through 100 based on the brightness of the photo.
My goal is to have these images in a 37x15 rectangular grid where the centermost horizontal row of images are the brightest and then the outward images are the darkest.
So the ending result would be the images being renamed img[1].jpg img[2].jpg img[3].jpg from the top left to the bottom right, once I combine these later, they would be a gradient of the bottom and top being the darkest images, and the center most horizontal images being the brightest in color.
I already have a function that determines the brightness between 0-100, and a loop for the rows that determine the values row, but stuck after that.
function getAvgLuminance($filename, $num_samples=30) {
global $rows;
// needs a mimetype check
$img = imagecreatefromjpeg($filename);
$width = imagesx($img);
$height = imagesy($img);
$x_step = intval($width/$num_samples);
$y_step = intval($height/$num_samples);
$total_lum = 0;
$sample_no = 1;
for ($x=0; $x<$width; $x+=$x_step) {
for ($y=0; $y<$height; $y+=$y_step) {
$rgb = imagecolorat($img, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
// choose a simple luminance formula from here
// http://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
$lum = ($r+$r+$b+$g+$g+$g)/6;
$total_lum += $lum;
$sample_no++;
}
}
// work out the average
$avg_lum = $total_lum / $sample_no;
return ($avg_lum / 255) * $rows;
}
$rows=36;
$col=14;
$imgs_resource_dir = 'imgs';
$allFiles = scandir($imgs_resource_dir);
$imlist=array_diff($allFiles, array('.', '..'));
$rowCenter = $rows/2;
while($rows > $ri++){
$FromTop = ( $rowCenter - $ri );
$FromBottom = $rowCenter- ( $rows-$ri) ;
$RowPoint = $FromTop > 0 ? $FromTop : $FromBottom;
}// end row loop
//start image loop
foreach($imlist as $imgfile ){
$pathtoImage = $imgs_resource_dir.'/'.$imgfile ;
$lumss= getAvgLuminance($pathtoImage);
echo 'str '.$lumss.'<br>';
}//end foreach loop

Related

How to convert a grayscale image to pure black and white in php?

I'm trying to convert a grayscale image to pure black and white in PHP using the GD library.
The purpose would be to detect the cervical cells within the image.
I'll leave the PHP code and a MatLab one (I wrote this code in MatLab and I'm trying to obtain the same result in PHP). Basically, I'm having trouble accessing each individual pixel's color and modifying it. sample image
PHP:
<?php
$im = imagecreatefromjpeg("celule.jpg");
function imagetograyscale($im)
{
if (imageistruecolor($im)) {
imagetruecolortopalette($im, false, 256);
}
for ($c = 0; $c < imagecolorstotal($im); $c++) {
$col = imagecolorsforindex($im, $c);
$gray = round(0.299 * $col['red'] + 0.587 * $col['green'] + 0.114 * $col['blue']);
imagecolorset($im, $c, $gray, $gray, $gray);
}
}
imagetograyscale($im);
//imagefilter($im, IMG_FILTER_CONTRAST, -255); //i'm not looking for this effect
header('Content-type: image/jpeg');
imagejpeg($im);
$C = imagesx($im); //width
$L = imagesy($im); //height
echo "Dimensiuni imagine: latime $C, inaltime $L <br>";
//scanning through the image
for($x = 0; $x < $L; $x++) { //each line
for($y = 0; $y < $C; $y++) { //each column
// pixel color at (x, y)
$color = imagecolorat($im, $y, $x);
$color = imagecolorsforindex($im, $color); //getting rgb values
$RED[$x][$y] = $color["red"]; //each rgb component
$GREEN[$x][$y] = $color["green"];
$BLUE[$x][$y] = $color["blue"];
}
}
?>
MATLAB:
clear all, clc, close all;
I = imread('celule.jpg');
imshow(I)
title('original');
a=rgb2gray(I);
figure;
imshow(a)
title('grayscale');
s=size(a);
for i=1:s(1)
for j=1:s(2)
if a(i,j)>190
a(i,j)=0;
else a(i,j)=255;
end
end
end
figure;
imshow(a)
title('pure black and white');
Here's a way to do that with gd:
#!/usr/bin/php -f
<?php
// Open image and get dimensions
$im = imagecreatefromjpeg("cellule.jpg");
$w = imagesx($im);
$h = imagesy($im);
// Convert to greyscale
imagefilter($im,IMG_FILTER_GRAYSCALE);
imagepng($im, "grey.png"); // DEBUG only
// Allocate a new palette image to hold the b&w output
$out = imagecreate($w,$h);
// Allocate b&w palette entries
$black = imagecolorallocate($out,0,0,0);
$white = imagecolorallocate($out,255,255,255);
// Iterate over all pixels, thresholding to pure b&w
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
// Get current color
$index = imagecolorat($im, $x, $y);
$grey = imagecolorsforindex($im, $index)['red'];
// Set pixel white if below threshold - don't bother settting black as image is initially black anyway
if ($grey <= 190) {
imagesetpixel($out,$x,$y,$white);
}
}
}
imagepng($out, "result.png");
?>

Check pixels pattern

How can I check for a pixel pattern in PHP?
I mean I wanna use as condition that pixel A has xxx value and the following pixel B has another value yyy.
This is what I wrote:
$img = imagecreatefrompng("myimage.png");
$w = imagesx($img);
$h = imagesy($img);
for($y=0;$y<$h;$y++) {
for($x=0;$x<$w;$x++) {
$rgb = imagecolorat($img, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
echo "#".$r.$g.$b.",";
$pixel = $r.$g.$b;
if ($pixel == "481023" and $pixel+1???
}
echo "<br />\r\n";
}
I'd like to ask also if I can speed up the whole thing by incrementing the $x value by 2 every for cycle. This because I have a pattern of 2 pixels, maybe I can use something like:
for($x=0;$x<$w;$x+2) {
//...
if ($pixel == "xxx") {//check the following pixel}
else if ($pixel == "yyy") {//check the previous pixel}
}
You might want to define a function like:
function getpixelat($img,$x,$y) {
$rgb = imagecolorat($img,$x,$y);
$r = dechex(($rgb >> 16) & 0xFF);
$g = dechex(($rgb >> 8) & 0xFF);
$b = dechex($rgb & 0xFF);
return $r.$g.$b;
}
Notice the dechex - you need this if you want it to look like an HTML colour code. Otherwise "white" would be 255255255 instead of ffffff and you'd also get ambiguous colours - is 202020 a dark gray (20,20,20) or "red with a slight hint of blue" (202,0,20)?
Once you have this, it should be a simple matter:
for( $y=0; $y<$h; $y++) {
for( $x=0; $x<$w; $x++) {
$pixel = getpixelat($img,$x,$y);
if( $pixel == "481023" && getpixelat($img,$x+1,$y) == "998877") {
// pattern! Do something here.
$x++; // increment X so we don't bother checking the next pixel again.
}
}
}

How to find the Dominant color in image?

i want to find the dominant color in image,
how can i do it ?
it would be great if i can get this in HEX code (exm: #eeeeee)
To find the most "dominant" color in an image, meaning the color that is most prevalent in the image: you'd need to create a histogram of the image.
Here is an the code from this article on how to create a histogram in PHP. (Website has gone off line several times)
<?php
$source_file = "test_image.jpg";
// histogram options
$maxheight = 300;
$barwidth = 2;
$im = ImageCreateFromJpeg($source_file);
$imgw = imagesx($im);
$imgh = imagesy($im);
// n = total number or pixels
$n = $imgw*$imgh;
$histo = array();
for ($i=0; $i<$imgw; $i++)
{
for ($j=0; $j<$imgh; $j++)
{
// get the rgb value for current pixel
$rgb = ImageColorAt($im, $i, $j);
// extract each value for r, g, b
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
// get the Value from the RGB value
$V = round(($r + $g + $b) / 3);
// add the point to the histogram
$histo[$V] += $V / $n;
}
}
// find the maximum in the histogram in order to display a normated graph
$max = 0;
for ($i=0; $i<255; $i++)
{
if ($histo[$i] > $max)
{
$max = $histo[$i];
}
}
echo "<div style='width: ".(256*$barwidth)."px; border: 1px solid'>";
for ($i=0; $i<255; $i++)
{
$val += $histo[$i];
$h = ( $histo[$i]/$max )*$maxheight;
echo "<img src=\"img.gif\" width=\"".$barwidth."\"
height=\"".$h."\" border=\"0\">";
}
echo "</div>";
?>
In that example $max is your most "dominant" color.
There is a PHP class developed that handles this, named color extract. However, know that doing this on the server side will require substantial system resources. You may wish to instead do this with canvas.
Try this: http://www.coolphptools.com/color_extract.
The Image Color Extract PHP class pulls the most common colors (in percentages) out of an image file. The color values are in hexadecimal.
Sounds like a delightful code to write! I made a function awhile back that goes through every pixel and adds a shade to each one. What you could do is:
For Each Pixel, find the highest color (r,g,or b) and do the math ($colorG++ or something)
at the end, find out what one is the largest, and there would be your highest rgb shade.
I wonder what color would come out if you used the resulting rgb value...
In regard to tkone answer, the $max is just a parameter showing density of the color at an image. I would change the code a bit to return the HEX color:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Empty Document</title>
</head>
<body>
<?php
error_reporting(0);
function rgb2hex($rgb) {
$hex = "#";
$hex .= str_pad(dechex($rgb[0]), 2, "0", STR_PAD_LEFT);
$hex .= str_pad(dechex($rgb[1]), 2, "0", STR_PAD_LEFT);
$hex .= str_pad(dechex($rgb[2]), 2, "0", STR_PAD_LEFT);
return $hex; // returns the hex value including the number sign (#)
}
$source_file = "image.jpg";
// histogram options
$maxheight = 300;
$barwidth = 2;
$im = ImageCreateFromJpeg($source_file);
$imgw = imagesx($im);
$imgh = imagesy($im);
// n = total number or pixels
$n = $imgw*$imgh;
$histo = array();
for ($i=0; $i<$imgw; $i++)
{
for ($j=0; $j<$imgh; $j++)
{
// get the rgb value for current pixel
$rgb = ImageColorAt($im, $i, $j);
//echo $rgb."<br>";
// extract each value for r, g, b
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
// get the Value from the RGB value
$V = round(($r + $g + $b) / 3);
//echo $V."<br>";
// add the point to the histogram
$histo[$V] += $V / $n;
$histo_color[$V] = rgb2hex([$r,$g,$b]);
}
}
// find the maximum in the histogram in order to display a normated graph
$max = 0;
for ($i=0; $i<255; $i++)
{
if ($histo[$i] > $max)
{
$max = $histo[$i];
}
}
echo "<div style='width: ".(256*$barwidth)."px; border: 1px solid'>";
for ($i=0; $i<255; $i++)
{
$val += $histo[$i];
$h = ( $histo[$i]/$max )*$maxheight;
echo "<img src=\"img.gif\" width=\"".$barwidth."\"
height=\"".$h."\" border=\"0\">";
}
echo "</div>";
$key = array_search ($max, $histo);
$col = $histo_color[$key];
?>
<p style="min-width:100px; min-height:100px; background-color:<?php echo $col?>;"></p>
<img src="<?php echo $source_file?>">
</body>
</html>
Also, it is worth mentioning that this is just the most 'repeated' color at the image that cannot absolutely considered 'dominant' color.
PHP Simple Color Thief
🖼 Detect the Dominant Color used in an Image
Works very fast!
PHP:
require 'color.php';
$image = 'https://cdn.pixabay.com/photo/2012/11/24/07/43/colorful-67134_960_720.jpg'
$default_color = 'ffffff';
echo simple_color_thief($image, $default_color);
Will return the Hex Color: e0a654
The color.php File:
/*
PHP Simple Color Thief
======================
Detect the Dominant Color used in an Image
Copyright 2019 Igor Gaffling
*/
function simple_color_thief($img, $default='eee') {
if(#exif_imagetype($img)) { // CHECK IF IT IS AN IMAGE
$type = getimagesize($img)[2]; // GET TYPE
if ($type === 1) { // GIF
$image = imagecreatefromgif($img);
// IF IMAGE IS TRANSPARENT (alpha=127) RETURN fff FOR WHITE
if (imagecolorsforindex($image, imagecolorstotal($image)-1)['alpha'] == 127) return 'fff';
} else if ($type === 2) { // JPG
$image = imagecreatefromjpeg($img);
} else if ($type === 3) { // PNG
$image = imagecreatefrompng($img);
// IF IMAGE IS TRANSPARENT (alpha=127) RETURN fff FOR WHITE
if ((imagecolorat($image, 0, 0) >> 24) & 0x7F === 127) return 'fff';
} else { // NO CORRECT IMAGE TYPE (GIF, JPG or PNG)
return $default;
}
} else { // NOT AN IMAGE
return $default;
}
$newImg = imagecreatetruecolor(1, 1); // FIND DOMINANT COLOR
imagecopyresampled($newImg, $image, 0,0,0,0,1,1, imagesx($image), imagesy($image));
return dechex(imagecolorat($newImg, 0, 0)); // RETURN HEX COLOR
}
// DEMO
foreach(glob('./*.{jpg,png,gif}', GLOB_BRACE) as $i) {
echo '<div style="width:26%;padding:50px;background:#'.
simple_color_thief($i,'f00').
';display:inline-block"><img style="height:200px" src="'.
$i.'"></div>';
}
Source: https://github.com/gaffling/PHP-Simple-Color-Thief/
You should have a look at GD and Image Functions.
There is a similar question on SO about extracting color information from an image with PHP, and it links to this class on github.
You give an image ressouce as argument.
Ex:
$im=imagecreatefromjpeg("path/to/image");
getDominantcolor($im);
NB: This function will little bit slow down your page since it will compare each color of the image to all other color to make the statistic.
It returns rgb value of the dominant color as array
function getDominantcolor($im){
$width=imagesx($im);
$height=imagesy($im);
$colorArr=[];
$comparArr=[];
$colCount=0;
//fixed height
for ($j=0; $j < $height; $j++) {
//fetching color on widths
for ($i=0; $i < $height; $i++) {
$colorArr[]=imagecolorat ( $im ,$i ,$j );
}
}
//fixed height
for ($col=0; $col < count($colorArr); $col++) {
for ($cel=0; $cel < count($colorArr); $cel++) {
if($colorArr[$col]===$colorArr[$cel]){
$colCount+=1;
}
}
$comparArr[]=$colCount;
$colCount=0;
}
foreach ($comparArr as $key => $value) {
if($value===max($comparArr)){
$max_index=$key;
break;
}
}
$rgb=$colorArr[$max_index];
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
return ['r'=>$r,'g'=>$g,'b'=>$b];
}
Though its in javascript but color-thief is best for getting dominant color in image.
https://github.com/lokesh/color-thief

PHP Load image into array, 2 bit

I want to load an entire image (PNG) into a 2-dimensional array where a black pixel is true and a white pixel is false.
What's the most efficient way of doing this?
Should I convert the image into bitmap and attempt to read that in, or is there a more efficient method?
This should do:
$image = imagecreatefrompng("input.png");
$width = imagesx($image);
$height = imagesy($image);
$colors = array();
for ($y = 0; $y < $height; $y++)
{
for ($x = 0; $x < $width; $x++)
{
$rgb = imagecolorat($image, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$black = ($r == 0 && $g == 0 && $b == 0);
$colors[$x][$y] = $black;
}
}
A probably more efficient way would be using Imagick::exportImagePixels().

Pixel per Pixel image, transparent turned into black

I read a couple of thing about this, but I can't figure how to put it in my code.
Here it is :
function go($image) {
// Open the image
$getimage=imagecreatefrompng($image);
//Get the width/height
$w = imagesx($getimage);
$h = imagesy($getimage);
//init Count variable, when it reach the width, skip a line
$count = 0;
// For each line
for($y=0;$y<$h;$y++) {
// For each column
for($x=0;$x<$w;$x++) {
$rgba = imagecolorat($getimage, $x, $y);
$r = ($rgba >> 16) & 0xFF;
$g = ($rgba >> 8) & 0xFF;
$b = $rgba & 0xFF;
$a = ($rgba & 0x7F000000) >> 24;
echo '<div class="pix" style="background-color: rgba('.$r.', '.$g.', '.$b.', '.$a.');"></div>';
$count++;
if($count==$w) {echo '<br>'; $count = 0; }
}
}
echo $pixel_gen;
}
If oyu want to see what it looks like, clic here: http://narks.xtreemhost.com/
And double-click on any icon, popup will appear. (Note: dbl-clinking on any icon will show the same image (I didnt fixed this yet)
Any idea how i can make the black pixel appear like the real pixel with alpha) ?
Thanks for your help!
EDITED
(New code, i put only the first lines since i want to save space)
function go($image) {
// Open the image
$getimage=imagecreatefrompng($image);
imagealphablending($getimage, false);
imagesavealpha($getimage, true);
//Get the width/height
$w = imagesx($getimage);
$h = imagesy($getimage);
[...]
To see what it looks like now, visit the website above and double-click on an icon.
EDIT 2
I just tried (for a test) with :
$getimage=imagecreatefrompng('iconDB/lib/chat_fav_48.png');
imagealphablending($getimage, false);
imagesavealpha($getimage, true);
header("Content-type: image/png");
imagepng($getimage);
imagedestroy($getimage);
and then with
$getimage=imagecreatefrompng('iconDB/lib/chat_fav_48.png');
header("Content-type: image/png");
imagepng($getimage);
imagedestroy($getimage);
The first is okay and the second make pixels black. So it is when i get each pixel's RGB colors and when I display it. Anyone see a mistake there?
Here is the correct working code, in order to complete this question.
function go($image) {
// Open the image
$getimage=imagecreatefrompng($image);
imagealphablending($getimage, true);
imagesavealpha($getimage, true);
//Get the width/height
$w = imagesx($getimage);
$h = imagesy($getimage);
//init Count variable, when it reach the width, skip a line
$count = 0;
// For each line
for($y=0;$y<$h;$y++) {
// For each column
for($x=0;$x<$w;$x++) {
// Get the image color for this pixel
$rgba = imagecolorat($getimage, $x, $y);
$r = ($rgba >> 16) & 0xFF;
$g = ($rgba >> 8) & 0xFF;
$b = $rgba & 0xFF;
$a = ($rgba & 0x7F000000) >> 24;
//Calculating the correct Alpha value for rgba display in css
$a = (127-$a)/127;
echo '<div class="pix" style="background-color: rgba('.$r.', '.$g.', '.$b.', '.$a.');"></div>';
$count++;
if($count==$w) {echo '<br>'; $count = 0; }
}
}
echo $pixel_gen;
}
I hope it will be useful for someone
According to comments on the imagecreatefrompng page, you need to call imagealphablending and imagesavealpha
imagealphablending($getimage, false);
imagesavealpha($getimage, true);
There are also other comments about alpha transparency and PNGs on that page.

Categories