From 77e8c510f48f91fc2c4b417a754327deb3386f18 Mon Sep 17 00:00:00 2001 From: markmental Date: Fri, 21 Nov 2025 02:56:46 +0000 Subject: [PATCH] Initial Commit --- .gitignore | 2 + Gemfile | 7 ++ README.md | 223 ++++++++++++++++++++++++++++++++++++ app.rb | 292 ++++++++++++++++++++++++++++++++++++++++++++++++ start-server.sh | 3 + 5 files changed, 527 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 README.md create mode 100644 app.rb create mode 100755 start-server.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..56af776 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +public/ +*.lock diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..9949163 --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem "sinatra" +gem "sinatra-contrib" +gem "mini_magick" +gem "rackup" +gem "puma" diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ba04c8 --- /dev/null +++ b/README.md @@ -0,0 +1,223 @@ +# πŸ“Έ Rubymagick β€” Simple Ruby Image Converter & Pixelation Tool + +**Rubymagick** is a tiny Ruby/Sinatra web app for converting images (like PNGs) into **JPEGs**, shrinking file sizes, or applying **fun retro effects** such as CRT scanlines and adjustable pixelation. + +It’s designed to be lightweight, easy to run locally, and perfect for: + +* Compressing PNGs into small JPGs +* Preparing images for websites or blog posts +* Pixelating art or photos (SNES / PS1 / Game Boy style) +* Adding fake CRT scanlines for retro aesthetics +* Quickly batch-converting images through a browser + +No account, no cloud upload β€” just run it on your own machine. + +--- + +## ✨ Features + +### βœ”οΈ JPEG Conversion + +Upload any image (PNG, JPG, WebP, HEIC, etc.) and convert it into a JPEG with adjustable quality. + +### βœ”οΈ Adjustable JPEG Quality Slider + +Choose any value from **10–100**. Lower quality = smaller file size. + +### βœ”οΈ Pixelation Effect (with slider) + +A fully adjustable pixelation slider: + +* Factor **2** β†’ subtle pixelation +* Factor **8** β†’ chunky SNES/GBA style +* Factor **12–25** β†’ extreme blocky PS1 / Minecraft look + +### βœ”οΈ CRT / Scanline Effect + +Simulates a low-resolution CRT display: + +* Downscales to fake 480p +* Adds contrast + noise +* Optionally overlays scanlines if `public/scanlines.png` exists + +### βœ”οΈ Local, Private, Simple + +Everything runs on your machine. +Nothing leaves your computer. + +--- + +## πŸ›  Requirements + +You need the following gems: + +``` +sinatra +sinatra-contrib +mini_magick +rackup +puma +``` + +Install them with: + +```bash +gem install sinatra sinatra-contrib mini_magick rackup puma +``` + +And you must have ImageMagick installed: + +### Debian/Ubuntu + +```bash +sudo apt install imagemagick +``` + +### Fedora/Rocky/RHEL + +```bash +sudo dnf install imagemagick +``` + +### Arch + +```bash +sudo pacman -S imagemagick +``` + +--- + +## πŸš€ Running the App + +Save the project as `app.rb`, then run: + +```bash +bundle exec ruby app.rb +``` + +Or if you're not using Bundler: + +```bash +ruby app.rb +``` + +A provided `start-server.sh` Bash script is also available + +Then visit: + +``` +http://localhost:4567/ +``` + +--- + +## πŸ–Ό How to Use + +1. Open the web UI. +2. Upload an image (PNG, JPG, WEBP, etc.) +3. Choose your desired JPEG output quality. +4. Select an effect (None, CRT, or Pixelated). +5. If you choose Pixelated β†’ adjust the intensity slider. +6. Click **Convert to .jpg**. +7. Download your JPEG file. + +Converted files are stored in: + +``` +public/output/ +``` + +--- + +## πŸŽ› Effects Explained + +### πŸ”Έ CRT / Scanline Mode + +This effect simulates an old-school CRT monitor: + +* Resizes image down to low resolution +* Boosts contrast +* Adds light noise for texture +* If `public/scanlines.png` exists, overlays it + +Good for: + +* Retro edits +* Vaporwave / synthwave style +* Terminal-style effects + +--- + +### πŸ”Έ Pixelation Mode (Adjustable) + +Uses nearest-neighbor downscale β†’ upscale trick. + +Formula: + +``` +small_w = width / factor +small_h = height / factor +``` + +Then scales back up with no filtering. + +Great for: + +* Pixel art effects +* Lo-fi game textures +* Retro aesthetic +* Meme-style blur blocks + +--- + +## πŸ“ Optional: Add Custom Scanlines + +Place a PNG named: + +``` +public/scanlines.png +``` + +It will be automatically applied when CRT mode is selected. + +--- + +## 🧩 Project Structure + +Typical layout: + +``` +rubymagick/ + β”œβ”€ app.rb + β”œβ”€ Gemfile + β”œβ”€ public/ + β”‚ β”œβ”€ output/ + β”‚ └─ scanlines.png (optional) +``` + +Output files go into `public/output/`. + +--- + +## πŸ“ About This App + +Rubymagick is intentionally small and hackable. +It’s perfect as: + +* A personal utility +* A learning project for Sinatra +* A way to explore ImageMagick through Ruby +* A lightweight image-prep tool for websites + +You can expand it easily with: + +* WebP/AVIF export +* Batch uploads +* Color palette reduction (NES/Game Boy) +* VHS distortion effects +* CLI wrapper mode + +Just modify the helper functions or add more UI elements. + +--- + diff --git a/app.rb b/app.rb new file mode 100644 index 0000000..69eab38 --- /dev/null +++ b/app.rb @@ -0,0 +1,292 @@ +#!/usr/bin/env ruby +# app.rb β€” Simple Ruby/Sinatra Image β†’ JPEG converter +# Supports: +# - JPEG quality slider +# - CRT/scanline retro effect +# - Pixelation (with user slider) +# +# Requires: +# gem install sinatra sinatra-contrib mini_magick rackup puma +# sudo apt install imagemagick +# +# Run: +# bundle exec ruby app.rb +# +# Then open: http://localhost:4567/ + +require "sinatra" +require "sinatra/reloader" if development? +require "mini_magick" +require "fileutils" +require "securerandom" + +set :bind, "0.0.0.0" +set :port, 4567 +set :public_folder, File.join(__dir__, "public") + +OUTPUT_DIR = File.join(settings.public_folder, "output") +FileUtils.mkdir_p OUTPUT_DIR + +# ------------------------------------------------------------------- +# HELPERS β€” Image effects + utilities +# ------------------------------------------------------------------- +helpers do + # ----------------------------------------------------------------- + # CRT / Scanline effect + # ----------------------------------------------------------------- + def apply_crt_effect(image) + image.combine_options do |c| + c.resize "640x480" + c.contrast + c.noise "2" + end + + scanlines_path = File.join(settings.public_folder, "scanlines.png") + if File.exist?(scanlines_path) + scan = MiniMagick::Image.open(scanlines_path) + scan.resize "#{image.width}x#{image.height}!" + image = image.composite(scan) do |c| + c.compose "overlay" + c.gravity "center" + end + end + + image + end + + # ----------------------------------------------------------------- + # Pixelation effect with user-adjustable factor + # ----------------------------------------------------------------- + def apply_pixelate_effect(image, factor = 8) + width = image.width + height = image.height + + small_w = [width / factor, 1].max + small_h = [height / factor, 1].max + + image.combine_options do |c| + c.filter "point" + c.resize "#{small_w}x#{small_h}!" + c.resize "#{width}x#{height}!" + end + + image + end + + # Human-readable formatting + def human_size(bytes) + kb = bytes / 1024.0 + return "#{kb.round(1)} KB" if kb < 1024 + mb = kb / 1024.0 + "#{mb.round(2)} MB" + end +end + +# ------------------------------------------------------------------- +# ROUTES +# ------------------------------------------------------------------- +get "/" do + erb :index +end + +post "/convert" do + unless params[:image] && params[:image][:tempfile] + @error = "Please choose an image file." + return erb :index + end + + tempfile = params[:image][:tempfile] + filename = params[:image][:filename] + quality = (params[:quality] || "80").to_i + effect = params[:effect] + + quality = 1 if quality < 1 + quality = 100 if quality > 100 + + begin + image = MiniMagick::Image.open(tempfile.path) + + # ------------------------------ + # Apply effects + # ------------------------------ + case effect + when "crt" + image = apply_crt_effect(image) + @effect_used = "CRT / scanline" + + when "pixel" + factor = (params[:pixel_factor] || 8).to_i + factor = 2 if factor < 2 + factor = 25 if factor > 25 + image = apply_pixelate_effect(image, factor) + @effect_used = "Pixelated (factor #{factor})" + + else + @effect_used = "None" + end + + # Convert to JPEG + image.format "jpg" + image.quality quality.to_s + + output_name = "converted-#{SecureRandom.hex(8)}.jpg" + output_path = File.join(OUTPUT_DIR, output_name) + image.write(output_path) + + @original_name = filename + @output_url = "/output/#{output_name}" + @output_size = human_size(File.size(output_path)) + @chosen_quality = quality + + erb :result + + rescue => e + @error = "Conversion failed: #{e.message}" + erb :index + end +end + +# ------------------------------------------------------------------- +# INLINE HTML TEMPLATES +# ------------------------------------------------------------------- +__END__ + +@@layout + + + + + + + Rubymagick JPG Converter + + + +

♦️ Image β†’ JPEG Converter

+ <%= yield %> + + + +@@index +
+ <% if @error %>
<%= @error %>
<% end %> + +
+ + + + + + + + + + + + + + + +
+
+ +@@result +
+

Conversion complete

+ +

+ Original: <%= @original_name %>
+ Quality: <%= @chosen_quality %>
+ Effect: <%= @effect_used %>
+ Output size: <%= @output_size %> +

+ + Converted image preview + +
+ Download JPEG +
+ diff --git a/start-server.sh b/start-server.sh new file mode 100755 index 0000000..0692b26 --- /dev/null +++ b/start-server.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +bundle3.3 exec ruby app.rb