Skip to content

Commit

Permalink
Linked libraries no longer automatically required
Browse files Browse the repository at this point in the history
  • Loading branch information
Vici37 committed Mar 23, 2023
1 parent 2d0c196 commit d9bed74
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 35 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Crystal Image (Processing)
# [Crystal Image (Processing)](http://troy.sornson.io/cr-image/)

This shard aims to provide feature rich image processing abilities, both for the purpose of
image manipulation as well as feature / information extraction from those images.
Expand All @@ -22,6 +22,23 @@ All sample images used are from [Unsplash](https://unsplash.com/).

## Usage

CrImage supports the formats:
* PPM
* JPEG (requires `libturbojpeg`)
* PNG (requirens `libspng`)
* WebP (requires `libwebp`)

For the formats that require a linked library, they must be `require`d explicitly:

```crystal
require "cr-image"
require "cr-image/jpeg"
require "cr-image/png"
require "cr-image/webp"
```

### Example

Assuming an image `moon.jpg` already exists

<img src="https://raw.githubusercontent.com/Vici37/cr-image/master/docs/images/moon.jpg" alt="Picture of moon"/>
Expand Down
3 changes: 3 additions & 0 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
require "digest"
require "spectator"
require "../src/cr-image"
require "../src/jpeg"
require "../src/png"
require "../src/webp"
require "./helpers/**"

module SpecHelper
Expand Down
16 changes: 15 additions & 1 deletion src/cr-image.cr
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
require "./cr-image/**"
require "./cr-image/operation/*"
require "./cr-image/format/save"
require "./cr-image/format/open"

# Native crystal image format implementations
require "./cr-image/format/ppm"

require "./cr-image/channel_type"
require "./cr-image/color"
require "./cr-image/exception"
require "./cr-image/mask"
require "./cr-image/region"
require "./cr-image/image"
require "./cr-image/grayscale_image"
require "./cr-image/rgba_image"
11 changes: 6 additions & 5 deletions src/cr-image/format/open.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
module CrImage::Format::Open
# Reads this image from file using the provided filename.
def open(filename : String) : self
{% begin %}
case filename
when .ends_with?(".ppm") then File.open(filename) { |f| self.from_ppm(f) }
when .ends_with?(".jpg"), .ends_with?(".jpeg") then File.open(filename) { |f| self.from_jpeg(f) }
when .ends_with?(".webp") then File.open(filename) { |f| self.from_webp(f) }
when .ends_with?(".png") then File.open(filename) { |f| self.from_png(f) }
else raise "Unknown file extension for filename #{filename}, only support .webp, .png, .ppm, .jpg, and .jpeg"
{% for format in SUPPORTED_FORMATS %}
when .ends_with?({{format[:extension]}}) then File.open(filename) { |file| self.from_{{format[:method].id}}(file) }
{% end %}
else raise Exception.new "Unknown file extension for filename #{filename}, cr-image only supports {{CrImage::Format::SUPPORTED_FORMATS.map(&.[:extension].id).join(", ").id}}"
end
{% end %}
end
end
2 changes: 2 additions & 0 deletions src/cr-image/format/ppm.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# image.save("other_image.ppm")
# ```
module CrImage::Format::PPM
{% CrImage::Format::SUPPORTED_FORMATS << {extension: ".ppm", method: "ppm"} %}

macro included
# Read `image_data` as PPM encoded bytes
def self.from_ppm(image_data : Bytes) : self
Expand Down
32 changes: 19 additions & 13 deletions src/cr-image/format/save.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@
# image.save("image.jpg")
# ```
# See `Open` for a convenience method to read images from the filesystem
module CrImage::Format::Save
# Write this image to file using the provided filename.
#
# This method _will not_ create intermediate directory paths. This method will throw an
# error if they don't exist.
def save(filename : String) : self
File.open(filename, "w") do |file|
case filename
when .ends_with?(".ppm") then to_ppm(file)
when .ends_with?(".jpg"), .ends_with?(".jpeg") then to_jpeg(file)
when .ends_with?(".webp") then to_webp(file)
when .ends_with?(".png") then to_png(file)
else raise "Unknown file extension for filename #{filename}, only support .webp, .png, .ppm, .jpg, and .jpeg"
module CrImage::Format
SUPPORTED_FORMATS = [] of Nil

module Save
# Write this image to file using the provided filename.
#
# This method _will not_ create intermediate directory paths. This method will throw an
# error if they don't exist.
def save(filename : String) : self
File.open(filename, "w") do |file|
{% begin %}
case filename
{% for format in SUPPORTED_FORMATS %}
when .ends_with?({{format[:extension]}}) then to_{{format[:method].id}}(file)
{% end %}
else raise Exception.new "Unknown file extension for filename #{filename}, cr-image only supports {{CrImage::Format::SUPPORTED_FORMATS.map(&.[:extension].id).join(", ").id}}"
end
{% end %}
end
end

self
end
end
15 changes: 8 additions & 7 deletions src/cr-image/image.cr
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
require "./bindings/*"
require "./format/*"
require "./operation/*"

# Common base class for `GrayscaleImage` and `RGBAImage`. All `Image`s are readable and saveable
# to the filesystem or `IO` stream.
abstract class CrImage::Image
macro subsclasses_include(mod)
{% for sub in @type.subclasses %}
class ::{{sub}}
include {{mod}}
end
{% end %}
end

macro inherited
include Format::JPEG
include Format::PPM
include Format::WebP
include Format::PNG

include Operation::BilinearResize
include Operation::BoxBlur
Expand Down
5 changes: 0 additions & 5 deletions src/cr-image/rgba_image.cr
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
require "./image"
require "./bindings/*"
require "./format/*"
require "./operation/*"

# An image with red, green, blue, and alpha color channels (i.e. a color image). This image type is likely the one read from and written to file (or `IO`).
class CrImage::RGBAImage < CrImage::Image
property red : Array(UInt8)
Expand Down
4 changes: 4 additions & 0 deletions src/jpeg.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require "./cr-image"
require "./lib-formats/jpeg"

CrImage::Image.subsclasses_include(CrImage::Format::JPEG)
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 6 additions & 1 deletion src/cr-image/format/jpeg.cr → src/lib-formats/jpeg.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "../bindings/lib_jpeg_turbo"
require "./bindings/lib_jpeg_turbo"

# Provides methods to read from and write to jpeg. Requires `libturbojpeg` to function.
#
Expand All @@ -13,6 +13,11 @@ require "../bindings/lib_jpeg_turbo"
# image.save("other_image.jpg")
# ```
module CrImage::Format::JPEG
{%
CrImage::Format::SUPPORTED_FORMATS << {extension: ".jpeg", method: "jpeg"}
CrImage::Format::SUPPORTED_FORMATS << {extension: ".jpg", method: "jpeg"}
%}

macro included
# Read `image_data` as JPEG encoded bytes
def self.from_jpeg(image_data : Bytes) : self
Expand Down
4 changes: 3 additions & 1 deletion src/cr-image/format/png.cr → src/lib-formats/png.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "../bindings/lib_spng"
require "./bindings/lib_spng"

# Provides methods to read from and write to PNG. Requires `libspng` to function.
#
Expand All @@ -13,6 +13,8 @@ require "../bindings/lib_spng"
# image.save("other_image.png")
# ```
module CrImage::Format::PNG
{% CrImage::Format::SUPPORTED_FORMATS << {extension: ".png", method: "png"} %}

macro included
# Read `image_data` and PNG encoded bytes
def self.from_png(image_data : Bytes) : self
Expand Down
4 changes: 3 additions & 1 deletion src/cr-image/format/webp.cr → src/lib-formats/webp.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "../bindings/lib_webp"
require "./bindings/lib_webp"

# Provides methods to read from and write to WebP. Requires `libwebp` to function.
#
Expand All @@ -13,6 +13,8 @@ require "../bindings/lib_webp"
# image.save("other_image.webp")
# ```
module CrImage::Format::WebP
{% CrImage::Format::SUPPORTED_FORMATS << {extension: ".webp", method: "webp"} %}

macro included
# Read `image_data` as WebP encoded bytes
def self.from_webp(image_data : Bytes) : self
Expand Down
4 changes: 4 additions & 0 deletions src/png.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require "./cr-image"
require "./lib-formats/png"

CrImage::Image.subsclasses_include(CrImage::Format::PNG)
4 changes: 4 additions & 0 deletions src/webp.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require "./cr-image"
require "./lib-formats/webp"

CrImage::Image.subsclasses_include(CrImage::Format::WebP)

0 comments on commit d9bed74

Please sign in to comment.