diff --git a/.standard.yml b/.standard.yml new file mode 100644 index 00000000..2c2c8fb2 --- /dev/null +++ b/.standard.yml @@ -0,0 +1,14 @@ +# ChunkyPNG uses and enforces standard.rb as code style (see https://github.com/testdouble/standard). +# For backwards compatilibity and idiosyncratic preferences of the main author, +# there are some minor differences listed in here. + +ignore: +- lib/chunky_png/**/*.rb: + # We allow `for` loops in the codebase, especially in hot paths, + # because they perform better than `each` blocks. + - "Style/For" + +- spec/chunky_png/**/*.rb: + # In RSpec, having to follow this rule will cause expectations to + # be less readable, specifically blocks for the `change` matcher. + - "Lint/AmbiguousBlockAssociation" diff --git a/Gemfile b/Gemfile index 49f41111..970079bf 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,10 @@ -source 'https://rubygems.org' +source "https://rubygems.org" gemspec platforms :jruby do - gem 'jruby-openssl' + gem "jruby-openssl" end platform :rbx do - gem 'rubysl' + gem "rubysl" end diff --git a/Rakefile b/Rakefile index 2d4103bd..40c87458 100644 --- a/Rakefile +++ b/Rakefile @@ -1,11 +1,11 @@ require "bundler/gem_tasks" require "rspec/core/rake_task" -Dir['tasks/*.rake'].each { |file| load(file) } +Dir["tasks/*.rake"].each { |file| load(file) } RSpec::Core::RakeTask.new(:spec) do |task| task.pattern = "./spec/**/*_spec.rb" - task.rspec_opts = ['--color'] + task.rspec_opts = ["--color"] end task default: [:spec] diff --git a/benchmarks/decoding_benchmark.rb b/benchmarks/decoding_benchmark.rb index 479f1a3b..903dab8e 100644 --- a/benchmarks/decoding_benchmark.rb +++ b/benchmarks/decoding_benchmark.rb @@ -1,26 +1,26 @@ -require 'rubygems' -require 'bundler/setup' +require "rubygems" +require "bundler/setup" -require 'benchmark' -require 'chunky_png' +require "benchmark" +require "chunky_png" def image_file(name) - File.join(File.dirname(__FILE__), '..', 'spec', 'resources', name) + File.join(File.dirname(__FILE__), "..", "spec", "resources", name) end def image_data(name) data = nil - File.open(image_file(name), 'rb') { |f| data = f.read } + File.open(image_file(name), "rb") { |f| data = f.read } data end -no_filtering_stream = image_data('pixelstream_fast_rgba.png') -up_filtering_stream = image_data('pixelstream_reference.png') -paeth_filtering_stream = image_data('pixelstream_best_compression.png') -rgba_pixelstream = image_data('pixelstream.rgba') -rgb_pixelstream = image_data('pixelstream.rgb') +no_filtering_stream = image_data("pixelstream_fast_rgba.png") +up_filtering_stream = image_data("pixelstream_reference.png") +paeth_filtering_stream = image_data("pixelstream_best_compression.png") +rgba_pixelstream = image_data("pixelstream.rgba") +rgb_pixelstream = image_data("pixelstream.rgb") -n = (ENV['N'] || '5').to_i +n = (ENV["N"] || "5").to_i puts "---------------------------------------------" puts "ChunkyPNG (#{ChunkyPNG::VERSION}) decoding benchmark (n=#{n})" @@ -28,9 +28,9 @@ def image_data(name) puts Benchmark.bmbm do |x| - x.report('PNG - no filtering') { n.times { ChunkyPNG::Image.from_blob(no_filtering_stream) } } - x.report('PNG - UP filtering') { n.times { ChunkyPNG::Image.from_blob(up_filtering_stream) } } - x.report('PNG - PAETH filtering') { n.times { ChunkyPNG::Image.from_blob(paeth_filtering_stream) } } - x.report('From RGBA pixelstream') { n.times { ChunkyPNG::Image.from_rgba_stream(240, 180, rgba_pixelstream) } } - x.report('From RGB pixelstream') { n.times { ChunkyPNG::Image.from_rgb_stream(240, 180, rgb_pixelstream) } } + x.report("PNG - no filtering") { n.times { ChunkyPNG::Image.from_blob(no_filtering_stream) } } + x.report("PNG - UP filtering") { n.times { ChunkyPNG::Image.from_blob(up_filtering_stream) } } + x.report("PNG - PAETH filtering") { n.times { ChunkyPNG::Image.from_blob(paeth_filtering_stream) } } + x.report("From RGBA pixelstream") { n.times { ChunkyPNG::Image.from_rgba_stream(240, 180, rgba_pixelstream) } } + x.report("From RGB pixelstream") { n.times { ChunkyPNG::Image.from_rgb_stream(240, 180, rgb_pixelstream) } } end diff --git a/benchmarks/encoding_benchmark.rb b/benchmarks/encoding_benchmark.rb index e2e1cb73..9e74eef1 100644 --- a/benchmarks/encoding_benchmark.rb +++ b/benchmarks/encoding_benchmark.rb @@ -1,17 +1,20 @@ -require 'rubygems' -require 'bundler/setup' +require "rubygems" +require "bundler/setup" -require 'benchmark' -require 'chunky_png' +require "benchmark" +require "chunky_png" image = ChunkyPNG::Image.new(240, 180, ChunkyPNG::Color::TRANSPARENT) # set some random pixels + +# rubocop:disable Layout/ExtraSpacing, Layout/SpaceInsideParens image[10, 20] = ChunkyPNG::Color.rgba(255, 0, 0, 255) image[50, 87] = ChunkyPNG::Color.rgba( 0, 255, 0, 255) image[33, 99] = ChunkyPNG::Color.rgba( 0, 0, 255, 255) +# rubocop:enable Layout/ExtraSpacing, Layout/SpaceInsideParens -n = (ENV['N'] || '5').to_i +n = (ENV["N"] || "5").to_i puts "---------------------------------------------" puts "ChunkyPNG (#{ChunkyPNG::VERSION}) encoding benchmark (n=#{n})" @@ -19,22 +22,22 @@ puts Benchmark.bmbm do |x| - x.report('Autodetect (indexed)') { n.times { image.to_blob } } + x.report("Autodetect (indexed)") { n.times { image.to_blob } } # Presets - x.report(':no_compression') { n.times { image.to_blob(:no_compression) } } - x.report(':fast_rgba') { n.times { image.to_blob(:fast_rgba) } } - x.report(':fast_rgb') { n.times { image.to_blob(:fast_rgb) } } - x.report(':good_compression') { n.times { image.to_blob(:good_compression) } } - x.report(':best_compression') { n.times { image.to_blob(:best_compression) } } + x.report(":no_compression") { n.times { image.to_blob(:no_compression) } } + x.report(":fast_rgba") { n.times { image.to_blob(:fast_rgba) } } + x.report(":fast_rgb") { n.times { image.to_blob(:fast_rgb) } } + x.report(":good_compression") { n.times { image.to_blob(:good_compression) } } + x.report(":best_compression") { n.times { image.to_blob(:best_compression) } } # Some options - x.report(':rgb') { n.times { image.to_blob(color_mode: ChunkyPNG::COLOR_TRUECOLOR) } } - x.report(':rgba') { n.times { image.to_blob(color_mode: ChunkyPNG::COLOR_TRUECOLOR_ALPHA) } } - x.report(':indexed') { n.times { image.to_blob(color_mode: ChunkyPNG::COLOR_INDEXED) } } - x.report(':interlaced') { n.times { image.to_blob(interlaced: true) } } + x.report(":rgb") { n.times { image.to_blob(color_mode: ChunkyPNG::COLOR_TRUECOLOR) } } + x.report(":rgba") { n.times { image.to_blob(color_mode: ChunkyPNG::COLOR_TRUECOLOR_ALPHA) } } + x.report(":indexed") { n.times { image.to_blob(color_mode: ChunkyPNG::COLOR_INDEXED) } } + x.report(":interlaced") { n.times { image.to_blob(interlaced: true) } } # Exports - x.report('to RGBA pixelstream') { n.times { image.to_rgba_stream } } - x.report('to RGB pixelstream') { n.times { image.to_rgb_stream } } + x.report("to RGBA pixelstream") { n.times { image.to_rgba_stream } } + x.report("to RGB pixelstream") { n.times { image.to_rgb_stream } } end diff --git a/benchmarks/filesize_benchmark.rb b/benchmarks/filesize_benchmark.rb index 55066046..c3d2ebbe 100644 --- a/benchmarks/filesize_benchmark.rb +++ b/benchmarks/filesize_benchmark.rb @@ -1,10 +1,10 @@ -require 'rubygems' -require 'bundler/setup' +require "rubygems" +require "bundler/setup" -require 'benchmark' -require 'chunky_png' +require "benchmark" +require "chunky_png" -files = ['pixelstream_reference.png', 'operations.png', 'clock.png'] +files = ["pixelstream_reference.png", "operations.png", "clock.png"] def encode_png(image, constraints = {}) filesize = nil @@ -13,7 +13,7 @@ def encode_png(image, constraints = {}) end files.each do |file| - filename = File.join(File.dirname(__FILE__), '..', 'spec', 'resources', file) + filename = File.join(File.dirname(__FILE__), "..", "spec", "resources", file) image = ChunkyPNG::Canvas.from_file(filename) puts "#{file}: #{image.width}x#{image.height} - #{image.palette.size} colors" diff --git a/chunky_png.gemspec b/chunky_png.gemspec index f4155dea..9ba86ac2 100644 --- a/chunky_png.gemspec +++ b/chunky_png.gemspec @@ -1,11 +1,9 @@ -# -*- encoding: utf-8 -*- - -lib = File.expand_path('../lib', __FILE__) +lib = File.expand_path("../lib", __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'chunky_png/version' +require "chunky_png/version" Gem::Specification.new do |s| - s.name = 'chunky_png' + s.name = "chunky_png" # Do not change the version and date fields by hand. This will be done # automatically by the gem release script. @@ -31,22 +29,22 @@ Gem::Specification.new do |s| provides a massive speed boost to encoding and decoding. EOT - s.authors = ['Willem van Bergen'] - s.email = ['willem@railsdoctors.com'] - s.homepage = 'https://github.com/wvanbergen/chunky_png/wiki' - s.license = 'MIT' + s.authors = ["Willem van Bergen"] + s.email = ["willem@railsdoctors.com"] + s.homepage = "https://github.com/wvanbergen/chunky_png/wiki" + s.license = "MIT" s.metadata = { - "source_code_uri" => "https://github.com/wvanbergen/chunky_png", - "wiki_uri" => "https://github.com/wvanbergen/chunky_png/wiki", + "source_code_uri" => "https://github.com/wvanbergen/chunky_png", + "wiki_uri" => "https://github.com/wvanbergen/chunky_png/wiki", } - s.add_development_dependency('rake') - s.add_development_dependency('standard') - s.add_development_dependency('yard', '~> 0.9') - s.add_development_dependency('rspec', '~> 3') + s.add_development_dependency("rake") + s.add_development_dependency("standard") + s.add_development_dependency("yard", "~> 0.9") + s.add_development_dependency("rspec", "~> 3") - s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source' - s.extra_rdoc_files = ['README.md', 'BENCHMARKING.rdoc', 'CONTRIBUTING.rdoc', 'CHANGELOG.rdoc'] + s.rdoc_options << "--title" << s.name << "--main" << "README.rdoc" << "--line-numbers" << "--inline-source" + s.extra_rdoc_files = ["README.md", "BENCHMARKING.rdoc", "CONTRIBUTING.rdoc", "CHANGELOG.rdoc"] s.files = `git ls-files`.split($/) s.test_files = s.files.grep(%r{^(test|spec|features)/}) diff --git a/lib/chunky_png.rb b/lib/chunky_png.rb index 7506b64b..cc8cff8c 100644 --- a/lib/chunky_png.rb +++ b/lib/chunky_png.rb @@ -1,8 +1,7 @@ # Basic requirements from standard library -require 'set' -require 'zlib' -require 'stringio' -require 'enumerator' +require "set" +require "zlib" +require "stringio" # ChunkyPNG - the pure ruby library to access PNG files. # @@ -22,7 +21,6 @@ # # @author Willem van Bergen module ChunkyPNG - ################################################### # PNG international standard defined constants ################################################### @@ -131,7 +129,7 @@ class InvalidUTF8 < ChunkyPNG::Exception class ExpectationFailed < ChunkyPNG::Exception end - # Exception that is raised if an expectation fails. + # Exception that when provided coordinates are out of bounds for the canvas class OutOfBounds < ChunkyPNG::ExpectationFailed end @@ -152,21 +150,21 @@ class UnitsUnknown < ChunkyPNG::Exception EXTRA_BYTE = "\0".force_encoding(Encoding::BINARY).freeze end -require 'chunky_png/version' +require "chunky_png/version" # PNG file structure -require 'chunky_png/datastream' -require 'chunky_png/chunk' +require "chunky_png/datastream" +require "chunky_png/chunk" # Colors -require 'chunky_png/palette' -require 'chunky_png/color' +require "chunky_png/palette" +require "chunky_png/color" # Geometry -require 'chunky_png/point' -require 'chunky_png/vector' -require 'chunky_png/dimension' +require "chunky_png/point" +require "chunky_png/vector" +require "chunky_png/dimension" # Canvas / Image classes -require 'chunky_png/canvas' -require 'chunky_png/image' +require "chunky_png/canvas" +require "chunky_png/image" diff --git a/lib/chunky_png/canvas.rb b/lib/chunky_png/canvas.rb index 52a25bf8..22bd8ae0 100644 --- a/lib/chunky_png/canvas.rb +++ b/lib/chunky_png/canvas.rb @@ -1,14 +1,14 @@ -require 'chunky_png/canvas/png_encoding' -require 'chunky_png/canvas/png_decoding' -require 'chunky_png/canvas/adam7_interlacing' -require 'chunky_png/canvas/stream_exporting' -require 'chunky_png/canvas/stream_importing' -require 'chunky_png/canvas/data_url_exporting' -require 'chunky_png/canvas/data_url_importing' -require 'chunky_png/canvas/operations' -require 'chunky_png/canvas/drawing' -require 'chunky_png/canvas/resampling' -require 'chunky_png/canvas/masking' +require "chunky_png/canvas/png_encoding" +require "chunky_png/canvas/png_decoding" +require "chunky_png/canvas/adam7_interlacing" +require "chunky_png/canvas/stream_exporting" +require "chunky_png/canvas/stream_importing" +require "chunky_png/canvas/data_url_exporting" +require "chunky_png/canvas/data_url_importing" +require "chunky_png/canvas/operations" +require "chunky_png/canvas/drawing" +require "chunky_png/canvas/resampling" +require "chunky_png/canvas/masking" module ChunkyPNG # The ChunkyPNG::Canvas class represents a raster image as a matrix of @@ -56,7 +56,6 @@ class Canvas # This array always should have +width * height+ elements. attr_reader :pixels - ################################################################# # CONSTRUCTORS ################################################################# @@ -78,9 +77,10 @@ class Canvas def initialize(width, height, initial = ChunkyPNG::Color::TRANSPARENT) @width, @height = width, height - if initial.kind_of?(Array) - unless initial.length == width * height - raise ArgumentError, "The initial array should have #{width}x#{height} = #{width*height} elements!" + if initial.is_a?(Array) + pixel_count = width * height + unless initial.length == pixel_count + raise ArgumentError, "The initial array should have #{width}x#{height} = #{pixel_count} elements!" end @pixels = initial else @@ -104,7 +104,6 @@ def self.from_canvas(canvas) new(canvas.width, canvas.height, canvas.pixels.dup) end - ################################################################# # PROPERTIES ################################################################# @@ -274,7 +273,7 @@ def palette # @return [true, false] True if the size and pixel values of the other # canvas are exactly the same as this canvas's size and pixel values. def eql?(other) - other.kind_of?(self.class) && + other.is_a?(self.class) && other.pixels == pixels && other.width == width && other.height == height @@ -298,7 +297,7 @@ def to_image def inspect inspected = "<#{self.class.name} #{width}x#{height} [" for y in 0...height - inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(' ') << ']' + inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(" ") << "]" end inspected << "\n]>" end @@ -360,13 +359,13 @@ def assert_width!(vector_length) # Throws an exception if the matrix width and height does not match this canvas' dimensions. def assert_size!(matrix_width, matrix_height) - if width != matrix_width + if width != matrix_width raise ChunkyPNG::ExpectationFailed, - 'The width of the matrix does not match the canvas width!' + "The width of the matrix does not match the canvas width!" end if height != matrix_height raise ChunkyPNG::ExpectationFailed, - 'The height of the matrix does not match the canvas height!' + "The height of the matrix does not match the canvas height!" end true end diff --git a/lib/chunky_png/canvas/adam7_interlacing.rb b/lib/chunky_png/canvas/adam7_interlacing.rb index b9b8f447..38f34997 100644 --- a/lib/chunky_png/canvas/adam7_interlacing.rb +++ b/lib/chunky_png/canvas/adam7_interlacing.rb @@ -1,6 +1,5 @@ module ChunkyPNG class Canvas - # Methods for decoding and encoding Adam7 interlacing. # # Adam7 interlacing extracts 7 pass images out of a single image, that can be encoded to a @@ -8,7 +7,6 @@ class Canvas # ChunkyPNG canvas and is used to extract the pass images from the original image, or to # reconstruct an original image from separate pass images. module Adam7Interlacing - # Returns an array with the x-shift, x-offset, y-shift and y-offset for the requested pass. # @param [Integer] pass The pass number, should be in 0..6. def adam7_multiplier_offset(pass) @@ -16,7 +14,7 @@ def adam7_multiplier_offset(pass) 3 - (pass >> 1), pass & 1 == 0 ? 0 : 8 >> ((pass + 1) >> 1), pass == 0 ? 3 : 3 - ((pass - 1) >> 1), - pass == 0 || pass & 1 == 1 ? 0 : 8 >> (pass >> 1) + pass == 0 || pass & 1 == 1 ? 0 : 8 >> (pass >> 1), ] end @@ -26,8 +24,10 @@ def adam7_multiplier_offset(pass) # @param [Integer] original_height The height of the original image. def adam7_pass_size(pass, original_width, original_height) x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass) - [ (original_width - x_offset + (1 << x_shift) - 1) >> x_shift, - (original_height - y_offset + (1 << y_shift) - 1) >> y_shift] + [ + (original_width - x_offset + (1 << x_shift) - 1) >> x_shift, + (original_height - y_offset + (1 << y_shift) - 1) >> y_shift, + ] end # Returns an array of the dimension of all the pass images. diff --git a/lib/chunky_png/canvas/data_url_exporting.rb b/lib/chunky_png/canvas/data_url_exporting.rb index 778d263e..e7d99bcd 100644 --- a/lib/chunky_png/canvas/data_url_exporting.rb +++ b/lib/chunky_png/canvas/data_url_exporting.rb @@ -6,7 +6,7 @@ module DataUrlExporting # easily be used inline in CSS or HTML. # @return [String] The canvas formatted as a data URL string. def to_data_url - ['data:image/png;base64,', to_blob].pack('A*m').gsub(/\n/, '') + ["data:image/png;base64,", to_blob].pack("A*m").delete("\n") end end end diff --git a/lib/chunky_png/canvas/data_url_importing.rb b/lib/chunky_png/canvas/data_url_importing.rb index 73c280ab..ddb2e604 100644 --- a/lib/chunky_png/canvas/data_url_importing.rb +++ b/lib/chunky_png/canvas/data_url_importing.rb @@ -2,7 +2,6 @@ module ChunkyPNG class Canvas # Methods to import a canvas from a PNG data URL. module DataUrlImporting - # Imports a canvas from a PNG data URL. # @param [String] string The data URL string to load from. # @return [Canvas] The imported canvas. @@ -10,7 +9,7 @@ module DataUrlImporting # formatted PNG data URL (i.e. it should start with "data:image/png;base64,") def from_data_url(string) if string =~ %r[^data:image/png;base64,((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)$] - from_blob($1.unpack('m').first) + from_blob($1.unpack("m").first) else raise SignatureMismatch, "The string was not a properly formatted data URL for a PNG image." end diff --git a/lib/chunky_png/canvas/drawing.rb b/lib/chunky_png/canvas/drawing.rb index df920602..12f2df6a 100644 --- a/lib/chunky_png/canvas/drawing.rb +++ b/lib/chunky_png/canvas/drawing.rb @@ -9,7 +9,6 @@ class Canvas # the bounds of the canvas; these pixels will simply be ignored. # @see ChunkyPNG::Canvas module Drawing - # Composes a pixel on the canvas by alpha blending a color with its # background color. # @@ -42,35 +41,34 @@ def bezier_curve(points, stroke_color = ChunkyPNG::Color::BLACK) when 2 then return line(points[0].x, points[0].y, points[1].x, points[1].y, stroke_color) end - curve_points = Array.new + curve_points = [] t = 0 n = points.length - 1 - bicof = 0 while t <= 100 - cur_p = ChunkyPNG::Point.new(0,0) + bicof = 0 + cur_p = ChunkyPNG::Point.new(0, 0) # Generate a float of t. t_f = t / 100.00 - cur_p.x += ((1 - t_f) ** n) * points[0].x - cur_p.y += ((1 - t_f) ** n) * points[0].y + cur_p.x += ((1 - t_f)**n) * points[0].x + cur_p.y += ((1 - t_f)**n) * points[0].y for i in 1...points.length - 1 - bicof = binomial_coefficient(n , i) + bicof = binomial_coefficient(n, i) - cur_p.x += (bicof * (1 - t_f) ** (n - i)) * (t_f ** i) * points[i].x - cur_p.y += (bicof * (1 - t_f) ** (n - i)) * (t_f ** i) * points[i].y + cur_p.x += (bicof * (1 - t_f)**(n - i)) * (t_f**i) * points[i].x + cur_p.y += (bicof * (1 - t_f)**(n - i)) * (t_f**i) * points[i].y i += 1 end - cur_p.x += (t_f ** n) * points[n].x - cur_p.y += (t_f ** n) * points[n].y + cur_p.x += (t_f**n) * points[n].x + cur_p.y += (t_f**n) * points[n].y curve_points << cur_p - bicof = 0 t += 1 end @@ -127,9 +125,7 @@ def line_xiaolin_wu(x0, y0, x1, y1, stroke_color, inclusive = true) w = 0xff - (e_acc >> 8) compose_pixel(x0, y0, ChunkyPNG::Color.fade(stroke_color, w)) if inclusive || i > 0 - compose_pixel(x0 + sx, - y0 + sy, - ChunkyPNG::Color.fade(stroke_color, 0xff - w)) + compose_pixel(x0 + sx, y0 + sy, ChunkyPNG::Color.fade(stroke_color, 0xff - w)) end y0 += sy end @@ -145,9 +141,7 @@ def line_xiaolin_wu(x0, y0, x1, y1, stroke_color, inclusive = true) w = 0xff - (e_acc >> 8) compose_pixel(x0, y0, ChunkyPNG::Color.fade(stroke_color, w)) if inclusive || i > 0 - compose_pixel(x0 + sx, - y0 + sy, - ChunkyPNG::Color.fade(stroke_color, 0xff - w)) + compose_pixel(x0 + sx, y0 + sy, ChunkyPNG::Color.fade(stroke_color, 0xff - w)) end x0 += sx end @@ -167,13 +161,10 @@ def line_xiaolin_wu(x0, y0, x1, y1, stroke_color, inclusive = true) # @param [Integer] stroke_color The stroke color to use for this polygon. # @param [Integer] fill_color The fill color to use for this polygon. # @return [ChunkyPNG::Canvas] Itself, with the polygon drawn. - def polygon(path, - stroke_color = ChunkyPNG::Color::BLACK, - fill_color = ChunkyPNG::Color::TRANSPARENT) - + def polygon(path, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT) vector = ChunkyPNG::Vector(*path) if path.length < 3 - raise ArgumentError, 'A polygon requires at least 3 points' + raise ArgumentError, "A polygon requires at least 3 points" end stroke_color = ChunkyPNG::Color.parse(stroke_color) @@ -215,10 +206,7 @@ def polygon(path, # @param [Integer] stroke_color The line color to use for this rectangle. # @param [Integer] fill_color The fill color to use for this rectangle. # @return [ChunkyPNG::Canvas] Itself, with the rectangle drawn. - def rect(x0, y0, x1, y1, - stroke_color = ChunkyPNG::Color::BLACK, - fill_color = ChunkyPNG::Color::TRANSPARENT) - + def rect(x0, y0, x1, y1, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT) stroke_color = ChunkyPNG::Color.parse(stroke_color) fill_color = ChunkyPNG::Color.parse(fill_color) @@ -248,16 +236,13 @@ def rect(x0, y0, x1, y1, # @param [Integer] stroke_color The color to use for the line. # @param [Integer] fill_color The color to use that fills the circle. # @return [ChunkyPNG::Canvas] Itself, with the circle drawn. - def circle(x0, y0, radius, - stroke_color = ChunkyPNG::Color::BLACK, - fill_color = ChunkyPNG::Color::TRANSPARENT) - + def circle(x0, y0, radius, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT) stroke_color = ChunkyPNG::Color.parse(stroke_color) fill_color = ChunkyPNG::Color.parse(fill_color) f = 1 - radius - ddF_x = 1 - ddF_y = -2 * radius + dd_f_x = 1 + dd_f_y = -2 * radius x = 0 y = radius @@ -272,13 +257,13 @@ def circle(x0, y0, radius, if f >= 0 y -= 1 - ddF_y += 2 - f += ddF_y + dd_f_y += 2 + f += dd_f_y end x += 1 - ddF_x += 2 - f += ddF_x + dd_f_x += 2 + f += dd_f_x unless fill_color == ChunkyPNG::Color::TRANSPARENT lines[y] = lines[y] ? [lines[y], x - 1].min : x - 1 diff --git a/lib/chunky_png/canvas/masking.rb b/lib/chunky_png/canvas/masking.rb index 8235fa5e..4037cdaa 100644 --- a/lib/chunky_png/canvas/masking.rb +++ b/lib/chunky_png/canvas/masking.rb @@ -1,13 +1,11 @@ module ChunkyPNG class Canvas - # The ChunkyPNG::Canvas::Masking module defines methods to perform masking # and theming operations on a {ChunkyPNG::Canvas}. The module is included into the Canvas class so all # these methods are available on every canvas. # # @see ChunkyPNG::Canvas module Masking - # Creates a new image, based on the current image but with a new theme color. # # This method will replace one color in an image with another image. This is done by @@ -67,7 +65,7 @@ def extract_mask(mask_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5) end end - [ self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels) ] + [self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels)] end # Changes the color of a mask image. diff --git a/lib/chunky_png/canvas/operations.rb b/lib/chunky_png/canvas/operations.rb index a85fd641..17923533 100644 --- a/lib/chunky_png/canvas/operations.rb +++ b/lib/chunky_png/canvas/operations.rb @@ -56,11 +56,14 @@ def compose!(other, offset_x = 0, offset_y = 0) for y in 0...other.height do for x in 0...other.width do - set_pixel(x + offset_x, - y + offset_y, - ChunkyPNG::Color.compose(other.get_pixel(x, y), - get_pixel(x + offset_x, - y + offset_y))) + set_pixel( + x + offset_x, + y + offset_y, + ChunkyPNG::Color.compose( + other.get_pixel(x, y), + get_pixel(x + offset_x, y + offset_y) + ) + ) end end self @@ -169,17 +172,16 @@ def crop(x, y, crop_width, crop_height) # coordinates are bigger then the original image. def crop!(x, y, crop_width, crop_height) if crop_width + x > width - raise ChunkyPNG::OutOfBounds, 'Original image width is too small!' + raise ChunkyPNG::OutOfBounds, "Original image width is too small!" end if crop_height + y > height - raise ChunkyPNG::OutOfBounds, 'Original image height is too small!' + raise ChunkyPNG::OutOfBounds, "Original image height is too small!" end if crop_width == width && x == 0 # We only need to crop off the top and/or bottom, so we can take a # shortcut. - replace_canvas!(crop_width, crop_height, - pixels.slice(y * width, width * crop_height)) + replace_canvas!(crop_width, crop_height, pixels.slice(y * width, width * crop_height)) else new_pixels = [] for cy in 0...crop_height do @@ -389,11 +391,11 @@ def border!(size, color = ChunkyPNG::Color::BLACK) # applied. # @raise [ChunkyPNG::OutOfBounds] when the other image doesn't fit. def check_size_constraints!(other, offset_x, offset_y) - if width < other.width + offset_x - raise ChunkyPNG::OutOfBounds, 'Background image width is too small!' + if width < other.width + offset_x + raise ChunkyPNG::OutOfBounds, "Background image width is too small!" end if height < other.height + offset_y - raise ChunkyPNG::OutOfBounds, 'Background image height is too small!' + raise ChunkyPNG::OutOfBounds, "Background image height is too small!" end end end diff --git a/lib/chunky_png/canvas/png_decoding.rb b/lib/chunky_png/canvas/png_decoding.rb index d7f6e2ee..a9781366 100644 --- a/lib/chunky_png/canvas/png_decoding.rb +++ b/lib/chunky_png/canvas/png_decoding.rb @@ -27,7 +27,6 @@ class Canvas # @see ChunkyPNG::Canvas::PNGEncoding # @see http://www.w3.org/TR/PNG/ The W3C PNG format specification module PNGDecoding - # Decodes a Canvas from a PNG encoded string. # @param [String] str The string to read from. # @return [ChunkyPNG::Canvas] The canvas decoded from the PNG encoded string. @@ -204,7 +203,6 @@ def decode_png_resample_1bit_value(value) value == 0x01 ? 0xff : 0x00 end - # Decodes a scanline of a 1-bit, indexed image into a row of pixels. # @param [String] stream The stream to decode from. # @param [Integer] pos The position in the stream on which the scanline starts (including the filter byte). @@ -258,8 +256,12 @@ def decode_png_pixels_from_scanline_truecolor_alpha_8bit(stream, pos, width, _de def decode_png_pixels_from_scanline_truecolor_alpha_16bit(stream, pos, width, _decoding_palette) pixels = [] stream.unpack("@#{pos + 1}n#{width * 4}").each_slice(4) do |r, g, b, a| - pixels << ChunkyPNG::Color.rgba(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g), - decode_png_resample_16bit_value(b), decode_png_resample_16bit_value(a)) + pixels << ChunkyPNG::Color.rgba( + decode_png_resample_16bit_value(r), + decode_png_resample_16bit_value(g), + decode_png_resample_16bit_value(b), + decode_png_resample_16bit_value(a), + ) end pixels end @@ -268,7 +270,7 @@ def decode_png_pixels_from_scanline_truecolor_alpha_16bit(stream, pos, width, _d # @params (see #decode_png_pixels_from_scanline_indexed_1bit) # @return (see #decode_png_pixels_from_scanline_indexed_1bit) def decode_png_pixels_from_scanline_truecolor_8bit(stream, pos, width, _decoding_palette) - stream.unpack("@#{pos + 1}" << ('NX' * width)).map { |c| c | 0x000000ff } + stream.unpack("@#{pos + 1}" << ("NX" * width)).map { |c| c | 0x000000ff } end # Decodes a scanline of a 16-bit, true color image into a row of pixels. @@ -357,7 +359,6 @@ def decode_png_pixels_from_scanline_method(color_mode, depth) when ChunkyPNG::COLOR_INDEXED then :"decode_png_pixels_from_scanline_indexed_#{depth}bit" when ChunkyPNG::COLOR_GRAYSCALE then :"decode_png_pixels_from_scanline_grayscale_#{depth}bit" when ChunkyPNG::COLOR_GRAYSCALE_ALPHA then :"decode_png_pixels_from_scanline_grayscale_alpha_#{depth}bit" - else nil end raise ChunkyPNG::NotSupported, "No decoder found for color mode #{color_mode} and #{depth}-bit depth!" unless respond_to?(decoder_method, true) @@ -378,7 +379,6 @@ def decode_png_pixels_from_scanline_method(color_mode, depth) # @param [ChunkyPNG::Palette] decoding_palette The palette to use to decode colors. # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream) def decode_png_image_pass(stream, width, height, color_mode, depth, start_pos, decoding_palette) - pixels = [] if width > 0 && height > 0 @@ -418,11 +418,11 @@ def decode_png_image_pass(stream, width, height, color_mode, depth, start_pos, d # @return [void] def decode_png_str_scanline(stream, pos, prev_pos, line_length, pixel_size) case stream.getbyte(pos) - when ChunkyPNG::FILTER_NONE then # noop - when ChunkyPNG::FILTER_SUB then decode_png_str_scanline_sub( stream, pos, prev_pos, line_length, pixel_size) - when ChunkyPNG::FILTER_UP then decode_png_str_scanline_up( stream, pos, prev_pos, line_length, pixel_size) - when ChunkyPNG::FILTER_AVERAGE then decode_png_str_scanline_average( stream, pos, prev_pos, line_length, pixel_size) - when ChunkyPNG::FILTER_PAETH then decode_png_str_scanline_paeth( stream, pos, prev_pos, line_length, pixel_size) + when ChunkyPNG::FILTER_NONE then # rubocop:disable Lint/EmptyWhen # no-op + when ChunkyPNG::FILTER_SUB then decode_png_str_scanline_sub(stream, pos, prev_pos, line_length, pixel_size) + when ChunkyPNG::FILTER_UP then decode_png_str_scanline_up(stream, pos, prev_pos, line_length, pixel_size) + when ChunkyPNG::FILTER_AVERAGE then decode_png_str_scanline_average(stream, pos, prev_pos, line_length, pixel_size) + when ChunkyPNG::FILTER_PAETH then decode_png_str_scanline_paeth(stream, pos, prev_pos, line_length, pixel_size) else raise ChunkyPNG::NotSupported, "Unknown filter type: #{stream.getbyte(pos)}!" end end @@ -481,7 +481,12 @@ def decode_png_str_scanline_paeth(stream, pos, prev_pos, line_length, pixel_size pa = (p - a).abs pb = (p - b).abs pc = (p - c).abs - pr = pa <= pb ? (pa <= pc ? a : c) : (pb <= pc ? b : c) + pr = if pa <= pb + pa <= pc ? a : c + else + pb <= pc ? b : c + end + stream.setbyte(cur_pos, (stream.getbyte(cur_pos) + pr) & 0xff) end end diff --git a/lib/chunky_png/canvas/png_encoding.rb b/lib/chunky_png/canvas/png_encoding.rb index 4144b1a4..8a7d8cc8 100644 --- a/lib/chunky_png/canvas/png_encoding.rb +++ b/lib/chunky_png/canvas/png_encoding.rb @@ -38,7 +38,7 @@ def write(io, constraints = {}) # @param constraints (see ChunkyPNG::Canvas::PNGEncoding#to_datastream) # @return [void] def save(filename, constraints = {}) - File.open(filename, 'wb') { |io| write(io, constraints) } + File.open(filename, "wb") { |io| write(io, constraints) } end # Encoded the canvas to a PNG formatted string. @@ -73,8 +73,13 @@ def to_datastream(constraints = {}) encoding = determine_png_encoding(constraints) ds = Datastream.new - ds.header_chunk = Chunk::Header.new(width: width, height: height, - color: encoding[:color_mode], depth: encoding[:bit_depth], interlace: encoding[:interlace]) + ds.header_chunk = Chunk::Header.new( + width: width, + height: height, + color: encoding[:color_mode], + depth: encoding[:bit_depth], + interlace: encoding[:interlace] + ) if encoding[:color_mode] == ChunkyPNG::COLOR_INDEXED ds.palette_chunk = encoding_palette.to_plte_chunk @@ -98,15 +103,14 @@ def to_datastream(constraints = {}) # Hash or a preset symbol. # @return [Hash] A hash with encoding options for {ChunkyPNG::Canvas::PNGEncoding#to_datastream} def determine_png_encoding(constraints = {}) - encoding = case constraints - when :fast_rgb then { color_mode: ChunkyPNG::COLOR_TRUECOLOR, compression: Zlib::BEST_SPEED } - when :fast_rgba then { color_mode: ChunkyPNG::COLOR_TRUECOLOR_ALPHA, compression: Zlib::BEST_SPEED } - when :best_compression then { compression: Zlib::BEST_COMPRESSION, filtering: ChunkyPNG::FILTER_PAETH } - when :good_compression then { compression: Zlib::BEST_COMPRESSION, filtering: ChunkyPNG::FILTER_NONE } - when :no_compression then { compression: Zlib::NO_COMPRESSION } - when :black_and_white then { color_mode: ChunkyPNG::COLOR_GRAYSCALE, bit_depth: 1 } - when Hash; constraints + when :fast_rgb then {color_mode: ChunkyPNG::COLOR_TRUECOLOR, compression: Zlib::BEST_SPEED} + when :fast_rgba then {color_mode: ChunkyPNG::COLOR_TRUECOLOR_ALPHA, compression: Zlib::BEST_SPEED} + when :best_compression then {compression: Zlib::BEST_COMPRESSION, filtering: ChunkyPNG::FILTER_PAETH} + when :good_compression then {compression: Zlib::BEST_COMPRESSION, filtering: ChunkyPNG::FILTER_NONE} + when :no_compression then {compression: Zlib::NO_COMPRESSION} + when :black_and_white then {color_mode: ChunkyPNG::COLOR_GRAYSCALE, bit_depth: 1} + when Hash then constraints else raise ChunkyPNG::Exception, "Unknown encoding preset: #{constraints.inspect}" end @@ -129,8 +133,8 @@ def determine_png_encoding(constraints = {}) encoding[:compression] ||= Zlib::DEFAULT_COMPRESSION encoding[:interlace] = case encoding[:interlace] - when nil, false then ChunkyPNG::INTERLACING_NONE; ChunkyPNG::INTERLACING_NONE - when true then ChunkyPNG::INTERLACING_ADAM7; ChunkyPNG::INTERLACING_ADAM7 + when nil, false then ChunkyPNG::INTERLACING_NONE + when true then ChunkyPNG::INTERLACING_ADAM7 else encoding[:interlace] end @@ -149,7 +153,6 @@ def determine_png_encoding(constraints = {}) # @param [Integer] interlace The interlacing method to use. # @return [String] The PNG encoded canvas as string. def encode_png_pixelstream(color_mode = ChunkyPNG::COLOR_TRUECOLOR, bit_depth = 8, interlace = ChunkyPNG::INTERLACING_NONE, filtering = ChunkyPNG::FILTER_NONE) - if color_mode == ChunkyPNG::COLOR_INDEXED raise ChunkyPNG::ExpectationFailed, "This palette is not suitable for encoding!" if encoding_palette.nil? || !encoding_palette.can_encode? raise ChunkyPNG::ExpectationFailed, "This palette has too many colors!" if encoding_palette.size > (1 << bit_depth) @@ -199,7 +202,6 @@ def encode_png_image_with_interlacing(color_mode, bit_depth = 8, filtering = Chu # @param [Integer] bit_depth The bit depth of the image. # @param [Integer] filtering The filtering method to use. def encode_png_image_pass_to_stream(stream, color_mode, bit_depth, filtering) - start_pos = stream.bytesize pixel_size = Color.pixel_bytesize(color_mode) line_width = Color.scanline_bytesize(color_mode, bit_depth, width) @@ -207,11 +209,12 @@ def encode_png_image_pass_to_stream(stream, color_mode, bit_depth, filtering) # Determine the filter method encode_method = encode_png_pixels_to_scanline_method(color_mode, bit_depth) filter_method = case filtering - when ChunkyPNG::FILTER_SUB; :encode_png_str_scanline_sub - when ChunkyPNG::FILTER_UP; :encode_png_str_scanline_up - when ChunkyPNG::FILTER_AVERAGE; :encode_png_str_scanline_average - when ChunkyPNG::FILTER_PAETH; :encode_png_str_scanline_paeth - else nil + when ChunkyPNG::FILTER_NONE then nil + when ChunkyPNG::FILTER_SUB then :encode_png_str_scanline_sub + when ChunkyPNG::FILTER_UP then :encode_png_str_scanline_up + when ChunkyPNG::FILTER_AVERAGE then :encode_png_str_scanline_average + when ChunkyPNG::FILTER_PAETH then :encode_png_str_scanline_paeth + else raise ArgumentError, "Filtering method #{filtering} is not supported" end 0.upto(height - 1) do |y| @@ -232,7 +235,7 @@ def encode_png_image_pass_to_stream(stream, color_mode, bit_depth, filtering) # @param [Array] pixels A row of pixels of the original image. # @return [String] The encoded scanline as binary string def encode_png_pixels_to_scanline_truecolor_8bit(pixels) - pixels.pack('x' + ('NX' * width)) + pixels.pack("x" + ("NX" * width)) end # Encodes a line of pixels using 8-bit truecolor alpha mode. @@ -248,16 +251,18 @@ def encode_png_pixels_to_scanline_truecolor_alpha_8bit(pixels) def encode_png_pixels_to_scanline_indexed_1bit(pixels) chars = [] pixels.each_slice(8) do |p1, p2, p3, p4, p5, p6, p7, p8| - chars << ((encoding_palette.index(p1) << 7) | - (encoding_palette.index(p2) << 6) | - (encoding_palette.index(p3) << 5) | - (encoding_palette.index(p4) << 4) | - (encoding_palette.index(p5) << 3) | - (encoding_palette.index(p6) << 2) | - (encoding_palette.index(p7) << 1) | - (encoding_palette.index(p8))) + chars << ( + (encoding_palette.index(p1) << 7) | + (encoding_palette.index(p2) << 6) | + (encoding_palette.index(p3) << 5) | + (encoding_palette.index(p4) << 4) | + (encoding_palette.index(p5) << 3) | + (encoding_palette.index(p6) << 2) | + (encoding_palette.index(p7) << 1) | + encoding_palette.index(p8) + ) end - chars.pack('xC*') + chars.pack("xC*") end # Encodes a line of pixels using 2-bit indexed mode. @@ -266,12 +271,14 @@ def encode_png_pixels_to_scanline_indexed_1bit(pixels) def encode_png_pixels_to_scanline_indexed_2bit(pixels) chars = [] pixels.each_slice(4) do |p1, p2, p3, p4| - chars << ((encoding_palette.index(p1) << 6) | - (encoding_palette.index(p2) << 4) | - (encoding_palette.index(p3) << 2) | - (encoding_palette.index(p4))) + chars << ( + (encoding_palette.index(p1) << 6) | + (encoding_palette.index(p2) << 4) | + (encoding_palette.index(p3) << 2) | + encoding_palette.index(p4) + ) end - chars.pack('xC*') + chars.pack("xC*") end # Encodes a line of pixels using 4-bit indexed mode. @@ -280,9 +287,9 @@ def encode_png_pixels_to_scanline_indexed_2bit(pixels) def encode_png_pixels_to_scanline_indexed_4bit(pixels) chars = [] pixels.each_slice(2) do |p1, p2| - chars << ((encoding_palette.index(p1) << 4) | (encoding_palette.index(p2))) + chars << ((encoding_palette.index(p1) << 4) | encoding_palette.index(p2)) end - chars.pack('xC*') + chars.pack("xC*") end # Encodes a line of pixels using 8-bit indexed mode. @@ -307,7 +314,7 @@ def encode_png_pixels_to_scanline_grayscale_1bit(pixels) (p7.nil? ? 0 : (p7 & 0x0000ffff) >> 15 << 1) | (p8.nil? ? 0 : (p8 & 0x0000ffff) >> 15)) end - chars.pack('xC*') + chars.pack("xC*") end # Encodes a line of pixels using 2-bit grayscale mode. @@ -321,7 +328,7 @@ def encode_png_pixels_to_scanline_grayscale_2bit(pixels) (p3.nil? ? 0 : (p3 & 0x0000ffff) >> 14 << 2) | (p4.nil? ? 0 : (p4 & 0x0000ffff) >> 14)) end - chars.pack('xC*') + chars.pack("xC*") end # Encodes a line of pixels using 2-bit grayscale mode. @@ -332,7 +339,7 @@ def encode_png_pixels_to_scanline_grayscale_4bit(pixels) pixels.each_slice(2) do |p1, p2| chars << ((p1.nil? ? 0 : ((p1 & 0x0000ffff) >> 12) << 4) | (p2.nil? ? 0 : ((p2 & 0x0000ffff) >> 12))) end - chars.pack('xC*') + chars.pack("xC*") end # Encodes a line of pixels using 8-bit grayscale mode. @@ -349,7 +356,6 @@ def encode_png_pixels_to_scanline_grayscale_alpha_8bit(pixels) pixels.pack("xn#{width}") end - # Returns the method name to use to decode scanlines into pixels. # @param [Integer] color_mode The color mode of the image. # @param [Integer] depth The bit depth of the image. @@ -357,20 +363,17 @@ def encode_png_pixels_to_scanline_grayscale_alpha_8bit(pixels) # @raise [ChunkyPNG::NotSupported] when the color_mode and/or bit depth is not supported. def encode_png_pixels_to_scanline_method(color_mode, depth) encoder_method = case color_mode - when ChunkyPNG::COLOR_TRUECOLOR; :"encode_png_pixels_to_scanline_truecolor_#{depth}bit" - when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; :"encode_png_pixels_to_scanline_truecolor_alpha_#{depth}bit" - when ChunkyPNG::COLOR_INDEXED; :"encode_png_pixels_to_scanline_indexed_#{depth}bit" - when ChunkyPNG::COLOR_GRAYSCALE; :"encode_png_pixels_to_scanline_grayscale_#{depth}bit" - when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; :"encode_png_pixels_to_scanline_grayscale_alpha_#{depth}bit" - else nil + when ChunkyPNG::COLOR_TRUECOLOR then :"encode_png_pixels_to_scanline_truecolor_#{depth}bit" + when ChunkyPNG::COLOR_TRUECOLOR_ALPHA then :"encode_png_pixels_to_scanline_truecolor_alpha_#{depth}bit" + when ChunkyPNG::COLOR_INDEXED then :"encode_png_pixels_to_scanline_indexed_#{depth}bit" + when ChunkyPNG::COLOR_GRAYSCALE then :"encode_png_pixels_to_scanline_grayscale_#{depth}bit" + when ChunkyPNG::COLOR_GRAYSCALE_ALPHA then :"encode_png_pixels_to_scanline_grayscale_alpha_#{depth}bit" end raise ChunkyPNG::NotSupported, "No encoder found for color mode #{color_mode} and #{depth}-bit depth!" unless respond_to?(encoder_method, true) encoder_method end - - # Encodes a scanline of a pixelstream without filtering. This is a no-op. # @param [String] stream The pixelstream to work on. This string will be modified. # @param [Integer] pos The starting position of the scanline. @@ -430,7 +433,12 @@ def encode_png_str_scanline_paeth(stream, pos, prev_pos, line_width, pixel_size) pa = (p - a).abs pb = (p - b).abs pc = (p - c).abs - pr = pa <= pb && pa <= pc ? a : (pb <= pc ? b : c) + pr = if pa <= pb && pa <= pc + a + else + pb <= pc ? b : c + end + stream.setbyte(pos + i, (stream.getbyte(pos + i) - pr) & 0xff) end stream.setbyte(pos, ChunkyPNG::FILTER_PAETH) diff --git a/lib/chunky_png/canvas/resampling.rb b/lib/chunky_png/canvas/resampling.rb index e4e1e2a5..56f13c4a 100644 --- a/lib/chunky_png/canvas/resampling.rb +++ b/lib/chunky_png/canvas/resampling.rb @@ -8,7 +8,6 @@ class Canvas # # @see ChunkyPNG::Canvas module Resampling - # Integer Interpolation between two values # # Used for generating indicies for interpolation (eg, nearest @@ -21,7 +20,7 @@ def steps(width, new_width) indicies, residues = steps_residues(width, new_width) for i in 1..new_width - indicies[i-1] = (indicies[i-1] + (residues[i-1] + 127)/255) + indicies[i - 1] = (indicies[i - 1] + (residues[i - 1] + 127) / 255) end indicies end @@ -35,8 +34,8 @@ def steps(width, new_width) # @param [Integer] new_width The width of the destination # @return [Array, Array] Two arrays of indicies and residues def steps_residues(width, new_width) - indicies = Array.new(new_width, obj=nil) - residues = Array.new(new_width, obj=nil) + indicies = Array.new(new_width, nil) + residues = Array.new(new_width, nil) # This works by accumulating the fractional error and # overflowing when necessary. @@ -45,15 +44,15 @@ def steps_residues(width, new_width) # 2 * new_width base_step = width / new_width err_step = (width % new_width) << 1 - denominator = (new_width) << 1 + denominator = new_width << 1 # Initial pixel index = (width - new_width) / denominator err = (width - new_width) % denominator for i in 1..new_width - indicies[i-1] = index - residues[i-1] = (255.0 * err.to_f / denominator.to_f).round + indicies[i - 1] = index + residues[i - 1] = (255.0 * err.to_f / denominator.to_f).round index += base_step err += err_step @@ -66,7 +65,6 @@ def steps_residues(width, new_width) [indicies, residues] end - # Resamples the canvas using nearest neighbor interpolation. # @param [Integer] new_width The width of the resampled canvas. # @param [Integer] new_height The height of the resampled canvas. @@ -75,8 +73,7 @@ def resample_nearest_neighbor!(new_width, new_height) steps_x = steps(width, new_width) steps_y = steps(height, new_height) - - pixels = Array.new(new_width*new_height) + pixels = Array.new(new_width * new_height) i = 0 for y in steps_y for x in steps_x @@ -100,19 +97,19 @@ def resample_bilinear!(new_width, new_height) index_x, interp_x = steps_residues(width, new_width) index_y, interp_y = steps_residues(height, new_height) - pixels = Array.new(new_width*new_height) + pixels = Array.new(new_width * new_height) i = 0 for y in 1..new_height # Clamp the indicies to the edges of the image - y1 = [index_y[y-1], 0].max - y2 = [index_y[y-1] + 1, height - 1].min - y_residue = interp_y[y-1] + y1 = [index_y[y - 1], 0].max + y2 = [index_y[y - 1] + 1, height - 1].min + y_residue = interp_y[y - 1] for x in 1..new_width # Clamp the indicies to the edges of the image - x1 = [index_x[x-1], 0].max - x2 = [index_x[x-1] + 1, width - 1].min - x_residue = interp_x[x-1] + x1 = [index_x[x - 1], 0].max + x2 = [index_x[x - 1] + 1, width - 1].min + x_residue = interp_x[x - 1] pixel_11 = get_pixel(x1, y1) pixel_21 = get_pixel(x2, y1) diff --git a/lib/chunky_png/canvas/stream_exporting.rb b/lib/chunky_png/canvas/stream_exporting.rb index 71856bdb..bdb158ff 100644 --- a/lib/chunky_png/canvas/stream_exporting.rb +++ b/lib/chunky_png/canvas/stream_exporting.rb @@ -10,7 +10,7 @@ module StreamExporting # # @return [String] The RGBA-formatted pixel data. def to_rgba_stream - pixels.pack('N*') + pixels.pack("N*") end # Creates an RGB-formatted pixelstream with the pixel data from this canvas. @@ -21,14 +21,14 @@ def to_rgba_stream # # @return [String] The RGB-formatted pixel data. def to_rgb_stream - pixels.pack('NX' * pixels.length) + pixels.pack("NX" * pixels.length) end # Creates a stream of the alpha channel of this canvas. # # @return [String] The 0-255 alpha values of all pixels packed as string def to_alpha_channel_stream - pixels.pack('C*') + pixels.pack("C*") end # Creates a grayscale stream of this canvas. @@ -38,7 +38,7 @@ def to_alpha_channel_stream # # @return [String] The 0-255 grayscale values of all pixels packed as string. def to_grayscale_stream - pixels.pack('nX' * pixels.length) + pixels.pack("nX" * pixels.length) end # Creates an ABGR-formatted pixelstream with the pixel data from this canvas. @@ -49,7 +49,7 @@ def to_grayscale_stream # # @return [String] The RGBA-formatted pixel data. def to_abgr_stream - pixels.pack('V*') + pixels.pack("V*") end end end diff --git a/lib/chunky_png/canvas/stream_importing.rb b/lib/chunky_png/canvas/stream_importing.rb index 61fb88d7..ad5339a7 100644 --- a/lib/chunky_png/canvas/stream_importing.rb +++ b/lib/chunky_png/canvas/stream_importing.rb @@ -2,7 +2,6 @@ module ChunkyPNG class Canvas # Methods to quickly load a canvas from a stream, encoded in RGB, RGBA, BGR or ABGR format. module StreamImporting - # Creates a canvas by reading pixels from an RGB formatted stream with a # provided with and height. # @@ -17,7 +16,7 @@ module StreamImporting def from_rgb_stream(width, height, stream) string = stream.respond_to?(:read) ? stream.read(3 * width * height) : stream.to_s[0, 3 * width * height] string << ChunkyPNG::EXTRA_BYTE # Add a fourth byte to the last RGB triple. - unpacker = 'NX' * (width * height) + unpacker = "NX" * (width * height) pixels = string.unpack(unpacker).map { |color| color | 0x000000ff } new(width, height, pixels) end @@ -52,7 +51,7 @@ def from_rgba_stream(width, height, stream) def from_bgr_stream(width, height, stream) string = ChunkyPNG::EXTRA_BYTE.dup # Add a first byte to the first BGR triple. string << (stream.respond_to?(:read) ? stream.read(3 * width * height) : stream.to_s[0, 3 * width * height]) - pixels = string.unpack("@1" << ('XV' * (width * height))).map { |color| color | 0x000000ff } + pixels = string.unpack("@1" << ("XV" * (width * height))).map { |color| color | 0x000000ff } new(width, height, pixels) end diff --git a/lib/chunky_png/chunk.rb b/lib/chunky_png/chunk.rb index a496af00..15389e57 100644 --- a/lib/chunky_png/chunk.rb +++ b/lib/chunky_png/chunk.rb @@ -16,10 +16,10 @@ module Chunk # @param io [IO, #read] The IO stream to read from. # @return [ChunkyPNG::Chung::Base] The loaded chunk instance. def self.read(io) - length, type = read_bytes(io, 8).unpack('Na4') + length, type = read_bytes(io, 8).unpack("Na4") content = read_bytes(io, length) - crc = read_bytes(io, 4).unpack('N').first + crc = read_bytes(io, 4).unpack("N").first verify_crc!(type, content, crc) CHUNK_TYPES.fetch(type, Generic).read(type, content) @@ -74,8 +74,8 @@ def initialize(type, attributes = {}) # @param io [IO] The IO stream to write to. # @param content [String] The content for this chunk. def write_with_crc(io, content) - io << [content.length].pack('N') << type << content - io << [Zlib.crc32(content, Zlib.crc32(type))].pack('N') + io << [content.length].pack("N") << type << content + io << [Zlib.crc32(content, Zlib.crc32(type))].pack("N") end # Writes the chunk to the IO stream. @@ -84,7 +84,7 @@ def write_with_crc(io, content) # and will calculate and append the checksum automatically. # @param io [IO] The IO stream to write to. def write(io) - write_with_crc(io, content || '') + write_with_crc(io, content || "") end end @@ -95,7 +95,7 @@ class Generic < Base # written by the +write+ method. attr_accessor :content - def initialize(type, content = '') + def initialize(type, content = "") super(type, content: content) end @@ -118,11 +118,10 @@ def self.read(type, content) # Note that it is still possible to access the chunk for such an image, but # ChunkyPNG will raise an exception if you try to access the pixel data. class Header < Base - attr_accessor :width, :height, :depth, :color, :compression, :filtering, - :interlace + attr_accessor :width, :height, :depth, :color, :compression, :filtering, :interlace def initialize(attrs = {}) - super('IHDR', attrs) + super("IHDR", attrs) @depth ||= 8 @color ||= ChunkyPNG::COLOR_TRUECOLOR @compression ||= ChunkyPNG::COMPRESSION_DEFAULT @@ -137,7 +136,7 @@ def initialize(attrs = {}) # @return [ChunkyPNG::Chunk::End] The new Header chunk instance with the # variables set to the values according to the content. def self.read(type, content) - fields = content.unpack('NNC5') + fields = content.unpack("NNC5") new( width: fields[0], height: fields[1], @@ -160,8 +159,8 @@ def content color, compression, filtering, - interlace - ].pack('NNC5') + interlace, + ].pack("NNC5") end end @@ -169,7 +168,7 @@ def content # not contain any data. class End < Base def initialize - super('IEND') + super("IEND") end # Reads the END chunk. It will check if the content is empty. @@ -180,7 +179,7 @@ def initialize # @return [ChunkyPNG::Chunk::End] The new End chunk instance. # @raise [ChunkyPNG::ExpectationFailed] Raises an exception if the content was not empty. def self.read(type, content) - raise ExpectationFailed, 'The IEND chunk should be empty!' if content.bytesize > 0 + raise ExpectationFailed, "The IEND chunk should be empty!" if content.bytesize > 0 new end @@ -222,7 +221,7 @@ class Transparency < Generic # @return [Array] Returns an array of alpha channel values # [0-255]. def palette_alpha_channel - content.unpack('C*') + content.unpack("C*") end # Returns the truecolor entry to be replaced by transparent pixels, @@ -232,9 +231,8 @@ def palette_alpha_channel # # @return [Integer] The color to replace with fully transparent pixels. def truecolor_entry(bit_depth) - values = content.unpack('nnn').map do |c| - ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", c) - end + decode_method_name = :"decode_png_resample_#{bit_depth}bit_value" + values = content.unpack("nnn").map { |c| ChunkyPNG::Canvas.send(decode_method_name, c) } ChunkyPNG::Color.rgb(*values) end @@ -246,7 +244,7 @@ def truecolor_entry(bit_depth) # @return [Integer] The (grayscale) color to replace with fully # transparent pixels. def grayscale_entry(bit_depth) - value = ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", content.unpack('n')[0]) + value = ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", content.unpack("n")[0]) ChunkyPNG::Color.grayscale(value) end end @@ -263,7 +261,7 @@ def self.combine_chunks(data_chunks) def self.split_in_chunks(data, level = Zlib::DEFAULT_COMPRESSION, chunk_size = 2147483647) streamdata = Zlib::Deflate.deflate(data, level) # TODO: Split long streamdata over multiple chunks - [ ChunkyPNG::Chunk::ImageData.new('IDAT', streamdata) ] + [ChunkyPNG::Chunk::ImageData.new("IDAT", streamdata)] end end @@ -279,12 +277,12 @@ class Text < Base attr_accessor :keyword, :value def initialize(keyword, value) - super('tEXt') + super("tEXt") @keyword, @value = keyword, value end def self.read(type, content) - keyword, value = content.unpack('Z*a*') + keyword, value = content.unpack("Z*a*") new(keyword, value) end @@ -293,7 +291,7 @@ def self.read(type, content) # # @return The content that should be written to the datastream. def content - [keyword, value].pack('Z*a*') + [keyword, value].pack("Z*a*") end end @@ -307,12 +305,12 @@ class CompressedText < Base attr_accessor :keyword, :value def initialize(keyword, value) - super('zTXt') + super("zTXt") @keyword, @value = keyword, value end def self.read(type, content) - keyword, compression, value = content.unpack('Z*Ca*') + keyword, compression, value = content.unpack("Z*Ca*") raise ChunkyPNG::NotSupported, "Compression method #{compression.inspect} not supported!" unless compression == ChunkyPNG::COMPRESSION_DEFAULT new(keyword, Zlib::Inflate.inflate(value)) end @@ -325,8 +323,8 @@ def content [ keyword, ChunkyPNG::COMPRESSION_DEFAULT, - Zlib::Deflate.deflate(value) - ].pack('Z*Ca*') + Zlib::Deflate.deflate(value), + ].pack("Z*Ca*") end end @@ -338,23 +336,23 @@ class Physical < Base attr_accessor :ppux, :ppuy, :unit def initialize(ppux, ppuy, unit = :unknown) - raise ArgumentError, 'unit must be either :meters or :unknown' unless [:meters, :unknown].member?(unit) - super('pHYs') + raise ArgumentError, "unit must be either :meters or :unknown" unless [:meters, :unknown].member?(unit) + super("pHYs") @ppux, @ppuy, @unit = ppux, ppuy, unit end def dpix - raise ChunkyPNG::UnitsUnknown, 'the PNG specifies its physical aspect ratio, but does not specify the units of its pixels\' physical dimensions' unless unit == :meters + raise ChunkyPNG::UnitsUnknown, "the PNG specifies its physical aspect ratio, but does not specify the units of its pixels' physical dimensions" unless unit == :meters ppux * INCHES_PER_METER end def dpiy - raise ChunkyPNG::UnitsUnknown, 'the PNG specifies its physical aspect ratio, but does not specify the units of its pixels\' physical dimensions' unless unit == :meters + raise ChunkyPNG::UnitsUnknown, "the PNG specifies its physical aspect ratio, but does not specify the units of its pixels' physical dimensions" unless unit == :meters ppuy * INCHES_PER_METER end def self.read(type, content) - ppux, ppuy, unit = content.unpack('NNC') + ppux, ppuy, unit = content.unpack("NNC") unit = unit == 1 ? :meters : :unknown new(ppux, ppuy, unit) end @@ -362,7 +360,7 @@ def self.read(type, content) # Assembles the content to write to the stream for this chunk. # @return [String] The binary content that should be written to the datastream. def content - [ppux, ppuy, unit == :meters ? 1 : 0].pack('NNC') + [ppux, ppuy, unit == :meters ? 1 : 0].pack("NNC") end INCHES_PER_METER = 0.0254 @@ -383,8 +381,8 @@ def content class InternationalText < Base attr_accessor :keyword, :text, :language_tag, :translated_keyword, :compressed, :compression - def initialize(keyword, text, language_tag = '', translated_keyword = '', compressed = ChunkyPNG::UNCOMPRESSED_CONTENT, compression = ChunkyPNG::COMPRESSION_DEFAULT) - super('iTXt') + def initialize(keyword, text, language_tag = "", translated_keyword = "", compressed = ChunkyPNG::UNCOMPRESSED_CONTENT, compression = ChunkyPNG::COMPRESSION_DEFAULT) + super("iTXt") @keyword = keyword @text = text @language_tag = language_tag @@ -401,16 +399,16 @@ def initialize(keyword, text, language_tag = '', translated_keyword = '', compre # @raise [ChunkyPNG::NotSupported] If the chunk refers to an unsupported compression method. # Currently uncompressed data and deflate are supported. def self.read(type, content) - keyword, compressed, compression, language_tag, translated_keyword, text = content.unpack('Z*CCZ*Z*a*') + keyword, compressed, compression, language_tag, translated_keyword, text = content.unpack("Z*CCZ*Z*a*") raise ChunkyPNG::NotSupported, "Compression flag #{compressed.inspect} not supported!" unless compressed == ChunkyPNG::UNCOMPRESSED_CONTENT || compressed == ChunkyPNG::COMPRESSED_CONTENT raise ChunkyPNG::NotSupported, "Compression method #{compression.inspect} not supported!" unless compression == ChunkyPNG::COMPRESSION_DEFAULT text = Zlib::Inflate.inflate(text) if compressed == ChunkyPNG::COMPRESSED_CONTENT - text.force_encoding('utf-8') + text.force_encoding("utf-8") raise ChunkyPNG::InvalidUTF8, "Invalid unicode encountered in iTXt chunk" unless text.valid_encoding? - translated_keyword.force_encoding('utf-8') + translated_keyword.force_encoding("utf-8") raise ChunkyPNG::InvalidUTF8, "Invalid unicode encountered in iTXt chunk" unless translated_keyword.valid_encoding? new(keyword, text, language_tag, translated_keyword, compressed, compression) @@ -419,10 +417,10 @@ def self.read(type, content) # Assembles the content to write to the stream for this chunk. # @return [String] The binary content that should be written to the datastream. def content - text_field = text.encode('utf-8') + text_field = text.encode("utf-8") text_field = compressed == ChunkyPNG::COMPRESSED_CONTENT ? Zlib::Deflate.deflate(text_field) : text_field - [keyword, compressed, compression, language_tag, translated_keyword.encode('utf-8'), text_field].pack('Z*CCZ*Z*a*') + [keyword, compressed, compression, language_tag, translated_keyword.encode("utf-8"), text_field].pack("Z*CCZ*Z*a*") end end @@ -434,15 +432,15 @@ def content # # @see ChunkyPNG::Chunk.read CHUNK_TYPES = { - 'IHDR' => Header, - 'IEND' => End, - 'IDAT' => ImageData, - 'PLTE' => Palette, - 'tRNS' => Transparency, - 'tEXt' => Text, - 'zTXt' => CompressedText, - 'iTXt' => InternationalText, - 'pHYs' => Physical, + "IHDR" => Header, + "IEND" => End, + "IDAT" => ImageData, + "PLTE" => Palette, + "tRNS" => Transparency, + "tEXt" => Text, + "zTXt" => CompressedText, + "iTXt" => InternationalText, + "pHYs" => Physical, } end end diff --git a/lib/chunky_png/color.rb b/lib/chunky_png/color.rb index b7bb3c24..8152c27e 100644 --- a/lib/chunky_png/color.rb +++ b/lib/chunky_png/color.rb @@ -1,5 +1,4 @@ module ChunkyPNG - # Factory method to return a color value, based on the arguments given. # # @overload Color(r, g, b, a) @@ -29,7 +28,7 @@ module ChunkyPNG # @raise [ArgumentError] if the arguments weren't understood as a color. # @see ChunkyPNG::Color # @see ChunkyPNG::Color.parse - def self.Color(*args) + def self.Color(*args) # rubocop:disable Naming/MethodName # API backwards compatibility case args.length when 1 then ChunkyPNG::Color.parse(args.first) when 2 then (ChunkyPNG::Color.parse(args.first) & 0xffffff00) | args[1].to_i @@ -38,6 +37,7 @@ def self.Color(*args) else raise ArgumentError, "Don't know how to create a color from #{args.inspect}!" end end + # rubocop:enable Naming/MethodName # The Color module defines methods for handling colors. Within the ChunkyPNG # library, the concepts of pixels and colors are both used, and they are @@ -82,7 +82,7 @@ module Color # @return [Integer] The color value, with the opacity applied if one was # given. def parse(source) - return source if source.kind_of?(Integer) + return source if source.is_a?(Integer) case source.to_s when /^\d+$/ then source.to_s.to_i when HEX3_COLOR_REGEXP, HEX6_COLOR_REGEXP then from_hex(source.to_s) @@ -164,14 +164,14 @@ def from_rgba_stream(stream, pos = 0) # @raise [ArgumentError] if the value given is not a hex color notation. def from_hex(hex_value, opacity = nil) base_color = case hex_value - when HEX3_COLOR_REGEXP - $1.gsub(/([0-9a-f])/i, '\1\1').hex << 8 - when HEX6_COLOR_REGEXP - $1.hex << 8 - else - raise ArgumentError, "Not a valid hex color notation: #{hex_value.inspect}!" - end - opacity ||= $2 ? $2.hex : 0xff + when HEX3_COLOR_REGEXP + $1.gsub(/([0-9a-f])/i, '\1\1').hex << 8 + when HEX6_COLOR_REGEXP + $1.hex << 8 + else + raise ArgumentError, "Not a valid hex color notation: #{hex_value.inspect}!" + end + opacity ||= $2 ? $2.hex : 0xff base_color | opacity end @@ -193,6 +193,7 @@ def from_hsv(hue, saturation, value, alpha = 255) raise ArgumentError, "Hue must be between 0 and 360" unless (0..360).cover?(hue) raise ArgumentError, "Saturation must be between 0 and 1" unless (0..1).cover?(saturation) raise ArgumentError, "Value/brightness must be between 0 and 1" unless (0..1).cover?(value) + chroma = value * saturation rgb = cylindrical_to_cubic(hue, saturation, value, chroma) rgb.map! { |component| ((component + value - chroma) * 255).to_i } @@ -218,6 +219,7 @@ def from_hsl(hue, saturation, lightness, alpha = 255) raise ArgumentError, "Hue #{hue} was not between 0 and 360" unless (0..360).cover?(hue) raise ArgumentError, "Saturation #{saturation} was not between 0 and 1" unless (0..1).cover?(saturation) raise ArgumentError, "Lightness #{lightness} was not between 0 and 1" unless (0..1).cover?(lightness) + chroma = (1 - (2 * lightness - 1).abs) * saturation rgb = cylindrical_to_cubic(hue, saturation, lightness, chroma) rgb.map! { |component| ((component + lightness - 0.5 * chroma) * 255).to_i } @@ -499,7 +501,7 @@ def decompose_color(color, mask, bg, tolerance = 1) # @see #decompose_alpha def alpha_decomposable?(color, mask, bg, tolerance = 1) components = decompose_alpha_components(color, mask, bg) - sum = components.inject(0) { |a,b| a + b } + sum = components.inject(0) { |a, b| a + b } max = components.max * 3 components.max <= 255 && components.min >= 0 && (sum + tolerance * 3) >= max end @@ -520,7 +522,7 @@ def alpha_decomposable?(color, mask, bg, tolerance = 1) # @see #alpha_decomposable? def decompose_alpha(color, mask, bg) components = decompose_alpha_components(color, mask, bg) - (components.inject(0) { |a,b| a + b } / 3.0).round + (components.inject(0) { |a, b| a + b } / 3.0).round end # Decomposes an alpha channel for either the r, g or b color channel. @@ -552,7 +554,7 @@ def decompose_alpha_components(color, mask, bg) [ decompose_alpha_component(:r, color, mask, bg), decompose_alpha_component(:g, color, mask, bg), - decompose_alpha_component(:b, color, mask, bg) + decompose_alpha_component(:b, color, mask, bg), ] end @@ -567,7 +569,7 @@ def decompose_alpha_components(color, mask, bg) # @param [Boolean] include_alpha # @return [String] The color in hex notation, starting with a pound sign. def to_hex(color, include_alpha = true) - include_alpha ? ('#%08x' % color) : ('#%06x' % [color >> 8]) + include_alpha ? ("#%08x" % color) : ("#%06x" % [color >> 8]) end # Returns an array with the separate HSV components of a color. @@ -638,7 +640,7 @@ def to_hsl(color, include_alpha = false) # @return [Fixnum] min The magnitude of the smallest scaled rgb component (0-1) # @private def hue_and_chroma(color) - scaled_rgb = to_truecolor_bytes(color) + scaled_rgb = to_truecolor_bytes(color) scaled_rgb.map! { |component| component.fdiv(255) } min, max = scaled_rgb.minmax chroma = max - min @@ -906,14 +908,14 @@ def euclidean_distance_rgba(pixel_after, pixel_before) def html_color(color_name, opacity = nil) if color_name.to_s =~ HTML_COLOR_REGEXP opacity ||= $2 ? ($2.to_f * 255.0).round : 0xff - base_color_name = $1.gsub(/[^a-z]+/i, '').downcase.to_sym + base_color_name = $1.gsub(/[^a-z]+/i, "").downcase.to_sym return PREDEFINED_COLORS[base_color_name] | opacity if PREDEFINED_COLORS.key?(base_color_name) end raise ArgumentError, "Unknown color name #{color_name}!" end # @return [Integer] Black pixel/color - BLACK = rgb( 0, 0, 0) + BLACK = rgb(0, 0, 0) # @return [Integer] White pixel/color WHITE = rgb(255, 255, 255) diff --git a/lib/chunky_png/datastream.rb b/lib/chunky_png/datastream.rb index 75c6f4c2..7a5072e5 100644 --- a/lib/chunky_png/datastream.rb +++ b/lib/chunky_png/datastream.rb @@ -1,5 +1,4 @@ module ChunkyPNG - # The Datastream class represents a PNG formatted datastream. It supports # both reading from and writing to strings, streams and files. # @@ -10,7 +9,7 @@ module ChunkyPNG # @see ChunkyPNG::Chunk class Datastream # The signature that each PNG file or stream should begin with. - SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10].pack('C8').force_encoding(Encoding::BINARY).freeze + SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10].pack("C8").force_encoding(Encoding::BINARY).freeze # The header chunk of this datastream. # @return [ChunkyPNG::Chunk::Header] @@ -55,7 +54,7 @@ class << self # @param [String] str The PNG encoded string to load from. # @return [ChunkyPNG::Datastream] The loaded datastream instance. def from_blob(str) - from_io(StringIO.new(str, 'rb')) + from_io(StringIO.new(str, "rb")) end alias from_string from_blob @@ -65,7 +64,7 @@ def from_blob(str) # @return [ChunkyPNG::Datastream] The loaded datastream instance. def from_file(filename) ds = nil - File.open(filename, 'rb') { |f| ds = from_io(f) } + File.open(filename, "rb") { |f| ds = from_io(f) } ds end @@ -126,7 +125,7 @@ def each_chunk yield(palette_chunk) if palette_chunk yield(transparency_chunk) if transparency_chunk yield(physical_chunk) if physical_chunk - data_chunks.each { |chunk| yield(chunk) } + data_chunks.each { |chunk| yield(chunk) } yield(end_chunk) end @@ -173,14 +172,14 @@ def write(io) # Saves this datastream as a PNG file. # @param [String] filename The filename to use. def save(filename) - File.open(filename, 'wb') { |f| write(f) } + File.open(filename, "wb") { |f| write(f) } end # Encodes this datastream into a string. # @return [String] The encoded PNG datastream. def to_blob str = StringIO.new - str.set_encoding('ASCII-8BIT') + str.set_encoding("ASCII-8BIT") write(str) str.string end diff --git a/lib/chunky_png/dimension.rb b/lib/chunky_png/dimension.rb index 374a4f25..041cf23c 100644 --- a/lib/chunky_png/dimension.rb +++ b/lib/chunky_png/dimension.rb @@ -1,5 +1,4 @@ module ChunkyPNG - # Creates a {ChunkyPNG::Dimension} instance using arguments that can be interpreted # as width and height. # @@ -45,8 +44,8 @@ def self.build_dimension_from_object(source) when Array ChunkyPNG::Dimension.new(source[0], source[1]) when Hash - width = source[:width] || source['width'] - height = source[:height] || source['height'] + width = source[:width] || source["width"] + height = source[:height] || source["height"] ChunkyPNG::Dimension.new(width, height) when ChunkyPNG::Dimension::DIMENSION_REGEXP ChunkyPNG::Dimension.new($1, $2) diff --git a/lib/chunky_png/image.rb b/lib/chunky_png/image.rb index 5d00f5f8..37daa390 100644 --- a/lib/chunky_png/image.rb +++ b/lib/chunky_png/image.rb @@ -1,5 +1,4 @@ module ChunkyPNG - # ChunkyPNG::Image is an extension of the {ChunkyPNG::Canvas} class, that # also includes support for metadata. # diff --git a/lib/chunky_png/palette.rb b/lib/chunky_png/palette.rb index 14695676..1f58a0dd 100644 --- a/lib/chunky_png/palette.rb +++ b/lib/chunky_png/palette.rb @@ -40,12 +40,8 @@ def self.from_chunks(palette_chunk, transparency_chunk = nil) decoding_map = [] index = 0 - palatte_bytes = palette_chunk.content.unpack('C*') - if transparency_chunk - alpha_channel = transparency_chunk.content.unpack('C*') - else - alpha_channel = [] - end + palatte_bytes = palette_chunk.content.unpack("C*") + alpha_channel = transparency_chunk ? transparency_chunk.content.unpack("C*") : [] index = 0 palatte_bytes.each_slice(3) do |bytes| @@ -165,7 +161,7 @@ def index(color) # # @return [ChunkyPNG::Chunk::Transparency] The tRNS chunk. def to_trns_chunk - ChunkyPNG::Chunk::Transparency.new('tRNS', map { |c| ChunkyPNG::Color.a(c) }.pack('C*')) + ChunkyPNG::Chunk::Transparency.new("tRNS", map { |c| ChunkyPNG::Color.a(c) }.pack("C*")) end # Creates a PLTE chunk that corresponds with this palette to store the r, @@ -186,7 +182,7 @@ def to_plte_chunk colors += ChunkyPNG::Color.to_truecolor_bytes(color) end - ChunkyPNG::Chunk::Palette.new('PLTE', colors.pack('C*')) + ChunkyPNG::Chunk::Palette.new("PLTE", colors.pack("C*")) end # Determines the most suitable colormode for this palette. @@ -219,7 +215,6 @@ def determine_bit_depth when 3..4 then 2 when 5..16 then 4 when 17..256 then 8 - else nil end end end diff --git a/lib/chunky_png/point.rb b/lib/chunky_png/point.rb index 8b56fb2e..f73b92f4 100644 --- a/lib/chunky_png/point.rb +++ b/lib/chunky_png/point.rb @@ -1,5 +1,4 @@ module ChunkyPNG - # Factory method to create {ChunkyPNG::Point} instances. # # This method tries to be as flexible as possible with regards to the given input: besides @@ -46,8 +45,8 @@ def self.build_point_from_object(source) when Array ChunkyPNG::Point.new(source[0], source[1]) when Hash - x = source[:x] || source['x'] - y = source[:y] || source['y'] + x = source[:x] || source["x"] + y = source[:y] || source["y"] ChunkyPNG::Point.new(x, y) when ChunkyPNG::Point::POINT_REGEXP ChunkyPNG::Point.new($1.to_i, $2.to_i) diff --git a/lib/chunky_png/rmagick.rb b/lib/chunky_png/rmagick.rb index c3fd2dbb..281c487e 100644 --- a/lib/chunky_png/rmagick.rb +++ b/lib/chunky_png/rmagick.rb @@ -1,7 +1,6 @@ -require 'rmagick' +require "rmagick" module ChunkyPNG - # Methods for importing and exporting RMagick image objects. # # By default, this module is disabled because of the dependency on RMagick. @@ -20,14 +19,13 @@ module ChunkyPNG # updated_canvas = ChunkyPNG::RMagick.import(image) # module RMagick - extend self # Imports an RMagick image as Canvas object. # @param [Magick::Image] image The image to import # @return [ChunkyPNG::Canvas] The canvas, constructed from the RMagick image. def import(image) - pixels = image.export_pixels_to_str(0, 0, image.columns, image.rows, 'RGBA') + pixels = image.export_pixels_to_str(0, 0, image.columns, image.rows, "RGBA") ChunkyPNG::Canvas.from_rgba_stream(image.columns, image.rows, pixels) end @@ -36,7 +34,7 @@ def import(image) # @return [Magick::Image] The RMagick image constructed from the Canvas instance. def export(canvas) image = Magick::Image.new(canvas.width, canvas.height) - image.import_pixels(0, 0, canvas.width, canvas.height, 'RGBA', canvas.pixels.pack('N*')) + image.import_pixels(0, 0, canvas.width, canvas.height, "RGBA", canvas.pixels.pack("N*")) image end end diff --git a/lib/chunky_png/vector.rb b/lib/chunky_png/vector.rb index b27bfe9b..45363275 100644 --- a/lib/chunky_png/vector.rb +++ b/lib/chunky_png/vector.rb @@ -1,5 +1,4 @@ module ChunkyPNG - # Factory method for {ChunkyPNG::Vector} instances. # # @overload Vector(x0, y0, x1, y1, x2, y2, ...) @@ -17,8 +16,7 @@ module ChunkyPNG # @raise [ArgumentError] If the given arguments could not be understood as a vector. # @see ChunkyPNG::Vector def self.Vector(*args) - - return args.first if args.length == 1 && args.first.kind_of?(ChunkyPNG::Vector) + return args.first if args.length == 1 && args.first.is_a?(ChunkyPNG::Vector) if args.length == 1 && args.first.respond_to?(:scan) ChunkyPNG::Vector.new(ChunkyPNG::Vector.multiple_from_string(args.first)) # e.g. ['1,1 2,2 3,3'] @@ -166,7 +164,7 @@ def dimension # @return [Array] The list of points interpreted from the input array. def self.multiple_from_array(source) return [] if source.empty? - if source.first.kind_of?(Numeric) || source.first =~ /^\d+$/ + if source.first.is_a?(Numeric) || source.first =~ /^\d+$/ raise ArgumentError, "The points array is expected to have an even number of items!" if source.length % 2 != 0 points = [] diff --git a/spec/chunky_png/canvas/adam7_interlacing_spec.rb b/spec/chunky_png/canvas/adam7_interlacing_spec.rb index 5e6a5e4e..47504d6b 100644 --- a/spec/chunky_png/canvas/adam7_interlacing_spec.rb +++ b/spec/chunky_png/canvas/adam7_interlacing_spec.rb @@ -1,48 +1,48 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::Adam7Interlacing do include ChunkyPNG::Canvas::Adam7Interlacing - describe '#adam7_pass_sizes' do + describe "#adam7_pass_sizes" do it "should get the pass sizes for a 8x8 image correctly" do expect(adam7_pass_sizes(8, 8)).to eql [ - [1, 1], [1, 1], [2, 1], [2, 2], [4, 2], [4, 4], [8, 4] - ] + [1, 1], [1, 1], [2, 1], [2, 2], [4, 2], [4, 4], [8, 4], + ] end it "should get the pass sizes for a 12x12 image correctly" do expect(adam7_pass_sizes(12, 12)).to eql [ - [2, 2], [1, 2], [3, 1], [3, 3], [6, 3], [6, 6], [12, 6] - ] + [2, 2], [1, 2], [3, 1], [3, 3], [6, 3], [6, 6], [12, 6], + ] end it "should get the pass sizes for a 33x47 image correctly" do expect(adam7_pass_sizes(33, 47)).to eql [ - [5, 6], [4, 6], [9, 6], [8, 12], [17, 12], [16, 24], [33, 23] - ] + [5, 6], [4, 6], [9, 6], [8, 12], [17, 12], [16, 24], [33, 23], + ] end it "should get the pass sizes for a 1x1 image correctly" do expect(adam7_pass_sizes(1, 1)).to eql [ - [1, 1], [0, 1], [1, 0], [0, 1], [1, 0], [0, 1], [1, 0] - ] + [1, 1], [0, 1], [1, 0], [0, 1], [1, 0], [0, 1], [1, 0], + ] end it "should get the pass sizes for a 0x0 image correctly" do expect(adam7_pass_sizes(0, 0)).to eql [ - [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0] - ] + [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], + ] end it "should always maintain the same amount of pixels in total" do [[8, 8], [12, 12], [33, 47], [1, 1], [0, 0]].each do |(width, height)| pass_sizes = adam7_pass_sizes(width, height) - expect(pass_sizes.inject(0) { |sum, (w, h)| sum + (w*h) }).to eql width * height + expect(pass_sizes.inject(0) { |sum, (w, h)| sum + (w * h) }).to eql width * height end end end - describe '#adam7_multiplier_offset' do + describe "#adam7_multiplier_offset" do it "should get the multiplier and offset values for pass 1 correctly" do expect(adam7_multiplier_offset(0)).to eql [3, 0, 3, 0] end @@ -72,7 +72,7 @@ end end - describe '#adam7_merge_pass' do + describe "#adam7_merge_pass" do it "should merge the submatrices correctly" do submatrices = [ ChunkyPNG::Canvas.new(1, 1, 168430335), # r = 10 @@ -84,23 +84,22 @@ ChunkyPNG::Canvas.new(8, 4, 1175063295), # r = 70 ] - canvas = ChunkyPNG::Image.new(8,8) + canvas = ChunkyPNG::Image.new(8, 8) submatrices.each_with_index { |m, pass| adam7_merge_pass(pass, canvas, m) } - expect(canvas).to eql reference_image('adam7') + expect(canvas).to eql reference_image("adam7") end end - describe '#adam7_extract_pass' do - before(:each) { @canvas = reference_canvas('adam7') } + describe "#adam7_extract_pass" do + before(:each) { @canvas = reference_canvas("adam7") } 1.upto(7) do |pass| it "should extract pass #{pass} correctly" do sm = adam7_extract_pass(pass - 1, @canvas) expect(sm.pixels.length).to eql sm.width * sm.height expect(sm.pixels.uniq.length).to eql 1 - expect(ChunkyPNG::Color.r(sm[0,0])).to eql pass * 10 + expect(ChunkyPNG::Color.r(sm[0, 0])).to eql pass * 10 end end end - end diff --git a/spec/chunky_png/canvas/data_url_exporting_spec.rb b/spec/chunky_png/canvas/data_url_exporting_spec.rb index 72d2c99d..b2331d0c 100644 --- a/spec/chunky_png/canvas/data_url_exporting_spec.rb +++ b/spec/chunky_png/canvas/data_url_exporting_spec.rb @@ -1,11 +1,14 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas do - - describe '#to_data_url' do + describe "#to_data_url" do it "should export a sample canvas to an RGBA stream correctly" do - canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8), - ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)]) + canvas = ChunkyPNG::Canvas.new(2, 2, [ + ChunkyPNG::Color.rgba(1, 2, 3, 4), + ChunkyPNG::Color.rgba(5, 6, 7, 8), + ChunkyPNG::Color.rgba(4, 3, 2, 1), + ChunkyPNG::Color.rgba(8, 7, 6, 5), + ]) expect(canvas.to_data_url).to eql "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEUBAgMEAwIFBgcIBwazgAAdAAAABHRSTlMEAQgFhYDlfQAAAAxJREFUeJxjUmAKAAAAwAB1GNhIEwAAAABJRU5ErkJggg==" end diff --git a/spec/chunky_png/canvas/data_url_importing_spec.rb b/spec/chunky_png/canvas/data_url_importing_spec.rb index dff98be7..2d0ba7e4 100644 --- a/spec/chunky_png/canvas/data_url_importing_spec.rb +++ b/spec/chunky_png/canvas/data_url_importing_spec.rb @@ -1,15 +1,14 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas do - - describe '.from_data_url' do + describe ".from_data_url" do it "should import an image from a data URL" do - data_url = reference_canvas('operations').to_data_url - expect(ChunkyPNG::Canvas.from_data_url(data_url)).to eql reference_canvas('operations') + data_url = reference_canvas("operations").to_data_url + expect(ChunkyPNG::Canvas.from_data_url(data_url)).to eql reference_canvas("operations") end it "should raise an exception if the string is not a proper data URL" do - expect { ChunkyPNG::Canvas.from_data_url('whatever') }.to raise_error(ChunkyPNG::SignatureMismatch) + expect { ChunkyPNG::Canvas.from_data_url("whatever") }.to raise_error(ChunkyPNG::SignatureMismatch) end end end diff --git a/spec/chunky_png/canvas/drawing_spec.rb b/spec/chunky_png/canvas/drawing_spec.rb index 6c40e2a1..318add9d 100644 --- a/spec/chunky_png/canvas/drawing_spec.rb +++ b/spec/chunky_png/canvas/drawing_spec.rb @@ -1,12 +1,11 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::Drawing do - - describe '#compose_pixel' do + describe "#compose_pixel" do subject { ChunkyPNG::Canvas.new(1, 1, ChunkyPNG::Color.rgb(200, 150, 100)) } it "should compose colors correctly" do - subject.compose_pixel(0,0, ChunkyPNG::Color(100, 150, 200, 128)) + subject.compose_pixel(0, 0, ChunkyPNG::Color(100, 150, 200, 128)) expect(subject[0, 0]).to eql ChunkyPNG::Color(150, 150, 150) end @@ -20,11 +19,11 @@ end end - describe '#line' do + describe "#line" do it "should draw lines correctly with anti-aliasing" do - canvas = ChunkyPNG::Canvas.new(31, 31, ChunkyPNG::Color::WHITE) + # rubocop:disable Layout/SpaceInsideParens # for improved readability canvas.line( 0, 0, 30, 30, ChunkyPNG::Color::BLACK) canvas.line( 0, 30, 30, 0, ChunkyPNG::Color::BLACK) canvas.line(15, 30, 15, 0, ChunkyPNG::Color.rgba(200, 0, 0, 128)) @@ -33,13 +32,14 @@ canvas.line( 0, 15, 30, 0, ChunkyPNG::Color.rgba( 0, 200, 0, 128)) canvas.line( 0, 30, 15, 0, ChunkyPNG::Color.rgba( 0, 0, 200, 128), false) canvas.line(15, 0, 30, 30, ChunkyPNG::Color.rgba( 0, 0, 200, 128)) + # rubocop:enable Layout/SpaceInsideParens - expect(canvas).to eql reference_canvas('lines') + expect(canvas).to eql reference_canvas("lines") end it "should draw partial lines if the coordinates are partially out of bounds" do canvas = ChunkyPNG::Canvas.new(1, 2, ChunkyPNG::Color::WHITE) - canvas.line(-5, -5, 0, 0, '#000000') + canvas.line(-5, -5, 0, 0, "#000000") expect(canvas.pixels).to eql [ChunkyPNG::Color::BLACK, ChunkyPNG::Color::WHITE] end @@ -57,13 +57,13 @@ end end - describe '#rect' do - subject { ChunkyPNG::Canvas.new(16, 16, '#ffffff') } + describe "#rect" do + subject { ChunkyPNG::Canvas.new(16, 16, "#ffffff") } it "should draw a rectangle with the correct colors" do - subject.rect(1, 1, 10, 10, ChunkyPNG::Color.rgba(0, 255, 0, 80), ChunkyPNG::Color.rgba(255, 0, 0, 100)) + subject.rect(1, 1, 10, 10, ChunkyPNG::Color.rgba(0, 255, 0, 80), ChunkyPNG::Color.rgba(255, 0, 0, 100)) subject.rect(5, 5, 14, 14, ChunkyPNG::Color.rgba(0, 0, 255, 160), ChunkyPNG::Color.rgba(255, 255, 0, 100)) - expect(subject).to eql reference_canvas('rect') + expect(subject).to eql reference_canvas("rect") end it "should return itself to allow chaining" do @@ -81,19 +81,19 @@ end end - describe '#circle' do + describe "#circle" do subject { ChunkyPNG::Canvas.new(32, 32, ChunkyPNG::Color.rgba(0, 0, 255, 128)) } it "should draw circles" do - subject.circle(11, 11, 10, ChunkyPNG::Color('red @ 0.5'), ChunkyPNG::Color('white @ 0.2')) - subject.circle(21, 21, 10, ChunkyPNG::Color('green @ 0.5')) - expect(subject).to eql reference_canvas('circles') + subject.circle(11, 11, 10, ChunkyPNG::Color("red @ 0.5"), ChunkyPNG::Color("white @ 0.2")) + subject.circle(21, 21, 10, ChunkyPNG::Color("green @ 0.5")) + expect(subject).to eql reference_canvas("circles") end it "should draw partial circles when going of the canvas bounds" do subject.circle(0, 0, 10, ChunkyPNG::Color(:red)) subject.circle(31, 16, 10, ChunkyPNG::Color(:black), ChunkyPNG::Color(:white, 0xaa)) - expect(subject).to eql reference_canvas('partial_circles') + expect(subject).to eql reference_canvas("partial_circles") end it "should return itself to allow chaining" do @@ -101,78 +101,78 @@ end end - describe '#polygon' do + describe "#polygon" do subject { ChunkyPNG::Canvas.new(22, 22) } it "should draw an filled triangle when using 3 control points" do - subject.polygon('(2,2) (20,5) (5,20)', ChunkyPNG::Color(:black, 0xaa), ChunkyPNG::Color(:red, 0x44)) - expect(subject).to eql reference_canvas('polygon_triangle_filled') + subject.polygon("(2,2) (20,5) (5,20)", ChunkyPNG::Color(:black, 0xaa), ChunkyPNG::Color(:red, 0x44)) + expect(subject).to eql reference_canvas("polygon_triangle_filled") end it "should draw a unfilled polygon with 6 control points" do - subject.polygon('(2,2) (12, 1) (20,5) (18,18) (5,20) (1,12)', ChunkyPNG::Color(:black)) - expect(subject).to eql reference_canvas('polygon_unfilled') + subject.polygon("(2,2) (12, 1) (20,5) (18,18) (5,20) (1,12)", ChunkyPNG::Color(:black)) + expect(subject).to eql reference_canvas("polygon_unfilled") end it "should draw a vertically crossed filled polygon with 4 control points" do - subject.polygon('(2,2) (21,2) (2,21) (21,21)', ChunkyPNG::Color(:black), ChunkyPNG::Color(:red)) - expect(subject).to eql reference_canvas('polygon_filled_vertical') + subject.polygon("(2,2) (21,2) (2,21) (21,21)", ChunkyPNG::Color(:black), ChunkyPNG::Color(:red)) + expect(subject).to eql reference_canvas("polygon_filled_vertical") end it "should draw a vertically crossed filled polygon with 4 control points" do - subject.polygon('(2,2) (2,21) (21,2) (21,21)', ChunkyPNG::Color(:black), ChunkyPNG::Color(:red)) - expect(subject).to eql reference_canvas('polygon_filled_horizontal') + subject.polygon("(2,2) (2,21) (21,2) (21,21)", ChunkyPNG::Color(:black), ChunkyPNG::Color(:red)) + expect(subject).to eql reference_canvas("polygon_filled_horizontal") end it "should return itself to allow chaining" do - expect(subject.polygon('(2,2) (20,5) (5,20)')).to equal(subject) + expect(subject.polygon("(2,2) (20,5) (5,20)")).to equal(subject) end end - describe '#bezier_curve' do + describe "#bezier_curve" do subject { ChunkyPNG::Canvas.new(24, 24, ChunkyPNG::Color::WHITE) } it "should draw a bezier curve starting at the first point" do - subject.bezier_curve('3,20 10,10, 20,20') + subject.bezier_curve("3,20 10,10, 20,20") expect(subject[3, 20]).to eql ChunkyPNG::Color::BLACK end it "should draw a bezier curve ending at the last point" do - subject.bezier_curve('3,20 10,10, 20,20') + subject.bezier_curve("3,20 10,10, 20,20") expect(subject[20, 20]).to eql ChunkyPNG::Color::BLACK end it "should draw a bezier curve with a color of green" do - subject.bezier_curve('3,20 10,10, 20,20', :green) + subject.bezier_curve("3,20 10,10, 20,20", :green) expect(subject[3, 20]).to eql ChunkyPNG::Color(:green) end it "should draw a three point bezier curve" do - expect(subject.bezier_curve('1,23 12,10 23,23')).to eql reference_canvas('bezier_three_point') + expect(subject.bezier_curve("1,23 12,10 23,23")).to eql reference_canvas("bezier_three_point") end it "should draw a three point bezier curve flipped" do - expect(subject.bezier_curve('1,1 12,15 23,1')).to eql reference_canvas('bezier_three_point_flipped') + expect(subject.bezier_curve("1,1 12,15 23,1")).to eql reference_canvas("bezier_three_point_flipped") end it "should draw a four point bezier curve" do - expect(subject.bezier_curve('1,23 1,5 22,5 22,23')).to eql reference_canvas('bezier_four_point') + expect(subject.bezier_curve("1,23 1,5 22,5 22,23")).to eql reference_canvas("bezier_four_point") end it "should draw a four point bezier curve flipped" do - expect(subject.bezier_curve('1,1 1,19 22,19 22,1')).to eql reference_canvas('bezier_four_point_flipped') + expect(subject.bezier_curve("1,1 1,19 22,19 22,1")).to eql reference_canvas("bezier_four_point_flipped") end it "should draw a four point bezier curve with a shape of an s" do - expect(subject.bezier_curve('1,23 1,5 22,23 22,5')).to eql reference_canvas('bezier_four_point_s') + expect(subject.bezier_curve("1,23 1,5 22,23 22,5")).to eql reference_canvas("bezier_four_point_s") end it "should draw a five point bezier curve" do - expect(subject.bezier_curve('10,23 1,10 12,5 23,10 14,23')).to eql reference_canvas('bezier_five_point') + expect(subject.bezier_curve("10,23 1,10 12,5 23,10 14,23")).to eql reference_canvas("bezier_five_point") end it "should draw a six point bezier curve" do - expect(subject.bezier_curve('1,23 4,15 8,20 2,2 23,15 23,1')).to eql reference_canvas('bezier_six_point') + expect(subject.bezier_curve("1,23 4,15 8,20 2,2 23,15 23,1")).to eql reference_canvas("bezier_six_point") end end end diff --git a/spec/chunky_png/canvas/masking_spec.rb b/spec/chunky_png/canvas/masking_spec.rb index 61d89fff..282715cd 100644 --- a/spec/chunky_png/canvas/masking_spec.rb +++ b/spec/chunky_png/canvas/masking_spec.rb @@ -1,41 +1,40 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::Masking do - - subject { reference_canvas('clock') } + subject { reference_canvas("clock") } before(:all) do - @theme_color = ChunkyPNG::Color('#e10f7a') - @new_color = ChunkyPNG::Color('#ff0000') - @background_color = ChunkyPNG::Color('white') + @theme_color = ChunkyPNG::Color("#e10f7a") + @new_color = ChunkyPNG::Color("#ff0000") + @background_color = ChunkyPNG::Color("white") end - describe '#change_theme_color!' do + describe "#change_theme_color!" do it "should change the theme color correctly" do subject.change_theme_color!(@theme_color, @new_color) - expect(subject).to eql reference_canvas('clock_updated') + expect(subject).to eql reference_canvas("clock_updated") end end - describe '#extract_mask' do + describe "#extract_mask" do it "should create the correct base and mask image" do base, mask = subject.extract_mask(@theme_color, @background_color) - expect(base).to eql reference_canvas('clock_base') - expect(mask).to eql reference_canvas('clock_mask') + expect(base).to eql reference_canvas("clock_base") + expect(mask).to eql reference_canvas("clock_mask") end it "should create a mask image with only one opaque color" do - base, mask = subject.extract_mask(@theme_color, @background_color) + _, mask = subject.extract_mask(@theme_color, @background_color) expect(mask.palette.opaque_palette.size).to eql 1 end end - describe '#change_mask_color!' do - before { @mask = reference_canvas('clock_mask') } + describe "#change_mask_color!" do + before { @mask = reference_canvas("clock_mask") } it "should replace the mask color correctly" do @mask.change_mask_color!(@new_color) - expect(@mask).to eql reference_canvas('clock_mask_updated') + expect(@mask).to eql reference_canvas("clock_mask_updated") end it "should still only have one opaque color" do @@ -44,7 +43,7 @@ end it "should raise an exception when the mask image has more than once color" do - not_a_mask = reference_canvas('operations') + not_a_mask = reference_canvas("operations") expect { not_a_mask.change_mask_color!(@new_color) }.to raise_error(ChunkyPNG::ExpectationFailed) end end diff --git a/spec/chunky_png/canvas/operations_spec.rb b/spec/chunky_png/canvas/operations_spec.rb index acfd2b5f..3eb7f601 100644 --- a/spec/chunky_png/canvas/operations_spec.rb +++ b/spec/chunky_png/canvas/operations_spec.rb @@ -1,16 +1,15 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::Operations do + subject { reference_canvas("operations") } - subject { reference_canvas('operations') } - - describe '#grayscale' do + describe "#grayscale" do it "should not return itself" do subject.grayscale.should_not equal(subject) end it "should convert the image correctly" do - expect(subject.grayscale).to eql reference_canvas('operations_grayscale') + expect(subject.grayscale).to eql reference_canvas("operations_grayscale") end it "should not adjust the current image" do @@ -18,20 +17,20 @@ end end - describe '#grayscale!' do + describe "#grayscale!" do it "should return itself" do expect(subject.grayscale!).to equal(subject) end it "should convert the image correctly" do subject.grayscale! - expect(subject).to eql reference_canvas('operations_grayscale') + expect(subject).to eql reference_canvas("operations_grayscale") end end - describe '#crop' do + describe "#crop" do it "should crop the right pixels from the original canvas" do - expect(subject.crop(10, 5, 4, 8)).to eql reference_canvas('cropped') + expect(subject.crop(10, 5, 4, 8)).to eql reference_canvas("cropped") end it "should not return itself" do @@ -47,19 +46,19 @@ end end - describe '#crop!' do - context 'when cropping both width and height' do + describe "#crop!" do + context "when cropping both width and height" do let(:crop_opts) { [10, 5, 4, 8] } it "should crop the right pixels from the original canvas" do subject.crop!(*crop_opts) - expect(subject).to eql reference_canvas('cropped') + expect(subject).to eql reference_canvas("cropped") end it "should have a new width and height" do expect { subject.crop!(*crop_opts) }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('16x16')) - .to(ChunkyPNG::Dimension('4x8')) + .from(ChunkyPNG::Dimension("16x16")) + .to(ChunkyPNG::Dimension("4x8")) end it "should return itself" do @@ -72,13 +71,13 @@ it "should crop the right pixels from the original canvas" do subject.crop!(*crop_opts) - expect(subject).to eql reference_canvas('cropped_height') + expect(subject).to eql reference_canvas("cropped_height") end it "should have a new width and height" do expect { subject.crop!(*crop_opts) }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('16x16')) - .to(ChunkyPNG::Dimension('16x8')) + .from(ChunkyPNG::Dimension("16x16")) + .to(ChunkyPNG::Dimension("16x8")) end it "should return itself" do @@ -93,91 +92,90 @@ end end - describe '#compose' do + describe "#compose" do it "should compose pixels correctly" do subcanvas = ChunkyPNG::Canvas.new(4, 8, ChunkyPNG::Color.rgba(0, 0, 0, 75)) - expect(subject.compose(subcanvas, 8, 4)).to eql reference_canvas('composited') + expect(subject.compose(subcanvas, 8, 4)).to eql reference_canvas("composited") end it "should leave the original intact" do - subject.compose(ChunkyPNG::Canvas.new(1,1)) - expect(subject).to eql reference_canvas('operations') + subject.compose(ChunkyPNG::Canvas.new(1, 1)) + expect(subject).to eql reference_canvas("operations") end it "should not return itself" do - subject.compose(ChunkyPNG::Canvas.new(1,1)).should_not equal(subject) + subject.compose(ChunkyPNG::Canvas.new(1, 1)).should_not equal(subject) end it "should raise an exception when the pixels to compose fall outside the image" do - expect { subject.compose(ChunkyPNG::Canvas.new(1,1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) + expect { subject.compose(ChunkyPNG::Canvas.new(1, 1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) end end - describe '#compose!' do + describe "#compose!" do it "should compose pixels correctly" do subcanvas = ChunkyPNG::Canvas.new(4, 8, ChunkyPNG::Color.rgba(0, 0, 0, 75)) subject.compose!(subcanvas, 8, 4) - expect(subject).to eql reference_canvas('composited') + expect(subject).to eql reference_canvas("composited") end it "should return itself" do - expect(subject.compose!(ChunkyPNG::Canvas.new(1,1))).to equal(subject) + expect(subject.compose!(ChunkyPNG::Canvas.new(1, 1))).to equal(subject) end it "should compose a base image and mask correctly" do - base = reference_canvas('clock_base') - mask = reference_canvas('clock_mask_updated') + base = reference_canvas("clock_base") + mask = reference_canvas("clock_mask_updated") base.compose!(mask) - expect(base).to eql reference_canvas('clock_updated') + expect(base).to eql reference_canvas("clock_updated") end it "should raise an exception when the pixels to compose fall outside the image" do - expect { subject.compose!(ChunkyPNG::Canvas.new(1,1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) + expect { subject.compose!(ChunkyPNG::Canvas.new(1, 1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) end end - describe '#replace' do + describe "#replace" do it "should replace the correct pixels" do subcanvas = ChunkyPNG::Canvas.new(3, 2, ChunkyPNG::Color.rgb(200, 255, 0)) - expect(subject.replace(subcanvas, 5, 4)).to eql reference_canvas('replaced') + expect(subject.replace(subcanvas, 5, 4)).to eql reference_canvas("replaced") end it "should not return itself" do - subject.replace(ChunkyPNG::Canvas.new(1,1)).should_not equal(subject) + subject.replace(ChunkyPNG::Canvas.new(1, 1)).should_not equal(subject) end it "should leave the original intact" do - subject.replace(ChunkyPNG::Canvas.new(1,1)) - expect(subject).to eql reference_canvas('operations') + subject.replace(ChunkyPNG::Canvas.new(1, 1)) + expect(subject).to eql reference_canvas("operations") end it "should raise an exception when the pixels to replace fall outside the image" do - expect { subject.replace(ChunkyPNG::Canvas.new(1,1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) + expect { subject.replace(ChunkyPNG::Canvas.new(1, 1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) end end - describe '#replace!' do + describe "#replace!" do it "should replace the correct pixels" do subcanvas = ChunkyPNG::Canvas.new(3, 2, ChunkyPNG::Color.rgb(200, 255, 0)) subject.replace!(subcanvas, 5, 4) - expect(subject).to eql reference_canvas('replaced') + expect(subject).to eql reference_canvas("replaced") end it "should return itself" do - expect(subject.replace!(ChunkyPNG::Canvas.new(1,1))).to equal(subject) + expect(subject.replace!(ChunkyPNG::Canvas.new(1, 1))).to equal(subject) end it "should raise an exception when the pixels to replace fall outside the image" do - expect { subject.replace!(ChunkyPNG::Canvas.new(1,1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) + expect { subject.replace!(ChunkyPNG::Canvas.new(1, 1), 16, 16) }.to raise_error(ChunkyPNG::OutOfBounds) end end end describe ChunkyPNG::Canvas::Operations do - subject { ChunkyPNG::Canvas.new(2, 3, [1, 2, 3, 4, 5, 6]) } - describe '#flip_horizontally!' do + describe "#flip_horizontally!" do it "should flip the pixels horizontally in place" do subject.flip_horizontally! expect(subject).to eql ChunkyPNG::Canvas.new(2, 3, [5, 6, 3, 4, 1, 2]) @@ -188,7 +186,7 @@ end end - describe '#flip_horizontally' do + describe "#flip_horizontally" do it "should flip the pixels horizontally" do expect(subject.flip_horizontally).to eql ChunkyPNG::Canvas.new(2, 3, [5, 6, 3, 4, 1, 2]) end @@ -202,7 +200,7 @@ end end - describe '#flip_vertically!' do + describe "#flip_vertically!" do it "should flip the pixels vertically" do subject.flip_vertically! expect(subject).to eql ChunkyPNG::Canvas.new(2, 3, [2, 1, 4, 3, 6, 5]) @@ -213,7 +211,7 @@ end end - describe '#flip_vertically' do + describe "#flip_vertically" do it "should flip the pixels vertically" do expect(subject.flip_vertically).to eql ChunkyPNG::Canvas.new(2, 3, [2, 1, 4, 3, 6, 5]) end @@ -227,9 +225,9 @@ end end - describe '#rotate_left' do + describe "#rotate_left" do it "should rotate the pixels 90 degrees counter-clockwise" do - expect(subject.rotate_left).to eql ChunkyPNG::Canvas.new(3, 2, [2, 4, 6, 1, 3, 5] ) + expect(subject.rotate_left).to eql ChunkyPNG::Canvas.new(3, 2, [2, 4, 6, 1, 3, 5]) end it "should not return itself" do @@ -253,10 +251,10 @@ end end - describe '#rotate_left!' do + describe "#rotate_left!" do it "should rotate the pixels 90 degrees clockwise" do subject.rotate_left! - expect(subject).to eql ChunkyPNG::Canvas.new(3, 2, [2, 4, 6, 1, 3, 5] ) + expect(subject).to eql ChunkyPNG::Canvas.new(3, 2, [2, 4, 6, 1, 3, 5]) end it "should return itself" do @@ -265,13 +263,13 @@ it "should change the image dimensions" do expect { subject.rotate_left! }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('2x3')).to(ChunkyPNG::Dimension('3x2')) + .from(ChunkyPNG::Dimension("2x3")).to(ChunkyPNG::Dimension("3x2")) end end - describe '#rotate_right' do + describe "#rotate_right" do it "should rotate the pixels 90 degrees clockwise" do - expect(subject.rotate_right).to eql ChunkyPNG::Canvas.new(3, 2, [5, 3, 1, 6, 4, 2] ) + expect(subject.rotate_right).to eql ChunkyPNG::Canvas.new(3, 2, [5, 3, 1, 6, 4, 2]) end it "should not return itself" do @@ -295,10 +293,10 @@ end end - describe '#rotate_right!' do + describe "#rotate_right!" do it "should rotate the pixels 90 degrees clockwise" do subject.rotate_right! - expect(subject).to eql ChunkyPNG::Canvas.new(3, 2, [5, 3, 1, 6, 4, 2] ) + expect(subject).to eql ChunkyPNG::Canvas.new(3, 2, [5, 3, 1, 6, 4, 2]) end it "should return itself" do @@ -307,12 +305,12 @@ it "should change the image dimensions" do expect { subject.rotate_right! }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('2x3')) - .to(ChunkyPNG::Dimension('3x2')) + .from(ChunkyPNG::Dimension("2x3")) + .to(ChunkyPNG::Dimension("3x2")) end end - describe '#rotate_180' do + describe "#rotate_180" do it "should rotate the pixels 180 degrees" do expect(subject.rotate_180).to eql ChunkyPNG::Canvas.new(2, 3, [6, 5, 4, 3, 2, 1]) end @@ -326,7 +324,7 @@ end end - describe '#rotate_180!' do + describe "#rotate_180!" do it "should rotate the pixels 180 degrees" do subject.rotate_180! expect(subject).to eql ChunkyPNG::Canvas.new(2, 3, [6, 5, 4, 3, 2, 1]) @@ -339,7 +337,6 @@ end describe ChunkyPNG::Canvas::Operations do - subject { ChunkyPNG::Canvas.new(4, 4).rect(1, 1, 2, 2, 255, 255) } describe "#trim" do @@ -372,19 +369,18 @@ it "should change the image dimensions" do expect { subject.trim! }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('4x4')) - .to(ChunkyPNG::Dimension('2x2')) + .from(ChunkyPNG::Dimension("4x4")) + .to(ChunkyPNG::Dimension("2x2")) end end end describe ChunkyPNG::Canvas::Operations do - subject { ChunkyPNG::Canvas.new(4, 4) } describe "#border" do it "should add the border" do - expect(subject.border(2)).to eql reference_canvas('operations_border') + expect(subject.border(2)).to eql reference_canvas("operations_border") end it "should not return itself" do @@ -399,7 +395,7 @@ describe "#border!" do it "should add the border" do subject.border!(2) - expect(subject).to eql reference_canvas('operations_border') + expect(subject).to eql reference_canvas("operations_border") end it "should return itself" do @@ -413,8 +409,8 @@ it "should change the image dimensions" do expect { subject.border!(1) }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('4x4')) - .to(ChunkyPNG::Dimension('6x6')) + .from(ChunkyPNG::Dimension("4x4")) + .to(ChunkyPNG::Dimension("6x6")) end end end diff --git a/spec/chunky_png/canvas/png_decoding_spec.rb b/spec/chunky_png/canvas/png_decoding_spec.rb index d7dd32f2..a0841716 100644 --- a/spec/chunky_png/canvas/png_decoding_spec.rb +++ b/spec/chunky_png/canvas/png_decoding_spec.rb @@ -1,97 +1,96 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::PNGDecoding do include ChunkyPNG::Canvas::PNGDecoding - describe '#decode_png_scanline' do - + describe "#decode_png_scanline" do it "should decode a line without filtering as is" do - stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*') + stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack("C*") decode_png_str_scanline(stream, 0, nil, 9, 3) - expect(stream.unpack('@1C*')).to eql [255, 255, 255, 255, 255, 255, 255, 255, 255] + expect(stream.unpack("@1C*")).to eql [255, 255, 255, 255, 255, 255, 255, 255, 255] end it "should decode a line with sub filtering correctly" do # all white pixels - stream = [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0].pack('C*') + stream = [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0].pack("C*") decode_png_str_scanline(stream, 0, nil, 9, 3) - expect(stream.unpack('@1C*')).to eql [255, 255, 255, 255, 255, 255, 255, 255, 255] + expect(stream.unpack("@1C*")).to eql [255, 255, 255, 255, 255, 255, 255, 255, 255] # all black pixels - stream = [ChunkyPNG::FILTER_SUB, 0, 0, 0, 0, 0, 0, 0, 0, 0].pack('C*') + stream = [ChunkyPNG::FILTER_SUB, 0, 0, 0, 0, 0, 0, 0, 0, 0].pack("C*") decode_png_str_scanline(stream, 0, nil, 9, 3) - expect(stream.unpack('@1C*')).to eql [0, 0, 0, 0, 0, 0, 0, 0, 0] + expect(stream.unpack("@1C*")).to eql [0, 0, 0, 0, 0, 0, 0, 0, 0] # various colors - stream = [ChunkyPNG::FILTER_SUB, 255, 0, 45, 0, 255, 0, 112, 200, 178].pack('C*') + stream = [ChunkyPNG::FILTER_SUB, 255, 0, 45, 0, 255, 0, 112, 200, 178].pack("C*") decode_png_str_scanline(stream, 0, nil, 9, 3) - expect(stream.unpack('@1C*')).to eql [255, 0, 45, 255, 255, 45, 111, 199, 223] + expect(stream.unpack("@1C*")).to eql [255, 0, 45, 255, 255, 45, 111, 199, 223] end it "should decode a line with up filtering correctly" do # previous line has various pixels previous = [ChunkyPNG::FILTER_UP, 255, 255, 255, 127, 127, 127, 0, 0, 0] current = [ChunkyPNG::FILTER_UP, 0, 127, 255, 0, 127, 255, 0, 127, 255] - stream = (previous + current).pack('C*') + stream = (previous + current).pack("C*") decode_png_str_scanline(stream, 10, 0, 9, 3) - expect(stream.unpack('@11C9')).to eql [255, 126, 254, 127, 254, 126, 0, 127, 255] + expect(stream.unpack("@11C9")).to eql [255, 126, 254, 127, 254, 126, 0, 127, 255] end it "should decode a line with average filtering correctly" do - previous = [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120] - current = [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53] - stream = (previous + current).pack('C*') + previous = [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120] # rubocop:disable Layout/ExtraSpacing + current = [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53] # rubocop:disable Layout/ExtraSpacing + stream = (previous + current).pack("C*") decode_png_str_scanline(stream, 13, 0, 12, 3) - expect(stream.unpack('@14C12')).to eql [5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165] + expect(stream.unpack("@14C12")).to eql [5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165] end it "should decode a line with paeth filtering correctly" do - previous = [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120] - current = [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0] - stream = (previous + current).pack('C*') + previous = [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120] # rubocop:disable Layout/ExtraSpacing + current = [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0] # rubocop:disable Layout/ExtraSpacing + stream = (previous + current).pack("C*") decode_png_str_scanline(stream, 13, 0, 12, 3) - expect(stream.unpack('@14C12')).to eql [10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120] + expect(stream.unpack("@14C12")).to eql [10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120] end end - describe '#decode_png_extract_4bit_value' do + describe "#decode_png_extract_4bit_value" do it "should extract the high bits successfully" do - expect(decode_png_extract_4bit_value('10010110'.to_i(2), 0)).to eql '1001'.to_i(2) + expect(decode_png_extract_4bit_value("10010110".to_i(2), 0)).to eql "1001".to_i(2) end it "should extract the low bits successfully" do - expect(decode_png_extract_4bit_value('10010110'.to_i(2), 17)).to eql '0110'.to_i(2) + expect(decode_png_extract_4bit_value("10010110".to_i(2), 17)).to eql "0110".to_i(2) end end - describe '#decode_png_extract_2bit_value' do + describe "#decode_png_extract_2bit_value" do it "should extract the first 2 bits successfully" do - expect(decode_png_extract_2bit_value('10010110'.to_i(2), 0)).to eql '10'.to_i(2) + expect(decode_png_extract_2bit_value("10010110".to_i(2), 0)).to eql "10".to_i(2) end it "should extract the second 2 bits successfully" do - expect(decode_png_extract_2bit_value('10010110'.to_i(2), 5)).to eql '01'.to_i(2) + expect(decode_png_extract_2bit_value("10010110".to_i(2), 5)).to eql "01".to_i(2) end it "should extract the third 2 bits successfully" do - expect(decode_png_extract_2bit_value('10010110'.to_i(2), 2)).to eql '01'.to_i(2) + expect(decode_png_extract_2bit_value("10010110".to_i(2), 2)).to eql "01".to_i(2) end it "should extract the low two bits successfully" do - expect(decode_png_extract_2bit_value('10010110'.to_i(2), 7)).to eql '10'.to_i(2) + expect(decode_png_extract_2bit_value("10010110".to_i(2), 7)).to eql "10".to_i(2) end end - describe '#decode_png_extract_1bit_value' do + describe "#decode_png_extract_1bit_value" do it "should extract all separate bits correctly" do - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 0)).to eql 1 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 1)).to eql 0 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 2)).to eql 0 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 3)).to eql 1 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 4)).to eql 0 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 5)).to eql 1 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 6)).to eql 1 - expect(decode_png_extract_1bit_value('10010110'.to_i(2), 7)).to eql 0 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 0)).to eql 1 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 1)).to eql 0 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 2)).to eql 0 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 3)).to eql 1 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 4)).to eql 0 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 5)).to eql 1 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 6)).to eql 1 + expect(decode_png_extract_1bit_value("10010110".to_i(2), 7)).to eql 0 end end end diff --git a/spec/chunky_png/canvas/png_encoding_spec.rb b/spec/chunky_png/canvas/png_encoding_spec.rb index 5d28d58f..0fbb4083 100644 --- a/spec/chunky_png/canvas/png_encoding_spec.rb +++ b/spec/chunky_png/canvas/png_encoding_spec.rb @@ -1,9 +1,9 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::PNGEncoding do include ChunkyPNG::Canvas::PNGEncoding - context 'determining encoding options' do + context "determining encoding options" do [:indexed, :grayscale, :grayscale_alpha, :truecolor, :truecolor_alpha].each do |color_mode_name| it "should encode an image with color mode #{color_mode_name} correctly" do canvas = ChunkyPNG::Canvas.new(10, 10, ChunkyPNG::Color.rgb(100, 100, 100)) @@ -17,7 +17,7 @@ end it "should encode an image with 2 colors using 1-bit indexed color mode" do - @canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p01.png')) + @canvas = ChunkyPNG::Canvas.from_file(png_suite_file("basic", "basn3p01.png")) ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob) expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED expect(ds.header_chunk.depth).to eql 1 @@ -25,7 +25,7 @@ end it "should encode an image with 4 colors using 2-bit indexed color mode" do - @canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p02.png')) + @canvas = ChunkyPNG::Canvas.from_file(png_suite_file("basic", "basn3p02.png")) ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob) expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED expect(ds.header_chunk.depth).to eql 2 @@ -33,7 +33,7 @@ end it "should encode an image with 16 colors using 4-bit indexed color mode" do - @canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p04.png')) + @canvas = ChunkyPNG::Canvas.from_file(png_suite_file("basic", "basn3p04.png")) ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob) expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED expect(ds.header_chunk.depth).to eql 4 @@ -41,7 +41,7 @@ end it "should encode an image with 256 colors using 8-bit indexed color mode" do - @canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p08.png')) + @canvas = ChunkyPNG::Canvas.from_file(png_suite_file("basic", "basn3p08.png")) ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob) expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED expect(ds.header_chunk.depth).to eql 8 @@ -49,7 +49,7 @@ end it "should use a higher bit depth than necessary if requested" do - @canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p01.png')) + @canvas = ChunkyPNG::Canvas.from_file(png_suite_file("basic", "basn3p01.png")) ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob(bit_depth: 4)) expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED expect(ds.header_chunk.depth).to eql 4 @@ -57,7 +57,7 @@ end it "should encode an image with interlacing correctly" do - input_canvas = ChunkyPNG::Canvas.from_file(resource_file('operations.png')) + input_canvas = ChunkyPNG::Canvas.from_file(resource_file("operations.png")) blob = input_canvas.to_blob(interlace: true) ds = ChunkyPNG::Datastream.from_blob(blob) @@ -66,55 +66,57 @@ end it "should save an image using the normal routine correctly" do - canvas = reference_canvas('operations') - expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::DEFAULT_COMPRESSION).and_return('') + canvas = reference_canvas("operations") + expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::DEFAULT_COMPRESSION).and_return("") canvas.to_blob end it "should save an image using the :fast_rgba routine correctly" do - canvas = reference_canvas('operations') + canvas = reference_canvas("operations") expect(canvas).to_not receive(:encode_png_str_scanline_none) expect(canvas).to_not receive(:encode_png_str_scanline_sub) expect(canvas).to_not receive(:encode_png_str_scanline_up) expect(canvas).to_not receive(:encode_png_str_scanline_average) expect(canvas).to_not receive(:encode_png_str_scanline_paeth) - expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_SPEED).and_return('') + expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_SPEED).and_return("") canvas.to_blob(:fast_rgba) end it "should save an image using the :good_compression routine correctly" do - canvas = reference_canvas('operations') + canvas = reference_canvas("operations") expect(canvas).to_not receive(:encode_png_str_scanline_none) expect(canvas).to_not receive(:encode_png_str_scanline_sub) expect(canvas).to_not receive(:encode_png_str_scanline_up) expect(canvas).to_not receive(:encode_png_str_scanline_average) expect(canvas).to_not receive(:encode_png_str_scanline_paeth) - expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('') + expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return("") canvas.to_blob(:good_compression) end it "should save an image using the :best_compression routine correctly" do - canvas = reference_canvas('operations') + canvas = reference_canvas("operations") expect(canvas).to receive(:encode_png_str_scanline_paeth).exactly(canvas.height).times - expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('') + expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return("") canvas.to_blob(:best_compression) end it "should save an image with black and white only if requested" do - ds = ChunkyPNG::Datastream.from_blob(reference_canvas('lines').to_blob(:black_and_white)) + ds = ChunkyPNG::Datastream.from_blob(reference_canvas("lines").to_blob(:black_and_white)) expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_GRAYSCALE expect(ds.header_chunk.depth).to eql 1 end end - describe 'different color modes and bit depths' do + describe "different color modes and bit depths" do before do @canvas = ChunkyPNG::Canvas.new(2, 2) + # rubocop:disable Layout/ExtraSpacing, Layout/SpaceInsideParens @canvas[0, 0] = ChunkyPNG::Color.rgba( 1, 2, 3, 4) @canvas[1, 0] = ChunkyPNG::Color.rgba(252, 253, 254, 255) @canvas[0, 1] = ChunkyPNG::Color.rgba(255, 254, 253, 252) @canvas[1, 1] = ChunkyPNG::Color.rgba( 4, 3, 2, 1) + # rubocop:enable Layout/ExtraSpacing, Layout/SpaceInsideParens @canvas.encoding_palette = @canvas.palette @canvas.encoding_palette.to_plte_chunk @@ -172,64 +174,71 @@ end end - describe 'different filter methods' do - + describe "different filter methods" do it "should encode a scanline without filtering correctly" do - stream = [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2].pack('C*') + stream = [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2].pack("C*") encode_png_str_scanline_none(stream, 0, nil, 9, 3) - expect(stream.unpack('C*')).to eql [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2] + expect(stream.unpack("C*")).to eql [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2] end it "should encode a scanline with sub filtering correctly" do - stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255, - ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*') + stream = [ + ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255, + ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255, + ].pack("C*") # Check line with previous line encode_png_str_scanline_sub(stream, 10, 0, 9, 3) - expect(stream.unpack('@10C10')).to eql [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0] + expect(stream.unpack("@10C10")).to eql [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0] # Check line without previous line encode_png_str_scanline_sub(stream, 0, nil, 9, 3) - expect(stream.unpack('@0C10')).to eql [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0] + expect(stream.unpack("@0C10")).to eql [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0] end it "should encode a scanline with up filtering correctly" do - stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255, - ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*') + stream = [ + ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255, + ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255, + ].pack("C*") # Check line with previous line encode_png_str_scanline_up(stream, 10, 0, 9, 3) - expect(stream.unpack('@10C10')).to eql [ChunkyPNG::FILTER_UP, 0, 0, 0, 0, 0, 0, 0, 0, 0] + expect(stream.unpack("@10C10")).to eql [ChunkyPNG::FILTER_UP, 0, 0, 0, 0, 0, 0, 0, 0, 0] # Check line without previous line encode_png_str_scanline_up(stream, 0, nil, 9, 3) - expect(stream.unpack('@0C10')).to eql [ChunkyPNG::FILTER_UP, 255, 255, 255, 255, 255, 255, 255, 255, 255] + expect(stream.unpack("@0C10")).to eql [ChunkyPNG::FILTER_UP, 255, 255, 255, 255, 255, 255, 255, 255, 255] end it "should encode a scanline with average filtering correctly" do - stream = [ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120, - ChunkyPNG::FILTER_NONE, 5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165].pack('C*') + stream = [ + ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120, # rubocop:disable Layout/ExtraSpacing + ChunkyPNG::FILTER_NONE, 5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165, # rubocop:disable Layout/ExtraSpacing + ].pack("C*") # Check line with previous line encode_png_str_scanline_average(stream, 13, 0, 12, 3) - expect(stream.unpack('@13C13')).to eql [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53] + expect(stream.unpack("@13C13")).to eql [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53] # Check line without previous line encode_png_str_scanline_average(stream, 0, nil, 12, 3) - expect(stream.unpack('@0C13')).to eql [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 35, 40, 45, 50, 55, 50, 65, 70, 80] + expect(stream.unpack("@0C13")).to eql [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 35, 40, 45, 50, 55, 50, 65, 70, 80] end it "should encode a scanline with paeth filtering correctly" do - stream = [ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120, - ChunkyPNG::FILTER_NONE, 10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120].pack('C*') + stream = [ + ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120, # rubocop:disable Layout/ExtraSpacing + ChunkyPNG::FILTER_NONE, 10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120, # rubocop:disable Layout/ExtraSpacing + ].pack("C*") # Check line with previous line encode_png_str_scanline_paeth(stream, 13, 0, 12, 3) - expect(stream.unpack('@13C13')).to eql [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0] + expect(stream.unpack("@13C13")).to eql [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0] # Check line without previous line encode_png_str_scanline_paeth(stream, 0, nil, 12, 3) - expect(stream.unpack('@0C13')).to eql [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 30, 30, 30, 30, 30, 20, 30, 30, 40] + expect(stream.unpack("@0C13")).to eql [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 30, 30, 30, 30, 30, 20, 30, 30, 40] end end end diff --git a/spec/chunky_png/canvas/resampling_spec.rb b/spec/chunky_png/canvas/resampling_spec.rb index fdd46cc4..7135e7d8 100644 --- a/spec/chunky_png/canvas/resampling_spec.rb +++ b/spec/chunky_png/canvas/resampling_spec.rb @@ -1,11 +1,9 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas::Resampling do + subject { reference_canvas("clock") } - subject { reference_canvas('clock') } - - describe '#resample_nearest_neighbor' do - + describe "#resample_nearest_neighbor" do it "should downscale from 2x2 to 1x1 correctly" do canvas = ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4]) expect(canvas.resample_nearest_neighbor(1, 1)).to eql ChunkyPNG::Canvas.new(1, 1, [4]) @@ -17,15 +15,15 @@ end it "should upscale both axis of the image" do - expect(subject.resample_nearest_neighbor(45, 45)).to eql reference_canvas('clock_nn_xup_yup') + expect(subject.resample_nearest_neighbor(45, 45)).to eql reference_canvas("clock_nn_xup_yup") end it "should downscale both axis of the image" do - expect(subject.resample_nearest_neighbor(12, 12)).to eql reference_canvas('clock_nn_xdown_ydown') + expect(subject.resample_nearest_neighbor(12, 12)).to eql reference_canvas("clock_nn_xdown_ydown") end it "should downscale the x-axis and upscale the y-axis of the image" do - expect(subject.resample_nearest_neighbor(20, 50)).to eql reference_canvas('clock_nn_xdown_yup') + expect(subject.resample_nearest_neighbor(20, 50)).to eql reference_canvas("clock_nn_xdown_yup") end it "should not return itself" do @@ -37,20 +35,20 @@ end end - describe '#resample_nearest_neighbor!' do + describe "#resample_nearest_neighbor!" do it "should upscale both axis of the image" do subject.resample_nearest_neighbor!(45, 45) - expect(subject).to eql reference_canvas('clock_nn_xup_yup') + expect(subject).to eql reference_canvas("clock_nn_xup_yup") end it "should downscale both axis of the image" do subject.resample_nearest_neighbor!(12, 12) - expect(subject).to eql reference_canvas('clock_nn_xdown_ydown') + expect(subject).to eql reference_canvas("clock_nn_xdown_ydown") end it "should downscale the x-axis and upscale the y-axis of the image" do subject.resample_nearest_neighbor!(20, 50) - expect(subject).to eql reference_canvas('clock_nn_xdown_yup') + expect(subject).to eql reference_canvas("clock_nn_xdown_yup") end it "should return itself" do @@ -58,7 +56,7 @@ end it "should change the original image's dimensions" do - expect { subject.resample_nearest_neighbor!(1, 1) }.to change { subject.dimension }.to(ChunkyPNG::Dimension('1x1')) + expect { subject.resample_nearest_neighbor!(1, 1) }.to change { subject.dimension }.to(ChunkyPNG::Dimension("1x1")) end end @@ -74,15 +72,15 @@ end it "should upscale both axis of the image" do - expect(subject.resample_bilinear(45, 45)).to eql reference_canvas('clock_bl_xup_yup') + expect(subject.resample_bilinear(45, 45)).to eql reference_canvas("clock_bl_xup_yup") end it "should downscale both axis of the image" do - expect(subject.resample_bilinear(12, 12)).to eql reference_canvas('clock_bl_xdown_ydown') + expect(subject.resample_bilinear(12, 12)).to eql reference_canvas("clock_bl_xdown_ydown") end it "should downscale the x-axis and upscale the y-axis of the image" do - expect(subject.resample_bilinear(20, 50)).to eql reference_canvas('clock_bl_xdown_yup') + expect(subject.resample_bilinear(20, 50)).to eql reference_canvas("clock_bl_xdown_yup") end it "should not return itself" do @@ -94,20 +92,20 @@ end end - describe '#resample_bilinear!' do + describe "#resample_bilinear!" do it "should upscale both axis of the image" do subject.resample_bilinear!(45, 45) - expect(subject).to eql reference_canvas('clock_bl_xup_yup') + expect(subject).to eql reference_canvas("clock_bl_xup_yup") end it "should downscale both axis of the image" do subject.resample_bilinear!(12, 12) - expect(subject).to eql reference_canvas('clock_bl_xdown_ydown') + expect(subject).to eql reference_canvas("clock_bl_xdown_ydown") end it "should downscale the x-axis and upscale the y-axis of the image" do subject.resample_bilinear!(20, 50) - expect(subject).to eql reference_canvas('clock_bl_xdown_yup') + expect(subject).to eql reference_canvas("clock_bl_xdown_yup") end it "should return itself" do @@ -115,7 +113,7 @@ end it "should change the original image's dimensions" do - expect { subject.resample_bilinear!(1, 1) }.to change { subject.dimension }.to(ChunkyPNG::Dimension('1x1')) + expect { subject.resample_bilinear!(1, 1) }.to change { subject.dimension }.to(ChunkyPNG::Dimension("1x1")) end end end diff --git a/spec/chunky_png/canvas/stream_exporting_spec.rb b/spec/chunky_png/canvas/stream_exporting_spec.rb index 2243027d..2f464ebd 100644 --- a/spec/chunky_png/canvas/stream_exporting_spec.rb +++ b/spec/chunky_png/canvas/stream_exporting_spec.rb @@ -1,59 +1,79 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas do - - describe '#to_rgba_stream' do + describe "#to_rgba_stream" do it "should export a sample canvas to an RGBA stream correctly" do - canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8), - ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)]) + canvas = ChunkyPNG::Canvas.new(2, 2, [ + ChunkyPNG::Color.rgba(1, 2, 3, 4), + ChunkyPNG::Color.rgba(5, 6, 7, 8), + ChunkyPNG::Color.rgba(4, 3, 2, 1), + ChunkyPNG::Color.rgba(8, 7, 6, 5), + ]) - expect(canvas.to_rgba_stream).to eql [1,2,3,4,5,6,7,8,4,3,2,1,8,7,6,5].pack('C16') + expect(canvas.to_rgba_stream).to eql [1, 2, 3, 4, 5, 6, 7, 8, 4, 3, 2, 1, 8, 7, 6, 5].pack("C16") end it "should export an image to an RGBA datastream correctly" do - expect(reference_canvas('pixelstream_reference').to_rgba_stream).to eql resource_data('pixelstream.rgba') + expect(reference_canvas("pixelstream_reference").to_rgba_stream).to eql resource_data("pixelstream.rgba") end end - describe '#to_rgb_stream' do + describe "#to_rgb_stream" do it "should export a sample canvas to an RGBA stream correctly" do - canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8), - ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)]) + canvas = ChunkyPNG::Canvas.new(2, 2, [ + ChunkyPNG::Color.rgba(1, 2, 3, 4), + ChunkyPNG::Color.rgba(5, 6, 7, 8), + ChunkyPNG::Color.rgba(4, 3, 2, 1), + ChunkyPNG::Color.rgba(8, 7, 6, 5), + ]) - expect(canvas.to_rgb_stream).to eql [1,2,3,5,6,7,4,3,2,8,7,6].pack('C12') + expect(canvas.to_rgb_stream).to eql [1, 2, 3, 5, 6, 7, 4, 3, 2, 8, 7, 6].pack("C12") end it "should export an image to an RGB datastream correctly" do - expect(reference_canvas('pixelstream_reference').to_rgb_stream).to eql resource_data('pixelstream.rgb') + expect(reference_canvas("pixelstream_reference").to_rgb_stream).to eql resource_data("pixelstream.rgb") end end - describe '#to_grayscale_stream' do - + describe "#to_grayscale_stream" do it "should export a grayscale image to a grayscale datastream correctly" do - canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.grayscale(1), ChunkyPNG::Color.grayscale(2), - ChunkyPNG::Color.grayscale(3), ChunkyPNG::Color.grayscale(4)]) - expect(canvas.to_grayscale_stream).to eql [1,2,3,4].pack('C4') - end + canvas = ChunkyPNG::Canvas.new(2, 2, [ + ChunkyPNG::Color.grayscale(1), + ChunkyPNG::Color.grayscale(2), + ChunkyPNG::Color.grayscale(3), + ChunkyPNG::Color.grayscale(4), + ]) + expect(canvas.to_grayscale_stream).to eql [1, 2, 3, 4].pack("C4") + end it "should export a color image to a grayscale datastream, using B values" do - canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8), - ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)]) - expect(canvas.to_grayscale_stream).to eql [3,7,2,6].pack('C4') + canvas = ChunkyPNG::Canvas.new(2, 2, [ + ChunkyPNG::Color.rgba(1, 2, 3, 4), + ChunkyPNG::Color.rgba(5, 6, 7, 8), + ChunkyPNG::Color.rgba(4, 3, 2, 1), + ChunkyPNG::Color.rgba(8, 7, 6, 5), + ]) + + expect(canvas.to_grayscale_stream).to eql [3, 7, 2, 6].pack("C4") end end - describe '#to_alpha_channel_stream' do + describe "#to_alpha_channel_stream" do it "should export an opaque image to an alpha channel datastream correctly" do - grayscale_array = Array.new(reference_canvas('pixelstream_reference').pixels.length, 255) - expect(reference_canvas('pixelstream_reference').to_alpha_channel_stream).to eql grayscale_array.pack('C*') + grayscale_array = Array.new(reference_canvas("pixelstream_reference").pixels.length, 255) + expect(reference_canvas("pixelstream_reference").to_alpha_channel_stream).to eql grayscale_array.pack("C*") end it "should export a transparent image to an alpha channel datastream correctly" do - canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8), - ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)]) - expect(canvas.to_alpha_channel_stream).to eql [4,8,1,5].pack('C4') + canvas = ChunkyPNG::Canvas.new(2, 2, [ + ChunkyPNG::Color.rgba(1, 2, 3, 4), + ChunkyPNG::Color.rgba(5, 6, 7, 8), + ChunkyPNG::Color.rgba(4, 3, 2, 1), + ChunkyPNG::Color.rgba(8, 7, 6, 5), + ]) + + expect(canvas.to_alpha_channel_stream).to eql [4, 8, 1, 5].pack("C4") end end end diff --git a/spec/chunky_png/canvas/stream_importing_spec.rb b/spec/chunky_png/canvas/stream_importing_spec.rb index c1401042..8564968f 100644 --- a/spec/chunky_png/canvas/stream_importing_spec.rb +++ b/spec/chunky_png/canvas/stream_importing_spec.rb @@ -1,30 +1,29 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas do - - describe '.from_rgb_stream' do + describe ".from_rgb_stream" do it "should load an image correctly from a datastream" do - File.open(resource_file('pixelstream.rgb')) do |stream| + File.open(resource_file("pixelstream.rgb")) do |stream| matrix = ChunkyPNG::Canvas.from_rgb_stream(240, 180, stream) - expect(matrix).to eql reference_canvas('pixelstream_reference') + expect(matrix).to eql reference_canvas("pixelstream_reference") end end end - describe '.from_bgr_stream' do + describe ".from_bgr_stream" do it "should load an image correctly from a datastream" do - File.open(resource_file('pixelstream.bgr')) do |stream| + File.open(resource_file("pixelstream.bgr")) do |stream| matrix = ChunkyPNG::Canvas.from_bgr_stream(240, 180, stream) - expect(matrix).to eql reference_canvas('pixelstream_reference') + expect(matrix).to eql reference_canvas("pixelstream_reference") end end end - describe '.from_rgba_stream' do + describe ".from_rgba_stream" do it "should load an image correctly from a datastream" do - File.open(resource_file('pixelstream.rgba')) do |stream| + File.open(resource_file("pixelstream.rgba")) do |stream| matrix = ChunkyPNG::Canvas.from_rgba_stream(240, 180, stream) - expect(matrix).to eql reference_canvas('pixelstream_reference') + expect(matrix).to eql reference_canvas("pixelstream_reference") end end end diff --git a/spec/chunky_png/canvas_spec.rb b/spec/chunky_png/canvas_spec.rb index 2cae306e..9d459b90 100644 --- a/spec/chunky_png/canvas_spec.rb +++ b/spec/chunky_png/canvas_spec.rb @@ -1,17 +1,16 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Canvas do - subject { ChunkyPNG::Canvas.new(1, 1, ChunkyPNG::Color::WHITE) } it { should respond_to(:width) } it { should respond_to(:height) } it { should respond_to(:pixels) } - describe '#initialize' do + describe "#initialize" do it "should accept a single color value as background color" do - canvas = ChunkyPNG::Canvas.new(2, 2, 'red @ 0.8') - expect(canvas[1, 0]).to eql ChunkyPNG::Color.parse('red @ 0.8') + canvas = ChunkyPNG::Canvas.new(2, 2, "red @ 0.8") + expect(canvas[1, 0]).to eql ChunkyPNG::Color.parse("red @ 0.8") end it "should raise an error if the color value is not understood" do @@ -19,7 +18,7 @@ end it "should accept an array as initial pixel values" do - canvas = ChunkyPNG::Canvas.new(2, 2, [1,2,3,4]) + canvas = ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4]) expect(canvas[0, 0]).to eql 1 expect(canvas[1, 0]).to eql 2 expect(canvas[0, 1]).to eql 3 @@ -27,32 +26,32 @@ end it "should raise an ArgumentError if the initial array does not have the correct number of elements" do - expect { ChunkyPNG::Canvas.new(2, 2, [1,2,3]) }.to raise_error(ArgumentError) - expect { ChunkyPNG::Canvas.new(2, 2, [1,2,3,4,5]) }.to raise_error(ArgumentError) + expect { ChunkyPNG::Canvas.new(2, 2, [1, 2, 3]) }.to raise_error(ArgumentError) + expect { ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4, 5]) }.to raise_error(ArgumentError) end it "should use a transparent background by default" do canvas = ChunkyPNG::Canvas.new(1, 1) - expect(canvas[0,0]).to eql ChunkyPNG::Color::TRANSPARENT + expect(canvas[0, 0]).to eql ChunkyPNG::Color::TRANSPARENT end end - describe '#dimension' do + describe "#dimension" do it "should return the dimensions as a Dimension instance" do - expect(subject.dimension).to eql ChunkyPNG::Dimension('1x1') + expect(subject.dimension).to eql ChunkyPNG::Dimension("1x1") end end - describe '#area' do + describe "#area" do it "should return the dimensions as two-item array" do - expect(subject.area).to eql ChunkyPNG::Dimension('1x1').area + expect(subject.area).to eql ChunkyPNG::Dimension("1x1").area end end - describe '#include?' do + describe "#include?" do it "should return true if the coordinates are within bounds, false otherwise" do + # rubocop:disable Layout/SpaceInsideParens expect(subject.include_xy?( 0, 0)).to eql true - expect(subject.include_xy?(-1, 0)).to eql false expect(subject.include_xy?( 1, 0)).to eql false expect(subject.include_xy?( 0, -1)).to eql false @@ -61,11 +60,12 @@ expect(subject.include_xy?(-1, 1)).to eql false expect(subject.include_xy?( 1, -1)).to eql false expect(subject.include_xy?( 1, 1)).to eql false + # rubocop:enable Layout/SpaceInsideParens end it "should accept strings, arrays, hashes and points as well" do - expect(subject).to include('0, 0') - expect(subject).to_not include('0, 1') + expect(subject).to include("0, 0") + expect(subject).to_not include("0, 1") expect(subject).to include([0, 0]) expect(subject).to_not include([0, 1]) expect(subject).to include(y: 0, x: 0) @@ -75,23 +75,23 @@ end end - describe '#include_x?' do + describe "#include_x?" do it "should return true if the x-coordinate is within bounds, false otherwise" do - expect(subject.include_x?( 0)).to eql true + expect(subject.include_x?(0)).to eql true expect(subject.include_x?(-1)).to eql false - expect(subject.include_x?( 1)).to eql false + expect(subject.include_x?(1)).to eql false end end - describe '#include_y?' do + describe "#include_y?" do it "should return true if the y-coordinate is within bounds, false otherwise" do - expect(subject.include_y?( 0)).to eql true + expect(subject.include_y?(0)).to eql true expect(subject.include_y?(-1)).to eql false - expect(subject.include_y?( 1)).to eql false + expect(subject.include_y?(1)).to eql false end end - describe '#assert_xy!' do + describe "#assert_xy!" do it "should not raise an exception if the coordinates are within bounds" do expect(subject).to receive(:include_xy?).with(0, 0).and_return(true) expect { subject.send(:assert_xy!, 0, 0) }.to_not raise_error @@ -103,7 +103,7 @@ end end - describe '#assert_x!' do + describe "#assert_x!" do it "should not raise an exception if the x-coordinate is within bounds" do expect(subject).to receive(:include_x?).with(0).and_return(true) expect { subject.send(:assert_x!, 0) }.to_not raise_error @@ -115,7 +115,7 @@ end end - describe '#[]' do + describe "#[]" do it "should return the pixel value if the coordinates are within bounds" do expect(subject[0, 0]).to eql ChunkyPNG::Color::WHITE end @@ -126,7 +126,7 @@ end end - describe '#get_pixel' do + describe "#get_pixel" do it "should return the pixel value if the coordinates are within bounds" do expect(subject.get_pixel(0, 0)).to eql ChunkyPNG::Color::WHITE end @@ -138,7 +138,7 @@ end end - describe '#[]=' do + describe "#[]=" do it "should change the pixel's color value" do expect { subject[0, 0] = ChunkyPNG::Color::BLACK }.to change { subject[0, 0] } .from(ChunkyPNG::Color::WHITE) @@ -151,7 +151,7 @@ end end - describe 'set_pixel' do + describe "set_pixel" do it "should change the pixel's color value" do expect { subject.set_pixel(0, 0, ChunkyPNG::Color::BLACK) }.to change { subject[0, 0] } .from(ChunkyPNG::Color::WHITE) @@ -165,7 +165,7 @@ end end - describe '#set_pixel_if_within_bounds' do + describe "#set_pixel_if_within_bounds" do it "should change the pixel's color value" do expect { subject.set_pixel_if_within_bounds(0, 0, ChunkyPNG::Color::BLACK) }.to change { subject[0, 0] } .from(ChunkyPNG::Color::WHITE) @@ -184,8 +184,8 @@ end end - describe '#row' do - before { @canvas = reference_canvas('operations') } + describe "#row" do + before { @canvas = reference_canvas("operations") } it "should give an out of bounds exception when y-coordinate is out of bounds" do expect { @canvas.row(-1) }.to raise_error(ChunkyPNG::OutOfBounds) @@ -199,8 +199,8 @@ end end - describe '#column' do - before { @canvas = reference_canvas('operations') } + describe "#column" do + before { @canvas = reference_canvas("operations") } it "should give an out of bounds exception when x-coordinate is out of bounds" do expect { @canvas.column(-1) }.to raise_error(ChunkyPNG::OutOfBounds) @@ -214,21 +214,21 @@ end end - describe '#replace_canvas' do + describe "#replace_canvas" do it "should change the dimension of the canvas" do - expect { subject.send(:replace_canvas!, 2, 2, [1,2,3,4]) }.to change { subject.dimension } - .from(ChunkyPNG::Dimension('1x1')) - .to(ChunkyPNG::Dimension('2x2')) + expect { subject.send(:replace_canvas!, 2, 2, [1, 2, 3, 4]) }.to change { subject.dimension } + .from(ChunkyPNG::Dimension("1x1")) + .to(ChunkyPNG::Dimension("2x2")) end it "should change the pixel array" do - expect { subject.send(:replace_canvas!, 2, 2, [1,2,3,4]) }.to change { subject.pixels } - .from([ChunkyPNG::Color('white')]) - .to([1,2,3,4]) + expect { subject.send(:replace_canvas!, 2, 2, [1, 2, 3, 4]) }.to change { subject.pixels } + .from([ChunkyPNG::Color("white")]) + .to([1, 2, 3, 4]) end it "should return itself" do - expect(subject.send(:replace_canvas!, 2, 2, [1,2,3,4])).to equal(subject) + expect(subject.send(:replace_canvas!, 2, 2, [1, 2, 3, 4])).to equal(subject) end end end diff --git a/spec/chunky_png/color_spec.rb b/spec/chunky_png/color_spec.rb index 9356bb32..10a0cd49 100644 --- a/spec/chunky_png/color_spec.rb +++ b/spec/chunky_png/color_spec.rb @@ -1,22 +1,22 @@ -require 'spec_helper' +require "spec_helper" -describe 'ChunyPNG.Color' do - it 'should interpret 4 arguments as RGBA values' do +describe "ChunyPNG.Color" do + it "should interpret 4 arguments as RGBA values" do expect(ChunkyPNG::Color(1, 2, 3, 4)).to eql ChunkyPNG::Color.rgba(1, 2, 3, 4) end - it 'should interpret 3 arguments as RGBA values' do + it "should interpret 3 arguments as RGBA values" do expect(ChunkyPNG::Color(1, 2, 3)).to eql ChunkyPNG::Color.rgb(1, 2, 3) end - it 'should interpret 2 arguments as a color to parse and an opacity value' do - expect(ChunkyPNG::Color('0x0a649664', 0xaa)).to eql 0x0a6496aa - expect(ChunkyPNG::Color('spring green @ 0.6666', 0xff)).to eql 0x00ff7fff + it "should interpret 2 arguments as a color to parse and an opacity value" do + expect(ChunkyPNG::Color("0x0a649664", 0xaa)).to eql 0x0a6496aa + expect(ChunkyPNG::Color("spring green @ 0.6666", 0xff)).to eql 0x00ff7fff end - it 'should interpret 1 argument as a color to parse' do - expect(ChunkyPNG::Color).to receive(:parse).with('0x0a649664') - ChunkyPNG::Color('0x0a649664') + it "should interpret 1 argument as a color to parse" do + expect(ChunkyPNG::Color).to receive(:parse).with("0x0a649664") + ChunkyPNG::Color("0x0a649664") end end @@ -34,85 +34,87 @@ @blue = 0x0000ffff end - describe '#parse' do - it 'should interpret a hex string correctly' do - expect(parse('0x0a649664')).to eql ChunkyPNG::Color.from_hex('#0a649664') + describe "#parse" do + it "should interpret a hex string correctly" do + expect(parse("0x0a649664")).to eql ChunkyPNG::Color.from_hex("#0a649664") end - it 'should interpret a color name correctly' do + it "should interpret a color name correctly" do expect(parse(:spring_green)).to eql 0x00ff7fff - expect(parse('spring green')).to eql 0x00ff7fff - expect(parse('spring green @ 0.6666')).to eql 0x00ff7faa + expect(parse("spring green")).to eql 0x00ff7fff + expect(parse("spring green @ 0.6666")).to eql 0x00ff7faa end - it 'should return numbers as is' do - expect(parse('12345')).to eql 12345 + it "should return numbers as is" do + expect(parse("12345")).to eql 12345 expect(parse(12345)).to eql 12345 end end - describe '#pixel_bytesize' do - it 'should return the normal amount of bytes with a bit depth of 8' do + describe "#pixel_bytesize" do + it "should return the normal amount of bytes with a bit depth of 8" do expect(pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8)).to eql 3 end - it 'should return a multiple of the normal amount of bytes with a bit depth greater than 8' do + it "should return a multiple of the normal amount of bytes with a bit depth greater than 8" do expect(pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 16)).to eql 6 expect(pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 16)).to eql 8 expect(pixel_bytesize(ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 16)).to eql 4 end - it 'should return 1 with a bit depth lower than 0' do + it "should return 1 with a bit depth lower than 0" do expect(pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 4)).to eql 1 expect(pixel_bytesize(ChunkyPNG::COLOR_INDEXED, 2)).to eql 1 expect(pixel_bytesize(ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 1)).to eql 1 end end - describe '#pass_bytesize' do - it 'should calculate a pass size correctly' do + describe "#pass_bytesize" do + it "should calculate a pass size correctly" do expect(pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 10, 10)).to eql 310 end - it 'should return 0 if one of the dimensions is zero' do + it "should return 0 if one of the dimensions is zero" do expect(pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 0, 10)).to eql 0 expect(pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 10, 0)).to eql 0 end end - describe '#rgba' do - it 'should represent pixels as the correct number' do + describe "#rgba" do + it "should represent pixels as the correct number" do + # rubocop:disable Layout/ExtraSpacing, Layout/SpaceInsideParens expect(rgba(255, 255, 255, 255)).to eql @white expect(rgba( 0, 0, 0, 255)).to eql @black expect(rgba( 10, 100, 150, 255)).to eql @opaque expect(rgba( 10, 100, 150, 100)).to eql @non_opaque expect(rgba( 10, 100, 150, 0)).to eql @fully_transparent + # rubocop:enable Layout/ExtraSpacing, Layout/SpaceInsideParens end end - describe '#from_hex' do - it 'should load colors correctly from hex notation' do - expect(from_hex('0a649664')).to eql @non_opaque - expect(from_hex('#0a649664')).to eql @non_opaque - expect(from_hex('0x0a649664')).to eql @non_opaque - expect(from_hex('0a6496')).to eql @opaque - expect(from_hex('#0a6496')).to eql @opaque - expect(from_hex('0x0a6496')).to eql @opaque - expect(from_hex('abc')).to eql 0xaabbccff - expect(from_hex('#abc')).to eql 0xaabbccff - expect(from_hex('0xabc')).to eql 0xaabbccff - end - - it 'should allow setting opacity explicitly' do - expect(from_hex('0x0a6496', 0x64)).to eql @non_opaque - expect(from_hex('#0a6496', 0x64)).to eql @non_opaque - expect(from_hex('0xabc', 0xdd)).to eql 0xaabbccdd - expect(from_hex('#abc', 0xdd)).to eql 0xaabbccdd + describe "#from_hex" do + it "should load colors correctly from hex notation" do + expect(from_hex("0a649664")).to eql @non_opaque + expect(from_hex("#0a649664")).to eql @non_opaque + expect(from_hex("0x0a649664")).to eql @non_opaque + expect(from_hex("0a6496")).to eql @opaque + expect(from_hex("#0a6496")).to eql @opaque + expect(from_hex("0x0a6496")).to eql @opaque + expect(from_hex("abc")).to eql 0xaabbccff + expect(from_hex("#abc")).to eql 0xaabbccff + expect(from_hex("0xabc")).to eql 0xaabbccff + end + + it "should allow setting opacity explicitly" do + expect(from_hex("0x0a6496", 0x64)).to eql @non_opaque + expect(from_hex("#0a6496", 0x64)).to eql @non_opaque + expect(from_hex("0xabc", 0xdd)).to eql 0xaabbccdd + expect(from_hex("#abc", 0xdd)).to eql 0xaabbccdd end end - describe '#from_hsv' do - it 'should load colors correctly from an HSV triple' do + describe "#from_hsv" do + it "should load colors correctly from an HSV triple" do # At 0 brightness, should be @black independent of hue or sat expect(from_hsv(0, 0, 0)).to eql @black expect(from_hsv(100, 1, 0)).to eql @black @@ -135,7 +137,7 @@ expect(from_hsv(0, 0.5, 0.5)).to eql from_hsv(360.0, 0.5, 0.5) end - it 'should optionally accept a fourth param for alpha' do + it "should optionally accept a fourth param for alpha" do expect(from_hsv(0, 1, 1, 255)).to eql @red expect(from_hsv(120, 1, 1, 255)).to eql @green expect(from_hsv(240, 1, 1, 255)).to eql @blue @@ -145,8 +147,8 @@ end end - describe '#from_hsl' do - it 'should load colors correctly from an HSL triple' do + describe "#from_hsl" do + it "should load colors correctly from an HSL triple" do # At 0 lightness, should always be black expect(from_hsl(0, 0, 0)).to eql @black expect(from_hsl(100, 0, 0)).to eql @black @@ -163,16 +165,16 @@ expect(from_hsl(240, 1, 0.5)).to eql @blue # Random colors - from_hsl(87.27, 0.5, 0.5686) == 0x96c85aff - from_hsl(271.83, 0.5399, 0.4176) == 0x6e31a4ff - from_hsl(63.6, 0.5984, 0.4882) == 0xbec732ff + expect(from_hsl(87.27, 0.5, 0.5686)).to eql 0x95c759ff + expect(from_hsl(271.83, 0.5399, 0.4176)).to eql 0x6d30a3ff + expect(from_hsl(63.6, 0.5984, 0.4882)).to eql 0xbec631ff # Hue 0 and hue 360 should be equivalent expect(from_hsl(0, 0.5, 0.5)).to eql from_hsl(360, 0.5, 0.5) expect(from_hsl(0, 0.5, 0.5)).to eql from_hsl(360.0, 0.5, 0.5) end - it 'should optionally accept a fourth param for alpha' do + it "should optionally accept a fourth param for alpha" do expect(from_hsl(0, 1, 0.5, 255)).to eql @red expect(from_hsl(120, 1, 0.5, 255)).to eql @green expect(from_hsl(240, 1, 0.5, 255)).to eql @blue @@ -182,35 +184,35 @@ end end - describe '#html_color' do - it 'should find the correct color value' do + describe "#html_color" do + it "should find the correct color value" do expect(html_color(:springgreen)).to eql 0x00ff7fff expect(html_color(:spring_green)).to eql 0x00ff7fff - expect(html_color('springgreen')).to eql 0x00ff7fff - expect(html_color('spring green')).to eql 0x00ff7fff - expect(html_color('SpringGreen')).to eql 0x00ff7fff - expect(html_color('SPRING_GREEN')).to eql 0x00ff7fff + expect(html_color("springgreen")).to eql 0x00ff7fff + expect(html_color("spring green")).to eql 0x00ff7fff + expect(html_color("SpringGreen")).to eql 0x00ff7fff + expect(html_color("SPRING_GREEN")).to eql 0x00ff7fff end - it 'should set the opacity level explicitly' do + it "should set the opacity level explicitly" do expect(html_color(:springgreen, 0xff)).to eql 0x00ff7fff expect(html_color(:springgreen, 0xaa)).to eql 0x00ff7faa expect(html_color(:springgreen, 0x00)).to eql 0x00ff7f00 end - it 'should set opacity levels from the color name' do - expect(html_color('Spring green @ 1.0')).to eql 0x00ff7fff - expect(html_color('Spring green @ 0.666')).to eql 0x00ff7faa - expect(html_color('Spring green @ 0.0')).to eql 0x00ff7f00 + it "should set opacity levels from the color name" do + expect(html_color("Spring green @ 1.0")).to eql 0x00ff7fff + expect(html_color("Spring green @ 0.666")).to eql 0x00ff7faa + expect(html_color("Spring green @ 0.0")).to eql 0x00ff7f00 end - it 'should raise for an unkown color name' do + it "should raise for an unkown color name" do expect { html_color(:nonsense) }.to raise_error(ArgumentError) end end - describe '#opaque?' do - it 'should correctly check for opaqueness' do + describe "#opaque?" do + it "should correctly check for opaqueness" do expect(opaque?(@white)).to eql true expect(opaque?(@black)).to eql true expect(opaque?(@opaque)).to eql true @@ -219,8 +221,8 @@ end end - describe 'extraction of separate color channels' do - it 'should extract components from a color correctly' do + describe "extraction of separate color channels" do + it "should extract components from a color correctly" do expect(r(@opaque)).to eql 10 expect(g(@opaque)).to eql 100 expect(b(@opaque)).to eql 150 @@ -228,47 +230,47 @@ end end - describe '#grayscale_teint' do - it 'should calculate the correct grayscale teint' do + describe "#grayscale_teint" do + it "should calculate the correct grayscale teint" do expect(grayscale_teint(@opaque)).to eql 79 expect(grayscale_teint(@non_opaque)).to eql 79 end end - describe '#to_grayscale' do - it 'should use the grayscale teint for r, g and b' do + describe "#to_grayscale" do + it "should use the grayscale teint for r, g and b" do gs = to_grayscale(@non_opaque) expect(r(gs)).to eql grayscale_teint(@non_opaque) expect(g(gs)).to eql grayscale_teint(@non_opaque) expect(b(gs)).to eql grayscale_teint(@non_opaque) end - it 'should preserve the alpha channel' do + it "should preserve the alpha channel" do expect(a(to_grayscale(@non_opaque))).to eql a(@non_opaque) expect(a(to_grayscale(@opaque))).to eql ChunkyPNG::Color::MAX end end - describe '#to_hex' do - it 'should represent colors correcly using hex notation' do - expect(to_hex(@white)).to eql '#ffffffff' - expect(to_hex(@black)).to eql '#000000ff' - expect(to_hex(@opaque)).to eql '#0a6496ff' - expect(to_hex(@non_opaque)).to eql '#0a649664' - expect(to_hex(@fully_transparent)).to eql '#0a649600' + describe "#to_hex" do + it "should represent colors correcly using hex notation" do + expect(to_hex(@white)).to eql "#ffffffff" + expect(to_hex(@black)).to eql "#000000ff" + expect(to_hex(@opaque)).to eql "#0a6496ff" + expect(to_hex(@non_opaque)).to eql "#0a649664" + expect(to_hex(@fully_transparent)).to eql "#0a649600" end - it 'should represent colors correcly using hex notation without alpha channel' do - expect(to_hex(@white, false)).to eql '#ffffff' - expect(to_hex(@black, false)).to eql '#000000' - expect(to_hex(@opaque, false)).to eql '#0a6496' - expect(to_hex(@non_opaque, false)).to eql '#0a6496' - expect(to_hex(@fully_transparent, false)).to eql '#0a6496' + it "should represent colors correcly using hex notation without alpha channel" do + expect(to_hex(@white, false)).to eql "#ffffff" + expect(to_hex(@black, false)).to eql "#000000" + expect(to_hex(@opaque, false)).to eql "#0a6496" + expect(to_hex(@non_opaque, false)).to eql "#0a6496" + expect(to_hex(@fully_transparent, false)).to eql "#0a6496" end end - describe '#to_hsv' do - it 'should return a [hue, saturation, value] array' do + describe "#to_hsv" do + it "should return a [hue, saturation, value] array" do expect(to_hsv(@white)).to eql [0, 0.0, 1.0] expect(to_hsv(@black)).to eql [0, 0.0, 0.0] expect(to_hsv(@red)).to eql [0, 1.0, 1.0] @@ -279,7 +281,7 @@ expect(to_hsv(0x805440ff)[2]).to be_within(0.01).of(0.5) end - it 'should optionally include the alpha channel' do + it "should optionally include the alpha channel" do expect(to_hsv(@white, true)).to eql [0, 0.0, 1.0, 255] expect(to_hsv(@red, true)).to eql [0, 1.0, 1.0, 255] expect(to_hsv(@blue, true)).to eql [240, 1.0, 1.0, 255] @@ -289,8 +291,8 @@ end end - describe '#to_hsl' do - it 'should return a [hue, saturation, lightness] array' do + describe "#to_hsl" do + it "should return a [hue, saturation, lightness] array" do expect(to_hsl(@white)).to eql [0, 0.0, 1.0] expect(to_hsl(@black)).to eql [0, 0.0, 0.0] expect(to_hsl(@red)).to eql [0, 1.0, 0.5] @@ -298,7 +300,7 @@ expect(to_hsl(@green)).to eql [120, 1.0, 0.5] end - it 'should optionally include the alpha channel in the returned array' do + it "should optionally include the alpha channel in the returned array" do expect(to_hsl(@white, true)).to eql [0, 0.0, 1.0, 255] expect(to_hsl(@black, true)).to eql [0, 0.0, 0.0, 255] expect(to_hsl(@red, true)).to eql [0, 1.0, 0.5, 255] @@ -309,79 +311,78 @@ end end - describe 'conversion to other formats' do - it 'should convert the individual color values back correctly' do + describe "conversion to other formats" do + it "should convert the individual color values back correctly" do expect(to_truecolor_bytes(@opaque)).to eql [10, 100, 150] expect(to_truecolor_alpha_bytes(@non_opaque)).to eql [10, 100, 150, 100] end end - describe '#compose' do - - it 'should use the foregorund color as is when the background color is fully transparent' do + describe "#compose" do + it "should use the foregorund color as is when the background color is fully transparent" do expect(compose(@non_opaque, @fully_transparent)).to eql @non_opaque end - it 'should use the foregorund color as is when an opaque color is given as foreground color' do + it "should use the foregorund color as is when an opaque color is given as foreground color" do expect(compose(@opaque, @white)).to eql @opaque end - it 'should use the background color as is when a fully transparent pixel is given as foreground color' do + it "should use the background color as is when a fully transparent pixel is given as foreground color" do expect(compose(@fully_transparent, @white)).to eql @white end - it 'should compose pixels correctly with both algorithms' do + it "should compose pixels correctly with both algorithms" do expect(compose_quick(@non_opaque, @white)).to eql 0x9fc2d6ff expect(compose_precise(@non_opaque, @white)).to eql 0x9fc2d6ff end end - describe '#decompose_alpha' do - it 'should decompose the alpha channel correctly' do + describe "#decompose_alpha" do + it "should decompose the alpha channel correctly" do expect(decompose_alpha(0x9fc2d6ff, @opaque, @white)).to eql 0x00000064 end - it 'should return fully transparent if the background channel matches the resulting color' do + it "should return fully transparent if the background channel matches the resulting color" do expect(decompose_alpha(0xabcdefff, 0xff000000, 0xabcdefff)).to eql 0x00 end - it 'should return fully opaque if the background channel matches the mask color' do + it "should return fully opaque if the background channel matches the mask color" do expect(decompose_alpha(0xff000000, 0xabcdefff, 0xabcdefff)).to eql 0xff end - it 'should return fully opaque if the resulting color matches the mask color' do + it "should return fully opaque if the resulting color matches the mask color" do expect(decompose_alpha(0xabcdefff, 0xabcdefff, 0xffffffff)).to eql 255 end end - describe '#blend' do - it 'should blend colors correctly' do + describe "#blend" do + it "should blend colors correctly" do expect(blend(@opaque, @black)).to eql 0x05324bff end - it 'should not matter what color is used as foreground, and what as background' do + it "should not matter what color is used as foreground, and what as background" do expect(blend(@opaque, @black)).to eql blend(@black, @opaque) end end - describe '#euclidean_distance_rgba' do + describe "#euclidean_distance_rgba" do subject { euclidean_distance_rgba(color_a, color_b) } - context 'with white and black' do + context "with white and black" do let(:color_a) { @white } let(:color_b) { @black } it { should == Math.sqrt(195_075) } # sqrt(255^2 * 3) end - context 'with black and white' do + context "with black and white" do let(:color_a) { @black } let(:color_b) { @white } it { should == Math.sqrt(195_075) } # sqrt(255^2 * 3) end - context 'with the same colors' do + context "with the same colors" do let(:color_a) { @white } let(:color_b) { @white } diff --git a/spec/chunky_png/datastream_spec.rb b/spec/chunky_png/datastream_spec.rb index eff97cd7..0f9d83e1 100644 --- a/spec/chunky_png/datastream_spec.rb +++ b/spec/chunky_png/datastream_spec.rb @@ -1,16 +1,14 @@ -# coding: utf-8 -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Datastream do - - describe '.from_io'do + describe ".from_io" do it "should raise an error when loading a file with a bad signature" do - filename = resource_file('damaged_signature.png') + filename = resource_file("damaged_signature.png") expect { ChunkyPNG::Datastream.from_file(filename) }.to raise_error(ChunkyPNG::SignatureMismatch) end it "should raise an error if the CRC of a chunk is incorrect" do - filename = resource_file('damaged_chunk.png') + filename = resource_file("damaged_chunk.png") expect { ChunkyPNG::Datastream.from_file(filename) }.to raise_error(ChunkyPNG::CRCMismatch) end @@ -20,37 +18,37 @@ end it "should read a stream with trailing data without failing" do - filename = resource_file('trailing_bytes_after_iend_chunk.png') + filename = resource_file("trailing_bytes_after_iend_chunk.png") image = ChunkyPNG::Datastream.from_file(filename) expect(image).to be_instance_of(ChunkyPNG::Datastream) end end - describe '#metadata' do + describe "#metadata" do it "should load uncompressed tXTt chunks correctly" do - filename = resource_file('text_chunk.png') + filename = resource_file("text_chunk.png") ds = ChunkyPNG::Datastream.from_file(filename) - expect(ds.metadata['Title']).to eql 'My amazing icon!' - expect(ds.metadata['Author']).to eql "Willem van Bergen" + expect(ds.metadata["Title"]).to eql "My amazing icon!" + expect(ds.metadata["Author"]).to eql "Willem van Bergen" end it "should load compressed zTXt chunks correctly" do - filename = resource_file('ztxt_chunk.png') + filename = resource_file("ztxt_chunk.png") ds = ChunkyPNG::Datastream.from_file(filename) - expect(ds.metadata['Title']).to eql 'PngSuite' - expect(ds.metadata['Copyright']).to eql "Copyright Willem van Schaik, Singapore 1995-96" + expect(ds.metadata["Title"]).to eql "PngSuite" + expect(ds.metadata["Copyright"]).to eql "Copyright Willem van Schaik, Singapore 1995-96" end it "ignores iTXt chunks" do - filename = resource_file('itxt_chunk.png') + filename = resource_file("itxt_chunk.png") ds = ChunkyPNG::Datastream.from_file(filename) expect(ds.metadata).to be_empty end end - describe '#physical_chunk' do - it 'should read and write pHYs chunks correctly' do - filename = resource_file('clock.png') + describe "#physical_chunk" do + it "should read and write pHYs chunks correctly" do + filename = resource_file("clock.png") ds = ChunkyPNG::Datastream.from_file(filename) expect(ds.physical_chunk.unit).to eql :meters expect(ds.physical_chunk.dpix.round).to eql 72 @@ -59,83 +57,83 @@ expect(ds.physical_chunk).not_to be_nil end - it 'should raise ChunkyPNG::UnitsUnknown if we request dpi but the units are unknown' do + it "should raise ChunkyPNG::UnitsUnknown if we request dpi but the units are unknown" do physical_chunk = ChunkyPNG::Chunk::Physical.new(2835, 2835, :unknown) - expect{physical_chunk.dpix}.to raise_error(ChunkyPNG::UnitsUnknown) - expect{physical_chunk.dpiy}.to raise_error(ChunkyPNG::UnitsUnknown) + expect { physical_chunk.dpix }.to raise_error(ChunkyPNG::UnitsUnknown) + expect { physical_chunk.dpiy }.to raise_error(ChunkyPNG::UnitsUnknown) end end - describe '#iTXt_chunk' do - it 'should read iTXt chunks correctly' do - filename = resource_file('itxt_chunk.png') + describe "#iTXt_chunk" do + it "should read iTXt chunks correctly" do + filename = resource_file("itxt_chunk.png") ds = ChunkyPNG::Datastream.from_file(filename) int_text_chunks = ds.chunks.select { |chunk| chunk.is_a?(ChunkyPNG::Chunk::InternationalText) } expect(int_text_chunks.length).to eq(2) - coach_uk = int_text_chunks.find { |chunk| chunk.language_tag == 'en-gb' } - coach_us = int_text_chunks.find { |chunk| chunk.language_tag == 'en-us' } + coach_uk = int_text_chunks.find { |chunk| chunk.language_tag == "en-gb" } + coach_us = int_text_chunks.find { |chunk| chunk.language_tag == "en-us" } expect(coach_uk).to_not be_nil expect(coach_us).to_not be_nil - expect(coach_uk.keyword).to eq('coach') - expect(coach_uk.text).to eq('bus with of higher standard of comfort, usually chartered or used for longer journeys') - expect(coach_uk.translated_keyword).to eq('bus') + expect(coach_uk.keyword).to eq("coach") + expect(coach_uk.text).to eq("bus with of higher standard of comfort, usually chartered or used for longer journeys") + expect(coach_uk.translated_keyword).to eq("bus") expect(coach_uk.compressed).to eq(ChunkyPNG::UNCOMPRESSED_CONTENT) expect(coach_uk.compression).to eq(ChunkyPNG::COMPRESSION_DEFAULT) - expect(coach_us.keyword).to eq('coach') - expect(coach_us.text).to eq('US extracurricular sports teacher at a school (UK: PE teacher) lowest class on a passenger aircraft (UK: economy)') - expect(coach_us.translated_keyword).to eq('trainer') + expect(coach_us.keyword).to eq("coach") + expect(coach_us.text).to eq("US extracurricular sports teacher at a school (UK: PE teacher) lowest class on a passenger aircraft (UK: economy)") + expect(coach_us.translated_keyword).to eq("trainer") expect(coach_us.compressed).to eq(ChunkyPNG::COMPRESSED_CONTENT) expect(coach_us.compression).to eq(ChunkyPNG::COMPRESSION_DEFAULT) end - it 'should write iTXt chunks correctly' do - expected_hex = %w(0000 001d 6954 5874 436f 6d6d 656e 7400 0000 0000 4372 6561 7465 6420 7769 7468 2047 494d 5064 2e65 07).join('') + it "should write iTXt chunks correctly" do + expected_hex = %w[0000 001d 6954 5874 436f 6d6d 656e 7400 0000 0000 4372 6561 7465 6420 7769 7468 2047 494d 5064 2e65 07].join("") stream = StringIO.new - itext = ChunkyPNG::Chunk::InternationalText.new('Comment', 'Created with GIMP') + itext = ChunkyPNG::Chunk::InternationalText.new("Comment", "Created with GIMP") itext.write(stream) - generated_hex = stream.string.unpack('H*').join('') + generated_hex = stream.string.unpack("H*").join("") expect(generated_hex).to eq(expected_hex) end - it 'should handle incorrect UTF-8 encoding in iTXt chunks' do - incorrect_text_encoding = [0, 0, 0, 14, 105, 84, 88, 116, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 0, 195, 40, 17, 87, 97, 213].pack('C*') - incorrect_translated_keyword_encoding = [0, 0, 0, 19, 105, 84, 88, 116, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 226, 130, 40, 0, 116, 101, 115, 116, 228, 53, 113, 182].pack('C*') + it "should handle incorrect UTF-8 encoding in iTXt chunks" do + incorrect_text_encoding = [0, 0, 0, 14, 105, 84, 88, 116, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 0, 195, 40, 17, 87, 97, 213].pack("C*") + incorrect_translated_keyword_encoding = [0, 0, 0, 19, 105, 84, 88, 116, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 226, 130, 40, 0, 116, 101, 115, 116, 228, 53, 113, 182].pack("C*") expect { ChunkyPNG::Chunk.read(StringIO.new(incorrect_text_encoding)) }.to raise_error(ChunkyPNG::InvalidUTF8) expect { ChunkyPNG::Chunk.read(StringIO.new(incorrect_translated_keyword_encoding)) }.to raise_error(ChunkyPNG::InvalidUTF8) end - it 'should handle UTF-8 in iTXt compressed chunks correctly' do - parsed = serialized_chunk(ChunkyPNG::Chunk::InternationalText.new('Comment', '✨', '', '💩', ChunkyPNG::COMPRESSED_CONTENT)) + it "should handle UTF-8 in iTXt compressed chunks correctly" do + parsed = serialized_chunk(ChunkyPNG::Chunk::InternationalText.new("Comment", "✨", "", "💩", ChunkyPNG::COMPRESSED_CONTENT)) - expect(parsed.text).to eq('✨') + expect(parsed.text).to eq("✨") expect(parsed.text.encoding).to eq(Encoding::UTF_8) - expect(parsed.translated_keyword).to eq('💩') + expect(parsed.translated_keyword).to eq("💩") expect(parsed.translated_keyword.encoding).to eq(Encoding::UTF_8) end - it 'should handle UTF-8 in iTXt chunks correctly' do - parsed = serialized_chunk(ChunkyPNG::Chunk::InternationalText.new('Comment', '✨', '', '💩')) + it "should handle UTF-8 in iTXt chunks correctly" do + parsed = serialized_chunk(ChunkyPNG::Chunk::InternationalText.new("Comment", "✨", "", "💩")) - expect(parsed.text).to eq('✨') + expect(parsed.text).to eq("✨") expect(parsed.text.encoding).to eq(Encoding::UTF_8) - expect(parsed.translated_keyword).to eq('💩') + expect(parsed.translated_keyword).to eq("💩") expect(parsed.translated_keyword.encoding).to eq(Encoding::UTF_8) end - it 'should transform non UTF-8 iTXt fields to UTF-8 on write' do - parsed = serialized_chunk(ChunkyPNG::Chunk::InternationalText.new('Comment', '®'.encode('Windows-1252'), '', 'ƒ'.encode('Windows-1252'))) + it "should transform non UTF-8 iTXt fields to UTF-8 on write" do + parsed = serialized_chunk(ChunkyPNG::Chunk::InternationalText.new("Comment", "®".encode("Windows-1252"), "", "ƒ".encode("Windows-1252"))) - expect(parsed.text).to eq('®') + expect(parsed.text).to eq("®") expect(parsed.text.encoding).to eq(Encoding::UTF_8) - expect(parsed.translated_keyword).to eq('ƒ') + expect(parsed.translated_keyword).to eq("ƒ") expect(parsed.translated_keyword.encoding).to eq(Encoding::UTF_8) end end diff --git a/spec/chunky_png/dimension_spec.rb b/spec/chunky_png/dimension_spec.rb index f357416b..8a7b4b0f 100644 --- a/spec/chunky_png/dimension_spec.rb +++ b/spec/chunky_png/dimension_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Dimension do subject { ChunkyPNG::Dimension.new(2, 3) } @@ -6,31 +6,31 @@ it { should respond_to(:width) } it { should respond_to(:height) } - describe '#area' do + describe "#area" do it "should calculate the area correctly" do expect(subject.area).to eql 6 end end end -describe 'ChunkyPNG.Dimension' do +describe "ChunkyPNG.Dimension" do subject { ChunkyPNG::Dimension.new(1, 2) } it "should create a dimension from a 2-item array" do expect(ChunkyPNG::Dimension([1, 2])).to eql subject - expect(ChunkyPNG::Dimension(['1', '2'])).to eql subject + expect(ChunkyPNG::Dimension(["1", "2"])).to eql subject end it "should create a dimension from a hash with width and height keys" do expect(ChunkyPNG::Dimension(width: 1, height: 2)).to eql subject - expect(ChunkyPNG::Dimension('width' => '1', 'height' => '2')).to eql subject + expect(ChunkyPNG::Dimension("width" => "1", "height" => "2")).to eql subject end it "should create a dimension from a point-like string" do [ - ChunkyPNG::Dimension('1,2'), - ChunkyPNG::Dimension('1 2'), - ChunkyPNG::Dimension('(1 , 2)'), + ChunkyPNG::Dimension("1,2"), + ChunkyPNG::Dimension("1 2"), + ChunkyPNG::Dimension("(1 , 2)"), ChunkyPNG::Dimension("{1x2}"), ChunkyPNG::Dimension("[1\t2}"), ].all? { |point| point == subject } diff --git a/spec/chunky_png/image_spec.rb b/spec/chunky_png/image_spec.rb index d05d237f..1e6438bb 100644 --- a/spec/chunky_png/image_spec.rb +++ b/spec/chunky_png/image_spec.rb @@ -1,31 +1,28 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Image do - describe '#metadata' do - + describe "#metadata" do it "should load metadata from an existing file" do - image = ChunkyPNG::Image.from_file(resource_file('text_chunk.png')) - expect(image.metadata['Title']).to eql 'My amazing icon!' - expect(image.metadata['Author']).to eql 'Willem van Bergen' + image = ChunkyPNG::Image.from_file(resource_file("text_chunk.png")) + expect(image.metadata["Title"]).to eql "My amazing icon!" + expect(image.metadata["Author"]).to eql "Willem van Bergen" end it "should write metadata to the file correctly" do - filename = resource_file('_metadata.png') + filename = resource_file("_metadata.png") image = ChunkyPNG::Image.new(10, 10) - image.metadata['Title'] = 'My amazing icon!' - image.metadata['Author'] = 'Willem van Bergen' + image.metadata["Title"] = "My amazing icon!" + image.metadata["Author"] = "Willem van Bergen" image.save(filename) metadata = ChunkyPNG::Datastream.from_file(filename).metadata - expect(metadata['Title']).to eql 'My amazing icon!' - expect(metadata['Author']).to eql 'Willem van Bergen' + expect(metadata["Title"]).to eql "My amazing icon!" + expect(metadata["Author"]).to eql "Willem van Bergen" end it "should load empty images correctly" do - expect do - ChunkyPNG::Image.from_file(resource_file('empty.png')) - end.to_not raise_error + expect { ChunkyPNG::Image.from_file(resource_file("empty.png")) }.to_not raise_error end end end diff --git a/spec/chunky_png/point_spec.rb b/spec/chunky_png/point_spec.rb index 1d342efc..62d1a489 100644 --- a/spec/chunky_png/point_spec.rb +++ b/spec/chunky_png/point_spec.rb @@ -1,58 +1,56 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Point do - subject { ChunkyPNG::Point.new(1, 2) } it { should respond_to(:x) } it { should respond_to(:y) } - describe '#within_bounds?' do + describe "#within_bounds?" do it { should be_within_bounds(2, 3) } - it { should_not be_within_bounds('1x3') } + it { should_not be_within_bounds("1x3") } it { should_not be_within_bounds(2, 2) } - it { should_not be_within_bounds('[1 2]') } + it { should_not be_within_bounds("[1 2]") } end - describe '#<=>' do + describe "#<=>" do it "should return 0 if the coordinates are identical" do - expect((subject <=> ChunkyPNG::Point.new(1, 2))).to eql 0 + expect((subject <=> ChunkyPNG::Point.new(1, 2))).to eql(0) end it "should return -1 if the y coordinate is smaller than the other one" do - expect((subject <=> ChunkyPNG::Point.new(1, 3))).to eql -1 - expect((subject <=> ChunkyPNG::Point.new(0, 3))).to eql -1 # x doesn't matter - expect((subject <=> ChunkyPNG::Point.new(2, 3))).to eql -1 # x doesn't matter + expect((subject <=> ChunkyPNG::Point.new(1, 3))).to eql(-1) + expect((subject <=> ChunkyPNG::Point.new(0, 3))).to eql(-1) # x doesn't matter + expect((subject <=> ChunkyPNG::Point.new(2, 3))).to eql(-1) # x doesn't matter end it "should return 1 if the y coordinate is larger than the other one" do - expect((subject <=> ChunkyPNG::Point.new(1, 0))).to eql 1 - expect((subject <=> ChunkyPNG::Point.new(0, 0))).to eql 1 # x doesn't matter - expect((subject <=> ChunkyPNG::Point.new(2, 0))).to eql 1 # x doesn't matter + expect((subject <=> ChunkyPNG::Point.new(1, 0))).to eql(1) + expect((subject <=> ChunkyPNG::Point.new(0, 0))).to eql(1) # x doesn't matter + expect((subject <=> ChunkyPNG::Point.new(2, 0))).to eql(1) # x doesn't matter end it "should return -1 if the x coordinate is smaller and y is the same" do - expect((subject <=> ChunkyPNG::Point.new(2, 2))).to eql -1 + expect((subject <=> ChunkyPNG::Point.new(2, 2))).to eql(-1) end it "should return 1 if the x coordinate is larger and y is the same" do - expect((subject <=> ChunkyPNG::Point.new(0, 2))).to eql 1 + expect((subject <=> ChunkyPNG::Point.new(0, 2))).to eql(1) end end end -describe 'ChunkyPNG.Point' do +describe "ChunkyPNG.Point" do subject { ChunkyPNG::Point.new(1, 2) } - it "should create a point from a 2-item array" do expect(ChunkyPNG::Point([1, 2])).to eql subject - expect(ChunkyPNG::Point(['1', '2'])).to eql subject + expect(ChunkyPNG::Point(["1", "2"])).to eql subject end it "should create a point from a hash with x and y keys" do expect(ChunkyPNG::Point(x: 1, y: 2)).to eql subject - expect(ChunkyPNG::Point('x' => '1', 'y' => '2')).to eql subject + expect(ChunkyPNG::Point("x" => "1", "y" => "2")).to eql subject end it "should create a point from a ChunkyPNG::Dimension object" do @@ -62,9 +60,9 @@ it "should create a point from a point-like string" do [ - ChunkyPNG::Point('1,2'), - ChunkyPNG::Point('1 2'), - ChunkyPNG::Point('(1 , 2)'), + ChunkyPNG::Point("1,2"), + ChunkyPNG::Point("1 2"), + ChunkyPNG::Point("(1 , 2)"), ChunkyPNG::Point("{1,\t2}"), ChunkyPNG::Point("[1 2}"), ].all? { |point| point == subject } diff --git a/spec/chunky_png/rmagick_spec.rb b/spec/chunky_png/rmagick_spec.rb index e53bfb75..07a3d81c 100644 --- a/spec/chunky_png/rmagick_spec.rb +++ b/spec/chunky_png/rmagick_spec.rb @@ -1,23 +1,22 @@ -require 'spec_helper' +require "spec_helper" begin - require 'chunky_png/rmagick' + require "chunky_png/rmagick" describe ChunkyPNG::RMagick do - it "should import an image from RMagick correctly" do - image = Magick::Image.read(resource_file('composited.png')).first + image = Magick::Image.read(resource_file("composited.png")).first canvas = ChunkyPNG::RMagick.import(image) - expect(canvas).to eql reference_canvas('composited') + expect(canvas).to eql reference_canvas("composited") end it "should export an image to RMagick correctly" do - canvas = reference_canvas('composited') + canvas = reference_canvas("composited") image = ChunkyPNG::RMagick.export(canvas) - image.format = 'PNG32' + image.format = "PNG32" expect(canvas).to eql ChunkyPNG::Canvas.from_blob(image.to_blob) end end -rescue LoadError => e +rescue LoadError # skipping RMagick tests end diff --git a/spec/chunky_png/vector_spec.rb b/spec/chunky_png/vector_spec.rb index 3c534ecf..bfdeeea2 100644 --- a/spec/chunky_png/vector_spec.rb +++ b/spec/chunky_png/vector_spec.rb @@ -1,17 +1,17 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG::Vector do subject { ChunkyPNG::Vector.new([ChunkyPNG::Point.new(2, 5), ChunkyPNG::Point.new(1, 3), ChunkyPNG::Point.new(4, 6)]) } it { should respond_to(:points) } - describe '#length' do + describe "#length" do it "shopuld have 3 items" do expect(subject.length).to eql(3) end end - describe '#x_range' do + describe "#x_range" do it "should get the right range of x values" do expect(subject.x_range).to eql(1..4) end @@ -29,7 +29,7 @@ end end - describe '#y_range' do + describe "#y_range" do it "should get the right range of y values" do expect(subject.y_range).to eql(3..6) end @@ -47,7 +47,7 @@ end end - describe '#offset' do + describe "#offset" do it "should return a ChunkyPNG::Point" do expect(subject.offset).to be_kind_of(ChunkyPNG::Point) end @@ -58,7 +58,7 @@ end end - describe '#dimension' do + describe "#dimension" do it "should return a ChunkyPNG::Dimension" do expect(subject.dimension).to be_kind_of(ChunkyPNG::Dimension) end @@ -69,26 +69,30 @@ end end - describe '#edges' do + describe "#edges" do it "should get three edges when closing the path" do - expect(subject.edges(true).to_a).to eql [[ChunkyPNG::Point.new(2, 5), ChunkyPNG::Point.new(1, 3)], - [ChunkyPNG::Point.new(1, 3), ChunkyPNG::Point.new(4, 6)], - [ChunkyPNG::Point.new(4, 6), ChunkyPNG::Point.new(2, 5)]] + expect(subject.edges(true).to_a).to eql [ + [ChunkyPNG::Point.new(2, 5), ChunkyPNG::Point.new(1, 3)], + [ChunkyPNG::Point.new(1, 3), ChunkyPNG::Point.new(4, 6)], + [ChunkyPNG::Point.new(4, 6), ChunkyPNG::Point.new(2, 5)], + ] end it "should get two edges when not closing the path" do - expect(subject.edges(false).to_a).to eql [[ChunkyPNG::Point.new(2, 5), ChunkyPNG::Point.new(1, 3)], - [ChunkyPNG::Point.new(1, 3), ChunkyPNG::Point.new(4, 6)]] + expect(subject.edges(false).to_a).to eql [ + [ChunkyPNG::Point.new(2, 5), ChunkyPNG::Point.new(1, 3)], + [ChunkyPNG::Point.new(1, 3), ChunkyPNG::Point.new(4, 6)], + ] end end end -describe 'ChunkyPNG.Vector' do +describe "ChunkyPNG.Vector" do let(:example) { ChunkyPNG::Vector.new([ChunkyPNG::Point.new(2, 4), ChunkyPNG::Point.new(1, 2), ChunkyPNG::Point.new(3, 6)]) } it "should return an empty vector when given an empty array" do expect(ChunkyPNG::Vector()).to eql ChunkyPNG::Vector.new([]) - expect(ChunkyPNG::Vector(*[])).to eql ChunkyPNG::Vector.new([]) + expect(ChunkyPNG::Vector(*[])).to eql ChunkyPNG::Vector.new([]) # rubocop:disable Lint/UnneededSplatExpansion end it "should raise an error when an odd number of numerics is given" do @@ -96,14 +100,14 @@ end it "should create a vector from a string" do - expect(ChunkyPNG::Vector('(2,4) (1,2) (3,6)')).to eql example + expect(ChunkyPNG::Vector("(2,4) (1,2) (3,6)")).to eql example end it "should create a vector from a flat array" do - expect(ChunkyPNG::Vector(2,4,1,2,3,6)).to eql example + expect(ChunkyPNG::Vector(2, 4, 1, 2, 3, 6)).to eql example end it "should create a vector from a nested array" do - expect(ChunkyPNG::Vector('(2,4)', [1, 2], x: 3, y: 6)).to eql example + expect(ChunkyPNG::Vector("(2,4)", [1, 2], x: 3, y: 6)).to eql example end end diff --git a/spec/chunky_png_spec.rb b/spec/chunky_png_spec.rb index 282313c7..68b59e4a 100644 --- a/spec/chunky_png_spec.rb +++ b/spec/chunky_png_spec.rb @@ -1,7 +1,7 @@ -require 'spec_helper' +require "spec_helper" describe ChunkyPNG do it "should have a VERSION constant" do - expect(ChunkyPNG.const_defined?('VERSION')).to eql true + expect(ChunkyPNG.const_defined?("VERSION")).to be_truthy end end diff --git a/spec/png_suite_spec.rb b/spec/png_suite_spec.rb index 39ea6161..ea5c3807 100644 --- a/spec/png_suite_spec.rb +++ b/spec/png_suite_spec.rb @@ -1,8 +1,7 @@ -require 'spec_helper' +require "spec_helper" -describe 'PNG testuite' do - - context 'Decoding broken images' do +describe "PNG testuite" do + context "Decoding broken images" do png_suite_files(:broken).each do |file| it "should report #{File.basename(file)} as broken" do expect { ChunkyPNG::Image.from_file(file) }.to raise_error(ChunkyPNG::Exception) @@ -10,24 +9,22 @@ end end - context 'Decoding supported images' do - png_suite_files(:basic, '*.png').each do |file| - - reference = file.sub(/\.png$/, '.rgba') + context "Decoding supported images" do + png_suite_files(:basic, "*.png").each do |file| + reference = file.sub(/\.png$/, ".rgba") color_mode = file.match(/[in](\d)[apgc](\d\d)\.png$/)[1].to_i bit_depth = file.match(/[in](\d)[apgc](\d\d)\.png$/)[2].to_i it "should decode #{File.basename(file)} (color mode: #{color_mode}, bit depth: #{bit_depth}) exactly the same as the reference image" do decoded = ChunkyPNG::Canvas.from_file(file) - File.open(reference, 'rb') { |f| expect(decoded.to_rgba_stream).to eql f.read } + expect(decoded.to_rgba_stream).to eql(File.read(reference, mode: "rb")) end end end - context 'Decoding text chunks' do - + context "Decoding text chunks" do it "should not find metadata in a file without text chunks" do - image = ChunkyPNG::Image.from_file(png_suite_file(:metadata, 'cm0n0g04.png')) + image = ChunkyPNG::Image.from_file(png_suite_file(:metadata, "cm0n0g04.png")) expect(image.metadata).to be_empty end @@ -42,10 +39,9 @@ # end end - context 'Decoding filter methods' do - png_suite_files(:filtering, '*_reference.png').each do |reference_file| - - file = reference_file.sub(/_reference\.png$/, '.png') + context "Decoding filter methods" do + png_suite_files(:filtering, "*_reference.png").each do |reference_file| + file = reference_file.sub(/_reference\.png$/, ".png") filter_method = file.match(/f(\d\d)[a-z0-9]+\.png/)[1].to_i it "should decode #{File.basename(file)} (filter method: #{filter_method}) exactly the same as the reference image" do @@ -56,54 +52,53 @@ end end - context 'Decoding different chunk splits' do + context "Decoding different chunk splits" do it "should decode grayscale images successfully regardless of the data chunk ordering and splitting" do - reference = ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi1n0g16.png')).imagedata - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi2n0g16.png')).imagedata).to eql reference - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi4n0g16.png')).imagedata).to eql reference - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi9n0g16.png')).imagedata).to eql reference + reference = ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi1n0g16.png")).imagedata + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi2n0g16.png")).imagedata).to eql reference + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi4n0g16.png")).imagedata).to eql reference + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi9n0g16.png")).imagedata).to eql reference end it "should decode color images successfully regardless of the data chunk ordering and splitting" do - reference = ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi1n2c16.png')).imagedata - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi2n2c16.png')).imagedata).to eql reference - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi4n2c16.png')).imagedata).to eql reference - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, 'oi9n2c16.png')).imagedata).to eql reference + reference = ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi1n2c16.png")).imagedata + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi2n2c16.png")).imagedata).to eql reference + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi4n2c16.png")).imagedata).to eql reference + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:chunk_ordering, "oi9n2c16.png")).imagedata).to eql reference end end - context 'Decoding different compression levels' do + context "Decoding different compression levels" do it "should decode the image successfully regardless of the compression level" do - reference = ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z00n2c08.png')).imagedata - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z03n2c08.png')).imagedata).to eql reference - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z06n2c08.png')).imagedata).to eql reference - expect(ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, 'z09n2c08.png')).imagedata).to eql reference + reference = ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, "z00n2c08.png")).imagedata + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, "z03n2c08.png")).imagedata).to eql reference + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, "z06n2c08.png")).imagedata).to eql reference + expect(ChunkyPNG::Datastream.from_file(png_suite_file(:compression_levels, "z09n2c08.png")).imagedata).to eql reference end end - context 'Decoding transparency' do - png_suite_files(:transparency, 'tp0*.png').each do |file| + context "Decoding transparency" do + png_suite_files(:transparency, "tp0*.png").each do |file| it "should not have transparency in #{File.basename(file)}" do - expect(ChunkyPNG::Color.a(ChunkyPNG::Image.from_file(file)[0,0])).to eql 255 + expect(ChunkyPNG::Color.a(ChunkyPNG::Image.from_file(file)[0, 0])).to eql 255 end end - png_suite_files(:transparency, 'tp1*.png').each do |file| + png_suite_files(:transparency, "tp1*.png").each do |file| it "should have transparency in #{File.basename(file)}" do - expect(ChunkyPNG::Color.a(ChunkyPNG::Image.from_file(file)[0,0])).to eql 0 + expect(ChunkyPNG::Color.a(ChunkyPNG::Image.from_file(file)[0, 0])).to eql 0 end end - png_suite_files(:transparency, 'tb*.png').each do |file| + png_suite_files(:transparency, "tb*.png").each do |file| it "should have transparency in #{File.basename(file)}" do - expect(ChunkyPNG::Color.a(ChunkyPNG::Image.from_file(file)[0,0])).to eql 0 + expect(ChunkyPNG::Color.a(ChunkyPNG::Image.from_file(file)[0, 0])).to eql 0 end end end - context 'Decoding different sizes' do - - png_suite_files(:sizes, '*n*.png').each do |file| + context "Decoding different sizes" do + png_suite_files(:sizes, "*n*.png").each do |file| dimension = file.match(/s(\d\d)n\dp\d\d/)[1].to_i it "should create a canvas with a #{dimension}x#{dimension} size" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9c00f855..abbcf23c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,9 +1,8 @@ -require 'rubygems' -require 'bundler/setup' -require 'chunky_png' +require "rubygems" +require "bundler/setup" +require "chunky_png" module PNGSuite - def png_suite_file(kind, file) File.join(png_suite_dir(kind), file) end @@ -12,21 +11,19 @@ def png_suite_dir(kind) File.expand_path("./png_suite/#{kind}", File.dirname(__FILE__)) end - def png_suite_files(kind, pattern = '*.png') + def png_suite_files(kind, pattern = "*.png") Dir[File.join(png_suite_dir(kind), pattern)] end end - module ResourceFileHelper - def resource_file(name) File.expand_path("./resources/#{name}", File.dirname(__FILE__)) end def resource_data(name) data = nil - File.open(resource_file(name), 'rb') { |f| data = f.read } + File.open(resource_file(name), "rb") { |f| data = f.read } data end @@ -39,14 +36,13 @@ def reference_image(name) end def display(png) - filename = resource_file('_tmp.png') + filename = resource_file("_tmp.png") png.save(filename) `open #{filename}` end end module ChunkOperationsHelper - def serialized_chunk(chunk) chunk.write(stream = StringIO.new) stream.rewind diff --git a/tasks/benchmarks.rake b/tasks/benchmarks.rake index 80d92f4b..f40c945c 100644 --- a/tasks/benchmarks.rake +++ b/tasks/benchmarks.rake @@ -1,24 +1,23 @@ all_benchamrk_tasks = [] namespace(:benchmark) do - - Dir[File.join(File.dirname(__FILE__), '..', 'benchmarks', '*_benchmark.rb')]. each do |benchmark_file| - task_name = File.basename(benchmark_file, '_benchmark.rb').to_sym - + Dir[File.join(File.dirname(__FILE__), "..", "benchmarks", "*_benchmark.rb")]. each do |benchmark_file| + task_name = File.basename(benchmark_file, "_benchmark.rb").to_sym + desc "Run the #{task_name} benchmark." task(task_name, :n) do |task, args| - ENV['N'] = args[:n] if args[:n] + ENV["N"] = args[:n] if args[:n] load(File.expand_path(benchmark_file)) end - + all_benchamrk_tasks << "benchmark:#{task_name}" end end unless all_benchamrk_tasks.empty? - desc 'Run the whole benchmark suite' + desc "Run the whole benchmark suite" task(:benchmark, :n) do |task, args| - all_benchamrk_tasks.each do |t| + all_benchamrk_tasks.each do |t| task(t).invoke(args[:n]) puts end