0xSina
0xSina

Reputation: 21603

rmagick compress and convert png to jpg

I am trying to compress a png and save it as jpg:

i = Image.read("http://ds4jk3cl4iz0o.cloudfront.net/e2558b0d34221d3270189320173dabc2.png").first

it's size is 799 kb:

http://ds4jk3cl4iz0o.cloudfront.net/e2558b0d34221d3270189320173dabc2.png=>e2558b0d34221d3270189320173dabc2.png PNG 640x639 640x639+0+0 DirectClass 8-bit 799kb 

I set the format to jpeg and quality to 10 (i.e very poor quality so file size should be greatly reduced):

i.format = 'JPEG'

i.write("itest10.png") { self.quality = 10 }

The size actually increases to 800kb!

 => http://ds4jk3cl4iz0o.cloudfront.net/e2558b0d34221d3270189320173dabc2.png=>itest40.png PNG 640x639 640x639+0+0 DirectClass 8-bit 800kb 

1) Why?

2) How can I compress the photo so the size is < 150kb ?

Thanks!

Upvotes: 3

Views: 6960

Answers (2)

Neil Slater
Neil Slater

Reputation: 27227

The use of '.png' extension will change the format back to PNG on the call to write.

There are two possible solutions.

First, I'd recommend using the normal file extension for your format if possible, because a lot of computer systems will rely on that:

i = Image.read( 'demo.png' ).first
i.format = 'JPEG'
i.write( 'demo_compressed.jpg' ) { |image| image.quality = 10 }

If this is not possible, you can set the format inside the block passed to write, and this will apply the format after the extension has been processed:

i = Image.read( 'demo.png' ).first
i.write( 'demo_compressed.png' ) do |image|
  image.format = 'JPEG'
  image.quality = 10
end

In both the above cases, I get the expected high compression (and low quality) jpeg format image.


This has been updated due to recent RMagick changes (thanks to titan for posting comment). The orginal code snippets were

i.write( 'demo_compressed.jpg' ) { self.quality = 10 }

and

i.write( 'demo_compressed.png' ) do
  self.format = 'JPEG'
  self.quality = 10
end

These may still work in older RMagick installations.

Upvotes: 10

gKreator
gKreator

Reputation: 69

I tried the other answer and I was still having issues with the transparency. This code here work fine for me:

img_list = Magick::ImageList.new

img_list.read( 'image.png' )

img_list.new_image( img_list.first.columns, img_list.first.rows ) { 

  self.background_color = "white" 

}

imageJPG = img_list.reverse.flatten_images

imageJPG.write( "out.jpg" ) 

The idea is first create an imageList then load the PNG image into it and after that add a new image to that list and set its bg to be white. Then just reverse the order of the list then flatten the image list into a single image. To add compression just do the self.quality thing from the above answer.

Upvotes: 4

Related Questions