#/*
# *  Copyright 2007-2010 hkrn <hikarin@users.sourceforge.jp>
# *
# *  Licensed under the Apache License, Version 2.0 (the "License");
# *  you may not use this file except in compliance with the License.
# *  You may obtain a copy of the License at
# *
# *      http://www.apache.org/licenses/LICENSE-2.0
# *
# *  Unless required by applicable law or agreed to in writing, software
# *  distributed under the License is distributed on an "AS IS" BASIS,
# *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# *  See the License for the specific language governing permissions and
# *  limitations under the License.
# */
#
# $Id: Thumbnail.pm 1901 2009-12-31 02:40:20Z hikarin $
#

package Img0ch::Upload::Thumbnail;

use strict;

sub create {
    my ( $iClass, $iKernel, $args ) = @_;
    my $ext = $args->{ext} || return 0;
    $ext ne 'jpg' and $ext ne 'gif' and $ext ne 'png' and return 1;

    my $fh  = $args->{fh}   || return 0;
    my $src = $args->{path} || return 0;
    my $iConfig       = $iKernel->get_config();
    my $handler       = $iConfig->get('ImageHandler') || 'repng2jpeg';
    my $scaled_width  = Img0ch::Kernel::intval( $args->{width} ) || 1;
    my $scaled_height = Img0ch::Kernel::intval( $args->{height} ) || 1;

    if ( $handler eq 'repng2jpeg' ) {
        my $binary = $^O eq 'MSWin32' ? 'repng2jpeg.exe' : 'repng2jpeg';
        my $repng2jpeg = join '/', $iConfig->get('SystemPath'), $binary;
        -x $repng2jpeg or $iKernel->throw_io_exception($repng2jpeg);

        defined $File::Temp::VERSION or require File::Temp;
        my ( undef, $temp ) = File::Temp::tempfile( UNLINK => 1 );

        open my $fh, '|-',
            "${repng2jpeg} ${src} ${temp}"
            . " ${scaled_width} ${scaled_height} 90"
            or $iKernel->throw_io_exception($repng2jpeg);
        close $fh or $iKernel->throw_io_exception($repng2jpeg);

        $fh = $iKernel->get_read_file_handle($temp);
        binmode $fh;
        while ( read( $fh, my $buffer, 8192 ) ) {
            print ${fh} $buffer or $iKernel->throw_io_exception($temp);
        }
        close $fh or $iKernel->throw_io_exception($temp);
    }
    elsif ( $handler eq 'Imager' ) {
        defined $Imager::VERSION or require Imager;
        my $orig = Imager->new();
        $orig->read( file => $src )
            or $iKernel->throw_exception( $orig->errstr() );
        my $scaled = $orig->scale(
            xpixels => $scaled_width,
            ypixels => $scaled_height,
            type    => 'min',
        ) or $iKernel->throw_exception( $orig->errstr() );

        my $buffer;
        $ext eq 'jpg' and $ext = 'jpeg';
        $scaled->write( data => \$buffer, type => $ext )
            or $iKernel->throw_exception( $scaled->errstr() );
        binmode $fh;
        print {$fh} $buffer or $iKernel->throw_io_exception($src);
    }
    elsif ( $handler eq 'GD' ) {
        defined $GD::VERSION or require GD;
        $ext eq 'gif' and $GD::VERSION <= 2.15 and return 1;

        my $constructor = {
            'jpg' => sub { return GD::Image->newFromJpeg( $_[0] ) },
            'gif' => sub { return GD::Image->newFromGif( $_[0] ) },
            'png' => sub { return GD::Image->newFromPng( $_[0] ) },
            }->{$ext}
            || return 0;
        my $gd = GD::Image->new( $scaled_width, $scaled_height );
        my $src = $constructor->($src);
        $gd->copyResampled( $src, 0, 0, 0, 0, $scaled_width, $scaled_height,
            $src->getBounds() );

        binmode $fh;
        if ( $ext eq 'jpg' ) {
            print ${fh} $gd->jpeg(100) or $iKernel->throw_io_exception($src);
        }
        elsif ( $ext eq 'gif' ) {
            print ${fh} $gd->gif() or $iKernel->throw_io_exception($src);
        }
        elsif ( $ext eq 'png' ) {
            print ${fh} $gd->png() or $iKernel->throw_io_exception($src);
        }
    }
    elsif ( $handler eq 'PerlMagick' ) {
        defined $Image::Magick::VERSION or require Image::Magick;
        my $magick = Image::Magick->new();
        my $trap   = sub {
            my ( $iKernel, $retval ) = @_;
            $retval and $iKernel->throw_exception("${retval}");
        };
        $trap->( $iKernel, $magick->Read($src) );
        $trap->(
            $iKernel,
            $magick->Scale(
                width  => $scaled_width,
                height => $scaled_height
            )
        );
        $trap->( $iKernel, $magick->Set( type => 'Optimize' ) );
        my @blob = $magick->ImageToBlob();
        binmode $fh;
        print ${fh} $blob[0] or $iKernel->throw_io_exception($src);
    }
    else {
        return 0;
    }
    return 1;
}

1;
__END__
