Rails + Carrierwave + RMagick : Crop only if image is large - ruby

I am using carrier-wave to upload images. On upload I am creating thumbnails for the image which is done using Rmagick method, resize_to_fill like below.
version :thumb do
process :resize_to_fill=> [150, 150]
end
Here is output of all the RMagick methods carrierwave supports (none of which I want):
:resize_to_fill => [150,150]
This works fine on larger images but my smaller images are enlarged to 150 x 150.
:resize_to_fit => [150,150]
Again it was resized, I want it left alone!
:resize_to_limit => [150,150]
This one leaves it as is, but larger images are not cropped. They are resized to keep the aspect ratio.
Here is the result I want and how my small and larger images should look.
How do this? I want smaller images to be left alone and crop only larger images to 150 x 150. Is there another method or options I can pass to resize_to_fill?

I solved it by modifying :resize_to_fill carrierwave method as described in their code here.
I just made a new method with the same code with a check to see if the uploaded image is smaller. Here is the new method:
def resize_to_fill_modfied(width, height, gravity=::Magick::CenterGravity)
manipulate! do |img|
img.crop_resized!(width, height, gravity) unless (img.columns <= width && img.rows <= height)
img = yield(img) if block_given?
img
end
end
Does exactly what I want now.

Related

Making a long image without resizing

I need to put many images together side by side but without changing the height or width of any of them. That is to say, it will just be one image of a constant height but very long width as the image are sitting horizontally.
I've been using Python and the PIL library but what I've tried so far is producing an image that makes all the images smaller to concatenate into one long image.
Image.MAX_IMAGE_PIXELS = 100000000 # For PIL Image error when handling very large images
imgs = [ Image.open(i) for i in list_of_images ]
widths, heights = zip(*(i.size for i in imgs))
total_width = sum(widths)
max_height = max(heights)
new_im = Image.new('RGB', (total_width, max_height))
# Place first image
new_im.paste(imgs[0],(0,0))
# Iteratively append images in list horizontally
hoffset=0
for i in range(1,len(imgs),1):
hoffset=imgs[i-1].size[0]+hoffset # update offset**
new_im.paste(imgs[i],(hoffset,0))
new_im.save('row.jpg')
The result I'm getting now is one image made up of concatenated images in a horizontal row. This is what I want, except the images are being made smaller and smaller in the concatenation process. I want the end result to not make the images smaller and instead produce an image made of the input images with their original size. So the output image will just have to have a very long width.
It seems you have a bug while updating the offsets.
You should replace your iteration block with:
imgs = [Image.open(i) for i in list_of_images]
widths, heights = zip(*(i.size for i in imgs))
new_img = Image.new('RGB', (sum(widths), max(heights)))
h_offset = 0
for i, img in enumerate(imgs):
new_img.paste(img, (h_offset, 0))
h_offset += img.size[0]

MiniMagick Resize Image

I'm trying to use MiniMagick to resize 2 images and overlay one on top of the other. Heres the code I am using
require "mini_magick"
first_image = MiniMagick::Image.new("spider.jpg")
first_image = first_image.resize("250x250")
second_image = MiniMagick::Image.new("q.png")
second_image = second_image.resize("250x250")
result = first_image.composite(second_image) do |c|
c.compose "Over" # OverCompositeOp
c.gravity "center"
# c.resize("250x250")
end
result.write "output.jpg"
This overlays the images but neither is resized and the overlay image ends up awkwardly cropped. Ive tried making both the same size, making the bigger overlay image smaller and the smaller image bigger, but none seem to work. Any advice would be highly appreciated.

how to scale image by percentage by carrierwave

I want to generate images in 25%, 50%, 75% size from original image, but seems carrierwave's resize_to_fill/fit not support percentage. Anyone knows how to do like this?
Thanks.
After some research, i found one solution:
process :store_dimensions
version :r_3x do
process :resize_to_fit_by_percentage => 0.75
end
private
def resize_to_fit_by_percentage(percentage)
resize_to_fit model.width*percentage, nil
end
def store_dimensions
if file && model
model.width, model.height = ::MiniMagick::Image.open(file.file)[:dimensions]
end
end
Firstly get the dimension of the uploaded image, then define a custom resize method(here is resize_to_fi_by_percentage), and resize image in this method like the code does.

qtruby draw picture point by point

Hi I'm trying to write BMP reader writer in ruby and now i'm stuck on write it on screen.
I have picture stored in pixels array and on every pixel is stored rgb color.
But nothing happens in in window? What I'm doing wrong? Or is there any qt object to which i can stored pixel data and simply paint it?
def initialize
super
setWindowTitle "Transparent rectangles"
resize 590, 90
move 300, 300
show
end
def paintEvent event
painter = Qt::Painter.new self
bmp = BMP::Reader.new("picture.bmp")
drawPicture(painter,bmp.getPixels())
painter.end
end
def drawPicture(painter, pixels)
painter.setPen Qt::NoPen
0.upto(pixels.length-1) do |i|
0.upto(pixels[0].length-1) do |j|
painter.setBrush Qt::Brush.new Qt::Color.new pixels[i][j][2], pixels[i][j][1], pixels[i][j][0], 255
painter.drawPoint(i,j)
end
end
end
QPainter.drawPoint uses the current pen, not the brush. Call painter.setPen before each point.
But you would be much better off storing the pixels in a QImage. Qt already has support for reading BMP files so there's no need to implement that yourself unless you have a good reason to.

Cropping image with ImageScience

ImageScience is cool and light. I am using it in my sinatra app. But I can't understand how can I crop image with not square form and how can I make thumbnail with two dimensions.
As I found on ImageScience site:
ImageScience.with_image(file) do |img|
img.cropped_thumbnail(100) do |thumb|
thumb.save "#{file}_cropped.png"
end
img.thumbnail(100) do |thumb|
thumb.save "#{file}_thumb.png"
end
img.resize(100, 150) do |img2|
img2.save "#{file}_resize.png"
end
end
I can crop thumb and resize thumb only with ONE dimension but I want to use two, as in RMagick. For example I want to crop 100x200px box from image, or I want to make thumbnail with width or height not bigger then 300 (width) or 500 (height) pixels.
Use Devil instead:
Devil.with_image("horse.png") do |img|
img.crop(0, 0, 100, 100)
img.resize2(500, 500)
img.save("horse_resized.jpg", :quality => 85)
end
Wow, I've looked into ImageScience sources and found great method with_crop(left, top, right, bottom) which helped me with my problem.
http://seattlerb.rubyforge.org/image_science/ImageScience.html

Resources