sagnik Posted November 2, 2020 Posted November 2, 2020 Hello again, I've got a problem with PHP GD. The problem is I'm trying to draw charts (i.e.Bar) and I'm trying to draw the Bell Curve of a data or an array with "Normal Distribution", but the problem is the chart is not fitting inside the allocated image size (1920 x 1080) so the chart is exceeding the boundaries of the image. So I've just tried a library "JpGraph" it works very well but doesn't fit my requirements, so I saw that the library is using some kind of canvas to draw the chart and then merging the image with the original one and I'm trying to do the same but I couldn't understand how. Please help me out, it's very urgent, I've to finish the project within a week. public function histogram(array $samples, int $bins, string $heading = null, string $xAxisHeading = null, string $yAxisHeading = null) { if(is_array($samples)) { $data = $_bins = $this->calculateBins($samples, $bins); /* * Chart settings and create image */ // Margin between label and axis $labelMargin = 8; $count = count($samples); // Max value on y-axis $yMaxValue = max(array_column($data, 'count')); if($yMaxValue % 2 == 1) $yMaxValue++; // Distance between grid lines on y-axis $yLabelSpan = ceil($yMaxValue / $bins); $t1 = ($yLabelSpan * $bins); if($t1 > $yMaxValue) $yMaxValue = $t1; // Bar and line width $lineWidth = 1; $barWidth = 20; // Image dimensions $imageWidthActual = round(count($data) * $barWidth * ($labelMargin / 2)); $imageHeightActual = round((count($data) / 2) * $count / 2); $imageWidth = min(1920, $imageWidthActual); $imageHeight = min(1024, $imageHeightActual); // Grid dimensions and placement within image $gridTop = 40; $gridBottom = round(($imageHeight - $gridTop)); $gridLeft = 50; $gridRight = round(($imageWidth - $gridLeft)); $gridHeight = $gridBottom - $gridTop; $gridWidth = $gridRight - $gridLeft; // Bar space $barSpacing = $gridWidth / count($data); // Font settings $font = PHPML_ROOT.'assets/fonts/OpenSans-Regular.ttf'; $headingFont = PHPML_ROOT.'assets/fonts/OpenSans-Bold.ttf'; $fontSize = 10; $headingFontSize = 12; // Init image $chart = imagecreatetruecolor($imageWidth, $imageHeight); // Setup colors $backgroundColor = imagecolorallocate($chart, 255, 255, 255); $headingColor = imagecolorallocate($chart, 0, 0, 0); $axisColor = imagecolorallocate($chart, 85, 85, 85); $gridColor = imagecolorallocate($chart, 212, 212, 212); //$barColor = imagecolorallocate($chart, 47, 133, 217); $labelColor = $axisColor; imagefill($chart, 0, 0, $backgroundColor); imagesetthickness($chart, $lineWidth); /* * Print grid lines bottom up and Y-Labels */ for($i = 0; $i <= $yMaxValue; $i += $yLabelSpan) { $y = $gridBottom - $i * $gridHeight / $yMaxValue; // draw the line imageline($chart, $gridLeft, $y, $gridRight, $y, $gridColor); // draw right aligned label $labelBox = imagettfbbox($fontSize, 0, $font, strval($i)); $labelWidth = $labelBox[4] - $labelBox[0]; $labelX = $gridLeft - $labelWidth - $labelMargin; $labelY = $y + $fontSize / 2; imagettftext($chart, $fontSize, 0, $labelX, $labelY, $labelColor, $font, strval($i)); } /* * Draw x- and y-axis */ imageline($chart, $gridLeft, $gridTop, $gridLeft, $gridBottom, $axisColor); //Left //imageline($chart, $gridRight, $gridTop, $gridRight, $gridBottom, $axisColor); //Right //imageline($chart, $gridLeft, $gridTop, $gridRight, $gridTop, $axisColor); //Top imageline($chart, $gridLeft, $gridBottom, $gridRight, $gridBottom, $axisColor); //Bottom $headingBox = $this->getTextBoundingBox($chart, $headingFontSize, $headingFont, strval($heading), 0); $xAxisHeadingBox = $this->getTextBoundingBox($chart, $fontSize, $font, strval($xAxisHeading), 0); $yAxisHeadingBox = $this->getTextBoundingBox($chart, $fontSize, $font, strval($yAxisHeading), 90); if(!empty($heading)) imagettftext($chart, $headingFontSize, 0, $headingBox['x']['center'], $headingBox['y']['top'], $headingColor, $headingFont, $heading); if(!empty($xAxisHeading)) imagettftext($chart, $fontSize, 0, $xAxisHeadingBox['x']['center'], $xAxisHeadingBox['y']['bottom'], $headingColor, $font, $xAxisHeading); if(!empty($yAxisHeading)) imagettftext($chart, $fontSize, 90, $yAxisHeadingBox['x']['left'], $yAxisHeadingBox['y']['middle'], $headingColor, $font, $yAxisHeading); /* * Draw the bars with X-labels */ $itemX = $gridLeft + $barSpacing / 2; $canvasWidth = ($imageWidth * 2); $canvasHeight = ($imageHeight * 2); $canvas = imagecreatetruecolor($canvasWidth, $canvasHeight); $canvasBackgroundColor = imagecolorallocate($canvas, 255, 255, 255); $labelColor = imagecolorallocate($canvas, 85, 85, 85); $barColor = imagecolorallocate($canvas, 47, 133, 217); imagefill($canvas, 0, 0, $canvasBackgroundColor); foreach($data as $key => $bin) { // Draw the label $labelBox = imagettfbbox($fontSize, 0, $font, $key); $labelWidth = $labelBox[4] - $labelBox[0]; $labelX = $itemX - $labelWidth / 2; $labelY = $gridBottom + $labelMargin + $fontSize; imagettftext($canvas, $fontSize, 0, $labelX, $labelY, $labelColor, $font, $key); foreach($bin as $k=>$value) { // Draw the bar $x1 = $itemX - $barWidth / 2; $y1 = $gridBottom - $value / $yMaxValue * $gridHeight; $x2 = $itemX + $barWidth / 2; $y2 = $gridBottom - 1; imagefilledrectangle($canvas, $x1, $y1, $x2, $y2, $barColor); } $itemX += $barSpacing; } $resized = $this->resize($canvas, $imageWidth, $imageHeight); imagealphablending($canvas, false); imagesavealpha($canvas, true); //imagecopyresampled($chart, $canvas, 0, 0, 0, 0, $canvasWidth, $canvasHeight, $imageWidth, $imageHeight); imagecopymerge($chart, $resized, 0, 0, 0, 0, $canvasWidth, $canvasHeight, 100); //imagecopyresized($chart, $canvas, 10, 10, 0, 0, $canvasWidth, $canvasHeight, $imageWidth, $imageHeight); /* * Output image to browser */ //header('Content-Type: image/png'); ob_start(); imagepng($chart); $outBlob = ob_get_contents(); ob_end_clean(); imagedestroy($canvas); imagedestroy($chart); $outImg = "data: image/png;base64,".base64_encode($outBlob); /* * Output image to file */ //imagepng($chart, 'chart.png'); return $outImg; } return false; }
Krydos Posted November 2, 2020 Posted November 2, 2020 I know it's not what you're asking, but I've always used google charts to do what you're trying to do https://developers.google.com/chart They have the advantage over static images of being able to hover your mouse over it and see extra data like exact values at different times or whatever your data is. Google charts is how I did the memory/cpu bar graph in cpanel, and HelioHost has some admin charts for monitoring the servers too that have been working great for years. They're really quick and easy to set up. I just use php and loop through the data from the database and output the javascript onto the page. I can provide some example code if that's something you're interested in. 1
sagnik Posted November 2, 2020 Author Posted November 2, 2020 I understand but I want it to be solely based on PHP. It would be better if I could do it without any dependencies. And I'm trying to avoid any type of client-side scripts for now. But I'll do it for sure in the future.The project I'm currently working on is "PHPML" which is a PHP implementation of some Python Machine Learning libraries (like NumPy, scipy, matplotlib, NLP, etc.) as the project is currently under development I don't want to mess with client-side. I want the users to just import one PHP Script on a page and access all the libraries.But in the future if it becomes a need to include some javascripts for any reason I lok into it but for now I want to stick with PHP GD (if possible).
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now