From 9db349fcadadce09b16bb8c556d9f688e0f83345 Mon Sep 17 00:00:00 2001 From: Yannick Gagnon Date: Wed, 10 May 2023 11:05:02 -0400 Subject: [PATCH 01/10] Add wave bars customization options --- src/GdImageRenderer.cpp | 34 ++++++++++++++++++++++++++++++++-- src/GdImageRenderer.h | 8 ++++++++ src/OptionHandler.cpp | 3 +++ src/Options.cpp | 15 +++++++++++++++ src/Options.h | 8 ++++++++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index 3d4c29a..7551e2a 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -54,6 +54,9 @@ GdImageRenderer::GdImageRenderer() : background_color_(0), waveform_color_(0), axis_label_color_(0), + bar_width_(1), + bar_gap_(0), + bar_style_rounded_(false), render_axis_labels_(true), auto_amplitude_scale_(false), amplitude_scale_(1.0) @@ -78,6 +81,9 @@ bool GdImageRenderer::create( const int image_width, const int image_height, const WaveformColors& colors, + const int bar_width, + const int bar_gap, + const bool bar_style_rounded, const bool render_axis_labels, const bool auto_amplitude_scale, const double amplitude_scale) @@ -123,6 +129,8 @@ bool GdImageRenderer::create( return false; } + image_ = gdImageCreateTrueColor(image_width, image_height); + assert(sample_rate != 0); assert(samples_per_pixel != 0); @@ -132,6 +140,9 @@ bool GdImageRenderer::create( sample_rate_ = buffer.getSampleRate(); samples_per_pixel_ = samples_per_pixel; start_index_ = secondsToPixels(start_time); + bar_width_ = bar_width, + bar_gap_ = bar_gap, + bar_style_rounded_ = bar_style_rounded, render_axis_labels_ = render_axis_labels; auto_amplitude_scale_ = auto_amplitude_scale; amplitude_scale_ = amplitude_scale; @@ -210,6 +221,7 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const { // Avoid drawing over the right border const int max_x = render_axis_labels_ ? image_width_ - 1 : image_width_; + const int radius = (int)floor(bar_width_ / 2); // Avoid drawing over the top and bottom borders const int top_y = render_axis_labels_ ? 1 : 0; @@ -258,7 +270,9 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const const int height = waveform_bottom_y - waveform_top_y + 1; - for (int i = start_index, x = start_x; x < max_x && i < buffer_size; ++i, ++x) { + for (int i = start_index, x = start_x; i < buffer_size; ++i) { + if ( x + bar_width_ > max_x ) { break; } + // Convert range [-32768, 32727] to [0, 65535] int low = MathUtil::scale(buffer.getMinSample(channel, i), amplitude_scale) + 32768; int high = MathUtil::scale(buffer.getMaxSample(channel, i), amplitude_scale) + 32768; @@ -267,7 +281,13 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const int high_y = waveform_top_y + height - 1 - high * height / 65536; int low_y = waveform_top_y + height - 1 - low * height / 65536; - gdImageLine(image_, x, low_y, x, high_y, waveform_color_); + if ( bar_width_ > 1 ) { + drawRoundedRectangle(x, high_y, x + bar_width_, low_y, radius); + } else { + gdImageLine(image_, x, low_y, x, high_y, waveform_color_); + } + + x += bar_width_ + bar_gap_; } available_height -= row_height + 1; @@ -275,6 +295,16 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const } } +void GdImageRenderer::drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const int radius) const + { + gdImageFilledRectangle(image_, x1, y1, x2, y2, waveform_color_); + + if( bar_style_rounded_) { + gdImageFilledArc(image_, x1 + radius, y1, radius * 2, radius, 180, 360, waveform_color_, gdStyledBrushed); + gdImageFilledArc(image_, x1 + radius, y2, radius * 2, radius, 0, 180, waveform_color_, gdStyledBrushed); + } + } + //------------------------------------------------------------------------------ void GdImageRenderer::drawTimeAxisLabels() const diff --git a/src/GdImageRenderer.h b/src/GdImageRenderer.h index 9d21374..fd56057 100644 --- a/src/GdImageRenderer.h +++ b/src/GdImageRenderer.h @@ -52,6 +52,9 @@ class GdImageRenderer int image_width, int image_height, const WaveformColors& colors, + int bar_width, + int bar_gap, + bool bar_style_rounded, bool render_axis_labels, bool auto_amplitude_scale, double amplitude_scale @@ -71,6 +74,7 @@ class GdImageRenderer void drawBorder() const; void drawWaveform(const WaveformBuffer& buffer) const; + void drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const int radius) const; void drawTimeAxisLabels() const; @@ -100,6 +104,10 @@ class GdImageRenderer int waveform_color_; int axis_label_color_; + int bar_width_; + int bar_gap_; + bool bar_style_rounded_; + bool render_axis_labels_; bool auto_amplitude_scale_; diff --git a/src/OptionHandler.cpp b/src/OptionHandler.cpp index 105e010..ec9e43e 100644 --- a/src/OptionHandler.cpp +++ b/src/OptionHandler.cpp @@ -493,6 +493,9 @@ bool OptionHandler::renderWaveformImage( options.getImageWidth(), options.getImageHeight(), colors, + options.getBarWidth(), + options.getBarGap(), + options.isBarStyleRounded(), options.getRenderAxisLabels(), options.isAutoAmplitudeScale(), options.getAmplitudeScale())) diff --git a/src/Options.cpp b/src/Options.cpp index e727b3d..9cef2c9 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -60,6 +60,9 @@ Options::Options() : image_height_(0), bits_(16), has_bits_(false), + bar_width_(1), + bar_gap_(0), + bar_style_rounded_(false), render_axis_labels_(true), auto_amplitude_scale_(false), amplitude_scale_(1.0), @@ -162,6 +165,18 @@ bool Options::parseCommandLine(int argc, const char* const* argv) "waveform-color", po::value(&waveform_color_), "wave color (rrggbb[aa])" + )( + "bar-width", + po::value(&bar_width_)->default_value(1), + "bar width (pixels)" + )( + "bar-gap", + po::value(&bar_gap_)->default_value(0), + "bar gap (pixels)" + )( + "bar-style-rounded", + po::value(&bar_style_rounded_)->default_value(false), + "bar style rounded (default to square)" )( "axis-label-color", po::value(&axis_label_color_), diff --git a/src/Options.h b/src/Options.h index c19ae6b..7216eb6 100644 --- a/src/Options.h +++ b/src/Options.h @@ -103,6 +103,10 @@ class Options bool getRenderAxisLabels() const { return render_axis_labels_; } + int getBarWidth() const { return bar_width_; } + int getBarGap() const { return bar_gap_; } + bool isBarStyleRounded() const { return bar_style_rounded_; } + bool isAutoAmplitudeScale() const { return auto_amplitude_scale_; } double getAmplitudeScale() const { return amplitude_scale_; } @@ -165,6 +169,10 @@ class Options RGBA waveform_color_; RGBA axis_label_color_; + int bar_width_; + int bar_gap_; + bool bar_style_rounded_; + bool has_border_color_; bool has_background_color_; bool has_waveform_color_; From 093e8e279fe3349327d51e1cb30d86ea75956570 Mon Sep 17 00:00:00 2001 From: Chris Needham Date: Thu, 11 May 2023 21:14:05 +0100 Subject: [PATCH 02/10] Added missing #include --- src/GdImageRenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index 7551e2a..f42b33b 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include From 0a8780be6e648cc7176f42375e48730c8792733f Mon Sep 17 00:00:00 2001 From: Chris Needham Date: Thu, 11 May 2023 21:22:30 +0100 Subject: [PATCH 03/10] Fixed test cases --- test/GdImageRendererTest.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/GdImageRendererTest.cpp b/test/GdImageRendererTest.cpp index 3598553..a5d42d4 100644 --- a/test/GdImageRendererTest.cpp +++ b/test/GdImageRendererTest.cpp @@ -77,7 +77,7 @@ void GdImageRendererTest::testImageRendering(bool axis_labels, const std::string const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - result = renderer.create(buffer, 5.0, 1000, 300, colors, axis_labels, false, 1.0); // zoom: 128 + result = renderer.create(buffer, 5.0, 1000, 300, colors, 1, 0, false, axis_labels, false, 1.0); // zoom: 128 ASSERT_TRUE(result); result = renderer.saveAsPng(filename.c_str()); @@ -159,7 +159,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfImageWidthIsLessThanMinimum) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 0, 300, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 0, 300, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); @@ -179,7 +179,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfImageHeightIsLessThanMinimum) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 800, 0, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 800, 0, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); @@ -199,7 +199,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfSampleRateIsZero) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 800, 250, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 800, 250, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); @@ -219,7 +219,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfSampleRateIsNegative) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 800, 250, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 800, 250, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); @@ -239,7 +239,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfScaleIsZero) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 800, 250, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 800, 250, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); @@ -259,7 +259,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfScaleIsNegative) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 800, 250, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 800, 250, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); @@ -278,7 +278,7 @@ TEST_F(GdImageRendererTest, shouldReportErrorIfWaveformBufferIsEmpty) const WaveformColors& colors = audacity_waveform_colors; GdImageRenderer renderer; - bool result = renderer.create(buffer, 5.0, 800, 250, colors, true, false, 1.0); + bool result = renderer.create(buffer, 5.0, 800, 250, colors, 1, 0, false, true, false, 1.0); ASSERT_FALSE(result); ASSERT_TRUE(output.str().empty()); From d5e3df1624c64f51a35b6c0c75013365cb1f32fb Mon Sep 17 00:00:00 2001 From: Chris Needham Date: Sun, 14 May 2023 11:28:13 +0100 Subject: [PATCH 04/10] Fixed memory leak in GdImageRenderer The image was being created twice --- src/GdImageRenderer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index f42b33b..bf393ca 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -130,8 +130,6 @@ bool GdImageRenderer::create( return false; } - image_ = gdImageCreateTrueColor(image_width, image_height); - assert(sample_rate != 0); assert(samples_per_pixel != 0); From 22877347e5c06746a700864cd25175a88839469e Mon Sep 17 00:00:00 2001 From: Chris Needham Date: Sun, 14 May 2023 11:29:06 +0100 Subject: [PATCH 05/10] Fixed code formatting --- src/GdImageRenderer.cpp | 47 +++++++++++++++++++++++++++++++++-------- src/GdImageRenderer.h | 9 +++++++- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index bf393ca..64cce49 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -270,7 +270,9 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const const int height = waveform_bottom_y - waveform_top_y + 1; for (int i = start_index, x = start_x; i < buffer_size; ++i) { - if ( x + bar_width_ > max_x ) { break; } + if (x + bar_width_ > max_x) { + break; + } // Convert range [-32768, 32727] to [0, 65535] int low = MathUtil::scale(buffer.getMinSample(channel, i), amplitude_scale) + 32768; @@ -280,9 +282,10 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const int high_y = waveform_top_y + height - 1 - high * height / 65536; int low_y = waveform_top_y + height - 1 - low * height / 65536; - if ( bar_width_ > 1 ) { + if (bar_width_ > 1) { drawRoundedRectangle(x, high_y, x + bar_width_, low_y, radius); - } else { + } + else { gdImageLine(image_, x, low_y, x, high_y, waveform_color_); } @@ -294,15 +297,41 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const } } -void GdImageRenderer::drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const int radius) const - { +void GdImageRenderer::drawRoundedRectangle( + const int x1, + const int y1, + const int x2, + const int y2, + const int radius) const +{ gdImageFilledRectangle(image_, x1, y1, x2, y2, waveform_color_); - if( bar_style_rounded_) { - gdImageFilledArc(image_, x1 + radius, y1, radius * 2, radius, 180, 360, waveform_color_, gdStyledBrushed); - gdImageFilledArc(image_, x1 + radius, y2, radius * 2, radius, 0, 180, waveform_color_, gdStyledBrushed); + if (bar_style_rounded_) { + gdImageFilledArc( + image_, + x1 + radius, + y1, + radius * 2, + radius, + 180, + 360, + waveform_color_, + gdStyledBrushed + ); + + gdImageFilledArc( + image_, + x1 + radius, + y2, + radius * 2, + radius, + 0, + 180, + waveform_color_, + gdStyledBrushed + ); } - } +} //------------------------------------------------------------------------------ diff --git a/src/GdImageRenderer.h b/src/GdImageRenderer.h index fd56057..3da4074 100644 --- a/src/GdImageRenderer.h +++ b/src/GdImageRenderer.h @@ -74,7 +74,14 @@ class GdImageRenderer void drawBorder() const; void drawWaveform(const WaveformBuffer& buffer) const; - void drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const int radius) const; + + void drawRoundedRectangle( + const int x1, + const int y1, + const int x2, + const int y2, + const int radius + ) const; void drawTimeAxisLabels() const; From c74df452fee0740c796d8111dda2db6a8cf7ca32 Mon Sep 17 00:00:00 2001 From: Chris Needham Date: Sun, 14 May 2023 12:43:28 +0100 Subject: [PATCH 06/10] Fixed bar width Bars were one pixel too wide --- src/GdImageRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index 64cce49..8a85ce9 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -283,7 +283,7 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const int low_y = waveform_top_y + height - 1 - low * height / 65536; if (bar_width_ > 1) { - drawRoundedRectangle(x, high_y, x + bar_width_, low_y, radius); + drawRoundedRectangle(x, high_y, x + bar_width_ - 1, low_y, radius); } else { gdImageLine(image_, x, low_y, x, high_y, waveform_color_); From 1424660ec63efbe58b4638de2b8b5a18437de4a9 Mon Sep 17 00:00:00 2001 From: Yannick Gagnon Date: Mon, 15 May 2023 12:16:38 -0400 Subject: [PATCH 07/10] Fix Bar width / radius and add waveform-style-bars --- src/GdImageRenderer.cpp | 78 ++++++++++++++++++----------------------- src/GdImageRenderer.h | 11 ++---- src/OptionHandler.cpp | 1 + src/Options.cpp | 4 +++ src/Options.h | 2 ++ 5 files changed, 44 insertions(+), 52 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index 8a85ce9..623405b 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -55,6 +55,7 @@ GdImageRenderer::GdImageRenderer() : background_color_(0), waveform_color_(0), axis_label_color_(0), + waveform_style_bars_(false), bar_width_(1), bar_gap_(0), bar_style_rounded_(false), @@ -82,6 +83,7 @@ bool GdImageRenderer::create( const int image_width, const int image_height, const WaveformColors& colors, + const bool waveform_style_bars, const int bar_width, const int bar_gap, const bool bar_style_rounded, @@ -139,9 +141,10 @@ bool GdImageRenderer::create( sample_rate_ = buffer.getSampleRate(); samples_per_pixel_ = samples_per_pixel; start_index_ = secondsToPixels(start_time); - bar_width_ = bar_width, - bar_gap_ = bar_gap, - bar_style_rounded_ = bar_style_rounded, + waveform_style_bars_ = waveform_style_bars; + bar_width_ = bar_width; + bar_gap_ = bar_gap; + bar_style_rounded_ = bar_style_rounded; render_axis_labels_ = render_axis_labels; auto_amplitude_scale_ = auto_amplitude_scale; amplitude_scale_ = amplitude_scale; @@ -220,7 +223,7 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const { // Avoid drawing over the right border const int max_x = render_axis_labels_ ? image_width_ - 1 : image_width_; - const int radius = (int)floor(bar_width_ / 2); + const int radius = (int)ceil(bar_width_ / 2); // Avoid drawing over the top and bottom borders const int top_y = render_axis_labels_ ? 1 : 0; @@ -268,7 +271,6 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const } const int height = waveform_bottom_y - waveform_top_y + 1; - for (int i = start_index, x = start_x; i < buffer_size; ++i) { if (x + bar_width_ > max_x) { break; @@ -282,14 +284,13 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const int high_y = waveform_top_y + height - 1 - high * height / 65536; int low_y = waveform_top_y + height - 1 - low * height / 65536; - if (bar_width_ > 1) { - drawRoundedRectangle(x, high_y, x + bar_width_ - 1, low_y, radius); - } - else { + if ( waveform_style_bars_ ) { + drawRoundedRectangle(x, high_y, x + bar_width_ - 1, low_y - 1, radius); + x += bar_width_ + bar_gap_; + } else { gdImageLine(image_, x, low_y, x, high_y, waveform_color_); + x++; } - - x += bar_width_ + bar_gap_; } available_height -= row_height + 1; @@ -297,41 +298,30 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const } } -void GdImageRenderer::drawRoundedRectangle( - const int x1, - const int y1, - const int x2, - const int y2, - const int radius) const -{ - gdImageFilledRectangle(image_, x1, y1, x2, y2, waveform_color_); - - if (bar_style_rounded_) { - gdImageFilledArc( - image_, - x1 + radius, - y1, - radius * 2, - radius, - 180, - 360, - waveform_color_, - gdStyledBrushed - ); +void GdImageRenderer::drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const float radius) const + { + if( !bar_style_rounded_) { + gdImageFilledRectangle(image_, x1, y1, x2, y2, waveform_color_); + return; + } - gdImageFilledArc( - image_, - x1 + radius, - y2, - radius * 2, - radius, - 0, - 180, - waveform_color_, - gdStyledBrushed - ); + double rad = fmin(radius, floor(fmin((x2 - x1) / 2, (y2 - y1) / 2))); + int width = x2 - x1; + + if ( rad != 0 && rad * 2 != width ) { + // We need to fill the gap between the individual radiuses + gdImageFilledRectangle(image_, x1 + rad, y1, x2 - rad, y1 + rad, waveform_color_); + gdImageFilledRectangle(image_, x1 + rad, y2 - rad, x2 - rad, y2, waveform_color_); } -} + + // Drawing the arcs + gdImageFilledArc(image_, x1 + rad, y1 + rad, rad * 2, rad * 2, 180, 270, waveform_color_, gdStyledBrushed); // top left radius + gdImageFilledArc(image_, x2 - rad, y1 + rad, rad * 2, rad * 2, 270, 0, waveform_color_, gdStyledBrushed); // top right radius + gdImageFilledArc(image_, x2 - rad, y2 - rad, rad * 2, rad * 2, 0, 90, waveform_color_, gdStyledBrushed); // bottom right radius + gdImageFilledArc(image_, x1 + rad, y2 - rad, rad * 2, rad * 2, 90, 180, waveform_color_, gdStyledBrushed); // bottom left + + gdImageFilledRectangle(image_, x1, y1 + rad, x2, y2 - rad, waveform_color_); + } //------------------------------------------------------------------------------ diff --git a/src/GdImageRenderer.h b/src/GdImageRenderer.h index 3da4074..a3305ff 100644 --- a/src/GdImageRenderer.h +++ b/src/GdImageRenderer.h @@ -52,6 +52,7 @@ class GdImageRenderer int image_width, int image_height, const WaveformColors& colors, + bool waveform_style_bars, int bar_width, int bar_gap, bool bar_style_rounded, @@ -74,14 +75,7 @@ class GdImageRenderer void drawBorder() const; void drawWaveform(const WaveformBuffer& buffer) const; - - void drawRoundedRectangle( - const int x1, - const int y1, - const int x2, - const int y2, - const int radius - ) const; + void drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const float radius) const; void drawTimeAxisLabels() const; @@ -111,6 +105,7 @@ class GdImageRenderer int waveform_color_; int axis_label_color_; + bool waveform_style_bars_; int bar_width_; int bar_gap_; bool bar_style_rounded_; diff --git a/src/OptionHandler.cpp b/src/OptionHandler.cpp index ec9e43e..26a1bf5 100644 --- a/src/OptionHandler.cpp +++ b/src/OptionHandler.cpp @@ -493,6 +493,7 @@ bool OptionHandler::renderWaveformImage( options.getImageWidth(), options.getImageHeight(), colors, + options.isWaveFormStyleBars(), options.getBarWidth(), options.getBarGap(), options.isBarStyleRounded(), diff --git a/src/Options.cpp b/src/Options.cpp index 9cef2c9..6cb4f33 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -165,6 +165,10 @@ bool Options::parseCommandLine(int argc, const char* const* argv) "waveform-color", po::value(&waveform_color_), "wave color (rrggbb[aa])" + )( + "waveform-style-bars", + po::value(&waveform_style_bars_)->default_value(false), + "waveform style bars (default to normal))" )( "bar-width", po::value(&bar_width_)->default_value(1), diff --git a/src/Options.h b/src/Options.h index 7216eb6..b4bca3c 100644 --- a/src/Options.h +++ b/src/Options.h @@ -103,6 +103,7 @@ class Options bool getRenderAxisLabels() const { return render_axis_labels_; } + bool isWaveFormStyleBars() const { return waveform_style_bars_; } int getBarWidth() const { return bar_width_; } int getBarGap() const { return bar_gap_; } bool isBarStyleRounded() const { return bar_style_rounded_; } @@ -169,6 +170,7 @@ class Options RGBA waveform_color_; RGBA axis_label_color_; + bool waveform_style_bars_; int bar_width_; int bar_gap_; bool bar_style_rounded_; From ade05ef96baf9670f76a1cb7152425cbd5375cf7 Mon Sep 17 00:00:00 2001 From: Yannick Gagnon Date: Tue, 16 May 2023 07:25:00 -0400 Subject: [PATCH 08/10] Fix float to int automatic conversation issues --- src/GdImageRenderer.cpp | 80 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index 623405b..29f27c9 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -310,17 +310,81 @@ void GdImageRenderer::drawRoundedRectangle(const int x1, const int y1, const int if ( rad != 0 && rad * 2 != width ) { // We need to fill the gap between the individual radiuses - gdImageFilledRectangle(image_, x1 + rad, y1, x2 - rad, y1 + rad, waveform_color_); - gdImageFilledRectangle(image_, x1 + rad, y2 - rad, x2 - rad, y2, waveform_color_); + gdImageFilledRectangle( + image_, + (int)(x1 + rad), + y1, + (int)(x2 - rad), + (int)(y1 + rad), + waveform_color_ + ); + gdImageFilledRectangle( + image_, + (int)(x1 + rad), + (int)(y2 - rad), + (int)(x2 - rad), + y2, + waveform_color_ + ); } // Drawing the arcs - gdImageFilledArc(image_, x1 + rad, y1 + rad, rad * 2, rad * 2, 180, 270, waveform_color_, gdStyledBrushed); // top left radius - gdImageFilledArc(image_, x2 - rad, y1 + rad, rad * 2, rad * 2, 270, 0, waveform_color_, gdStyledBrushed); // top right radius - gdImageFilledArc(image_, x2 - rad, y2 - rad, rad * 2, rad * 2, 0, 90, waveform_color_, gdStyledBrushed); // bottom right radius - gdImageFilledArc(image_, x1 + rad, y2 - rad, rad * 2, rad * 2, 90, 180, waveform_color_, gdStyledBrushed); // bottom left - - gdImageFilledRectangle(image_, x1, y1 + rad, x2, y2 - rad, waveform_color_); + gdImageFilledArc( + image_, + (int)(x1 + rad), + (int)(y1 + rad), + (int)(rad * 2), + (int)(rad * 2), + 180, + 270, + waveform_color_, + gdStyledBrushed + ); // top left radius + + gdImageFilledArc( + image_, + (int)(x2 - rad), + (int)(y1 + rad), + (int)(rad * 2), + (int)(rad * 2), + 270, + 0, + waveform_color_, + gdStyledBrushed + ); // top right radius + + gdImageFilledArc( + image_, + (int)(x2 - rad), + (int)(y2 - rad), + (int)(rad * 2), + (int)(rad * 2), + 0, + 90, + waveform_color_, + gdStyledBrushed + ); // bottom right radius + + gdImageFilledArc( + image_, + (int)(x1 + rad), + (int)(y2 - rad), + (int)(rad * 2), + (int)(rad * 2), + 90, + 180, + waveform_color_, + gdStyledBrushed + ); // bottom left + + gdImageFilledRectangle( + image_, + x1, + (int)(y1 + rad), + x2, + (int)(y2 - rad), + waveform_color_ + ); } //------------------------------------------------------------------------------ From 856d6ca45c80d42a31143870f6806900497a351b Mon Sep 17 00:00:00 2001 From: Yannick Gagnon Date: Tue, 16 May 2023 08:35:13 -0400 Subject: [PATCH 09/10] Center bars across the y axis when generating bar waveform-style --- src/GdImageRenderer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index 29f27c9..a511c17 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -271,20 +271,27 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const } const int height = waveform_bottom_y - waveform_top_y + 1; + const int imageMiddleY = height / 2; for (int i = start_index, x = start_x; i < buffer_size; ++i) { if (x + bar_width_ > max_x) { break; } // Convert range [-32768, 32727] to [0, 65535] - int low = MathUtil::scale(buffer.getMinSample(channel, i), amplitude_scale) + 32768; - int high = MathUtil::scale(buffer.getMaxSample(channel, i), amplitude_scale) + 32768; + const int low = MathUtil::scale(buffer.getMinSample(channel, i), amplitude_scale) + 32768; + const int high = MathUtil::scale(buffer.getMaxSample(channel, i), amplitude_scale) + 32768; // Scale to fit the bitmap int high_y = waveform_top_y + height - 1 - high * height / 65536; int low_y = waveform_top_y + height - 1 - low * height / 65536; if ( waveform_style_bars_ ) { + const int barMiddleY = (low_y - high_y) / 2 + high_y; + const int distanceFromMiddleY = imageMiddleY - barMiddleY; + + high_y += distanceFromMiddleY; + low_y += distanceFromMiddleY; + drawRoundedRectangle(x, high_y, x + bar_width_ - 1, low_y - 1, radius); x += bar_width_ + bar_gap_; } else { From 3aa9d9578f1a84dab94d8bb797dfa5bb3ec81001 Mon Sep 17 00:00:00 2001 From: Yannick Gagnon Date: Tue, 16 May 2023 08:55:40 -0400 Subject: [PATCH 10/10] Rebase bbc/bar-customisation-for-png and Apply formatting --- src/GdImageRenderer.cpp | 15 +++++++++------ src/GdImageRenderer.h | 7 ++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/GdImageRenderer.cpp b/src/GdImageRenderer.cpp index a511c17..1318964 100644 --- a/src/GdImageRenderer.cpp +++ b/src/GdImageRenderer.cpp @@ -125,8 +125,6 @@ bool GdImageRenderer::create( return false; } - image_ = gdImageCreateTrueColor(image_width, image_height); - if (image_ == nullptr) { log(Error) << "Failed to create image\n"; return false; @@ -285,7 +283,7 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const int high_y = waveform_top_y + height - 1 - high * height / 65536; int low_y = waveform_top_y + height - 1 - low * height / 65536; - if ( waveform_style_bars_ ) { + if (waveform_style_bars_) { const int barMiddleY = (low_y - high_y) / 2 + high_y; const int distanceFromMiddleY = imageMiddleY - barMiddleY; @@ -305,9 +303,14 @@ void GdImageRenderer::drawWaveform(const WaveformBuffer& buffer) const } } -void GdImageRenderer::drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const float radius) const +void GdImageRenderer::drawRoundedRectangle( + const int x1, + const int y1, + const int x2, + const int y2, + const float radius) const { - if( !bar_style_rounded_) { + if(!bar_style_rounded_) { gdImageFilledRectangle(image_, x1, y1, x2, y2, waveform_color_); return; } @@ -315,7 +318,7 @@ void GdImageRenderer::drawRoundedRectangle(const int x1, const int y1, const int double rad = fmin(radius, floor(fmin((x2 - x1) / 2, (y2 - y1) / 2))); int width = x2 - x1; - if ( rad != 0 && rad * 2 != width ) { + if (rad != 0 && rad * 2 != width) { // We need to fill the gap between the individual radiuses gdImageFilledRectangle( image_, diff --git a/src/GdImageRenderer.h b/src/GdImageRenderer.h index a3305ff..97bd5e8 100644 --- a/src/GdImageRenderer.h +++ b/src/GdImageRenderer.h @@ -75,7 +75,12 @@ class GdImageRenderer void drawBorder() const; void drawWaveform(const WaveformBuffer& buffer) const; - void drawRoundedRectangle(const int x1, const int y1, const int x2, const int y2, const float radius) const; + void drawRoundedRectangle( + const int x1, + const int y1, + const int x2, + const int y2, + const float radius) const; void drawTimeAxisLabels() const;