Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl convert image to base64

Tags:

perl

I am using a service to send a picture to a server and they require the image be converted to base64 format before it is sent. I tried MIME::Base64 with this code:

use MIME::Base64 ();

open (IMAGE, "C:\\wamp\\www\\image.png") or die "$!";

$base64_string = IMAGE;
$encoded = encode_base64($base64_string);
print "Encode $encoded";

and got this error message

Undefined subroutine &mqin::encode_base64 called at line 6.

like image 884
Grigor Avatar asked Jul 02 '12 22:07

Grigor


1 Answers

When you specify an empty import list, like this:

use MIME::Base64 ();

You get no imports. That means that the function name encode_base64 will not be imported into the caller's namespace. You can either allow for the import to happen, or fully qualify the function name by referring to the package it lives in explicitly when you call it.

To import, change that line to:

use MIME::Base64;

The () parens are specifying that MIME::Base64 exports nothing to your namespace. The default behavior (without the parens) is to export encode_base64 and decode_base64. By using empty parenthesis in your import list you are overriding the convenient default behavior of importing those two function names. If you really don't want those functions polluting your main namespace you could retain your original use MIME::Base64 () line, and then fully-qualify your subroutine call:

$encoded = MIME::Base64::encode_base64($base64_string);

But it's a whole lot easier, and probably satisfactory to just allow the default export list to be processed by removing the parenthesis from your use line.

Alternatively, you can specify exactly what to import:

use MIME::Base64 ('encode_base64');

This will import only the encode_base64 function, but will not import decode_base64, thereby minimizing namespace pollution.

Update You're also not reading the file. This line:

$base64_string = IMAGE;

...should be updated like this:

$raw_string = do{ local $/ = undef; <IMAGE>; };
$encoded = encode_base64( $raw_string );

That problem would have been caught more verbosely if you had use strict 'subs' in effect. The problem is that "IMAGE" by itself is just a bareword, and Perl thinks it's a subroutine call. The angle brackets, "<>" are the common way of reading from a filehandle. The "local $/ = undef" part is just a means of ensuring that you slurp the entire file, not just until the first sequence that looks like a "\n" to Perl.

Update2: And as MOB points out, you either need to be escaping the backslashes in your path, or use forward slashes. Perl doesn't mind, even on Win32. Of course since you're taking the wise step of using or die $! on your open, you've already discovered this mistake.

like image 119
DavidO Avatar answered Nov 05 '22 16:11

DavidO