``````package Graphics::DZI::Document;

use strict;
use warnings;

our \$log;
use Log::Log4perl;
BEGIN {
\$log = Log::Log4perl->get_logger ();
}

Graphics::DZI::Document - DeepZoom Image Pyramid, Sparse Document Images

# prepare a bunch of Image::Magick objects
@pages = ......;

# create the overlay itself
use Graphics::DZI::Document;
my \$o = new Graphics::DZI::Document (pages => \@pages,
x => 80000, 'y' => 40000,
pack => 'linear',
squeeze => 256);

# use the Graphics::DZI::Files and add this as overlay

This subclass of L<Graphics::DZI::Overlay> handles documents as overlays for extremely sparse
DeepZoom images. Documents here are also images, but not a single one, but one for each document
page.

What is also different from a normal overlay image is that document overlays will show a different
number of images, depending on the zoom level. First, when the canvas is the dominant feature, only
a small first page is show. Whenever that first page is fairly readable, the first 4 pages are shown
in the slot. Then the next 9 or 16, depending on whether the growth is C<linear> or C<exponential>.

=cut

use Moose;
extends 'Graphics::DZI::Overlay';

Different to the superclass not the image, but a sequence of pages have to be passed in. Optionally,
a parameter C<pack> determines between C<linear> and C<exponential> growth of pages at higher
resolutions. With linear you actually get 1, 4, 9, 16, 25...  documents (so it is actually squared
linear). With exponential you get more aggressively 1, 4, 16, 32, ... pages.

=cut

use Moose::Util::TypeConstraints qw(enum);
enum 'packing' => qw( exponential linear );

has 'pages'     => (isa => 'ArrayRef',       is => 'rw', required => 1);
has '+image'    => (isa => 'Image::Magick',              required => 0);
has 'W'         => (isa => 'Int'   ,        is => 'rw');
has 'H'         => (isa => 'Int'   ,        is => 'rw');
has 'sqrt'      => (isa => 'Num',           is => 'rw');
has 'pack'      => (isa => 'packing',       is => 'rw', default => 'exponential');

sub BUILD {
my \$self = shift;
(\$self->{W}, \$self->{H}) = \$self->pages->->GetAttributes ('width', 'height');     # single document

use feature "switch";
given (\$self->{pack}) {
when ('linear')      {
use POSIX;
\$self->{ sqrt } = POSIX::ceil ( sqrt ( scalar @{\$self->pages}) );     # take the root + 1
}
when ('exponential') {
use POSIX;
my \$log2 = POSIX::ceil (log (scalar @{\$self->pages}) / log (2));      # next fitting 2-potenz
\$log2++ if \$log2 % 2;                                                 # we can only use even ones
\$self->{ sqrt }  = ( 2**(\$log2/2) );                                  # how many along one edge when we organize them into a square?
}
default { die "unhandled packing"; }
}

\$self->{ image } = _list2huge (\$self->sqrt, \$self->W, \$self->H, @{ \$self->pages }) ;
}

sub _list2huge {
my \$sqrt = shift;
my (\$W, \$H) = (shift, shift);

my \$dim = sprintf "%dx%d", map { \$_ * \$sqrt } (\$W, \$H);
\$log->debug ("building composite document: DIM \$dim (\$sqrt)");
use Image::Magick;
my \$huge = Image::Magick->new (\$dim);
\$huge->Transparent (color => 'white');

foreach my \$a (0 .. \$sqrt*\$sqrt - 1) {
last unless \$_[\$a];
my (\$j, \$i) = ( int( \$a / \$sqrt)  , \$a % \$sqrt );
\$log->debug ("    index \$a (x,y) = \$i \$j");

\$huge->Composite (image => \$_[\$a],
x     => \$i * \$W,
'y'    => \$j * \$H,
compose => 'Over',
);
}
#    \$huge->Display();
return \$huge;
}

=over

=item B<halfsize>

This will be called by the overall DZI algorithm whenever this overlay is to be size-reduced by 2.

=cut

sub halfsize {
my \$self = shift;

my (\$w, \$h) = \$self->image->GetAttributes ('width', 'height');                     # current dimensions
if (\$self->{ sqrt } > 1) {
use feature "switch";
given (\$self->{pack}) {
when ('linear')      { \$self->{ sqrt }--;    }                             # in linear packing we simply reduce the square root by one
when ('exponential') { \$self->{ sqrt } /= 2; }
default {}
}
\$self->{ image } = _list2huge (\$self->sqrt,                                    # pack sqrt x sqrt A4s into one image
\$self->W, \$self->H,
@{ \$self->pages });
}
\$self->image->Resize (width => int(\$w/2), height => int(\$h/2));                    # half size
\$self->{x} /= 2;                                                                   # dont forget x, y
\$self->{y} /= 2;
}

=back

Robert Barta, C<< <drrho at cpan.org> >>
{"ft_lang_label":"__label__en","ft_lang_prob":0.6496054,"math_prob":0.8588036,"size":4323,"snap":"2020-45-2020-50","text_gpt3_token_len":1296,"char_repetition_ratio":0.11715675,"word_repetition_ratio":0.039215688,"special_character_ratio":0.36456165,"punctuation_ratio":0.22470587,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9926997,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-11-26T07:01:31Z\",\"WARC-Record-ID\":\"<urn:uuid:d1ed8f4f-6295-4908-a127-8ed2e7355d83>\",\"Content-Length\":\"21097\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:f3ea2cee-0896-4d21-936c-acf95952a2a5>\",\"WARC-Concurrent-To\":\"<urn:uuid:b289b18a-5f99-4027-b37a-91ed44b935f2>\",\"WARC-IP-Address\":\"151.101.194.217\",\"WARC-Target-URI\":\"https://metacpan.org/release/Graphics-DZI/source/lib/Graphics/DZI/Document.pm\",\"WARC-Payload-Digest\":\"sha1:UWMSNONTKBYBEL6YRQ25MJC66ATTLZBG\",\"WARC-Block-Digest\":\"sha1:ZZQNQCU4K4ZTSW7FNUEMHH2EGSYMY5IF\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-50/CC-MAIN-2020-50_segments_1606141186761.30_warc_CC-MAIN-20201126055652-20201126085652-00642.warc.gz\"}"}