I am rendering audio waveforms directly from MP3’s on the fly as they are uploaded to the server. My upload script currently saves both the original mp3 and renders the waveform to a png.
Currently I render the background first to a rectangle. This code produces either a transparent or coloured background dependant upon the value of $background:
I am trying to create a transparent png overlay in PHP.
if (!$img) {
// create original image width based on amount of detail
// each waveform to be processed with be $height high, but will be condensed
// and resized later (if specified)
$img = imagecreatetruecolor($data_size / DETAIL, $height * sizeof($wavs_to_process));
// fill background of image
if ($background == "") {
// transparent background specified
imagesavealpha($img, true);
$transparentColor = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparentColor);
} else {
list($br, $bg, $bb) = html2rgb($background);
imagefilledrectangle($img, 0, 0, (int) ($data_size / DETAIL), $height * sizeof($wavs_to_process), imagecolorallocate($img, $br, $bg, $bb));
}
}
I then loop through the data points of a dynamically resampled MP3 and for each point I draw a line onto this background which renders the waveform image.
I use this code to produce the waveform image:
// don't print flat values on the canvas if not necessary
if (!($v / $height == 0.5 && !$draw_flat))
// draw the line on the image using the $v value and centering it vertically on the canvas
imageline(
$img,
// x1
(int) ($data_point / DETAIL),
// y1: height of the image minus $v as a percentage of the height for the wave amplitude
$height * $wav - $v,
// x2
(int) ($data_point / DETAIL),
// y2: same as y1, but from the bottom of the image
$height * $wav - ($height - $v),
imagecolorallocate($img, $r, $g, $b)
);
} else {
// skip this one due to lack of detail
fseek($handle, $ratio + $byte, SEEK_CUR);
}
}
This works perfectly, however I need to create the waveform as a transparent overlay in order to place it over a div with a CSS gradient. So, I need to render the background as #ffffff and the actual waveform itself needs to be transparent. In essence I need the transparency inverted on the produced png’s.
I have tried using:
imagecolorallocatealpha($img, 0, 0, 0, 127)
On the waveform rendering portion but always seem to just end up with a coloured rectangle with no visible waveform and I’m not sure where I am going wrong.
Any help would be greatly appreciated.
Please try the following. Disable blending modeDocs for the image:
This will enable that you can set pixels with alpha information directly. To do so, you need to allocate the color with the alphaDocs set to 100% transparent as well:
BTW, you can allocate the color once and then re-use it, so you don’t need to call the
imagecolorallocatealphafunction that often.Let me know if this works.