You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
5.4 KiB
193 lines
5.4 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Image Library
|
|
* --------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Image library.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deImage.h"
|
|
#include "deMemory.h"
|
|
#include "deInt32.h"
|
|
#include "deMath.h"
|
|
|
|
static int deImageFormat_getBytesPerPixel (deImageFormat format)
|
|
{
|
|
DE_ASSERT(format == DE_IMAGEFORMAT_XRGB8888 || format == DE_IMAGEFORMAT_ARGB8888);
|
|
DE_UNREF(format);
|
|
return 4;
|
|
}
|
|
|
|
static void* getPixelAddress (const deImage* image, int x, int y)
|
|
{
|
|
int offset = ((y*image->width) + x) * deImageFormat_getBytesPerPixel(image->format);
|
|
DE_ASSERT(deInBounds32(x, 0, image->width));
|
|
DE_ASSERT(deInBounds32(y, 0, image->height));
|
|
return (void*)((deUint8*)image->pixels + offset);
|
|
}
|
|
|
|
deImage* deImage_create (int width, int height, deImageFormat format)
|
|
{
|
|
deImage* image = DE_NEW(deImage);
|
|
int bpp = deImageFormat_getBytesPerPixel(format);
|
|
if (!image)
|
|
return DE_NULL;
|
|
|
|
image->width = width;
|
|
image->height = height;
|
|
image->format = format;
|
|
image->pixels = deMalloc(width * height * bpp);
|
|
if (!image->pixels)
|
|
{
|
|
deFree(image);
|
|
return DE_NULL;
|
|
}
|
|
memset(image->pixels, 0, width * height * bpp);
|
|
|
|
return image;
|
|
}
|
|
|
|
void deImage_destroy (deImage* image)
|
|
{
|
|
deFree(image->pixels);
|
|
deFree(image);
|
|
}
|
|
|
|
deARGB deImage_getPixel (const deImage* image, int x, int y)
|
|
{
|
|
void* addr = getPixelAddress(image, x, y);
|
|
switch (image->format)
|
|
{
|
|
case DE_IMAGEFORMAT_XRGB8888: return *(deARGB*)addr;
|
|
case DE_IMAGEFORMAT_ARGB8888: return *(deARGB*)addr;
|
|
default:
|
|
DE_FATAL("deImage_getPixel(): invalid format");
|
|
return deARGB_black();
|
|
}
|
|
}
|
|
|
|
void deImage_setPixel (deImage* image, int x, int y, deARGB argb)
|
|
{
|
|
void* addr = getPixelAddress(image, x, y);
|
|
switch (image->format)
|
|
{
|
|
case DE_IMAGEFORMAT_XRGB8888: *(deARGB*)addr = argb; break;
|
|
case DE_IMAGEFORMAT_ARGB8888: *(deARGB*)addr = argb; break;
|
|
default:
|
|
DE_FATAL("deImage_getPixel(): invalid format");
|
|
}
|
|
}
|
|
|
|
deImage* deImage_convertFormat (const deImage* image, deImageFormat format)
|
|
{
|
|
int width = image->width;
|
|
int height = image->height;
|
|
deImage* converted = deImage_create(width, height, format);
|
|
if (!converted)
|
|
return DE_NULL;
|
|
|
|
if (format == image->format)
|
|
memcpy(converted->pixels, image->pixels, width * height * deImageFormat_getBytesPerPixel(format));
|
|
else
|
|
{
|
|
int x, y;
|
|
for (y = 0; y < height; y++)
|
|
for (x = 0; x < width; x++)
|
|
deImage_setPixel(converted, x, y, deImage_getPixel(image, x, y));
|
|
}
|
|
|
|
return converted;
|
|
}
|
|
|
|
deImage* deImage_scale (const deImage* srcImage, int dstWidth, int dstHeight)
|
|
{
|
|
int srcWidth = srcImage->width;
|
|
int srcHeight = srcImage->height;
|
|
deImage* result = deImage_create(dstWidth, dstHeight, srcImage->format);
|
|
int x, y;
|
|
|
|
for (y = 0; y < dstHeight; y++)
|
|
{
|
|
for (x = 0; x < dstWidth; x++)
|
|
{
|
|
float xFloat = ((float)x + 0.5f) / (float)dstWidth * (float)srcImage->width - 0.5f;
|
|
float yFloat = ((float)y + 0.5f) / (float)dstHeight * (float)srcImage->height - 0.5f;
|
|
int xFixed = deFloorFloatToInt32(xFloat * 256.0f);
|
|
int yFixed = deFloorFloatToInt32(yFloat * 256.0f);
|
|
int xFactor = (xFixed & 0xFF);
|
|
int yFactor = (yFixed & 0xFF);
|
|
int f00 = ((256-xFactor) * (256-yFactor)) >> 8;
|
|
int f10 = ((256-xFactor) * yFactor) >> 8;
|
|
int f01 = (xFactor * (256-yFactor)) >> 8;
|
|
int f11 = (xFactor * yFactor) >> 8;
|
|
int x0 = (xFixed >> 8);
|
|
int y0 = (yFixed >> 8);
|
|
int x1 = deClamp32(x0+1, 0, srcWidth-1);
|
|
int y1 = deClamp32(y0+1, 0, srcHeight-1);
|
|
DE_ASSERT(deInBounds32(x0, 0, srcWidth));
|
|
DE_ASSERT(deInBounds32(y0, 0, srcHeight));
|
|
|
|
/* Filtering. */
|
|
{
|
|
deARGB p00 = deImage_getPixel(srcImage, x0, y0);
|
|
deARGB p10 = deImage_getPixel(srcImage, x1, y0);
|
|
deARGB p01 = deImage_getPixel(srcImage, x0, y1);
|
|
deARGB p11 = deImage_getPixel(srcImage, x1, y1);
|
|
deARGB pix = deARGB_add(deARGB_add(deARGB_multiply(p00, f00), deARGB_multiply(p10, f10)),
|
|
deARGB_add(deARGB_multiply(p01, f01), deARGB_multiply(p11, f11)));
|
|
deImage_setPixel(result, x, y, pix);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void deImage_copyToUint8RGBA (const deImage* image, deUint8* pixels)
|
|
{
|
|
int width = image->width;
|
|
int height = image->height;
|
|
int x,y;
|
|
|
|
for (y = 0; y < height; y++)
|
|
for (x = 0; x < width; x++)
|
|
{
|
|
deARGB pixel = deImage_getPixel(image, x, y);
|
|
int ndx = (y * width) + x;
|
|
pixels[4*ndx+0] = (deUint8)deARGB_getRed(pixel);
|
|
pixels[4*ndx+1] = (deUint8)deARGB_getGreen(pixel);
|
|
pixels[4*ndx+2] = (deUint8)deARGB_getBlue(pixel);
|
|
pixels[4*ndx+3] = (deUint8)deARGB_getAlpha(pixel);
|
|
}
|
|
}
|
|
|
|
void* deImage_getPixelPtr (const deImage* image)
|
|
{
|
|
return image->pixels;
|
|
}
|
|
|
|
int deImage_getWidth (const deImage* image)
|
|
{
|
|
return image->width;
|
|
}
|
|
|
|
int deImage_getHeight (const deImage* image)
|
|
{
|
|
return image->height;
|
|
}
|