/*-
 * Copyright (c) 1999,2000 Qube Software, Ltd.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of the source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Any redistribution solely in binary form must conspicuously
 *    reproduce the following disclaimer in documentation provided with the
 *    binary redistribution.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'', WITHOUT ANY WARRANTIES, EXPRESS
 * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  LICENSOR SHALL
 * NOT BE LIABLE FOR ANY LOSS OR DAMAGES RESULTING FROM THE USE OF THIS
 * SOFTWARE, EITHER ALONE OR IN COMBINATION WITH ANY OTHER SOFTWARE.
 * 
 * 	$Id: image.h,v 1.15 2000/04/20 16:15:51 n_hibma Exp $
 */

#ifndef __image_h__
#define __image_h__

#ifndef IMAGE_BEGIN
#define IMAGE_BEGIN	namespace Image {
#define IMAGE_END	}
#endif

#include "linkage.h"

#ifdef _MSC_VER
#pragma warning(disable : 4786) // truncated debug info
#endif

#include "utils.h"

IMAGE_BEGIN

using namespace Maths;
using namespace Utils;

struct EXPORT_QIMAGE Format
{
    // Some popular formats
    enum Type {
	RGB565,
	RGBA5551,
	RGBA4444,
	RGB888,
	RGBA8888,
	BGR888,
	GREY8
    };
    
    struct Channel {
			Channel(unsigned int o, unsigned int w)
			    : offset(o), width(w) {
			    mask = ((1U << w) - 1) << o;
			}
			Channel() {}

	float		get(unsigned int pixel) const;
	unsigned int	put(unsigned int pixel, float v) const;

	unsigned char	offset;
	unsigned char	width;
	unsigned int	mask;
    };

    // Constructors
			Format(Type);
			Format(unsigned int ro, unsigned int rw,
			       unsigned int go, unsigned int gw,
			       unsigned int bo, unsigned int bw);
			Format(unsigned int ro, unsigned int rw,
			       unsigned int go, unsigned int gw,
			       unsigned int bo, unsigned int bw,
			       unsigned int ao, unsigned int aw);

    // Features
    friend EXPORT_QIMAGE
    unsigned int	convert(unsigned int pixel,
				const Format& from,
				const Format& to);
    float		r(unsigned int pixel) const;
    float		g(unsigned int pixel) const;
    float		b(unsigned int pixel) const;
    float		a(unsigned int pixel) const;
    unsigned int	r(unsigned int pixel, float v) const;
    unsigned int	g(unsigned int pixel, float v) const;
    unsigned int	b(unsigned int pixel, float v) const;
    unsigned int	a(unsigned int pixel, float v) const;

    struct Channel	r_, g_, b_, a_;
};

/**
 * A Pixmap is a 2 dimensional array of pixels. The pixels are stored
 * in a variety of formats, selected when the pixmap is created. The
 * layout of the image in memory is such that the first pixel in
 * memory represents the bottom left of the image for consistency with 
 * QDraw textures.
 */
struct EXPORT_QIMAGE Pixmap : public Utils::Object
{
    /**
     * Construct a Pixmap given its dimensions using a well-defined
     * image format. The pack argument specifies how consecutive
     * scanlines are packed in memory.
     */
			Pixmap(unsigned int width,
			       unsigned int height,
			       unsigned int depth,
			       Format::Type format,
			       unsigned int pack = 32);

    /**
     * Construct a Pixmap given its dimensions using a user-defined
     * image format.
     */
			Pixmap(unsigned int width,
			       unsigned int height,
			       unsigned int depth,
			       const Format& format,
			       unsigned int pack = 32);

    /**
     * Load an image. This is pretty weak and should be
     * decomposed into i/o handlers and format handlers so that we can
     * load images from the network or from a database.
     */
    static Pixmap*      load(const char* file,
			     Format::Type,
			     unsigned int pack);

    /**
     * Load a BMP format image.
     */
    static Pixmap*      loadBMP(const char* file,
                                Format::Type,
                                unsigned int pack);

    /**
     * Load a JPEG format image.
     */
    static Pixmap*      loadJPEG(const char* file,
				 Format::Type,
				 unsigned int pack);

    /**
     * Load a PNG format image.
     */
    static Pixmap*      loadPNG(const char* file,
				Format::Type,
				unsigned int pack);

    /**
     * Load a TGA format image.
     */
    static Pixmap*      loadTGA(const char* file,
				Format::Type,
				unsigned int pack);

    /**
     * Unpack the data of type format into a pixmap
     */
    static Pixmap*      unpack(const unsigned char[],
			       const char* mimeType,
			       Format::Type, unsigned int pack);
    
    static Pixmap*	unpackJPEG(const unsigned char[],
				   Format::Type, unsigned int pack);
    static Pixmap*	unpackTGA(const unsigned char[],
				  Format::Type, unsigned int pack);
    static Pixmap*	unpackBMP(const unsigned char[],
				  Format::Type, unsigned int pack);

    /**
     * Destroy a pixmap and reclaim resources.
     */
			~Pixmap();

    /**
     * Return the dimensions of the image (width, height, depth).
     */
    Maths::Vec3ui	extent() const { return extent_; }

    /**
     * Return a description of the image format.
     */
    const Format&	format() const { return format_; }

    /**
     * Get at the bits - needed by GeomCache to rebuild a bitmap
     * from a stream.
     */
    void *              bits() const { return bits_; }

    /**
     * Get a single pixel from the image.
     */
    unsigned int	get(unsigned int x, unsigned int y) const;

    /**
     * Set a pixel in the image to a given value.
     */
    void		put(unsigned int x, unsigned int y,
			    unsigned int pixel);

    /**
     * Return the address of a pixel in the image.
     */
    void*		address(unsigned int x, unsigned int y);

    /**
     * Copy a rectangle from a source image to a destination image,
     * without scaling. Pixels in the source image are converted to
     * the format of the destination image.
     */
    friend EXPORT_QIMAGE
    void		copy(const Pixmap& from,
			     const Maths::Box2ui& fromRect,
			     Pixmap& to,
			     const Maths::Vec2ui& toCoord);

    /**
     * Copy a rectangle from a source image to a destination image,
     * scaling the source rectangle to fit into the destination
     * rectangle. Pixels in the source image are converted to the
     * format of the destination image.
     */
    friend EXPORT_QIMAGE
    void		copy(const Pixmap& from,
			     const Maths::Box2ui& fromRect,
			     Pixmap& to,
			     const Maths::Box2ui& toRect);
    

private:
    Maths::Vec3ui	extent_;	// (width, height, depth)
    unsigned int	stride_;	// bytes per line
    Format		format_;	// what kind of image
    void*		bits_;		// image data
};

IMAGE_END

#endif // __image_h__

// Local Variables:
// mode: c++
// End:
