//----------------------------------------------------------------------------- // // 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->WidthHeightType != 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; }