Introduction
This is a PHP class which can draw guitar chords, or any other string instruments for that matter.
It makes heavy use of the GD2 image library to build good looking chord diagrams in very few lines of code.
Background
Being an ukulele player myself (and bad guitar player also); I've visited tons of websites that were displaying guitar chords like "x23240" or without any description of the chord at all.
With the help of a few lines of PHP; I thought I could develop a highly customizable class to display those chords.
Using the Code
The class is named "chord
" an can be used very easily with few lines of codes. The code:
<?php
include('chord.inc.php');
$c = new chord(array('x',3,2,0,1,0));
$c->draw();
?>
It will output a PNG file like this one:
Points of Interest
The main point of interest is that the class is highly customizable. With a few more function calls you can set a title, margins, font sizes, custom colors and a custom background picture among other things.
Support for barre chords was also added. For instance, the following chord...
...was obtained by using:
<?php
include('chord.inc.php');
$c = new chord(array('x','x',0,0,0,8));
$c->setShowZeros(false);
$c->setMarginRight(20);
$c->setBarreChord(7,3,6);
$c->setStartingFret(5);
$c->draw();
?>
I wanted this class to work out of the box on any PHP5 setup, but in the meantime let users go more in depth with the class if they wished.
For instance, one interesting mechanism is the font. As you may be aware, GD2 with PHP has 5 built in fonts represented by numbers ranging from 1 to 5. They are rather ugly pixel fonts but they do work out of the box. In order to support both built in fonts and custom TTF fonts, people would upload on their webserver; there is some small logic in the setFontxxx methods:
<?php
function setFontTitle($v)
{
if(is_int($v))
{
if($v >= 1 && $v <= 5)
$this->fontTitle = $v;
else
throw new Exception('Built in font must be in 1 to 5 range');
}
else if(is_string($v))
{
$this->fontTitle = $v;
}
else
{
throw new Exception
('Use a TTF file or a number representing a built in font');
}
} ?>
With this logic, you can either do $c->setFontTitle('arial.ttf');
or $c->setFontTitle(5);
. Then, when it comes to drawing; the class calls "imagestring
" or "imagettftext
" which are PHP functions to draw text using built in fonts or TTF fonts respectively.
The rest of the interesting logic is located in the draw()
method of the class. A lot of logic has been added to support any size of chord. By default, the PNG picture will be 90x120 but as the user can set any size; the final result had to be consistent.
As such, the size of the circle representing a string
to be fretted is proportional to the fret spacing size. As such; if fancy values are used, the chord will react accordingly:
It is the responsibility of the user to tune the settings as he wishes.
Code-wise, this creates a lot of computations prior to drawing anything.
Namely, we need to:
- Count the number of strings
- Compute real width space available for drawing (without margin)
- Deduce space in pixels between each string
- Compute the size of upper symbols "o" or "x"
- Deduce total top margin
- If there is a title, compute the size of the text in pixel and add it to the total top margin
- Deduce real height space available for drawing (without margin)
- Compute the size in pixels between each fret
<?php
$nbStrings = count($this->data);
$realWidth = $this->width - $this->margin['left'] - $this->margin['right'];
$stringSpacing = ($realWidth / ($nbStrings-1));
$upperSymbolSize = intval(round($stringSpacing *
$this->upperSymbolSize));
$totalTopMargin = $this->margin['top'] + $upperSymbolSize;
$titleMargin = 0;
if(!empty($this->title))
{
if(is_int($this->fontTitle))
{
$titleMargin = imagefontheight($this->fontTitle);
}
else
{
$box = imagettfbboxextended($this->fontTitleSize,
0, $this->fontTitle, $this->title);
$titleMargin = $box['height'];
}
}
$totalTopMargin += $titleMargin;
$realHeight = $this->height - $totalTopMargin - $this->margin['bottom'];
$fretsSpacing = $realHeight / ($this->maxFrets);
?>
When we have all those values, the rest of the code is a piece of cake: draw a grid; draw the stuff where they need to be and this is it!
History
- 2010-07-25: First release