Module: Pdfrb::Image::Audit

Defined in:
lib/pdfrb/image/audit.rb

Overview

Read-only metadata extractor for embedded image XObjects. Used by Task::Optimize to find downsampling candidates and by callers that need to know what's in a document without re-parsing every stream.

Defined Under Namespace

Classes: ImageInfo

Class Method Summary collapse

Class Method Details

.all(document) ⇒ Object

Return an Array of all image infos (mirror of #each_image).



31
32
33
# File 'lib/pdfrb/image/audit.rb', line 31

def all(document)
  each_image(document).to_a
end

.channels_for(color_space) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/pdfrb/image/audit.rb', line 74

def channels_for(color_space)
  case color_space
  when :DeviceGray, :CalGray, :Indexed then 1
  when :DeviceCMYK then 4
  else
    # :DeviceRGB, :CalRGB, :Lab, nil, and ICCBased (default to
    # 3 channels when we can't introspect the profile) all share
    # this branch.
    3
  end
end

.decoded_size(image) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/pdfrb/image/audit.rb', line 64

def decoded_size(image)
  w = image.value[:Width]
  h = image.value[:Height]
  bpc = image.value[:BitsPerComponent] || 8
  return nil unless w && h

  channels = channels_for(image.value[:ColorSpace])
  (w * h * channels * bpc) / 8
end

.each_image(document) ⇒ Object

Enumerate every image XObject in document. Yields an ImageInfo per image; returns an Enumerator if no block given.



20
21
22
23
24
25
26
27
28
# File 'lib/pdfrb/image/audit.rb', line 20

def each_image(document)
  return enum_for(:each_image, document) unless block_given?

  document.each_indirect_object do |obj|
    next unless image_xobject?(obj)

    yield info_for(obj)
  end
end

.image_xobject?(obj) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
48
# File 'lib/pdfrb/image/audit.rb', line 44

def image_xobject?(obj)
  return false unless obj.is_a?(Pdfrb::Model::Cos::Stream)

  obj.value[:Type] == :XObject && obj.value[:Subtype] == :Image
end

.info_for(image) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/pdfrb/image/audit.rb', line 50

def info_for(image)
  ImageInfo.new(
    oid: image.oid,
    width: image.value[:Width],
    height: image.value[:Height],
    bits_per_component: image.value[:BitsPerComponent],
    color_space: image.value[:ColorSpace],
    filter_name: image.value[:Filter],
    decoded_bytesize: decoded_size(image),
    stream_bytesize: image.stream&.bytesize || 0,
    smask_oid: smask_oid(image)
  )
end

.oversized(document, target_pixels:) ⇒ Object

Find images whose pixel count exceeds target_pixels. Useful for spotting oversized images worth downsampling. Returns an Array of ImageInfo.



38
39
40
41
42
# File 'lib/pdfrb/image/audit.rb', line 38

def oversized(document, target_pixels:)
  all(document).select do |info|
    (info.width || 0) * (info.height || 0) > target_pixels
  end
end

.smask_oid(image) ⇒ Object



86
87
88
89
90
91
# File 'lib/pdfrb/image/audit.rb', line 86

def smask_oid(image)
  smask = image.value[:SMask]
  return nil unless smask.is_a?(Pdfrb::Model::Reference)

  smask.oid
end