Files
love-android/jni/devil-1.7.8/src-ILU/src/ilu_scale.c
T

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;
}