Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Referenced images inserted directly #264

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/Excel/Writer/XLSX.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1699,9 +1699,13 @@ See the C<write_handler 1-4> programs in the C<examples> directory for further e

This method can be used to insert a image into a worksheet. The image can be in PNG, JPEG or BMP format.

if $filename is a reference to a scalar, the image is actually contained as a binary in that variable.

$worksheet1->insert_image( 'A1', 'perl.bmp' );
$worksheet2->insert_image( 'A1', '../images/perl.bmp' );
$worksheet3->insert_image( 'A1', '.c:\images\perl.bmp' );
my $png = make_png();
$worksheet3->insert_image( 'A1', \$png);

The optional C<options> hash/hashref parameter can be used to set various options for the image. The defaults are:

Expand Down
9 changes: 8 additions & 1 deletion lib/Excel/Writer/XLSX/Package/Packager.pm
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,14 @@ sub _add_image_files {
_mkdir( $dir . '/xl' );
_mkdir( $dir . '/xl/media' );

copy( $filename, $dir . '/xl/media/image' . $index++ . $extension );
if (ref($filename) eq 'SCALAR') {
open my $out, '>', $dir . '/xl/media/image' . $index++ . $extension;
binmode $out;
print {$out} $$filename;
close $out;
} else {
copy( $filename, $dir . '/xl/media/image' . $index++ . $extension );
}
}
}

Expand Down
33 changes: 24 additions & 9 deletions lib/Excel/Writer/XLSX/Workbook.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2193,6 +2193,7 @@ sub _quote_sheetname {
# and extension. Also keep track of previously seen images to optimise out
# any duplicates.
#
my $img_counter = 0;
sub _get_image_properties {

my $self = shift;
Expand All @@ -2204,17 +2205,29 @@ sub _get_image_properties {
my $x_dpi = 96;
my $y_dpi = 96;
my $image_name;
my $img_scalar;
my $data;

if (ref $filename eq 'SCALAR') {
$data = $$filename;
$image_name = 'red'.($img_counter || ''); #just give it a name...
$img_counter += 2; #cheating for reusing test specs
$img_scalar =1;
} else {
( $image_name ) = fileparse( $filename );

# Open the image file and import the data.
my $fh = FileHandle->new( $filename );
croak "Couldn't import $filename: $!" unless defined $fh;
binmode $fh;

# Slurp the file into a string and do some size calcs.
$data = do { local $/; <$fh> };
$fh->close;
}


( $image_name ) = fileparse( $filename );

# Open the image file and import the data.
my $fh = FileHandle->new( $filename );
croak "Couldn't import $filename: $!" unless defined $fh;
binmode $fh;

# Slurp the file into a string and do some size calcs.
my $data = do { local $/; <$fh> };
my $size = length $data;
my $md5 = md5_hex($data);

Expand All @@ -2226,6 +2239,7 @@ sub _get_image_properties {
$self->_process_png( $data, $filename );

$self->{_image_types}->{png} = 1;
$image_name .= '.png' if $img_scalar;
}
elsif ( unpack( 'n', $data ) == 0xFFD8 ) {

Expand All @@ -2234,13 +2248,15 @@ sub _get_image_properties {
$self->_process_jpg( $data, $filename );

$self->{_image_types}->{jpeg} = 1;
$image_name .= '.jpg' if $img_scalar;
}
elsif ( unpack( 'A2', $data ) eq 'BM' ) {

# Test for BMPs.
( $type, $width, $height ) = $self->_process_bmp( $data, $filename );

$self->{_image_types}->{bmp} = 1;
$image_name .= '.bmp' if $img_scalar;
}
else {
croak "Unsupported image format for file: $filename\n";
Expand All @@ -2250,7 +2266,6 @@ sub _get_image_properties {
$x_dpi = 96 if $x_dpi == 0;
$y_dpi = 96 if $y_dpi == 0;

$fh->close;

return ( $type, $width, $height, $image_name, $x_dpi, $y_dpi, $md5 );
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Excel/Writer/XLSX/Worksheet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5833,7 +5833,7 @@ sub insert_image {
}

croak "Insufficient arguments in insert_image()" unless @_ >= 3;
croak "Couldn't locate $image: $!" unless -e $image;
croak "Couldn't locate $image: $!" unless ref $image || -e $image;

push @{ $self->{_images} },
[
Expand Down
87 changes: 87 additions & 0 deletions t/regression/image52.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
###############################################################################
#
# Tests the output of Excel::Writer::XLSX against Excel generated files.
#
# Copyright 2000-2020, John McNamara, [email protected]
#

use lib 't/lib';
use TestFunctions qw(_compare_xlsx_files _is_deep_diff);
use strict;
use warnings;

use MIME::Base64;
use Test::More tests => 1;

###############################################################################
#
# Tests setup.
#
my $filename = 'image51.xlsx'; #NB: reuse 51 xlsx
my $dir = 't/regression/';
my $got_filename = $dir . "ewx_$filename";
my $exp_filename = $dir . 'xlsx_files/' . $filename;

my $ignore_members = [];
my $ignore_elements = {};


###############################################################################
#
# Test the creation of a simple Excel::Writer::XLSX file with image(s)
# from binary reference.
#
use Excel::Writer::XLSX;

my $workbook = Excel::Writer::XLSX->new( $got_filename );
my $worksheet = $workbook->add_worksheet();


my $red_filename = $dir . 'images/red.png';
my $red2_filename = $dir . 'images/red2.png';
my $red = slurp_file($red_filename);
my $red2 = slurp_file($red2_filename);



$worksheet->insert_image( 'E9', \$red, {url => 'https://duckduckgo.com/?q=1'});
$worksheet->insert_image( 'E13', \$red2, {url => 'https://duckduckgo.com/?q=2'});

$workbook->close();

sub slurp_file{
my $filename = shift;
my $string;
open my $fh, '<', $filename or die "Couldn't open file: $!";
local $/ = undef;
binmode $fh;
$string = <$fh>;
close $fh;
return $string;
}
###############################################################################
#
# Compare the generated and existing Excel files.
#

my ( $got, $expected, $caption ) = _compare_xlsx_files(

$got_filename,
$exp_filename,
$ignore_members,
$ignore_elements,
);

_is_deep_diff( $got, $expected, $caption );


###############################################################################
#
# Cleanup.
#
unlink $got_filename;

__END__