Class: HexaPDF::Type::Image

Inherits:
Stream show all
Defined in:
lib/hexapdf/type/image.rb

Overview

Represents an image XObject of a PDF document.

See: PDF2.0 s8.8

Defined Under Namespace

Classes: Info

Constant Summary

Constants included from DictionaryFields

DictionaryFields::Boolean, DictionaryFields::PDFByteString, DictionaryFields::PDFDate

Instance Attribute Summary collapse

Attributes inherited from Object

#data, #document, #must_be_indirect

Instance Method Summary collapse

Methods inherited from Stream

#must_be_indirect?, #raw_stream, #set_filter, #stream, #stream=, #stream_decoder, #stream_encoder, #stream_source

Methods inherited from Dictionary

#[], #[]=, define_field, define_type, #delete, #each, each_field, #empty?, field, #key?, #to_h, type, #type

Methods inherited from Object

#<=>, #==, #cache, #cached?, #clear_cache, deep_copy, #deep_copy, #document?, #eql?, field, #gen, #gen=, #hash, #indirect?, #initialize, #inspect, make_direct, #must_be_indirect?, #null?, #oid, #oid=, #type, #validate, #value, #value=

Constructor Details

This class inherits a constructor from HexaPDF::Object

Instance Attribute Details

#source_pathObject

Returns the source path that was used when creating the image object.

This value is only set when the image object was created by using the image loading facility and not when the image is part of a loaded PDF file.



85
86
87
# File 'lib/hexapdf/type/image.rb', line 85

def source_path
  @source_path
end

Instance Method Details

#heightObject

Returns the height of the image.



93
94
95
# File 'lib/hexapdf/type/image.rb', line 93

def height
  self[:Height]
end

#infoObject

Returns an Info structure with information about the image.

Available accessors:

type

The type of the image. Either :jpeg, :jp2, :jbig2, :ccitt or :png.

width

The width of the image.

height

The height of the image.

color_space

The color space the image uses. Either :rgb, :cmyk, :gray or :other.

indexed

Whether the image uses an indexed color space or not.

components

The number of color components of the color space, or -1 if the number couldn’t be determined.

bits_per_component

The number of bits per color component.

writable

Whether the image can be written by HexaPDF.

extension

The file extension that would be used when writing the file. Either jpg, jpx or png. Only meaningful when writable is true.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/hexapdf/type/image.rb', line 121

def info
  result = Info.new
  result.width = self[:Width]
  result.height = self[:Height]
  result.bits_per_component = self[:BitsPerComponent]
  result.indexed = false
  result.writable = true

  filter, rest = *self[:Filter]
  case filter
  when :DCTDecode
    result.type = :jpeg
    result.extension = 'jpg'
  when :JPXDecode
    result.type = :jp2
    result.extension = 'jpx'
  when :JBIG2Decode
    result.type = :jbig2
  when :CCITTFaxDecode
    result.type = :ccitt
  else
    result.type = :png
    result.extension = 'png'
  end

  if rest || ![:FlateDecode, :DCTDecode, :JPXDecode, nil].include?(filter)
    result.writable = false
  end

  color_space, = *self[:ColorSpace]
  if color_space == :Indexed
    result.indexed = true
    color_space, = *self[:ColorSpace][1]
  end
  case color_space
  when :DeviceRGB, :CalRGB
    result.color_space = :rgb
    result.components = 3
  when :DeviceGray, :CalGray
    result.color_space = :gray
    result.components = 1
  when :DeviceCMYK
    result.color_space = :cmyk
    result.components = 4
    result.writable = false if result.type == :png
  when :ICCBased
    result.color_space = :icc
    result.components = self[:ColorSpace][1][:N]
    result.writable = false if result.type == :png && result.components == 4
  else
    result.color_space = :other
    result.components = -1
    result.writable = false if result.type == :png
  end

  smask = self[:SMask]
  if smask && (result.type != :png ||
               !(result.bits_per_component == 8 || result.bits_per_component == 16) ||
               result.bits_per_component != smask[:BitsPerComponent] ||
               result.width != smask[:Width] || result.height != smask[:Height])
    result.writable = false
  end

  result
end

#widthObject

Returns the width of the image.



88
89
90
# File 'lib/hexapdf/type/image.rb', line 88

def width
  self[:Width]
end

#write(name_or_io) ⇒ Object

:call-seq:

image.write(basename)
image.write(io)

Saves this image XObject to the file with the given name and appends the correct extension (if the name already contains this extension, the name is used as is), or the given IO object.

Raises an error if the image format is not supported.

The output format and extension depends on the image type as returned by the #info method:

:jpeg

Saved as a JPEG file with the extension ‘.jpg’

:jp2

Saved as a JPEG2000 file with the extension ‘.jpx’

:png

Saved as a PNG file with the extension ‘.png’



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/hexapdf/type/image.rb', line 202

def write(name_or_io)
  info = self.info

  unless info.writable
    raise HexaPDF::Error, "PDF image format not supported for writing"
  end

  io = if name_or_io.kind_of?(String)
         File.open(name_or_io.sub(/\.#{info.extension}\z/, '') << "." << info.extension, "wb")
       else
         name_or_io
       end

  if info.type == :jpeg || info.type == :jp2
    source = stream_source
    while source.alive? && (chunk = source.resume)
      io << chunk
    end
  else
    write_png(io, info)
  end
ensure
  io.close if io && name_or_io.kind_of?(String)
end