Skip to content

Repository files navigation

Ruby Libgd


Germán Alberto Giménez Silva | Remote


Create Images with Ruby – Dynamic Image Generation using ruby-libgd

Create images with Ruby using the GD graphics library. This project demonstrates dynamic image generation in Ruby, allowing developers to programmatically create PNG and JPEG images.

# ruby-libgd is evolving very fast, so some examples may temporarily stop working
# Please report issues or ask for help — feedback is very welcome
# https://github.com/ggerman/ruby-libgd/issues or ggerman@gmail.com

Library Status

CI

ImplementedImplementedImplemented

Note: The images shown in Table 1, along with the code used to generate them, are available in the examples/ folder.

Native GD bindings for modern Ruby

What is ruby-libgd?

ruby-libgd is a modern native Ruby binding to the GD Graphics Library, providing Ruby with a fast, embeddable, server-side graphics engine.

It enables Ruby to generate images, charts, dashboards, GIS tiles, and scientific graphics without spawning external processes.

🐧Installation (Debian / Ubuntu /Dockerfile)

gem install ruby-libgd

System dependencies:

apt install -y libgd-dev pkg-config


🍎 macOS (Intel & Apple Silicon)

ruby-libgd is a native extension and depends on libgd, which must be installed via Homebrew.

Install libgd

brew install gd

Verify Homebrew’s install path:

brew --prefix gd

Typical values: Apple Silicon (M1 / M2 / M3): /opt/homebrew

Intel Macs: /usr/local

Install ruby-libgd

Apple Silicon (M1 / M2 / M3)

Homebrew installs libraries into /opt/homebrew, which Ruby’s native extension builder does not detect automatically.

Install using:

gem install ruby-libgd -- --with-gd-dir=/opt/homebrew

Intel macOS

gem install ruby-libgd

📚 Documentation


Examples:

All runnable examples live in:

examples/ basics/ image_processing/ charts/ images/

Each Ruby script in examples/ generates an image in examples/images/.

Links

GitHub: https://github.com/ggerman/ruby-libgd
RubyGems: https://rubygems.org/gems/ruby-libgd
Article: https://rubystacknews.com/2026/01/05/ruby-can-create-images-again/


Build & Runtime Environment

ruby-libgd is developed and tested against libgd 2.3.3 using a reproducible Docker environment.

This ensures that the native extension is compiled against a known, stable GD ABI and behaves consistently across systems.

Reference Dockerfile

FROM ruby:3.3
RUN apt update && apt -y upgrade
RUN apt install -y \
libgd-dev \
libgd3 \
libgd-tools \
pkg-config \
ruby-dev \
build-essential \
valgrind
RUN printf "prefix=/usr\n\exec_prefix=\${prefix}\n\libdir=\${exec_prefix}/lib/x86_64-linux-gnu\n\includedir=\${prefix}/include\n\\n\Name: gd\n\Description: GD Graphics Library\n\Version: 2.3\n\Libs: -L\${libdir} -lgd\n\Cflags: -I\${includedir}\n" \
> /usr/lib/x86_64-linux-gnu/pkgconfig/gd.pc
ENV PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
# Enforce dependency lockfile reproducibilityRUN bundle config --global frozen 1
COPY . .

Why this matters

ruby-libgd is a native C extension. The exact libgd version and build flags directly affect:

  • Alpha blending

  • Color accuracy

  • Filter behavior

  • Memory safety

Using a pinned, containerized build environment guarantees that:

  • The extension is compiled against libgd 2.3.x

  • pkg-config resolves the correct headers and linker flags

  • CI, contributors, and users see identical behavior

This is especially important for GIS, map tiles, and image pipelines where pixel-level consistency matters.

Example:

RubyStackNews

require"gd"WIDTH=800HEIGHT=400img=GD::Image.new(WIDTH,HEIGHT)# ----------------------------# Pastel palette# ----------------------------bg_top=[244,240,255]# lavenderbg_bottom=[230,248,255]# light skyaccent1=[255,140,180]# pastel pinkaccent2=[120,200,255]# pastel bluetext_main=[60,70,120]# deep indigoshadow=[180,190,220]# ----------------------------# Soft gradient background# ----------------------------(0...HEIGHT).eachdo |y|
t=y.to_f / (HEIGHT - 1)r=(bg_top[0] + (bg_bottom[0] - bg_top[0]) * t).to_ig=(bg_top[1] + (bg_bottom[1] - bg_top[1]) * t).to_ib=(bg_top[2] + (bg_bottom[2] - bg_top[2]) * t).to_iimg.line(0,y,WIDTH - 1,y,[r,g,b])end# ----------------------------# Floating pastel blobs# ----------------------------img.filled_circle(120,100,80,accent2)img.filled_circle(680,280,100,accent1)img.filled_circle(700,80,50,[200,230,255])# ----------------------------# Text# ----------------------------font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"title_size=52subtitle_size=20title="RubyStackNews"subtitle="The pulse of the Ruby ecosystem"# Manual centeringtitle_x=80title_y=190# Soft shadowimg.text(title,{x: title_x + 2,y: title_y + 2,size: title_size,color: shadow,font: font})# Main titleimg.text(title,{x: title_x,y: title_y,size: title_size,color: text_main,font: font})# Subtitleimg.text(subtitle,{x: title_x,y: title_y + 45,size: subtitle_size,color: [100,110,160],font: font})# ----------------------------# Call-to-action pill# ----------------------------pill_x=80pill_y=260pill_w=260pill_h=44img.filled_rectangle(pill_x,pill_y,pill_x + pill_w,pill_y + pill_h,[255,255,255])img.rectangle(pill_x,pill_y,pill_x + pill_w,pill_y + pill_h,accent2,thickness: 2)img.text("rubystacknews.com",{x: pill_x + 22,y: pill_y + 30,size: 20,color: text_main,font: font})# ----------------------------# Save# ----------------------------img.save("images/rubystacknews-banner.png")puts"Saved images/rubystacknews-banner.png"

License

MIT License. Copyright (c) 2025 Germán Alberto Giménez Silva.

About

Native Ruby bindings for the GD graphics library, providing fast image processing, drawing, filters, and alpha-blending without external dependencies.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

103 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages