Module: Mindee::Image::ImageUtils

Defined in:
lib/mindee.rb,
lib/mindee/image/image_utils.rb

Overview

Miscellaneous image operations.

Class Method Summary collapse

Class Method Details

.calculate_dimensions_from_media_box(image, media_box) ⇒ Array<Integer>

Computes the Height & Width from a page’s media box. Falls back to the size of the initial image.

Parameters:

  • image (MiniMagick::Image)

    The initial image that will fit into the page.

  • media_box (Array<Integer>, nil)

Returns:

  • (Array<Integer>)


82
83
84
85
86
87
88
89
90
91
# File 'lib/mindee/image/image_utils.rb', line 82

def self.calculate_dimensions_from_media_box(image, media_box)
  if !media_box.nil? && media_box.any?
    [
      media_box[2]&.to_i || image[:width].to_i,
      media_box[3]&.to_i || image[:height].to_i,
    ]
  else
    [image[:width].to_i, image[:height].to_i]
  end
end

.calculate_new_dimensions(original, max_width: nil, max_height: nil) ⇒ Object

Computes the new dimensions for a given SKBitmap, and returns a scaled down version of it relative to the provided bounds.

Parameters:

  • original (MiniMagick::Image)

    Input MiniMagick image.

  • max_width (Integer) (defaults to: nil)

    Maximum width. If not specified, the horizontal ratio will remain the same.

  • max_height (Integer) (defaults to: nil)

    Maximum height. If not specified, the vertical ratio will remain the same.

Raises:



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/mindee/image/image_utils.rb', line 62

def self.calculate_new_dimensions(original, max_width: nil, max_height: nil)
  raise Errors::MindeeImageError, 'Provided image could not be processed for resizing.' if original.nil?

  return [original.width, original.height] if max_width.nil? && max_height.nil?

  width_ratio = max_width ? max_width.to_f / original.width : Float::INFINITY
  height_ratio = max_height ? max_height.to_f / original.height : Float::INFINITY

  scale_factor = [width_ratio, height_ratio].min

  new_width = (original.width.to_f * scale_factor).to_i
  new_height = (original.height.to_f * scale_factor).to_i

  [new_width, new_height]
end

.compress_image_quality(image, quality) ⇒ Object

Compresses the quality of the provided MiniMagick image.

Parameters:

  • image (MiniMagick::Image)

    MiniMagick image handle.

  • quality (Integer)

    Quality to apply to the image. This is independent of a JPG’s base quality.



25
26
27
# File 'lib/mindee/image/image_utils.rb', line 25

def self.compress_image_quality(image, quality)
  image.quality quality.to_s
end

.crop_image(image, min_max_x, min_max_y) ⇒ Object

Crops a MiniMagick Image from a the given bounding box.

Parameters:



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/mindee/image/image_utils.rb', line 132

def self.crop_image(image, min_max_x, min_max_y)
  width = image[:width].to_i
  height = image[:height].to_i

  image.format('jpg')
  new_width = (min_max_x.max - min_max_x.min) * width
  new_height = (min_max_y.max - min_max_y.min) * height
  image.crop("#{new_width}x#{new_height}+#{min_max_x.min * width}+#{min_max_y.min * height}")

  image
end

.determine_file_extension(input_source) ⇒ String?

Retrieves the file extension from the main file to apply it to the extracted images. Note: coerces pdf as jpg.

Parameters:

Returns:

  • (String, nil)

    A valid file extension.



156
157
158
159
160
161
162
# File 'lib/mindee/image/image_utils.rb', line 156

def self.determine_file_extension(input_source)
  if input_source.pdf? || input_source.filename.downcase.end_with?('pdf')
    'jpg'
  else
    File.extname(input_source.filename.to_s).strip.downcase[1..].to_s
  end
end

.image_to_stringio(image, format = 'JPEG') ⇒ StringIO

Converts a StringIO containing an image into a MiniMagick image.

Parameters:

  • image (MiniMagick::Image)

    the input image.

  • format (String) (defaults to: 'JPEG')

    Format parameter, left open for the future, but should be JPEG for current use-cases.

Returns:

  • (StringIO)


48
49
50
51
52
53
54
55
# File 'lib/mindee/image/image_utils.rb', line 48

def self.image_to_stringio(image, format = 'JPEG')
  image.format format
  blob = image.to_blob
  stringio = StringIO.new(blob)
  stringio.rewind

  stringio
end

.normalize_polygon(polygon) ⇒ Object

Retrieves the bounding box of a polygon.

Parameters:



107
108
109
110
111
112
113
114
115
116
# File 'lib/mindee/image/image_utils.rb', line 107

def self.normalize_polygon(polygon)
  if polygon.is_a?(Mindee::Geometry::Polygon) ||
     (polygon.is_a?(Array) && polygon[0].is_a?(Mindee::Geometry::Point))
    Mindee::Geometry.get_bounding_box(polygon)
  elsif polygon.is_a?(Mindee::Geometry::Quadrilateral)
    polygon
  else
    raise Errors::MindeeGeometryError, 'Provided polygon has an invalid type.'
  end
end

.pdf_to_magick_image(pdf_stream, image_quality) ⇒ MiniMagick::Image

Transforms a PDF into a MagickImage. This is currently used for single-page PDFs.

Parameters:

  • pdf_stream (StringIO)

    Input stream.

  • image_quality (Integer)

    Quality to apply to the image.

Returns:

  • (MiniMagick::Image)


97
98
99
100
101
102
# File 'lib/mindee/image/image_utils.rb', line 97

def self.pdf_to_magick_image(pdf_stream, image_quality)
  compressed_image = MiniMagick::Image.read(pdf_stream.read)
  compressed_image.format('jpg')
  compressed_image.quality image_quality.to_s
  compressed_image
end

.read_page_content(pdf_stream) ⇒ MiniMagick::Image

Loads a buffer into a MiniMagick Image.

Parameters:

  • pdf_stream (StringIO)

    Buffer containg the PDF

Returns:

  • (MiniMagick::Image)

    a valid MiniMagick image handle.



122
123
124
125
# File 'lib/mindee/image/image_utils.rb', line 122

def self.read_page_content(pdf_stream)
  pdf_stream.rewind
  MiniMagick::Image.read(pdf_stream)
end

.resize_image(image, width, height) ⇒ Object

Resizes a provided MiniMagick Image with the given width & height, if present.

Parameters:

  • image (MiniMagick::Image)

    MiniMagick image handle.

  • width (Integer)

    Width to comply with.

  • height (Integer)

    Height to comply with.



12
13
14
15
16
17
18
19
20
# File 'lib/mindee/image/image_utils.rb', line 12

def self.resize_image(image, width, height)
  if width && height
    image.resize "#{width}x#{height}"
  elsif width
    image.resize width.to_s
  elsif height
    image.resize "x#{height}"
  end
end

.to_image(image) ⇒ MiniMagick::Image

Mostly here so that IDEs don’t get confused on the type (@type annotation fails sometimes.)

Parameters:

  • image (MiniMagick::Image, StringIO, File, Tempfile)

    The input image

Returns:

  • (MiniMagick::Image)


32
33
34
35
36
37
38
39
40
41
42
# File 'lib/mindee/image/image_utils.rb', line 32

def self.to_image(image)
  if image.is_a?(MiniMagick::Image)
    image
  elsif image.is_a?(StringIO) || image.is_a?(IO) || image.is_a?(File) || image.is_a?(Tempfile)
    image.rewind
    MiniMagick::Image.read(image)
  else
    img_class = image.class ? image.class.to_s : 'unknown format'
    raise Errors::MindeeImageError, "Expected an I/O object or a MiniMagick::Image. '#{img_class}' given instead."
  end
end

.write_image_to_buffer(image, buffer) ⇒ Object

Writes a MiniMagick::Image to a buffer.

Parameters:

  • image (MiniMagick::Image)

    a valid MiniMagick image.

  • buffer (StringIO)


148
149
150
# File 'lib/mindee/image/image_utils.rb', line 148

def self.write_image_to_buffer(image, buffer)
  image.write(buffer)
end