/*
 *   MediaMVP Server Library
 *   http://www.rst38.org.uk/vdr/mediamvp
 *
 *   Copyright (C) 2005, Dave Kelly
 *
 *   $Id: image.c,v 1.5 2005/03/31 10:45:58 dom Exp $
 *   $Date: 2005/03/31 10:45:58 $
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *
 *   Use ImageMagick libraries to blit an image to a surface 
 */

#include "libmvp_internal.h"
#include "libmvpimage.h"

#ifdef HAVE_MAGICK
#include <magick/api.h>
#endif

#ifdef HAVE_MAGICK
static int mvp_CopyImageToSurface(surface_t *surface,Image *image, int x0, int y0, int width, int depth, int rotate, mvp_scale_method_t stype)
{
    ExceptionInfo exception;
    int x,y, bpp;
    uint32_t rgb;
    Image *my_image = image;
    Image *resized_image = NULL;
    int x_offset = 0, y_offset = 0;
    int image_width, image_height;
    const PixelPacket *pixels = NULL;

    GetExceptionInfo(&exception);

    if ( image == (Image *) NULL ) {
        return -1;
    }

    if ( exception.severity != UndefinedException ) {
#if MAGICK_VERSION >= 6
        CatchException(&exception);
#else
        CatchImageException(image);
#endif
    }

    if (rotate != 0) {
        Image *new_image = RotateImage(image, rotate, &exception);
        
        if ( exception.severity != UndefinedException ) {
#if MAGICK_VERSION >= 6
            CatchException(&exception);
#else
            CatchImageException(new_image);
#endif
        }

        my_image = new_image;
    }


#if 0
    DescribeImage(my_image, stderr, 1);
#endif

    bpp = GetImageDepth(my_image, &exception);
    if(exception.severity != UndefinedException) {
#if MAGICK_VERSION >= 6
        CatchException(&exception);
#else
        CatchImageException(image);
#endif
    }

    Dprintf(DEBUG, "Image Depth: %u\n", bpp);

    image_width = my_image->columns;
    image_height = my_image->rows;

    switch (stype)
    {
    case SHRINK:
        if(my_image->columns > width )
            image_width = width;

        if(my_image->rows > depth )
            image_height = depth;
        break;

    case SCALE_DOWN:
    {
        double aspect = (double)my_image->columns/(double)my_image->rows;

        if (my_image->columns > my_image->rows)
        {
            if(my_image->columns > width )
            {
                image_width = width;
                image_height = (double)image_width/aspect;
            }

            if(image_height > depth )
            {
                image_height = depth;
                image_width = (double)image_height * aspect;
            }
        }
        else
        {
            if(my_image->rows > depth )
            {
                image_height = depth;
                image_width = (double)image_height * aspect;
            }

            if(image_width > width )
            {
                image_width = width;
                image_height = (double)image_width/aspect;
            }
        }

        break;
    }
    case EXPAND:
        image_width = width;
        image_height = depth;
        break;

    case SCALE_UP:
    {
        double aspect = (double)my_image->columns/(double)my_image->rows;

        if (my_image->columns > my_image->rows)
        {
            image_width = width;
            image_height = (double)image_width/aspect;

            if(image_height > depth )
            {
                image_height = depth;
                image_width = (double)image_height * aspect;
            }
        }
        else
        {
            image_height = depth;
            image_width = (double)image_height * aspect;

            if(image_width > width )
            {
                image_width = width;
                image_height = (double)image_width/aspect;
            }
        }

        break;
    }
    }
        
    if ( my_image->columns != image_width || my_image->rows != image_height ) {
        resized_image = SampleImage(my_image, image_width, image_height, &exception);
        if ( exception.severity != UndefinedException ) {
#if MAGICK_VERSION >= 6
            CatchException(&exception);
#else
            CatchImageException(my_image);
#endif
        }
    }

    /* Centre the image */
    if ( x0 == -1 ) {
        x_offset = (width / 2 ) - (image_width / 2);
        if ( x_offset < 0 ) {
            x_offset = 0;
        }
    } else {
        x_offset = x0;
    }

    if ( y0 == -1 ) {
        y_offset = (depth / 2 ) - (image_height / 2);
        if ( y_offset < 0 ) {
            y_offset = 0;
        }
    } else {
        y_offset = y0;
    }

    if(resized_image) {
        pixels = AcquireImagePixels(resized_image, 0, 0, image_width, image_height, &exception);
    } else {
        pixels = AcquireImagePixels(my_image, 0, 0, image_width, image_height, &exception);
    }


    if ( exception.severity != UndefinedException ) {
#if MAGICK_VERSION >= 6
        CatchException(&exception);
#else
        CatchImageException(image);
#endif
    }

    printf("%d %d %d %d\n",image_height,image_width,x_offset,y_offset);

    for(y = 0 ; y < image_height ; y++ ) {
        for(x = 0 ; x < image_width ; x++ ) {
            switch(bpp) {
            case 8:
                rgb =  ((pixels->opacity & 0xFF) << 24 ) +  ((pixels->red & 0xFF)<< 16) + ((pixels->green & 0xFF) << 8) + (pixels->blue & 0xFF);
                break;
            default:
                rgb =  ( pixels->opacity << 24) + (pixels->red << 16) + (pixels->green << 8) + (pixels->blue);
                break;
            }

            surface_set_pixel(surface, x + x_offset, y + y_offset, rgb);
            ++pixels;
        }
    }

    if(resized_image) {
        DestroyImage(resized_image);
    }

    if ( my_image != image ) {
        DestroyImage(my_image);
    }

    DestroyExceptionInfo(&exception);
    return 0;
}
#endif

int mvp_image_display(surface_t *surface,char *filename, int x0, int y0, int width, int depth, int rotate, mvp_scale_method_t stype)
{
#ifdef HAVE_MAGICK
    ExceptionInfo exception;
    Image *image;
    ImageInfo *image_info;

    GetExceptionInfo(&exception);

    image_info = CloneImageInfo((ImageInfo *)NULL);
    (void)strcpy(image_info->filename, filename);
    image = ReadImage(image_info, &exception);

    if ( image == (Image *) NULL ) {
        DestroyImageInfo(image_info);
        DestroyExceptionInfo(&exception);
        DestroyMagick();
        return -1;
    }

    if ( exception.severity != UndefinedException ) {
#if MAGICK_VERSION >= 6
        CatchException(&exception);
#else
        CatchImageException(image);
#endif
    }

    mvp_CopyImageToSurface(surface, image, x0, y0, width, depth, rotate, stype);

    DestroyImage(image);
    DestroyImageInfo(image_info);
    DestroyExceptionInfo(&exception);
    return 0;
#else  /* !HAVE_MAGICK */
    return -1;
#endif
}

int mvp_buffer_display(surface_t *surface,void *buffer, size_t buffer_len, int x0, int y0, int width, int depth, int rotate, mvp_scale_method_t stype)
{
#ifdef HAVE_MAGICK
    ExceptionInfo exception;
    Image *image;
    ImageInfo *image_info;

    GetExceptionInfo(&exception);

    image_info = CloneImageInfo((ImageInfo *)NULL);
    image = BlobToImage(image_info, buffer, buffer_len, &exception);

    if ( image == (Image *) NULL ) {
        DestroyImageInfo(image_info);
        DestroyExceptionInfo(&exception);
        DestroyMagick();
        return -1;
    }

    if ( exception.severity != UndefinedException ) {
#if MAGICK_VERSION >= 6
        CatchException(&exception);
#else
        CatchImageException(image);
#endif
    }

    mvp_CopyImageToSurface(surface, image, x0, y0, width, depth, rotate, stype);

    DestroyImage(image);
    DestroyImageInfo(image_info);
    DestroyExceptionInfo(&exception);
    return 0;
#else  /* !HAVE_MAGICK */
    return -1;
#endif
}

/*
 * Local Variables:
 *  indent-tabs-mode:nil
 *  require-final-newline:t
 *  c-basic-offset: 4
 * End:
 */
