RMagick: Rotate image with origin (matrix transform) - ruby

tl;dr: How can I use RMagick to rotate an image at a given point.
I created a website which allows user to manipulate 2 images online and composite these images on the server side to a single image.
I use regular css transform: rotate() for rotation on the client side.
On the server side I'm rotating the image using RMagick's rotate! method but the results differ from the web version.
(Presumably because of an origin issue (e.g. at which point of the image the rotation takes place)).
The web version rotates at the center of the image (transform-origin: 50% 50%). Unfortunately RMagick doesn't by default.
I read through the RMagick docs and found affine_transform which accepts a matrix and transforms the image. Is this the right method to use, if so how? I tried passing the css-matrix to that function but it doesn't work.
Somewhere in the RMagick documentation I read that Magick::Image#rotate accepts 3 parameters (degree, originX, originY) but my version says that it only accepts 2 parameters (and actually requires the second parameter to be a string...).
My code:
require 'rmagick'
include Magick
#label = Label.last
image = #label.image
json = #label.processing
image.background_color = "none"
image.resize!(json["size"]["width"], json["size"]["height"])
# how can I set the rotation origin to the center of the image?
image.rotate!(json["rotation"].to_i)
overlay.composite!(image, json["position"]["x"], json["position"]["y"],
Magick::OverCompositeOp)
overlay.write("output5.png")
The output I'm currently getting is this. The blue square is actually imagein the code. The heart is overlay.
My desired output looks like this: (Ignore background, border and controls)
If I don't use rotation at all, both images are identically. That's why I assume it's an rotation issue. Both images are equally in width and height.
edit: Apparently only Magick::RVG::Image accepts the originX & originY parameters I mentioned above. Still not able to transform the current image into a RVG Image. It might solve the issue if I can transform my Magick::Image into Magick::RVG::Image.

Okay I've found a solution for this problem. I have to use RVG which is a module to create vector graphics.
The #rotate(degree, originX, originY) method is defined in the RVG::Image class so I had to wrap my Magick::Image object with:
require 'rvg/rvg'
image = RVG::Image.new(magick_image, width, height, x, y)
canvas = RVG.new(width, height)
canvas.use image
overlay.composite!(canvas.draw, ...)
Writing this on mobile, I will add a detailed answer asap.

Related

Rotating an image after being added in a PDF using Reportlab

I'm trying to create a PDF document with an image that will be rotated.
I can successfully create the PDF document, add the image and save it, but as soon as I try rotating it, I'm having many issues.
One thing I'm trying to understand is where is the axe for the rotation, is it at 0,0 (bottom left for PDF) or somewhere else?
Here's my current running code:
output = BytesIO()
# create a new PDF with Reportlab
c = canvas.Canvas(output)
c.saveState()
c.translate(X?, Y?) # TODO find this !
c.rotate(45)
c.drawImage('path/to/image.png', position_left, position_top, width=img_width, height=img_height, mask='auto')
c.restoreState()
c.save()
(Since PDF documents (0,0) point is at bottom right, I have position_left and position_top that refers to the top left point of the document, where I want to place the image).
My issue here is that I don't know how what values to put on c.translate(X?, Y?) to make the image rotate on its center axis, i.e. stays at the same position on the document, but rotate on itself from its center point.
Is using c.translate(X?, Y?) would work or do I need to use advanced mechanisms to rotate "just" the image on the PDF document? If so, can you point me to the right track?
Thank you for your help.
You can use the technique mentioned in below SO Thread
A simple method for rotate images in reportlab
from reportlab.platypus.flowables import Image
class RotatedImage(Image):
def wrap(self,availWidth,availHeight):
h, w = Image.wrap(self,availHeight,availWidth)
return w, h
def draw(self):
self.canv.rotate(90)
Image.draw(self)
I = RotatedImage('../images/somelogo.gif')

Loading an Image object into pygame

I'm making a game were you can set the background image yourself.
The selected image is resized to make it fit the purpose, and then i want to load the picture into pygame.
I've something like:
image = Image.open('file')
image.thumbnail(size, Image.ANTIALIAS)
And now I want to load image into pygame.
of course I can use:
image.save(outfile, "JPEG")
background = pygame.image.load('outfile')
Is there a nice way without having to save the image to my hard drive?
Or is it possible that pygame resizes the image?
You can use pygame.transform.scale() to resize an image:
pygame.transform.scale()
resize to new resolution
scale(Surface, (width, height), DestSurface = None) -> Surface
Resizes the Surface to a new resolution. This is a fast scale operation that does not sample the results.
An optional destination surface can be used, rather than have it create a new one. This is quicker if you want to repeatedly scale something. However the destination must be the same size as the (width, height) passed in. Also the destination surface must be the same format.
So you don't have to use PIL.

Displaying a portrait image in KML without it being rotated to landscape

I am trying to reference images with a greater height than width (portrait format) in KML script for Google Earth; however, the image always comes out as landscape, or rotated left 90 degrees, e.g.
<img id="id_photo" src="2012_01_21-dscf03.jpg" width="500"></img>
I've tried everything I could think of. Is there a image tag to correct this, e.g., format="portrait"?
Thanks,
Walter
This sounds like an example of EXIF only rotation. Which GE probably doesn't honour.
Some cameras etc, 'rotate' a image so its the right way up by setting a flag in the EXIF data. The raw JPG itself, is still in the landscape format.
A display (or convert) program, should hopefilly notice this 'rotation required' flag, and rotate the image.
But Google Earth probably doesnt honor it, so you are just seeing the baseline image as its actully stored (unrotated)
Recommend trying one of the applications mentioned here:
http://jpegclub.org/losslessapps.html
(many note they have automatic correction - so should "fix" your jpg files)
This is already an old thread, but I stumbled on the same problem. And did not find a solution for my situation. Eventually I found a way around, so I thought I'd share it here.
Basically the solution is to rotate the offending images twice, once 90° to the left and then back again.
What you had was an image with a width larger than the height, but with an orientation tag that tells an application to rotate it 90° (but Google Earth does not).
After rotating it twice it is an image with width and height switched, and an orientation tag that says not to rotate it.
Now any application, including Google Earth, will display it correctly.
I used ExifTool to write the tags for all my images to a CSV file, created a list from that with all the pictures to rotate, and used that list to tell IrfanView twice to rotate them.

Ruby / RMagick rotate and combine images

I'm trying to rotate an image before composing it ontop of another, using RMagick with ruby. I can compose the overlaid image but when I try to rotate the image parts of the background are removed, like so...
Im not sure which CompositeOperator I should be using, or if this is the wrong approach all together?
image = Magick::Image.read("img.jpg").first
overlay = Magick::Image.read("./overlay.png").first
overlay.rotate!(9)
image.composite!(overlay, 100, 50, Magick::OverCompositeOp)
image.to_blob
Before rotating set your background to none:
overlay.background_color = "none"
Other possible methods to use after the rotation:
img.transparent_chroma(low, high, opacity=TransparentOpacity, invert=false)
img.transparent(color, opacity=TransparentOpacity)
so in your case:
overlay.transparent!("white")
you need to set the image transparency with the :opacity parameter
http://alternateidea.com/blog/articles/2005/9/19/custom-image-overlays-with-rmagick
http://www.ruby-forum.com/topic/119556
http://www.rhinocerus.net/forum/lang-ruby/63271-transparent-image-using-rmagick.html
RMagick: Convert CMYK EPS to RGB PNG maintaining transparent background

Add perspective to image in web

I have a squared formed image. I need to add perspective view to it and then make an animation that will restore image back to square view. This actions must work at least in all newest versions of browsers and without Flash.
I have tried to do this as follows:
Using RaphaelJS I can only clip image (create path and set fill to image url), not add perspective.
Canvas works as svg and vml in RaphaelJS... I can't add perspective with it's help.
CSS3 3D animation method rotateX adds perspective, but it is supported only by Chrome and Safary.
There is no way to add perspective to image using built in tools.
The only possible solution, I have found is using SVG add clip path to image - it doesn't add perspective view, but it's the best possible solution.
As I understand - we can use Canvas to add perspective, but you must write your own javascript algorithm to transform plain image to perspective view.

Resources