Class: AcroForge::ImageStamper
- Inherits:
-
Object
- Object
- AcroForge::ImageStamper
- Defined in:
- lib/acroforge/image_stamper.rb
Overview
Stamps JPG/PNG files into AcroForm widget rectangles.
Constant Summary collapse
- MAX_IMAGE_BYTES =
Caps a phone-camera passport photo from bloating the output PDF.
5 * 1024 * 1024
- MAX_IMAGE_DIMENSION =
4000- TARGET_PPI =
Auto-downsample images whose pixel resolution far exceeds this PPI at the widget’s rendered size. Requires ImageMagick on PATH.
200
Instance Method Summary collapse
- #stamp!(doc, field, path) ⇒ Object
-
#validate_image!(path) ⇒ Object
Trust boundary in front of ImageMagick: any malformed-input path raises a single error class so worker retry policies can key on it.
Instance Method Details
#stamp!(doc, field, path) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/acroforge/image_stamper.rb', line 16 def stamp!(doc, field, path) format, image_width, image_height = validate_image!(path) = field..first return unless && [:Rect] page = doc.pages.find { |candidate_page| candidate_page[:Annots]&.include?() } return unless page # Widget Rect is absolute page coords; canvas API is MediaBox-relative. media_box_x, media_box_y = page.box.value[0], page.box.value[1] rect_x_min, rect_y_min, rect_x_max, rect_y_max = [:Rect] slot_width = rect_x_max - rect_x_min slot_height = rect_y_max - rect_y_min slot_canvas_x = rect_x_min - media_box_x slot_canvas_y = rect_y_min - media_box_y stamp_path = prepare_image_for_slot(path, format, image_width, image_height, slot_width, slot_height) || path if stamp_path != path _, image_width, image_height = image_dimensions(stamp_path) end draw_width, draw_height = fit_inside(image_width, image_height, slot_width, slot_height) draw_x = slot_canvas_x + (slot_width - draw_width) / 2.0 draw_y = slot_canvas_y + (slot_height - draw_height) / 2.0 canvas = page.canvas(type: :overlay) canvas.fill_color(255, 255, 255) canvas.rectangle(slot_canvas_x, slot_canvas_y, slot_width, slot_height).fill canvas.image(stamp_path, at: [draw_x, draw_y], width: draw_width, height: draw_height) # Bake into the page so the widget's empty appearance doesn't repaint over the image. page[:Annots].delete() end |
#validate_image!(path) ⇒ Object
Trust boundary in front of ImageMagick: any malformed-input path raises a single error class so worker retry policies can key on it.
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/acroforge/image_stamper.rb', line 53 def validate_image!(path) size = File.size(path) if size > MAX_IMAGE_BYTES raise ImageTooLargeError, "#{path}: #{size} bytes exceeds #{MAX_IMAGE_BYTES} byte cap" end format, width, height = image_dimensions(path) if width > MAX_IMAGE_DIMENSION || height > MAX_IMAGE_DIMENSION raise ImageTooLargeError, "#{path}: #{width}x#{height}px exceeds #{MAX_IMAGE_DIMENSION}px per side" end [format, width, height] end |