/*
 *  ratlibimage.c
 *  RatLib
 *
 *  Created by Curtis Jones on 2009.11.13.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "ratlibimage.h"
#include "logger.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 *
 *
 */
int
ratlibimage_init (ratlibimage_t *image, opool_t *pool, const uint8_t *data, uint32_t options, uint32_t bpp, uint32_t width, uint32_t height)
{
	int error, count, i;
	pixel_t *pixel;
	
	if (unlikely(image == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null ratlibimage_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(data == NULL))
		LOG_ERROR_AND_RETURN(-2, "%s.. null data\n", __PRETTY_FUNCTION__);
	
	if (unlikely(bpp == 0 || bpp > 4))
		LOG_ERROR_AND_RETURN(-3, "%s.. invalid bpp (bytes per pixel)\n", __PRETTY_FUNCTION__);
	
	if (unlikely(width == 0))
		LOG_ERROR_AND_RETURN(-4, "%s.. invalid width (0)\n", __PRETTY_FUNCTION__);
	
	if (unlikely(height == 0))
		LOG_ERROR_AND_RETURN(-5, "%s.. invalid height (0)\n", __PRETTY_FUNCTION__);
	
	if (unlikely(0 != (error = cobject_init(&image->cobject, (cobject_destroy_func)ratlibimage_destroy, pool))))
		LOG_ERROR_AND_RETURN(-101, "%s.. failed to cobject_init, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	image->width = width;
	image->height = height;
	image->size = sizeof(pixel_t) * width * height;
	
	if (unlikely(NULL == (image->data = malloc(image->size))))
		LOG_ERROR_AND_RETURN(-102, "%s.. failed to malloc(%d), %s\n", __PRETTY_FUNCTION__, image->size, strerror(errno));
	
	memset(image->data, 0, image->size);
	
	pixel = image->data;
	count = width * height;
	
	for (i = 0; i < count; ++i, ++pixel) {
		pixel->r = *data; data++;
		pixel->g = *data; data++;
		pixel->b = *data; data++;
		pixel->a = 0;
	}
	
	return 0;
}

/**
 *
 *
 */
int
ratlibimage_destroy (ratlibimage_t *image)
{
	int error;
	
	if (unlikely(image == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null ratlibimage_t\n", __PRETTY_FUNCTION__);
	
	if (image->data != NULL) {
		free(image->data);
		image->data = NULL;
	}
	
	if (unlikely(0 != (error = cobject_destroy(&image->cobject))))
		LOG_ERROR_AND_RETURN(-101, "%s.. failed to cobject_destroy, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	return 0;
}

/**
 *
 *
 */
inline pixel_t*
ratlibimage_pixelatpoint (ratlibimage_t *image, ratlibpoint_t *point)
{
	if (unlikely(image == NULL))
		LOG_ERROR_AND_RETURN(NULL, "%s.. null ratlibimage_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(point == NULL))
		LOG_ERROR_AND_RETURN(NULL, "%s.. null ratlibpoint_t\n", __PRETTY_FUNCTION__);
	
	return image->data + (point->x + (point->y * image->width));
}

/**
 *
 *
 */
inline ratlibimage_t*
ratlibimage_retain (ratlibimage_t *image)
{
	if (unlikely(image == NULL))
		LOG_ERROR_AND_RETURN(NULL, "%s.. null ratlibimage_t\n", __PRETTY_FUNCTION__);
	
	return (ratlibimage_t*)cobject_retain(&image->cobject);
}

/**
 *
 *
 */
inline void
ratlibimage_release (ratlibimage_t *image)
{
	if (unlikely(image == NULL))
		LOG_ERROR_AND_RETURN(, "%s.. null ratlibimage_t\n", __PRETTY_FUNCTION__);
	
	cobject_release(&image->cobject);
}

/**
 *
 *
 */
inline int
pixel_equals (pixel_t *p1, pixel_t *p2)
{
	return p1->r == p2->r && p1->g == p2->g && p1->b == p2->b && p1->a == p2->a;
}

/**
 *
 *
 */
inline int
pixel_similar (pixel_t *p1, pixel_t *p2)
{
	return (abs(p1->r - p2->r) < 10) &&
	(abs(p1->g - p2->g) < 10) &&
	(abs(p1->b - p2->b) < 10);
}
