mirror of
https://github.com/love2d/love-android.git
synced 2026-08-16 00:02:31 +02:00
308 lines
7.9 KiB
C
308 lines
7.9 KiB
C
//-----------------------------------------------------------------------------
|
|
//
|
|
// ImageLib Utility Sources
|
|
// Copyright (C) 2000-2008 by Denton Woods
|
|
// Last modified: 12/27/2008
|
|
//
|
|
// Filename: src-ILU/src/ilu_scale.c
|
|
//
|
|
// Description: Scales an image.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#include "ilu_internal.h"
|
|
#include "ilu_states.h"
|
|
|
|
|
|
ILboolean ILAPIENTRY iluEnlargeImage(ILfloat XDim, ILfloat YDim, ILfloat ZDim)
|
|
{
|
|
if (XDim <= 0.0f || YDim <= 0.0f || ZDim <= 0.0f) {
|
|
ilSetError(ILU_INVALID_PARAM);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
iluCurImage = ilGetCurImage();
|
|
return iluScale((ILuint)(iluCurImage->Width * XDim), (ILuint)(iluCurImage->Height * YDim),
|
|
(ILuint)(iluCurImage->Depth * ZDim));
|
|
}
|
|
|
|
|
|
ILimage *iluScale1D_(ILimage *Image, ILimage *Scaled, ILuint Width);
|
|
ILimage *iluScale2D_(ILimage *Image, ILimage *Scaled, ILuint Width, ILuint Height);
|
|
ILimage *iluScale3D_(ILimage *Image, ILimage *Scaled, ILuint Width, ILuint Height, ILuint Depth);
|
|
|
|
|
|
ILboolean ILAPIENTRY iluScale(ILuint Width, ILuint Height, ILuint Depth)
|
|
{
|
|
ILimage *Temp;
|
|
ILboolean UsePal;
|
|
ILenum PalType;
|
|
ILenum Origin;
|
|
|
|
iluCurImage = ilGetCurImage();
|
|
if (iluCurImage == NULL) {
|
|
ilSetError(ILU_ILLEGAL_OPERATION);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
if (iluCurImage->Width == Width && iluCurImage->Height == Height && iluCurImage->Depth == Depth)
|
|
return IL_TRUE;
|
|
|
|
// A parameter of 0 is not valid. Let's just assume that the user wanted a value of 1 instead.
|
|
if (Width == 0) Width = 1;
|
|
if (Height == 0) Height = 1;
|
|
if (Depth == 0) Depth = 1;
|
|
|
|
if ((iluCurImage->Width<Width) || (iluCurImage->Height<Height)) // only do special scale if there is some zoom?
|
|
{
|
|
switch (iluFilter)
|
|
{
|
|
case ILU_SCALE_BOX:
|
|
case ILU_SCALE_TRIANGLE:
|
|
case ILU_SCALE_BELL:
|
|
case ILU_SCALE_BSPLINE:
|
|
case ILU_SCALE_LANCZOS3:
|
|
case ILU_SCALE_MITCHELL:
|
|
|
|
iluCurImage = ilGetCurImage();
|
|
if (iluCurImage == NULL) {
|
|
ilSetError(ILU_ILLEGAL_OPERATION);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
// Not supported yet.
|
|
if (iluCurImage->Type != IL_UNSIGNED_BYTE ||
|
|
iluCurImage->Format == IL_COLOUR_INDEX ||
|
|
iluCurImage->Depth > 1) {
|
|
ilSetError(ILU_ILLEGAL_OPERATION);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
if (iluCurImage->Width > Width) // shrink width first
|
|
{
|
|
Origin = iluCurImage->Origin;
|
|
Temp = iluScale_(iluCurImage, Width, iluCurImage->Height, iluCurImage->Depth);
|
|
if (Temp != NULL) {
|
|
if (!ilTexImage(Temp->Width, Temp->Height, Temp->Depth, Temp->Bpp, Temp->Format, Temp->Type, Temp->Data)) {
|
|
ilCloseImage(Temp);
|
|
return IL_FALSE;
|
|
}
|
|
iluCurImage->Origin = Origin;
|
|
ilCloseImage(Temp);
|
|
}
|
|
}
|
|
else if (iluCurImage->Height > Height) // shrink height first
|
|
{
|
|
Origin = iluCurImage->Origin;
|
|
Temp = iluScale_(iluCurImage, iluCurImage->Width, Height, iluCurImage->Depth);
|
|
if (Temp != NULL) {
|
|
if (!ilTexImage(Temp->Width, Temp->Height, Temp->Depth, Temp->Bpp, Temp->Format, Temp->Type, Temp->Data)) {
|
|
ilCloseImage(Temp);
|
|
return IL_FALSE;
|
|
}
|
|
iluCurImage->Origin = Origin;
|
|
ilCloseImage(Temp);
|
|
}
|
|
}
|
|
|
|
return (ILboolean)iluScaleAdvanced(Width, Height, iluFilter);
|
|
}
|
|
}
|
|
|
|
|
|
Origin = iluCurImage->Origin;
|
|
UsePal = (iluCurImage->Format == IL_COLOUR_INDEX);
|
|
PalType = iluCurImage->Pal.PalType;
|
|
Temp = iluScale_(iluCurImage, Width, Height, Depth);
|
|
if (Temp != NULL) {
|
|
if (!ilTexImage(Temp->Width, Temp->Height, Temp->Depth, Temp->Bpp, Temp->Format, Temp->Type, Temp->Data)) {
|
|
ilCloseImage(Temp);
|
|
return IL_FALSE;
|
|
}
|
|
iluCurImage->Origin = Origin;
|
|
ilCloseImage(Temp);
|
|
if (UsePal) {
|
|
if (!ilConvertImage(IL_COLOUR_INDEX, IL_UNSIGNED_BYTE))
|
|
return IL_FALSE;
|
|
ilConvertPal(PalType);
|
|
}
|
|
return IL_TRUE;
|
|
}
|
|
|
|
return IL_FALSE;
|
|
}
|
|
|
|
|
|
ILAPI ILimage* ILAPIENTRY iluScale_(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth)
|
|
{
|
|
ILimage *Scaled, *CurImage, *ToScale;
|
|
ILenum Format, PalType;
|
|
|
|
CurImage = ilGetCurImage();
|
|
Format = Image->Format;
|
|
if (Format == IL_COLOUR_INDEX) {
|
|
ilSetCurImage(Image);
|
|
PalType = Image->Pal.PalType;
|
|
ToScale = iConvertImage(iluCurImage, ilGetPalBaseType(Image->Pal.PalType), iluCurImage->Type);
|
|
}
|
|
else {
|
|
ToScale = Image;
|
|
}
|
|
|
|
// So we don't replicate this 3 times (one in each iluScalexD_() function.
|
|
Scaled = (ILimage*)icalloc(1, sizeof(ILimage));
|
|
if (ilCopyImageAttr(Scaled, ToScale) == IL_FALSE) {
|
|
ilCloseImage(Scaled);
|
|
if (ToScale != Image)
|
|
ilCloseImage(ToScale);
|
|
ilSetCurImage(CurImage);
|
|
return NULL;
|
|
}
|
|
if (ilResizeImage(Scaled, Width, Height, Depth, ToScale->Bpp, ToScale->Bpc) == IL_FALSE) {
|
|
ilCloseImage(Scaled);
|
|
if (ToScale != Image)
|
|
ilCloseImage(ToScale);
|
|
ilSetCurImage(CurImage);
|
|
return NULL;
|
|
}
|
|
|
|
if (Height <= 1 && Image->Height <= 1) {
|
|
iluScale1D_(ToScale, Scaled, Width);
|
|
}
|
|
if (Depth <= 1 && Image->Depth <= 1) {
|
|
iluScale2D_(ToScale, Scaled, Width, Height);
|
|
}
|
|
else {
|
|
iluScale3D_(ToScale, Scaled, Width, Height, Depth);
|
|
}
|
|
|
|
if (Format == IL_COLOUR_INDEX) {
|
|
//ilSetCurImage(Scaled);
|
|
//ilConvertImage(IL_COLOUR_INDEX);
|
|
ilSetCurImage(CurImage);
|
|
ilCloseImage(ToScale);
|
|
}
|
|
|
|
return Scaled;
|
|
}
|
|
|
|
|
|
ILimage *iluScale1D_(ILimage *Image, ILimage *Scaled, ILuint Width)
|
|
{
|
|
ILuint x1, x2;
|
|
ILuint NewX1, NewX2, NewX3, x, c;
|
|
ILdouble ScaleX, t1, t2, f;
|
|
ILushort *ShortPtr, *SShortPtr;
|
|
ILuint *IntPtr, *SIntPtr;
|
|
|
|
if (Image == NULL) {
|
|
ilSetError(ILU_ILLEGAL_OPERATION);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
ScaleX = (ILdouble)Width / Image->Width;
|
|
|
|
ShortPtr = (ILushort*)Image->Data;
|
|
SShortPtr = (ILushort*)Scaled->Data;
|
|
IntPtr = (ILuint*)Image->Data;
|
|
SIntPtr = (ILuint*)Scaled->Data;
|
|
|
|
if (iluFilter == ILU_NEAREST) {
|
|
switch (Image->Bpc)
|
|
{
|
|
case 1:
|
|
for (x = 0; x < Width; x++) {
|
|
NewX1 = x * Scaled->Bpp;
|
|
NewX2 = (ILuint)(x / ScaleX) * Image->Bpp;
|
|
for (c = 0; c < Scaled->Bpp; c++) {
|
|
Scaled->Data[NewX1 + c] = Image->Data[NewX2 + c];
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
for (x = 0; x < Width; x++) {
|
|
NewX1 = x * Scaled->Bpp;
|
|
NewX2 = (ILuint)(x / ScaleX) * Image->Bpp;
|
|
for (c = 0; c < Scaled->Bpp; c++) {
|
|
SShortPtr[NewX1 + c] = ShortPtr[NewX2 + c];
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
for (x = 0; x < Width; x++) {
|
|
NewX1 = x * Scaled->Bpp;
|
|
NewX2 = (ILuint)(x / ScaleX) * Image->Bpp;
|
|
for (c = 0; c < Scaled->Bpp; c++) {
|
|
SIntPtr[NewX1 + c] = IntPtr[NewX2 + c];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else { // IL_LINEAR or IL_BILINEAR
|
|
switch (Image->Bpc)
|
|
{
|
|
case 1:
|
|
NewX3 = 0;
|
|
for (x = 0; x < Width; x++) {
|
|
t1 = x / (ILdouble)Width;
|
|
t2 = t1 * Width - (ILuint)(t1 * Width);
|
|
f = (1.0 - cos(t2 * IL_PI)) * .5;
|
|
NewX1 = ((ILuint)(t1 * Width / ScaleX)) * Image->Bpp;
|
|
NewX2 = ((ILuint)(t1 * Width / ScaleX) + 1) * Image->Bpp;
|
|
|
|
for (c = 0; c < Scaled->Bpp; c++) {
|
|
x1 = Image->Data[NewX1 + c];
|
|
x2 = Image->Data[NewX2 + c];
|
|
|
|
Scaled->Data[NewX3 + c] = (ILubyte)(x1 * (1.0 - f) + x2 * f);
|
|
}
|
|
|
|
NewX3 += Scaled->Bpp;
|
|
}
|
|
break;
|
|
case 2:
|
|
NewX3 = 0;
|
|
for (x = 0; x < Width; x++) {
|
|
t1 = x / (ILdouble)Width;
|
|
t2 = t1 * Width - (ILuint)(t1 * Width);
|
|
f = (1.0 - cos(t2 * IL_PI)) * .5;
|
|
NewX1 = ((ILuint)(t1 * Width / ScaleX)) * Image->Bpp;
|
|
NewX2 = ((ILuint)(t1 * Width / ScaleX) + 1) * Image->Bpp;
|
|
|
|
for (c = 0; c < Scaled->Bpp; c++) {
|
|
x1 = ShortPtr[NewX1 + c];
|
|
x2 = ShortPtr[NewX2 + c];
|
|
|
|
SShortPtr[NewX3 + c] = (ILushort)(x1 * (1.0 - f) + x2 * f);
|
|
}
|
|
|
|
NewX3 += Scaled->Bpp;
|
|
}
|
|
break;
|
|
case 4:
|
|
NewX3 = 0;
|
|
for (x = 0; x < Width; x++) {
|
|
t1 = x / (ILdouble)Width;
|
|
t2 = t1 * Width - (ILuint)(t1 * Width);
|
|
f = (1.0 - cos(t2 * IL_PI)) * .5;
|
|
NewX1 = ((ILuint)(t1 * Width / ScaleX)) * Image->Bpp;
|
|
NewX2 = ((ILuint)(t1 * Width / ScaleX) + 1) * Image->Bpp;
|
|
|
|
for (c = 0; c < Scaled->Bpp; c++) {
|
|
x1 = IntPtr[NewX1 + c];
|
|
x2 = IntPtr[NewX2 + c];
|
|
|
|
SIntPtr[NewX3 + c] = (ILuint)(x1 * (1.0 - f) + x2 * f);
|
|
}
|
|
|
|
NewX3 += Scaled->Bpp;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Scaled;
|
|
}
|