Image::TextMode::Canvas - A canvas of text mode pixels


Image-TextMode documentation Contained in the Image-TextMode distribution.

Index


Code Index:

NAME

Top

Image::TextMode::Canvas - A canvas of text mode pixels

DESCRIPTION

Top

This module represents the graphical portion of an image, i.e. a grid of pixels.

ACCESSORS

Top

* width - the width of the canvas
* height - the height of the canvas
* pixeldata - an arrayref of arrayrefs of pixel data

METHODS

Top

new( %args )

Creates a new canvas.

getpixel( $x, $y )

Get raw pixel data at $x, $y.

getpixel_obj( $x, $y, \%options )

Create a pixel object data at $x, $y. Available options include:

putpixel( \%pixel, $x, $y )

Store pixel data at $x, $y.

dimensions( )

returns a list of the width and height of the image.

clear_screen( )

Clears the canvas pixel data.

clear_line( $y, [ \@range ] )

Clears the data at line $y. Specify a range to clear only a portion of line $y.

delete_line( $y )

Removes the line from the canvas, moving all subsquent lines up.

as_ascii( )

Returns only the character data stored in the canvas.

max_x( $line )

Finds the last defined pixel on a given line. Useful for optimizing writes in formats where width matters. Returns undef for a missing line.

ansiscale( $factor )

Perform nearest neighbor scaling in text mode. Returns a new textmode image.

    # scale down to 1/4 the original size
    my $scaled = $image->ansiscale( 0.25 );

AUTHOR

Top

Brian Cassidy <bricas@cpan.org>

COPYRIGHT AND LICENSE

Top


Image-TextMode documentation Contained in the Image-TextMode distribution.
package Image::TextMode::Canvas;

use Moose;

use Image::TextMode::Pixel;

has 'width' => ( is => 'rw', isa => 'Int', default => sub { 0 } );

has 'height' => ( is => 'rw', isa => 'Int', default => sub { 0 } );

has 'pixeldata' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );

sub getpixel {
    my ( $self, $x, $y ) = @_;
    return unless exists $self->pixeldata->[ $y ];    # avoid autovivification
    return $self->pixeldata->[ $y ]->[ $x ];
}

sub getpixel_obj {
    my ( $self, $x, $y, $options ) = @_;
    my $pixel = $self->getpixel( $x, $y );
    return unless $pixel;
    return Image::TextMode::Pixel->new( %$pixel, $options );
}

sub putpixel {
    my ( $self, $pixel, $x, $y ) = @_;
    $self->pixeldata->[ $y ]->[ $x ] = $pixel;

    my ( $w, $h ) = ( $x + 1, $y + 1 );
    $self->height( $h ) if $self->height < $h;
    $self->width( $w )  if $self->width < $w;
}

sub dimensions {
    my $self = shift;
    return $self->width, $self->height;
}

sub clear_screen {
    my $self = shift;
    $self->width( 0 );
    $self->height( 0 );
    $self->pixeldata( [] );
}

sub clear_line {
    my $self  = shift;
    my $y     = shift;
    my $range = shift;

    return unless defined $self->pixeldata->[ $y ];

    if ( !$range ) {
        $self->pixeldata->[ $y ] = [];
    }
    else {
        $range->[ 1 ] = @{ $self->pixeldata->[ $y ] } - 1 if $range->[ 1 ] == -1;
        $self->pixeldata->[ $y ]->[ $_ ] = undef
            for $range->[ 0 ] .. $range->[ 1 ];
    }
}

sub delete_line {
    my $self  = shift;
    my $y     = shift;

    return unless exists $self->pixeldata->[ $y ];

    delete @{ $self->pixeldata }[ $y ];
    $self->height( $self->height - 1 );
}

sub as_ascii {
    my ( $self ) = @_;

    my $output = '';
    for my $row ( @{ $self->pixeldata } ) {
        for my $col ( @$row ) {
            $output .= defined $col
                && defined $col->{ char } ? $col->{ char } : ' ';
        }
        $output .= "\n";
    }

    return $output;
}

sub max_x {
    my ( $self, $y ) = @_;
    my $line = $self->pixeldata->[ $y ];

    return unless $line;

    my $x;
    for ( 0 .. @$line - 1 ) {
        $x = $_ if defined $line->[ $_ ];
    }

    return $x;
}

sub ansiscale {
    my ( $self, $factor ) = @_;

    my $new    = ( ref $self )->new;
    my $width  = $self->width * $factor;
    my $height = $self->height * $factor;

    $width  = int( $width + 1 )  if int( $width ) != $width;
    $height = int( $height + 1 ) if int( $height ) != $height;

    my $oldpixels = $self->pixeldata;
    my $newpixels = [];

    my $inv_ratio = ( 1 / $factor );

    for my $y ( 0 .. $height - 1 ) {
        for my $x ( 0 .. $width - 1 ) {
            my $px = int( $x * $inv_ratio );
            my $py = int( $y * $inv_ratio );

            $newpixels->[ $y ]->[ $x ] = $oldpixels->[ $py ]->[ $px ];
        }
    }

    $new->width( $width );
    $new->height( $height );
    $new->pixeldata( $newpixels );
    return $new;
}

no Moose;

__PACKAGE__->meta->make_immutable;

1;