Encoding/decoding a image as Base64 (fails under Ruby1.9 but works under Ruby1.8)

Hi, the folowing code encodes and decodes a image file as Base64:

- Encode "icon.png" in Base64 as "base64.txt":

···

--------------------------------------
  File.open("base64.txt","w") do |file|
    file.write [open("icon.png").read].pack("m")
  end
--------------------------------------

- Decode "base64.txt" as a PNG "new_icon.png" file:
--------------------------------------
  File.open('new_icon.png', 'wb') do |file|
    file << (IO.readlines('base64.txt').to_s.unpack('m')).first
  end
--------------------------------------

It works perfectly under Ruby1.8 (after encoding and decoding "icon.png" is
exatcly the same as "new_icon.png", the same binay file).

However running under Ruby1.9 the result is different since "new_icon.png" is
a corrupted image file. When I try to open it with a image viewer I get this
error (under Linux):

  libpng warning: gAMA: CRC error
  libpng error: PNG unsigned integer out of range.

Which is the difference when using Ruby1.9? how to solve it?
Thanks a lot.

--
Iñaki Baz Castillo <ibc@aliax.net>

The difference is in the second step, the decoding process, since "base64.txt"
file is the same using Ruby1.8 or 1.9.

···

El Jueves, 3 de Diciembre de 2009, Iñaki Baz Castillo escribió:

Hi, the folowing code encodes and decodes a image file as Base64:

- Encode "icon.png" in Base64 as "base64.txt":
--------------------------------------
  File.open("base64.txt","w") do |file|
    file.write [open("icon.png").read].pack("m")
  end
--------------------------------------

- Decode "base64.txt" as a PNG "new_icon.png" file:
--------------------------------------
  File.open('new_icon.png', 'wb') do |file|
    file << (IO.readlines('base64.txt').to_s.unpack('m')).first
  end
--------------------------------------

It works perfectly under Ruby1.8 (after encoding and decoding "icon.png" is
exatcly the same as "new_icon.png", the same binay file).

However running under Ruby1.9 the result is different since "new_icon.png"
is a corrupted image file. When I try to open it with a image viewer I get
this error (under Linux):

  libpng warning: gAMA: CRC error
  libpng error: PNG unsigned integer out of range.

Which is the difference when using Ruby1.9? how to solve it?
Thanks a lot.

--
Iñaki Baz Castillo <ibc@aliax.net>

In Ruby 1.9, Array#to_s is an alias for Array#inspect.

In Ruby 1.8, Array#to_s worked like Array#join with no arguments.

Try this:
   IO.read "base64.txt"

···

On Thu, Dec 3, 2009 at 1:22 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

File.open("base64.txt","w") do |file|
file.write [open("icon.png").read].pack("m")
end

File.open('new_icon.png', 'wb') do |file|
file << (IO.readlines('base64.txt').to_s.unpack('m')).first
end

Which is the difference when using Ruby1.9? how to solve it?
Thanks a lot.

One thing strikes odd: you are not reading the file in binary mode.
It may be that 1.9 punishes you for that. You probably rather want

File.open("base64.txt","w") do |file|
  file.write [File.open("icon.png", "rb") {|io| io.read}].pack("m")
end

You can simplify decoding as

File.open('new_icon.png', 'wb') do |file|
   file.write(File.read('base64.txt').unpack('m').first)
end

Kind regards

robert

···

2009/12/3 Iñaki Baz Castillo <ibc@aliax.net>:

Hi, the folowing code encodes and decodes a image file as Base64:

- Encode "icon.png" in Base64 as "base64.txt":
--------------------------------------
File.open("base64.txt","w") do |file|
file.write [open("icon.png").read].pack("m")
end
--------------------------------------

- Decode "base64.txt" as a PNG "new_icon.png" file:
--------------------------------------
File.open('new_icon.png', 'wb') do |file|
file << (IO.readlines('base64.txt').to_s.unpack('m')).first
end
--------------------------------------

It works perfectly under Ruby1.8 (after encoding and decoding "icon.png" is
exatcly the same as "new_icon.png", the same binay file).

However running under Ruby1.9 the result is different since "new_icon.png" is
a corrupted image file. When I try to open it with a image viewer I get this
error (under Linux):

libpng warning: gAMA: CRC error
libpng error: PNG unsigned integer out of range.

Which is the difference when using Ruby1.9? how to solve it?
Thanks a lot.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Ok, the issue is fixed by uing "IO.read" rather than "IO.readlines":

- Decode "base64.txt" as a PNG "new_icon.png" file:

···

El Jueves, 3 de Diciembre de 2009, Iñaki Baz Castillo escribió:

The difference is in the second step, the decoding process, since
"base64.txt" file is the same using Ruby1.8 or 1.9.

--------------------------------------
   File.open('new_icon.png', 'wb') do |file|
     file << (IO.read('base64.txt').to_s.unpack('m')).first
   end
--------------------------------------

--
Iñaki Baz Castillo <ibc@aliax.net>

That makes lot of sense!
Thanks.

···

El Jueves, 3 de Diciembre de 2009, Robert Klemme escribió:

2009/12/3 Iñaki Baz Castillo <ibc@aliax.net>:
> Hi, the folowing code encodes and decodes a image file as Base64:
>
> - Encode "icon.png" in Base64 as "base64.txt":
> --------------------------------------
> File.open("base64.txt","w") do |file|
> file.write [open("icon.png").read].pack("m")
> end
> --------------------------------------
>
> - Decode "base64.txt" as a PNG "new_icon.png" file:
> --------------------------------------
> File.open('new_icon.png', 'wb') do |file|
> file << (IO.readlines('base64.txt').to_s.unpack('m')).first
> end
> --------------------------------------
>
>
> It works perfectly under Ruby1.8 (after encoding and decoding "icon.png"
> is exatcly the same as "new_icon.png", the same binay file).
>
> However running under Ruby1.9 the result is different since
> "new_icon.png" is a corrupted image file. When I try to open it with a
> image viewer I get this error (under Linux):
>
> libpng warning: gAMA: CRC error
> libpng error: PNG unsigned integer out of range.
>
>
> Which is the difference when using Ruby1.9? how to solve it?
> Thanks a lot.

One thing strikes odd: you are not reading the file in binary mode.
It may be that 1.9 punishes you for that. You probably rather want

File.open("base64.txt","w") do |file|
  file.write [File.open("icon.png", "rb") {|io| io.read}].pack("m")
end

You can simplify decoding as

File.open('new_icon.png', 'wb') do |file|
   file.write(File.read('base64.txt').unpack('m').first)
end

--
Iñaki Baz Castillo <ibc@aliax.net>

Yes. It seems that usng "to_s" could be a bit problematic under Ruby1.9 due to
the new behaviour...
Thanks.

···

El Jueves, 3 de Diciembre de 2009, Lars Christensen escribió:

On Thu, Dec 3, 2009 at 1:22 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:
> File.open("base64.txt","w") do |file|
> file.write [open("icon.png").read].pack("m")
> end
>
> File.open('new_icon.png', 'wb') do |file|
> file << (IO.readlines('base64.txt').to_s.unpack('m')).first
> end
>
> Which is the difference when using Ruby1.9? how to solve it?
> Thanks a lot.

In Ruby 1.9, Array#to_s is an alias for Array#inspect.

In Ruby 1.8, Array#to_s worked like Array#join with no arguments.

Try this:
   IO.read "base64.txt"

--
Iñaki Baz Castillo <ibc@aliax.net>

http://talklikeaduck.denhaven2.com/2009/10/27/its-the-little-things

···

On Thu, Dec 3, 2009 at 5:01 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

El Jueves, 3 de Diciembre de 2009, Lars Christensen escribió:

On Thu, Dec 3, 2009 at 1:22 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:
In Ruby 1.9, Array#to_s is an alias for Array#inspect.

In Ruby 1.8, Array#to_s worked like Array#join with no arguments.

Yes. It seems that usng "to_s" could be a bit problematic under Ruby1.9 due to
the new behaviour...

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale