/*
 *  libpipi       Proper image processing implementation 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.
 */

/*
 * pixels.c: pixel-level image manipulation
 */

#include "config.h"
#include "common.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <math.h>

#include "pipi.h"
#include "pipi_internals.h"

#define C2I(p) (pow(((double)p)/255., 2.2))
#define I2C(p) ((int)255.999*pow(((double)p), 1./2.2))

/* Return a direct pointer to an image's pixels. */
pipi_pixels_t *pipi_getpixels(pipi_image_t *img, pipi_format_t type)
{
    size_t bytes = 0;
    int x, y, i;

    if(type < 0 || type >= PIPI_PIXELS_MAX)
        return NULL;

    if(img->last_modified == type)
        return &img->p[type];

    /* Allocate pixels if necessary */
    if(!img->p[type].pixels)
    {
        switch(type)
        {
        case PIPI_PIXELS_RGBA32:
            bytes = img->w * img->h * 4 * sizeof(uint8_t);
            break;
        case PIPI_PIXELS_RGBA_F:
            bytes = img->w * img->h * 4 * sizeof(float);
            break;
        default:
            return NULL;
        }

        img->p[type].pixels = malloc(bytes);
    }

    /* Convert pixels */
    if(img->last_modified == PIPI_PIXELS_RGBA32
                  && type == PIPI_PIXELS_RGBA_F)
    {
        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA32].pixels;
        float *dest = (float *)img->p[type].pixels;

        for(y = 0; y < img->h; y++)
            for(x = 0; x < img->w; x++)
                for(i = 0; i < 4; i++)
                    dest[4 * (y * img->w + x) + i]
                        = C2I(src[4 * (y * img->w + x) + i]);
    }
    else if(img->last_modified == PIPI_PIXELS_RGBA_F
                       && type == PIPI_PIXELS_RGBA32)
    {
        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
        uint8_t *dest = (uint8_t *)img->p[type].pixels;

        for(y = 0; y < img->h; y++)
            for(x = 0; x < img->w; x++)
                for(i = 0; i < 4; i++)
                    dest[4 * (y * img->w + x) + i]
                        = I2C(src[4 * (y * img->w + x) + i]);
    }
    else
    {
        memset(img->p[type].pixels, 0, bytes);
    }

    img->last_modified = type;

    return &img->p[type];
}