//
//  libpipi       Pathetic image processing interface library
//  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
//                All Rights Reserved
//
//  $Id$
//
//  This library is free software. It comes without any warranty, to
//  the extent permitted by applicable law. You can redistribute it
//  and/or modify it under the terms of the Do What The Fuck You Want
//  To Public License, Version 2, as published by Sam Hocevar. See
//  http://sam.zoy.org/wtfpl/COPYING for more details.
//

using System;
using System.Runtime.InteropServices;
using System.Security;

namespace Pipi
{
    public class Picture
    {
        private IntPtr _picture;
        private string _filename;

        public string FileName
        {
            get { return _filename; }
        }

        private Picture(IntPtr p)
        {
            _picture = p;
        }

        [DllImport("libpipi-0.dll", CallingConvention=CallingConvention.Cdecl),
         SuppressUnmanagedCodeSecurity]
        private static extern int pipi_free(IntPtr img);
        ~Picture()
        {
            pipi_free(_picture);
        }

        [DllImport("libpipi-0.dll", CallingConvention=CallingConvention.Cdecl),
         SuppressUnmanagedCodeSecurity]
        private static extern IntPtr pipi_load(string s);
        public static Picture Load(string s)
        {
            IntPtr p = pipi_load(s);
            if(p == IntPtr.Zero)
                return null;

            Picture ret = new Picture(p);
            ret._filename = s;
            return ret;
        }

        [DllImport("libpipi-0.dll", CallingConvention=CallingConvention.Cdecl),
         SuppressUnmanagedCodeSecurity]
        private static extern int pipi_save(IntPtr p, string s);
        public int Save(string s)
        {
            return pipi_save(_picture, s);
        }

        [DllImport("libpipi-0.dll", CallingConvention=CallingConvention.Cdecl),
         SuppressUnmanagedCodeSecurity]
        private static extern int pipi_get_image_width(IntPtr img);
        public int Width
        {
            get { return pipi_get_image_width(_picture); }
        }

        [DllImport("libpipi-0.dll", CallingConvention=CallingConvention.Cdecl),
         SuppressUnmanagedCodeSecurity]
        private static extern int pipi_get_image_height(IntPtr img);
        public int Height
        {
            get { return pipi_get_image_height(_picture); }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PixelsStruct
        {
            public IntPtr pixels;
            public Int32 w, h, pitch, bpp;
            public Int64 bytes;
        }

        [DllImport("libpipi-0.dll", CallingConvention=CallingConvention.Cdecl),
         SuppressUnmanagedCodeSecurity]
        private static extern IntPtr pipi_getpixels(IntPtr img, int type);
        public byte[] GetPixels(int w, int h, int x, int y)
        {
            byte[] array = new byte[w * h * 4];
            IntPtr pixels = pipi_getpixels(_picture, 0);
            PixelsStruct p;
            Int64 address;

            p = (PixelsStruct)Marshal.PtrToStructure(pixels,
                                                     typeof(PixelsStruct));
            address = p.pixels.ToInt64();

            unsafe
            {
                for(int j = 0; j < h; j++)
                {
                    Marshal.Copy((IntPtr)(address + ((j + y) * p.w + x) * 4),
                                 array, j * w * 4, w * 4);
                    for(int i = 0; i < w; i++)
                    {
                        byte c = array[j * w * 4 + i * 4];
                        array[j * w * 4 + i * 4] = array[j * w * 4 + i * 4 + 2];
                        array[j * w * 4 + i * 4 + 2] = c;
                    }
                }
            }

            return array;
        }
    }
}