I want to clip an image if it goes beyond the dimensions of a bounding box. Just like how CSS overflow: hidden would do it. Eg.
pdf.grid([0, 0], [3, 27]).bounding_box do
pdf.image image_file
end
Now currently, this image would overflow outside the bounding box if its larger than it. Is there any way to clip the image when it goes beyond the bounding box. ? I know this is possible for text when using text_box.
you can set the size of the image or get the image to scale so it fits within a certain area while maintaining proportions, do not believe you can crop an image.
If your page is not dynamic, that is the image area will always be the same this should be OK.
pdf.image "image_file_path_&_name", :position => :center, :fit => [100,450];
This is based on v0.8.4.
Unfortunately, there seems to exist no proper way to crop an image to a bounding box at the moment. Faced with this problem I figured out this beauty:
class SamplePdf
include Prawn::View
def initialize
crop_width = 100 # your width here
crop_height = 50 # your height here
image_path = '/path/to/your_image.jpg'
bounding_box [0, 0], width: crop_width, height: crop_height do
pdf_obj, _ = build_image_object(image_path)
x, y = document.send(:image_position, crop_width, crop_height, {})
document.send(:move_text_position, crop_height)
label = "I#{document.send(:next_image_id)}"
document.state.page.xobjects.merge!(label => pdf_obj)
cm_params = PDF::Core.real_params([crop_width, 0, 0, crop_height, x, y - crop_height])
document.renderer.add_content("\nq\n#{cm_params} cm\n/#{label} Do\nQ")
end
end
end
It basically adapts the Prawn::Images#image method, but skips the calculation of the image's dimensions and the scaling respectively.
It's not exactly a clean solution. Please keep me posted if you find a better one.
You should keep in mind though that this snippet leverages some implementation details which are not part of Prawn's public API and can change anytime.
At the time of writing Prawn 2.0.1 was the most recent version.
Related
I'm having trouble in Kivy setting an image size. I want to keep the aspect ratio fixed but I also want to position things precisely over the top of the image.
To do this, I make a RelativeLayout that has the same size and position as the image. However, when I check the size of the layout, it is always slightly larger than the displayed image. Making precise alignment very difficult. The wiki mentions something like this:
By default, the image is centered and fits inside the widget bounding box. If you don’t want that, you can set allow_stretch to True and keep_ratio to False.
They also include code if you want to make the image slightly larger than the containing widget:
<-FullImage>:
canvas:
Color:
rgb: (1, 1, 1)
Rectangle:
texture: self.texture
size: self.width + 20, self.height + 20
pos: self.x - 10, self.y - 10
But nothing about making them exactly the same size!? Surely I should be able to dictate the containing widgets size so the aspect ratio etc. is exactly as required.
I have tried many things but whatever I try, I cannot get the outside edges of the displayed image and a layout to coincide.
Does anyone have any experience with this?
Apologies, I have discovered the problem, the images had a transparent border that I wasn't aware of (the images were passed on to me from elsewhere) I have removed this and it has solved the problem.
I have an image here at this link: http://i711.photobucket.com/albums/ww116/xuanchienuit/1.png
I am trying to insert this image as background to the pdf using the following method:
image_path = "..." #path to the image
pdf = Prawn::Document.new
pdf.image image_path, width: pdf.bounds.width, height: pdf.bounds.height
pdf.render_file "test.png"
And the output PDF is at this link: https://drive.google.com/file/d/0B5iZPOjOn1osUzJSUTdDZGROZzQ/view?usp=sharing
The problem is in the PDF, you can see a gray border on top and bottom of the image (if you don't see the border, try zooming in/out and you would see the border).
What is going on here? I think there could be something wrong with the image but I am not sure. I hope you guys will have a better thought.
Thanks in advance!
Rather than setting height and width, try setting the position, and letting the image scale to best fit the available space (match height, match width, match both)? You might -- all conjecture here -- be seeing some artifact of the image getting stretched to the pdf region (if the image dimensions don't match the pdf precisely).
pdf.image image_path,
:position => :center,
:vposition => :center,
:fit => [pdf.bounds.width, pdf.bounds.height]
I am using RMagick for creating thumbnails like this:
img = Magick::Image.read(image_url).first
target = Magick::Image.new(110, 110) do
self.background_color = 'white'
end
img.resize_to_fit!(110, 110)
target.composite(img, Magick::CenterGravity, Magick::CopyCompositeOp).write(thumb_path)
This works well - I'll load the current image, create a "space" for the new thumb and then will place it there.
However, I would need to create a thumb where would be the width 110px and the height would be automatically counted... How to do this?
Thank you
You'd rather use resize_to_fill!
Doc here
image = Magick::Image.read(image_url).first
image.format = "JPG"
image.change_geometry!("110X110") { |cols, rows| image.thumbnail! cols, rows }
image.write("<path to save thumbnail>")
This turns out to be super easy! ImageMagick and GraphicsMagick both maintain aspect ratios properly, so in your case, just give the max width you want the image to be. See http://www.imagemagick.org/script/command-line-processing.php#geometry to learn more about the magick dimension operators.
If you find that you're ruby process' RAM consumption is growing, you may want to switch to an external-exec image library, like https://github.com/mceachen/micro_magick. Also, switching to GraphicsMagick is an all-around win, BTW, giving better image encoding and in less time.
require 'micro_magick'
img = MicroMagick::Convert.new("input.png")
img.resize("110") # this restricts to width, if you want to restrict to height, use "x345"
img.unsharp(1.5) # This runs an "unsharp mask" convolution filter, and is optional
img.write("output.png")
I've got an image that i'd like to 'pad' with white space and centre.
In most cases I need to resize the image from 16 or 32 pixels up to 32 pixels.
If the image is 16 pixels, I want to add 8px of white space on each side, making it a 32 pixel image (with the original floating in the middle).
If it's a 32 pixel image, then nothing changes.
I'm using RMagick to do the conversion:
image.change_geometry!("#{size}x#{size}") { |cols, rows, img|
newimg = img.extent(cols, rows)
newimg.write("#{RAILS_ROOT}#{path}/#{name}.png")
}
Which is working OK, but the smaller images are in the top left of the new image, not centred.
I was looking at the gravity setting, it seems to be what I need, but I can't work out how to specify it in the call?
Thanks in advance.
Check the implementation of the following carrierwave function
http://rubydoc.info/gems/carrierwave/0.5.1/CarrierWave/RMagick#resize_and_pad-instance_method
This is a version of the above method by using only RMagick dependency
require 'RMagick'
include Magick
module Converter
def self.resize_and_pad(img, new_img_path, width, height, background=:transparent, gravity=::Magick::CenterGravity)
img.resize_to_fit!(width, height)
new_img = ::Magick::Image.new(width, height)
if background == :transparent
filled = new_img.matte_floodfill(1, 1)
else
filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
end
# destroy_image(new_img)
filled.composite!(img, gravity, ::Magick::OverCompositeOp)
# destroy_image(img)
# filled = yield(filled) if block_given?
# filled
filled.write new_img_path
end
end
The extent() method takes two more parameters, x & y offsets, which is where the image will be placed within the extent. If you're asking extent for a 100x100 image, for example, and your original is only 50x50, you'd do img.extent(100, 100, 25, 25) -- which would set the image to start at offset 25,25 (thus centering it).
NOTE: There's some issue with extent expecting to use negative offset values (in which case you'd want to do -25, -25) -- check this:
why is the behavior of extent (imagemagick) not uniform across my machines?
s it posible to align an image to the right and wrap text around the image like it is in html and css using the float:right property ?
If so how do you do this ?
I can align an image but dont't know how to wrap the text around it. The text is dynamic text therefore varies alot in length.
Thanks alot
Rick
One suggestion is to try nested bounding boxes. The main bounding box would have the text inside it. with at some point another bounding box for the image. Something along the lines of
bounding_box([x,y], :width => bounds.width, :height => 400) do
text "blah"
text "blah"
# image
bounding_box([bounds.right - image_width, 0], :width => image_width) do
image("path_to_file", :at => [0,0], :width => bounds)
text "more blah"
end
You may be able to simply use the image without the bounding box, but the bounding box would ensure that the text flows around it.