mirror of
https://github.com/love2d/megasource.git
synced 2026-08-17 19:24:09 +02:00
370 lines
12 KiB
C
370 lines
12 KiB
C
//-----------------------------------------------------------------------------
|
|
//
|
|
// ImageLib Utility Sources
|
|
// Copyright (C) 2000-2002 by Denton Woods
|
|
// Last modified: 05/25/2002 <--Y2K Compliant! =]
|
|
//
|
|
// Filename: src-ILU/src/ilu_rotate.c
|
|
//
|
|
// Description: Rotates an image.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#include "ilu_internal.h"
|
|
#include "ilu_states.h"
|
|
|
|
|
|
ILboolean ILAPIENTRY iluRotate(ILfloat Angle)
|
|
{
|
|
ILimage *Temp, *Temp1, *CurImage = NULL;
|
|
ILenum PalType = 0;
|
|
|
|
iluCurImage = ilGetCurImage();
|
|
if (iluCurImage == NULL) {
|
|
ilSetError(ILU_ILLEGAL_OPERATION);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
if (iluCurImage->Format == IL_COLOUR_INDEX) {
|
|
PalType = iluCurImage->Pal.PalType;
|
|
CurImage = iluCurImage;
|
|
iluCurImage = iConvertImage(iluCurImage, ilGetPalBaseType(CurImage->Pal.PalType), IL_UNSIGNED_BYTE);
|
|
}
|
|
|
|
Temp = iluRotate_(iluCurImage, Angle);
|
|
if (Temp != NULL) {
|
|
if (PalType != 0) {
|
|
ilCloseImage(iluCurImage);
|
|
Temp1 = iConvertImage(Temp, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
|
|
ilCloseImage(Temp);
|
|
Temp = Temp1;
|
|
ilSetCurImage(CurImage);
|
|
}
|
|
ilTexImage(Temp->Width, Temp->Height, Temp->Depth, Temp->Bpp, Temp->Format, Temp->Type, Temp->Data);
|
|
if (PalType != 0) {
|
|
iluCurImage = ilGetCurImage();
|
|
iluCurImage->Pal.PalSize = Temp->Pal.PalSize;
|
|
iluCurImage->Pal.PalType = Temp->Pal.PalType;
|
|
iluCurImage->Pal.Palette = (ILubyte*)ialloc(Temp->Pal.PalSize);
|
|
if (iluCurImage->Pal.Palette == NULL) {
|
|
ilCloseImage(Temp);
|
|
return IL_FALSE;
|
|
}
|
|
memcpy(iluCurImage->Pal.Palette, Temp->Pal.Palette, Temp->Pal.PalSize);
|
|
}
|
|
|
|
iluCurImage->Origin = Temp->Origin;
|
|
ilCloseImage(Temp);
|
|
return IL_TRUE;
|
|
}
|
|
return IL_FALSE;
|
|
}
|
|
|
|
|
|
ILboolean ILAPIENTRY iluRotate3D(ILfloat x, ILfloat y, ILfloat z, ILfloat Angle)
|
|
{
|
|
ILimage *Temp;
|
|
|
|
// return IL_FALSE;
|
|
|
|
iluCurImage = ilGetCurImage();
|
|
Temp = iluRotate3D_(iluCurImage, x, y, z, Angle);
|
|
if (Temp != NULL) {
|
|
ilTexImage(Temp->Width, Temp->Height, Temp->Depth, Temp->Bpp, Temp->Format, Temp->Type, Temp->Data);
|
|
iluCurImage->Origin = Temp->Origin;
|
|
ilSetPal(&Temp->Pal);
|
|
ilCloseImage(Temp);
|
|
return IL_TRUE;
|
|
}
|
|
return IL_FALSE;
|
|
}
|
|
|
|
|
|
//! Rotates a bitmap any angle.
|
|
// Code help comes from http://www.leunen.com/cbuilder/rotbmp.html.
|
|
ILAPI ILimage* ILAPIENTRY iluRotate_(ILimage *Image, ILfloat Angle)
|
|
{
|
|
ILimage *Rotated = NULL;
|
|
ILint x, y, c;
|
|
ILdouble Cos, Sin;
|
|
ILuint RotOffset, ImgOffset;
|
|
ILint MinX, MinY, MaxX, MaxY;
|
|
ILushort *ShortPtr;
|
|
ILuint *IntPtr;
|
|
ILdouble *DblPtr;
|
|
ILdouble Point1x, Point1y, Point2x, Point2y, Point3x, Point3y;
|
|
ILint SrcX, SrcY;
|
|
|
|
// Multiples of 90 are special.
|
|
Angle = (ILfloat)fmod((ILdouble)Angle, 360.0);
|
|
if (Angle < 0)
|
|
Angle = 360.0f + Angle;
|
|
|
|
Cos = (ILdouble)cos((IL_PI * Angle) / 180.0);
|
|
Sin = (ILdouble)sin((IL_PI * Angle) / 180.0);
|
|
|
|
Point1x = (-(ILint)Image->Height * Sin);
|
|
Point1y = (Image->Height * Cos);
|
|
Point2x = (Image->Width * Cos - Image->Height * Sin);
|
|
Point2y = (Image->Height * Cos + Image->Width * Sin);
|
|
Point3x = (Image->Width * Cos);
|
|
Point3y = (Image->Width * Sin);
|
|
|
|
MinX = (ILint)IL_MIN(0, IL_MIN(Point1x, IL_MIN(Point2x, Point3x)));
|
|
MinY = (ILint)IL_MIN(0, IL_MIN(Point1y, IL_MIN(Point2y, Point3y)));
|
|
MaxX = (ILint)IL_MAX(Point1x, IL_MAX(Point2x, Point3x));
|
|
MaxY = (ILint)IL_MAX(Point1y, IL_MAX(Point2y, Point3y));
|
|
|
|
Rotated = (ILimage*)icalloc(1, sizeof(ILimage));
|
|
if (Rotated == NULL)
|
|
return NULL;
|
|
if (ilCopyImageAttr(Rotated, Image) == IL_FALSE) {
|
|
ilCloseImage(Rotated);
|
|
return NULL;
|
|
}
|
|
|
|
if (ilResizeImage(Rotated, (ILuint)ceil(fabs(MaxX) - MinX), (ILuint)ceil(fabs(MaxY) - MinY), 1, Image->Bpp, Image->Bpc) == IL_FALSE) {
|
|
ilCloseImage(Rotated);
|
|
return IL_FALSE;
|
|
}
|
|
|
|
ilClearImage_(Rotated);
|
|
|
|
ShortPtr = (ILushort*)iluCurImage->Data;
|
|
IntPtr = (ILuint*)iluCurImage->Data;
|
|
DblPtr = (ILdouble*)iluCurImage->Data;
|
|
|
|
//if (iluFilter == ILU_NEAREST) {
|
|
switch (iluCurImage->Bpc)
|
|
{
|
|
case 1: // Byte-based (most images)
|
|
if (Angle == 90.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = x * Rotated->Bps + (Image->Width - 1 - y) * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
Rotated->Data[RotOffset + c] = Image->Data[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 180.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - y) * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
Rotated->Data[RotOffset + c] = Image->Data[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 270.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - x) * Rotated->Bps + y * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
Rotated->Data[RotOffset + c] = Image->Data[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (x = 0; x < (ILint)Rotated->Width; x++) {
|
|
for (y = 0; y < (ILint)Rotated->Height; y++) {
|
|
SrcX = (ILint)((x + MinX) * Cos + (y + MinY) * Sin);
|
|
SrcY = (ILint)((y + MinY) * Cos - (x + MinX) * Sin);
|
|
if (SrcX >= 0 && SrcX < (ILint)Image->Width && SrcY >= 0 && SrcY < (ILint)Image->Height) {
|
|
RotOffset = y * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = (ILuint)SrcY * Image->Bps + (ILuint)SrcX * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
Rotated->Data[RotOffset + c] = Image->Data[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2: // Short-based
|
|
Image->Bps /= 2; // Makes it easier to just
|
|
Rotated->Bps /= 2; // cast to short.
|
|
|
|
if (Angle == 90.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = x * Rotated->Bps + (Image->Width - 1 - y) * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILushort*)(Rotated->Data))[RotOffset + c] = ShortPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 180.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - y) * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILushort*)(Rotated->Data))[RotOffset + c] = ShortPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 270.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - x) * Rotated->Bps + y * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILushort*)(Rotated->Data))[RotOffset + c] = ShortPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (x = 0; x < (ILint)Rotated->Width; x++) {
|
|
for (y = 0; y < (ILint)Rotated->Height; y++) {
|
|
SrcX = (ILint)((x + MinX) * Cos + (y + MinY) * Sin);
|
|
SrcY = (ILint)((y + MinY) * Cos - (x + MinX) * Sin);
|
|
if (SrcX >= 0 && SrcX < (ILint)Image->Width && SrcY >= 0 && SrcY < (ILint)Image->Height) {
|
|
RotOffset = y * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = (ILuint)SrcY * Image->Bps + (ILuint)SrcX * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILushort*)(Rotated->Data))[RotOffset + c] = ShortPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Image->Bps *= 2;
|
|
Rotated->Bps *= 2;
|
|
break;
|
|
|
|
case 4: // Floats or 32-bit integers
|
|
Image->Bps /= 4;
|
|
Rotated->Bps /= 4;
|
|
|
|
if (Angle == 90.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = x * Rotated->Bps + (Image->Width - 1 - y) * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILuint*)(Rotated->Data))[RotOffset + c] = IntPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 180.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - y) * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILuint*)(Rotated->Data))[RotOffset + c] = IntPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 270.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - x) * Rotated->Bps + y * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILuint*)(Rotated->Data))[RotOffset + c] = IntPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (x = 0; x < (ILint)Rotated->Width; x++) {
|
|
for (y = 0; y < (ILint)Rotated->Height; y++) {
|
|
SrcX = (ILint)((x + MinX) * Cos + (y + MinY) * Sin);
|
|
SrcY = (ILint)((y + MinY) * Cos - (x + MinX) * Sin);
|
|
if (SrcX >= 0 && SrcX < (ILint)Image->Width && SrcY >= 0 && SrcY < (ILint)Image->Height) {
|
|
RotOffset = y * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = (ILuint)SrcY * Image->Bps + (ILuint)SrcX * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILuint*)(Rotated->Data))[RotOffset + c] = IntPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Image->Bps *= 4;
|
|
Rotated->Bps *= 4;
|
|
break;
|
|
|
|
case 8: // Double or 64-bit integers
|
|
Image->Bps /= 8;
|
|
Rotated->Bps /= 8;
|
|
|
|
if (Angle == 90.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = x * Rotated->Bps + (Image->Width - 1 - y) * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILdouble*)(Rotated->Data))[RotOffset + c] = DblPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 180.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - y) * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILdouble*)(Rotated->Data))[RotOffset + c] = DblPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (Angle == 270.0) {
|
|
for (x = 0; x < (ILint)Image->Width; x++) {
|
|
for (y = 0; y < (ILint)Image->Height; y++) {
|
|
RotOffset = (Image->Height - 1 - x) * Rotated->Bps + y * Rotated->Bpp;
|
|
ImgOffset = y * Image->Bps + x * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILdouble*)(Rotated->Data))[RotOffset + c] = DblPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (x = 0; x < (ILint)Rotated->Width; x++) {
|
|
for (y = 0; y < (ILint)Rotated->Height; y++) {
|
|
SrcX = (ILint)((x + MinX) * Cos + (y + MinY) * Sin);
|
|
SrcY = (ILint)((y + MinY) * Cos - (x + MinX) * Sin);
|
|
if (SrcX >= 0 && SrcX < (ILint)Image->Width && SrcY >= 0 && SrcY < (ILint)Image->Height) {
|
|
RotOffset = y * Rotated->Bps + x * Rotated->Bpp;
|
|
ImgOffset = (ILuint)SrcY * Image->Bps + (ILuint)SrcX * Image->Bpp;
|
|
for (c = 0; c < Rotated->Bpp; c++) {
|
|
((ILdouble*)(Rotated->Data))[RotOffset + c] = DblPtr[ImgOffset + c];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Image->Bps *= 8;
|
|
Rotated->Bps *= 8;
|
|
break;
|
|
}
|
|
|
|
return Rotated;
|
|
}
|
|
|
|
|
|
ILAPI ILimage* ILAPIENTRY iluRotate3D_(ILimage *Image, ILfloat x, ILfloat y, ILfloat z, ILfloat Angle)
|
|
{
|
|
Image; x; y; z; Angle;
|
|
return NULL;
|
|
}
|