Skip to content
Merged
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
1 change: 1 addition & 0 deletions IFComp/lib/IFComp/Controller/Entry.pm
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ sub _process_form {
# If clearing cover art, also clear the web-cover.
$entry->web_cover_file->remove;
$entry->clear_web_cover_file;
$entry->remove_web_cover_geometry_file;
}
}

Expand Down
94 changes: 91 additions & 3 deletions IFComp/lib/IFComp/Schema/Result/Entry.pm
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,8 @@ Readonly my @DEFAULT_INFORM_CONTENT => qw(

# $MAX_COVER_HEIGHT: This should be *twice* the maximum display-height
# (measured in CSS pixels) allowed by the ballot page for cover art.
Readonly my $MAX_COVER_HEIGHT => 700;
Readonly my $MAX_COVER_HEIGHT => 700;
Readonly my $WEB_COVER_GEOMETRY_FILENAME => 'geometry.txt';

has 'sort_title' => (
is => 'ro',
Expand Down Expand Up @@ -784,8 +785,9 @@ sub _build_cover_file {
sub _build_web_cover_file {
my $self = shift;

my $web_cover_file =
( $self->web_cover_directory->children( no_hidden => 1 ) )[0];
my ($web_cover_file) =
grep { $_->basename ne $WEB_COVER_GEOMETRY_FILENAME }
$self->web_cover_directory->children( no_hidden => 1 );

unless ( defined $web_cover_file ) {
my $cover_file = $self->cover_file;
Expand Down Expand Up @@ -954,25 +956,111 @@ sub cover_image {
return $image;
}

sub web_cover_geometry_file {
my $self = shift;

return $self->web_cover_directory->file($WEB_COVER_GEOMETRY_FILENAME);
}

sub _read_web_cover_geometry {
my $self = shift;

my $file = $self->web_cover_geometry_file;
return unless -e $file;

my @lines = $file->slurp( chomp => 1 );
return unless @lines >= 2;

my ( $width, $height ) = @lines[ 0, 1 ];
return unless $width =~ /^\d+$/ && $height =~ /^\d+$/;

return ( $width, $height );
}

sub _write_web_cover_geometry {
my ( $self, $width, $height ) = @_;

my $geometry_file = $self->web_cover_geometry_file;

# write atomically to ensure workers don't read half-written files
my $temp_file =
$geometry_file->dir->file( sprintf '.geometry.%s.tmp', $$ );

$temp_file->spew("$width\n$height\n");
rename $temp_file->stringify, $geometry_file->stringify
or die "Could not write web cover geometry for entry "
. $self->id . ": $!";
}

sub remove_web_cover_geometry_file {
my $self = shift;

my $file = $self->web_cover_geometry_file;
$file->remove if -e $file;
}

sub web_cover_geometry {
my $self = shift;

return unless $self->cover_exists;

my $web_cover_file = $self->web_cover_file;
return unless defined $web_cover_file && -e $web_cover_file;

if ( my @dims = $self->_read_web_cover_geometry ) {
return @dims;
}

my $image = Imager->new( file => $web_cover_file );
return unless $image;

my $width = $image->getwidth;
my $height = $image->getheight;
$self->_write_web_cover_geometry( $width, $height );

return ( $width, $height );
}

sub web_cover_width {
my $self = shift;

my ($width) = $self->web_cover_geometry;
return $width;
}

sub web_cover_height {
my $self = shift;

my ( undef, $height ) = $self->web_cover_geometry;
return $height;
}

sub create_web_cover_file {
my $self = shift;

if ( ( defined $self->web_cover_file ) && ( -e $self->web_cover_file ) ) {
$self->web_cover_file->remove;
}
$self->clear_web_cover_file;
$self->remove_web_cover_geometry_file;

return unless $self->cover_exists;

my $image = Imager->new( file => $self->cover_file );
my ( $width, $height );
if ( $image->getheight > $MAX_COVER_HEIGHT ) {
my $resized_image = $image->scale( ypixels => $MAX_COVER_HEIGHT );
$resized_image->write( file => $self->web_cover_file );
$width = $resized_image->getwidth;
$height = $resized_image->getheight;
}
else {
copy( $self->cover_file, $self->web_cover_file );
$width = $image->getwidth;
$height = $image->getheight;
}

$self->_write_web_cover_geometry( $width, $height );
}

# update_content_directory: Clean up (and possibly create) the content directory,
Expand Down
2 changes: 1 addition & 1 deletion IFComp/root/src/_current_entry_row.tt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[% IF entry.cover_exists %]
<div class="col-sm-4">
<div itemprop="image" itemscope itemtype="https://schema.org/ImageObject">
<a itemprop="contentUrl" href="[% c.uri_for_action( '/play/full_cover', [ entry.id ] ) %]" target="_blank"><img itemprop="thumbnailUrl" class="img-fluid" src="[% c.uri_for_action( '/play/cover', [ entry.id ] ) %]" alt="Cover art for [% entry.title %]" height="[% entry.cover_image.getheight %]" width="[% entry.cover_image.getwidth %]" loading="lazy"></a>
<a itemprop="contentUrl" href="[% c.uri_for_action( '/play/full_cover', [ entry.id ] ) %]" target="_blank"><img itemprop="thumbnailUrl" class="img-fluid" src="[% c.uri_for_action( '/play/cover', [ entry.id ] ) %]" alt="Cover art for [% entry.title %]" height="[% entry.web_cover_height %]" width="[% entry.web_cover_width %]" loading="lazy"></a>
[% IF (entry.genai_state / 2) % 2 == 1 %]
<span style="font-size: smaller;" itemprop="genai_cover"><em>Generative artificial intelligence was used to make this cover art.</em></span>
[% END %]
Expand Down
24 changes: 24 additions & 0 deletions IFComp/t/controller_Entry.t
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ ok( -e "$comp_dir/$id/web_cover/cover.png", "Cover web-version created." );
my $web_cover_image =
Imager->new( file => "$comp_dir/$id/web_cover/cover.png" );
is( $web_cover_image->getheight, 700, "Web-cover is scaled down." );
ok( -e "$comp_dir/$id/web_cover/geometry.txt",
"Web-cover geometry file created."
);
is( $entry->web_cover_height, 700, "Cached web-cover height is correct." );
is( $entry->web_cover_width,
$web_cover_image->getwidth,
"Cached web-cover width is correct."
);

######
# Modify entry, changing to a smaller cover image
Expand All @@ -120,6 +128,20 @@ ok( -e "$comp_dir/$id/web_cover/tiny_cover.png",
$web_cover_image =
Imager->new( file => "$comp_dir/$id/web_cover/tiny_cover.png" );
is( $web_cover_image->getheight, 200, "Web-cover is NOT scaled up." );
$entry = $schema->resultset('Entry')->find($entry_id);
is( $entry->web_cover_height, 200, "Cached web-cover height is updated." );
is( $entry->web_cover_width,
$web_cover_image->getwidth,
"Cached web-cover width is updated."
);

unlink "$comp_dir/$id/web_cover/geometry.txt"
or die "Could not remove geometry cache: $!";
is( $entry->web_cover_height, 200,
"Missing geometry cache is regenerated on read." );
ok( -e "$comp_dir/$id/web_cover/geometry.txt",
"Regenerated web-cover geometry file."
);

######
# Modify an entry, removing cover files
Expand All @@ -137,6 +159,8 @@ $mech->submit_form_ok(
ok( not( -e "$comp_dir/$id/cover/tiny_cover.png" ), "Cover deleted." );
ok( not( -e "$comp_dir/$id/web_cover/tiny_cover.png" ),
"Web cover deleted." );
ok( not( -e "$comp_dir/$id/web_cover/geometry.txt" ),
"Web-cover geometry file deleted." );

######
# Modify an entry, trying to upload a bogus image
Expand Down
Loading