13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Image Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * --------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Image library.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deImage.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int deImageFormat_getBytesPerPixel (deImageFormat format)
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(format == DE_IMAGEFORMAT_XRGB8888 || format == DE_IMAGEFORMAT_ARGB8888);
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(format);
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 4;
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void* getPixelAddress (const deImage* image, int x, int y)
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int offset = ((y*image->width) + x) * deImageFormat_getBytesPerPixel(image->format);
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(deInBounds32(x, 0, image->width));
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(deInBounds32(y, 0, image->height));
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (void*)((deUint8*)image->pixels + offset);
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_create (int width, int height, deImageFormat format)
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deImage*	image	= DE_NEW(deImage);
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			bpp		= deImageFormat_getBytesPerPixel(format);
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!image)
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	image->width	= width;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	image->height	= height;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	image->format	= format;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	image->pixels	= deMalloc(width * height * bpp);
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!image->pixels)
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(image);
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	memset(image->pixels, 0, width * height * bpp);
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return image;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deImage_destroy (deImage* image)
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(image->pixels);
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(image);
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeARGB deImage_getPixel (const deImage* image, int x, int y)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void* addr = getPixelAddress(image, x, y);
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (image->format)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_IMAGEFORMAT_XRGB8888:	return *(deARGB*)addr;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_IMAGEFORMAT_ARGB8888:	return *(deARGB*)addr;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!"deImage_getPixel(): invalid format");
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return deARGB_black();
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deImage_setPixel (deImage* image, int x, int y, deARGB argb)
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void* addr = getPixelAddress(image, x, y);
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (image->format)
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_IMAGEFORMAT_XRGB8888:	*(deARGB*)addr = argb;	break;
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_IMAGEFORMAT_ARGB8888:	*(deARGB*)addr = argb;	break;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!"deImage_getPixel(): invalid format");
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_convertFormat (const deImage* image, deImageFormat format)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			width		= image->width;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			height		= image->height;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deImage*	converted	= deImage_create(width, height, format);
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!converted)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (format == image->format)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		memcpy(converted->pixels, image->pixels, width * height * deImageFormat_getBytesPerPixel(format));
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int x, y;
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (y = 0; y < height; y++)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (x = 0; x < width; x++)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deImage_setPixel(converted, x, y, deImage_getPixel(image, x, y));
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return converted;
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_scale (const deImage* srcImage, int dstWidth, int dstHeight)
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			srcWidth	= srcImage->width;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			srcHeight	= srcImage->height;
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deImage*	result		= deImage_create(dstWidth, dstHeight, srcImage->format);
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			x, y;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (y = 0; y < dstHeight; y++)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (x = 0; x < dstWidth; x++)
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xFloat	= (float)(x + 0.5f) / (float)dstWidth * (float)srcImage->width - 0.5f;
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yFloat	= (float)(y + 0.5f) / (float)dstHeight * (float)srcImage->height - 0.5f;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		xFixed	= deFloorFloatToInt32(xFloat * 256.0f);
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		yFixed	= deFloorFloatToInt32(yFloat * 256.0f);
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		xFactor	= (xFixed & 0xFF);
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		yFactor	= (yFixed & 0xFF);
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		f00		= ((256-xFactor) * (256-yFactor)) >> 8;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		f10		= ((256-xFactor) * yFactor) >> 8;
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		f01		= (xFactor * (256-yFactor)) >> 8;
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		f11		= (xFactor * yFactor) >> 8;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		x0		= (xFixed >> 8);
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		y0		= (yFixed >> 8);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		x1		= deClamp32(x0+1, 0, srcWidth-1);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		y1		= deClamp32(y0+1, 0, srcHeight-1);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(deInBounds32(x0, 0, srcWidth));
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(deInBounds32(y0, 0, srcHeight));
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* Filtering. */
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deARGB p00 = deImage_getPixel(srcImage, x0, y0);
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deARGB p10 = deImage_getPixel(srcImage, x1, y0);
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deARGB p01 = deImage_getPixel(srcImage, x0, y1);
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deARGB p11 = deImage_getPixel(srcImage, x1, y1);
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deARGB pix = deARGB_add(deARGB_add(deARGB_multiply(p00, f00), deARGB_multiply(p10, f10)),
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										deARGB_add(deARGB_multiply(p01, f01), deARGB_multiply(p11, f11)));
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deImage_setPixel(result, x, y, pix);
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deImage_copyToUint8RGBA (const deImage* image, deUint8* pixels)
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int width	= image->width;
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int height	= image->height;
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int x,y;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (y = 0; y < height; y++)
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (x = 0; x < width; x++)
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deARGB	pixel	= deImage_getPixel(image, x, y);
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		ndx		= (y * width) + x;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pixels[4*ndx+0] = (deUint8)deARGB_getRed(pixel);
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pixels[4*ndx+1] = (deUint8)deARGB_getGreen(pixel);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pixels[4*ndx+2] = (deUint8)deARGB_getBlue(pixel);
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pixels[4*ndx+3] = (deUint8)deARGB_getAlpha(pixel);
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid* deImage_getPixelPtr (const deImage* image)
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return image->pixels;
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deImage_getWidth (const deImage* image)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return image->width;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deImage_getHeight (const deImage* image)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return image->height;
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
193