# File lib/pdf/writer/object/image.rb, line 157
157:   def initialize(parent, data, image, label)
158:     super(parent)
159: 
160:     @data = data
161: 
162:     @image_info = image
163: 
164:     @info = {
165:       'Type'    => '/XObject',
166:       'Subtype' => '/Image',
167:       'Width'   => image.width,
168:       'Height'  => image.height
169:     }
170: 
171:     case image.format
172:     when "JPEG"
173:       case image.channels
174:       when 1
175:         @info['ColorSpace'] = '/DeviceGray'
176:       when 4
177:         @info['ColorSpace'] = '/DeviceCMYK'
178:           # This should fix problems with CMYK JPEG colours inverted in
179:           # Adobe Acrobat. Enable only if appropriate.
180: #       @info['Decode'] = '[1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0]'
181:       else
182:         @info['ColorSpace'] = '/DeviceRGB'
183:       end
184:       @info['Filter'] = '/DCTDecode'
185:       @info['BitsPerComponent'] = 8
186:     when "PNG"
187:       if image.info[:compression_method] != 0
188:         raise TypeError, PDF::Writer::Lang[:png_unsupp_compres]
189:       end
190: 
191:       if image.info[:filter_method] != 0
192:         raise TypeError, PDF::Writer::Lang[:png_unsupp_filter]
193:       end
194: 
195:       data = data.dup
196:       data.extend(PDF::Writer::OffsetReader)
197: 
198:       data.read_o(8)  # Skip the default header
199: 
200:       ok      = true
201:       length  = data.size
202:       palette = ""
203:       idat    = ""
204: 
205:       while ok
206:         chunk_size  = data.read_o(4).unpack("N")[0]
207:         section     = data.read_o(4)
208:         case section
209:         when 'PLTE'
210:           palette << data.read_o(chunk_size)
211:         when 'IDAT'
212:           idat << data.read_o(chunk_size)
213:         when 'tRNS'
214:             # This chunk can only occur once and it must occur after the
215:             # PLTE chunk and before the IDAT chunk
216:           trans = {}
217:           case image.info[:color_type]
218:           when 3
219:               # Indexed colour, RGB. Each byte in this chunk is an alpha for
220:               # the palette index in the PLTE ("palette") chunk up until the
221:               # last non-opaque entry. Set up an array, stretching over all
222:               # palette entries which will be 0 (opaque) or 1 (transparent).
223:             trans[:type]  = 'indexed'
224:             trans[:data]  = data.read_o(chunk_size).unpack("C*")
225:           when 0
226:               # Greyscale. Corresponding to entries in the PLTE chunk.
227:               # Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1
228:             trans[:grayscale] = data.read_o(2).unpack("n")
229:             trans[:type]      = 'indexed'
230: #           trans[:data]      = data.read_o.unpack("C")
231:           when 2
232:               # True colour with proper alpha channel.
233:             trans[:rgb] = data.read_o(6).unpack("nnn")
234:           end
235:         else
236:           data.offset += chunk_size
237:         end
238: 
239:         ok = (section != "IEND")
240: 
241:         data.read_o(4)  # Skip the CRC
242:       end
243: 
244:       if image.bits > 8
245:         raise TypeError, PDF::Writer::Lang[:png_8bit_colour]
246:       end
247:       if image.info[:interlace_method] != 0
248:         raise TypeError, PDF::Writer::Lang[:png_interlace]
249:       end
250: 
251:       ncolor  = 1
252:       colour  = 'DeviceRGB'
253:       case image.info[:color_type]
254:       when 3
255:         nil
256:       when 2
257:         ncolor = 3
258:       when 0
259:         colour = 'DeviceGray'
260:       else
261:         raise TypeError, PDF::Writer::Lang[:png_alpha_trans]
262:       end
263: 
264:       @info['Filter'] = '[/FlateDecode]'
265:       @info['DecodeParms'] = "[<</Predictor 15 /Colors #{ncolor} /Columns #{image.width}>>]"
266:       @info['BitsPerComponent'] = image.bits.to_s
267: 
268:       unless palette.empty?
269:         @info['ColorSpace']  = " [ /Indexed /DeviceRGB #{(palette.size / 3) - 1} "
270:         contents            = PDF::Writer::Object::Contents.new(parent,
271:                                                                 self)
272:         contents.data       = palette
273:         @info['ColorSpace'] << "#{contents.oid} 0 R ]"
274: 
275:         if trans
276:           case trans[:type]
277:           when 'indexed'
278:             @info['Mask']   = " [ #{trans[:data].join(' ')} ] "
279:           end
280:         end
281:       else
282:         @info['ColorSpace'] = "/#{colour}"
283:       end
284: 
285:       @data = idat
286:     end
287: 
288:     @label = label
289: 
290:       # assign it a place in the named resource dictionary as an external
291:       # object, according to the label passed in with it.
292:     @parent.pages << self
293:       # also make sure that we have the right procset object for it.
294:     @parent.procset << 'ImageC'
295:   end