//! Retrieves information about the current bound image. void ILAPIENTRY iluGetImageInfo(ILinfo *Info) { iluCurImage = ilGetCurImage(); if (iluCurImage == NULL || Info == NULL) { ilSetError(ILU_ILLEGAL_OPERATION); return; } Info->Id = ilGetCurName(); Info->Data = ilGetData(); Info->Width = iluCurImage->Width; Info->Height = iluCurImage->Height; Info->Depth = iluCurImage->Depth; Info->Bpp = iluCurImage->Bpp; Info->SizeOfData = iluCurImage->SizeOfData; Info->Format = iluCurImage->Format; Info->Type = iluCurImage->Type; Info->Origin = iluCurImage->Origin; Info->Palette = iluCurImage->Pal.Palette; Info->PalType = iluCurImage->Pal.PalType; Info->PalSize = iluCurImage->Pal.PalSize; iGetIntegervImage(iluCurImage, IL_NUM_IMAGES, (ILint*)&Info->NumNext); iGetIntegervImage(iluCurImage, IL_NUM_MIPMAPS, (ILint*)&Info->NumMips); iGetIntegervImage(iluCurImage, IL_NUM_LAYERS, (ILint*)&Info->NumLayers); return; }
ILboolean ILAPIENTRY ilRegisterNumImages(ILuint Num) { ILimage *Next, *Prev; ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. ilCloseImage(iCurImage->Next); // Close any current "next" images. iCurImage->Next = NULL; if (Num == 0) // Just gets rid of all the "next" images. return IL_TRUE; iCurImage->Next = il2NewImage(1, 1, 1, 1, 1); if (iCurImage->Next == NULL) return IL_FALSE; Next = iCurImage->Next; Num--; while (Num) { Next->Next = il2NewImage(1, 1, 1, 1, 1); if (Next->Next == NULL) { // Clean up before we error out. Prev = iCurImage->Next; while (Prev) { Next = Prev->Next; ilCloseImage(Prev); Prev = Next; } return IL_FALSE; } Next = Next->Next; Num--; } return IL_TRUE; }
// Completely replaces the current image and the version in the image stack. ILAPI void ILAPIENTRY ilReplaceCurImage(ILimage *Image) { if (iCurImage) { ilActiveImage(0); ilCloseImage(iCurImage); } ImageStack[ilGetCurName()] = Image; iCurImage = Image; return; }
//! Overlays the image found in Src on top of the current bound image at the coords specified. ILboolean ILAPIENTRY ilOverlayImage(ILuint Source, ILint XCoord, ILint YCoord, ILint ZCoord) { ILuint Width, Height, Depth; ILuint Dest; Dest = ilGetCurName(); ilBindImage(Source); Width = iCurImage->Width; Height = iCurImage->Height; Depth = iCurImage->Depth; ilBindImage(Dest); return ilBlit(Source, XCoord, YCoord, ZCoord, 0, 0, 0, Width, Height, Depth); }
ILAPI ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX, ILint DestY, ILint DestZ, ILuint SrcX, ILuint SrcY, ILuint SrcZ, ILuint Width, ILuint Height, ILuint Depth) { ILimage * targetImage = iCurImage; ILuint targetName = ilGetCurName(); ilBindImage(Source); ILimage * sourceImage = iCurImage; ILboolean result = il2Blit(sourceImage, targetImage, DestX, DestY, DestZ, SrcX, SrcY, SrcZ, Width, Height, Depth); ilBindImage(targetName); return result; }
//! Copies everything from Src to the current bound image. ILAPI ILboolean ILAPIENTRY ilCopyImage(ILuint Src) { ILuint DestName = ilGetCurName(); ILimage *DestImage = iCurImage, *SrcImage; if (iCurImage == NULL || DestName == 0) { il2SetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } ilBindImage(Src); SrcImage = iCurImage; ilBindImage(DestName); return il2CopyImage(SrcImage, DestImage); return IL_TRUE; }
//! Copies everything from Src to the current bound image. ILboolean ILAPIENTRY ilCopyImage(ILuint Src) { ILuint DestName = ilGetCurName(); ILimage *DestImage = iCurImage, *SrcImage; if (iCurImage == NULL || DestName == 0) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } ilBindImage(Src); SrcImage = iCurImage; ilBindImage(DestName); ilTexImage(SrcImage->Width, SrcImage->Height, SrcImage->Depth, SrcImage->Bpp, SrcImage->Format, SrcImage->Type, SrcImage->Data); ilCopyImageAttr(DestImage, SrcImage); return IL_TRUE; }
//! Sets Param equal to the current value of the Mode void ILAPIENTRY ilGetIntegerv(ILenum Mode, ILint *Param) { if (Param == NULL) { ilSetError(IL_INVALID_PARAM); return; } *Param = 0; switch (Mode) { // Integer values case IL_COMPRESS_MODE: *Param = ilStates[ilCurrentPos].ilCompression; break; case IL_CUR_IMAGE: if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); break; } *Param = ilGetCurName(); break; case IL_FORMAT_MODE: *Param = ilStates[ilCurrentPos].ilFormatMode; break; case IL_INTERLACE_MODE: *Param = ilStates[ilCurrentPos].ilInterlace; break; case IL_KEEP_DXTC_DATA: *Param = ilStates[ilCurrentPos].ilKeepDxtcData; break; case IL_ORIGIN_MODE: *Param = ilStates[ilCurrentPos].ilOriginMode; break; case IL_MAX_QUANT_INDICES: *Param = ilStates[ilCurrentPos].ilQuantMaxIndexs; break; case IL_NEU_QUANT_SAMPLE: *Param = ilStates[ilCurrentPos].ilNeuSample; break; case IL_QUANTIZATION_MODE: *Param = ilStates[ilCurrentPos].ilQuantMode; break; case IL_TYPE_MODE: *Param = ilStates[ilCurrentPos].ilTypeMode; break; case IL_VERSION_NUM: *Param = IL_VERSION; break; // Image specific values case IL_ACTIVE_IMAGE: case IL_ACTIVE_MIPMAP: case IL_ACTIVE_LAYER: *Param = iGetActiveNum(Mode); break; // Format-specific values case IL_BMP_RLE: *Param = ilStates[ilCurrentPos].ilBmpRle; break; case IL_DXTC_FORMAT: *Param = ilStates[ilCurrentPos].ilDxtcFormat; break; case IL_JPG_QUALITY: *Param = ilStates[ilCurrentPos].ilJpgQuality; break; case IL_JPG_SAVE_FORMAT: *Param = ilStates[ilCurrentPos].ilJpgFormat; break; case IL_PCD_PICNUM: *Param = ilStates[ilCurrentPos].ilPcdPicNum; break; case IL_PNG_ALPHA_INDEX: *Param = ilStates[ilCurrentPos].ilPngAlphaIndex; break; case IL_PNG_INTERLACE: *Param = ilStates[ilCurrentPos].ilPngInterlace; break; case IL_SGI_RLE: *Param = ilStates[ilCurrentPos].ilSgiRle; break; case IL_TGA_CREATE_STAMP: *Param = ilStates[ilCurrentPos].ilTgaCreateStamp; break; case IL_TGA_RLE: *Param = ilStates[ilCurrentPos].ilTgaRle; break; case IL_VTF_COMP: *Param = ilStates[ilCurrentPos].ilVtfCompression; break; // Boolean values case IL_CONV_PAL: *Param = ilStates[ilCurrentPos].ilAutoConvPal; break; case IL_DEFAULT_ON_FAIL: *Param = ilStates[ilCurrentPos].ilDefaultOnFail; break; case IL_FILE_MODE: *Param = ilStates[ilCurrentPos].ilOverWriteFiles; break; case IL_FORMAT_SET: *Param = ilStates[ilCurrentPos].ilFormatSet; break; case IL_ORIGIN_SET: *Param = ilStates[ilCurrentPos].ilOriginSet; break; case IL_TYPE_SET: *Param = ilStates[ilCurrentPos].ilTypeSet; break; case IL_USE_KEY_COLOUR: *Param = ilStates[ilCurrentPos].ilUseKeyColour; break; case IL_BLIT_BLEND: *Param = ilStates[ilCurrentPos].ilBlitBlend; break; case IL_JPG_PROGRESSIVE: *Param = ilStates[ilCurrentPos].ilJpgProgressive; break; case IL_NVIDIA_COMPRESS: *Param = ilStates[ilCurrentPos].ilUseNVidiaDXT; break; case IL_SQUISH_COMPRESS: *Param = ilStates[ilCurrentPos].ilUseSquishDXT; break; default: iGetIntegervImage(iCurImage, Mode, Param); } return; }
ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX, ILint DestY, ILint DestZ, ILuint SrcX, ILuint SrcY, ILuint SrcZ, ILuint Width, ILuint Height, ILuint Depth) { register ILuint x, y, z, SrcIndex, DestIndex, ConvBps, ConvSizePlane; ILimage *Dest; ILubyte *Converted; ILuint DestName = ilGetCurName(); ILint c; ILfloat FrontPer, BackPer; ILenum DestOrigin, SrcOrigin; ILuint StartX, StartY, StartZ, AlphaOff; ILboolean DestFlipped = IL_FALSE; ILubyte *SrcTemp; if (DestName == 0 || iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) { // Dest DestFlipped = IL_TRUE; ilFlipImage(); } Dest = iCurImage; DestOrigin = iCurImage->Origin; ilBindImage(Source); SrcOrigin = iCurImage->Origin; if (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) { SrcTemp = iGetFlipped(iCurImage); if (SrcTemp == NULL) { ilBindImage(DestName); if (DestFlipped) ilFlipImage(); return IL_FALSE; } } else { SrcTemp = iCurImage->Data; } if (Dest == NULL || iCurImage == NULL) { ilSetError(IL_INVALID_PARAM); return IL_FALSE; } Converted = ilConvertBuffer(iCurImage->SizeOfData, iCurImage->Format, Dest->Format, iCurImage->Type, Dest->Type, SrcTemp); if (Converted == NULL) return IL_FALSE; ConvBps = Dest->Bpp * iCurImage->Width; ConvSizePlane = ConvBps * iCurImage->Height; StartX = DestX >= 0 ? 0 : -DestX; StartY = DestY >= 0 ? 0 : -DestY; StartZ = DestZ >= 0 ? 0 : -DestZ; Width = Width + SrcX < Dest->Width ? Width + SrcX : Dest->Width; Height = Height + SrcY < Dest->Height ? Height + SrcY : Dest->Height; Depth = Depth + SrcZ < Dest->Depth ? Depth + SrcZ : Dest->Depth; if (iCurImage->Format == IL_RGBA || iCurImage->Format == IL_BGRA || iCurImage->Format == IL_LUMINANCE_ALPHA) { if (iCurImage->Format == IL_LUMINANCE_ALPHA) AlphaOff = 1; else AlphaOff = 3; for (z = StartZ; z < Depth && z + DestZ < Dest->Depth; z++) { for (y = StartY; y < Height && y + DestY < Dest->Height; y++) { for (x = StartX; x < Width && x + DestX < Dest->Width; x++) { SrcIndex = (z + SrcZ) * ConvSizePlane + (y + SrcY) * ConvBps + (x + SrcX) * Dest->Bpp; DestIndex = (z + DestZ) * Dest->SizeOfPlane + (y + DestY) * Dest->Bps + (x + DestX) * Dest->Bpp; // Use the original alpha FrontPer = iCurImage->Data[(z + SrcZ) * iCurImage->SizeOfPlane + (y + SrcY) * iCurImage->Bps + (x + SrcX) * iCurImage->Bpp + 3] / 255.0f; BackPer = 1.0f - FrontPer; for (c = 0; c < Dest->Bpp - 1; c++) { Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c] * FrontPer + Dest->Data[DestIndex + c] * BackPer); } // Keep the original alpha. //Dest->Data[DestIndex + c + 1] = Dest->Data[DestIndex + c + 1]; } } } } else { for (z = StartZ; z < Depth && z + DestZ < Dest->Depth; z++) { for (y = StartY; y < Height && y + DestY < Dest->Height; y++) { for (x = StartX; x < Width && x + DestX < Dest->Width; x++) { for (c = 0; c < Dest->Bpp; c++) { Dest->Data[(z + DestZ) * Dest->SizeOfPlane + (y + DestY) * Dest->Bps + (x + DestX) * Dest->Bpp + c] = Converted[(z + SrcZ) * ConvSizePlane + (y + SrcY) * ConvBps + (x + SrcX) * Dest->Bpp + c]; } } } } } if (SrcTemp != iCurImage->Data) ifree(SrcTemp); ilBindImage(DestName); if (DestFlipped) ilFlipImage(); ifree(Converted); return IL_TRUE; }
//! Overlays the image found in Src on top of the current bound image at the coords specified. ILboolean ILAPIENTRY ilOverlayImage(ILuint Source, ILint XCoord, ILint YCoord, ILint ZCoord) { ILuint x, y, z, SrcIndex, DestIndex, ConvBps, ConvSizePlane; ILint c; ILimage *Dest;//, *Src; ILubyte *Converted; ILuint DestName = ilGetCurName(); ILfloat FrontPer, BackPer; ILenum DestOrigin, SrcOrigin; ILuint StartX, StartY, StartZ, AlphaOff; ILubyte *SrcTemp = NULL; ILboolean DestFlipped = IL_FALSE; if (DestName == 0 || iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) { // Dest DestFlipped = IL_TRUE; ilFlipImage(); } Dest = iCurImage; DestOrigin = iCurImage->Origin; ilBindImage(Source); SrcOrigin = iCurImage->Origin; if (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) { SrcTemp = iGetFlipped(iCurImage); if (SrcTemp == NULL) { ilBindImage(DestName); if (DestFlipped) ilFlipImage(); return IL_FALSE; } } else { SrcTemp = iCurImage->Data; } if (Dest == NULL || iCurImage == NULL) { ilSetError(IL_INVALID_PARAM); return IL_FALSE; } Converted = ilConvertBuffer(iCurImage->SizeOfData, iCurImage->Format, Dest->Format, iCurImage->Type, Dest->Type, SrcTemp); if (Converted == NULL) return IL_FALSE; ConvBps = Dest->Bpp * iCurImage->Width; ConvSizePlane = ConvBps * iCurImage->Height; StartX = XCoord >= 0 ? 0 : -XCoord; StartY = YCoord >= 0 ? 0 : -YCoord; StartZ = ZCoord >= 0 ? 0 : -ZCoord; if (iCurImage->Format == IL_RGBA || iCurImage->Format == IL_BGRA || iCurImage->Format == IL_LUMINANCE_ALPHA) { if (iCurImage->Format == IL_LUMINANCE_ALPHA) AlphaOff = 1; else AlphaOff = 3; for (z = StartZ; z < iCurImage->Depth && (ILint)z + ZCoord < (ILint)Dest->Depth; z++) { for (y = StartY; y < iCurImage->Height && (ILint)y + YCoord < (ILint)Dest->Height; y++) { for (x = StartX; x < iCurImage->Width && (ILint)x + XCoord < (ILint)Dest->Width; x++) { SrcIndex = z * ConvSizePlane + y * ConvBps + x * Dest->Bpp; DestIndex = (z + ZCoord) * Dest->SizeOfPlane + (y + YCoord) * Dest->Bps + (x + XCoord) * Dest->Bpp; FrontPer = iCurImage->Data[z * iCurImage->SizeOfPlane + y * iCurImage->Bps + x * iCurImage->Bpp + AlphaOff] / 255.0f; BackPer = 1.0f - FrontPer; for (c = 0; c < iCurImage->Bpp - 1; c++) { Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c] * FrontPer + Dest->Data[DestIndex + c] * BackPer); } // Keep the original alpha. //Dest->Data[DestIndex + c + 1] = Dest->Data[DestIndex + c + 1]; } } } } else { for (z = StartZ; z < iCurImage->Depth && z + ZCoord < Dest->Depth; z++) { for (y = StartY; y < iCurImage->Height && y + YCoord < Dest->Height; y++) { for (x = StartX; x < iCurImage->Width && x + XCoord < Dest->Width; x++) { for (c = 0; c < iCurImage->Bpp; c++) { Dest->Data[(z + ZCoord) * Dest->SizeOfPlane + (y + YCoord) * Dest->Bps + (x + XCoord) * Dest->Bpp + c] = Converted[z * ConvSizePlane + y * ConvBps + x * Dest->Bpp + c]; } } } } } if (SrcTemp != iCurImage->Data) ifree(SrcTemp); ilBindImage(DestName); if (DestFlipped) ilFlipImage(); ifree(Converted); return IL_TRUE; }
ILimage *iGetBaseImage() { return ImageStack[ilGetCurName()]; }
//@NEXT DestX,DestY,DestZ must be set to ILuint ILboolean ILAPIENTRY il2Blit(ILimage* aSource, ILimage* aTarget, ILint DestX, ILint DestY, ILint DestZ, ILuint SrcX, ILuint SrcY, ILuint SrcZ, ILuint Width, ILuint Height, ILuint Depth) { ILuint x, y, z, ConvBps, ConvSizePlane; ILubyte *Converted; ILuint DestName = ilGetCurName(); ILuint c; ILuint StartX, StartY, StartZ; ILboolean DestFlipped = IL_FALSE; ILboolean DoAlphaBlend = IL_FALSE; ILubyte *SrcTemp; ILfloat ResultAlpha; // Check if source and target images really exist if (aSource == NULL || aTarget == NULL) { il2SetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } // set the destination image to upper left origin if (aTarget->Origin == IL_ORIGIN_LOWER_LEFT) { // Dest DestFlipped = IL_TRUE; ilFlipImage(aTarget); } //determine alpha support DoAlphaBlend = il2IsEnabled(IL_BLIT_BLEND); //@TODO test if coordinates are inside the images (hard limit for source) // set the source image to upper left origin if (aSource->Origin == IL_ORIGIN_LOWER_LEFT) { SrcTemp = iGetFlipped(aSource); if (SrcTemp == NULL) { if (DestFlipped) ilFlipImage(aTarget); return IL_FALSE; } } else { SrcTemp = aSource->Data; } // convert source image to match the destination image type and format Converted = (ILubyte*)ilConvertBuffer(aSource->SizeOfData, aSource->Format, aTarget->Format, aSource->Type, aTarget->Type, NULL, SrcTemp); if (Converted == NULL) return IL_FALSE; ConvBps = aTarget->Bpp * aSource->Width; ConvSizePlane = ConvBps * aSource->Height; //@NEXT in next version this would have to be removed since Dest* will be unsigned StartX = DestX >= 0 ? 0 : -DestX; StartY = DestY >= 0 ? 0 : -DestY; StartZ = DestZ >= 0 ? 0 : -DestZ; // Limit the copy of data inside of the destination image if (Width + DestX > aTarget->Width) Width = aTarget->Width - DestX; if (Height + DestY > aTarget->Height) Height = aTarget->Height - DestY; if (Depth + DestZ > aTarget->Depth) Depth = aTarget->Depth - DestZ; //@TODO: non funziona con rgba if (aSource->Format == IL_RGBA || aSource->Format == IL_BGRA || aSource->Format == IL_LUMINANCE_ALPHA) { const ILuint bpp_without_alpha = aTarget->Bpp - 1; for (z = 0; z < Depth; z++) { for (y = 0; y < Height; y++) { for (x = 0; x < Width; x++) { const ILuint SrcIndex = (z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*aTarget->Bpp; const ILuint DestIndex = (z+DestZ)*aTarget->SizeOfPlane + (y+DestY)*aTarget->Bps + (x+DestX)*aTarget->Bpp; const ILuint AlphaIdx = SrcIndex + bpp_without_alpha; ILfloat FrontAlpha = 0; // foreground opacity ILfloat BackAlpha = 0; // background opacity switch (aTarget->Type) { case IL_BYTE: case IL_UNSIGNED_BYTE: FrontAlpha = Converted[AlphaIdx]/((float)IL_MAX_UNSIGNED_BYTE); BackAlpha = aTarget->Data[AlphaIdx]/((float)IL_MAX_UNSIGNED_BYTE); break; case IL_SHORT: case IL_UNSIGNED_SHORT: FrontAlpha = ((ILshort*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_SHORT); BackAlpha = ((ILshort*)aTarget->Data)[AlphaIdx]/((float)IL_MAX_UNSIGNED_SHORT); break; case IL_INT: case IL_UNSIGNED_INT: FrontAlpha = ((ILint*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_INT); BackAlpha = ((ILint*)aTarget->Data)[AlphaIdx]/((float)IL_MAX_UNSIGNED_INT); break; case IL_FLOAT: FrontAlpha = ((ILfloat*)Converted)[AlphaIdx]; BackAlpha = ((ILfloat*)aTarget->Data)[AlphaIdx]; break; case IL_DOUBLE: FrontAlpha = (ILfloat)(((ILdouble*)Converted)[AlphaIdx]); BackAlpha = (ILfloat)(((ILdouble*)aTarget->Data)[AlphaIdx]); break; } // In case of Alpha channel, the data is blended. // Computes composite Alpha if (DoAlphaBlend) { ResultAlpha = FrontAlpha + (1.0f - FrontAlpha) * BackAlpha; for (c = 0; c < bpp_without_alpha; c++) { aTarget->Data[DestIndex + c] = (ILubyte)( 0.5f + (Converted[SrcIndex + c] * FrontAlpha + (1.0f - FrontAlpha) * aTarget->Data[DestIndex + c] * BackAlpha) / ResultAlpha); } aTarget->Data[AlphaIdx] = (ILubyte)(0.5f + ResultAlpha * (float)IL_MAX_UNSIGNED_BYTE); } else { for (c = 0; c < aTarget->Bpp; c++) { aTarget->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c]); } } } } } } else { for( z = 0; z < Depth; z++ ) { for( y = 0; y < Height; y++ ) { for( x = 0; x < Width; x++ ) { for( c = 0; c < aTarget->Bpp; c++ ) { aTarget->Data[(z+DestZ)*aTarget->SizeOfPlane + (y+DestY)*aTarget->Bps + (x+DestX)*aTarget->Bpp + c] = Converted[(z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*aTarget->Bpp + c]; } } } } } if (SrcTemp != aSource->Data) ifree(SrcTemp); if (DestFlipped) ilFlipImage(aTarget); ifree(Converted); return IL_TRUE; }
ILboolean ILAPIENTRY ilRegisterLoad(const ILstring Ext, IL_LOADPROC Load) { iFormatL *TempNode, *NewNode; TempNode = LoadProcs; if (TempNode != NULL) { while (TempNode->Next != NULL) { TempNode = TempNode->Next; #ifndef _UNICODE if (!stricmp(TempNode->Ext, Ext)) { // already registered #else if (!wcsicmp(TempNode->Ext, Ext)) { #endif//_UNICODE return IL_TRUE; } } } NewNode = (iFormatL*)ialloc(sizeof(iFormatL)); if (NewNode == NULL) { return IL_FALSE; } if (LoadProcs == NULL) { LoadProcs = NewNode; } else { TempNode->Next = NewNode; } #ifndef _UNICODE NewNode->Ext = ilStrDup(Ext); #else NewNode->Ext = _wcsdup(Ext); #endif//_UNICODE NewNode->Load = Load; NewNode->Next = NULL; return IL_TRUE; } ILboolean ILAPIENTRY ilRegisterSave(const ILstring Ext, IL_SAVEPROC Save) { iFormatS *TempNode, *NewNode; TempNode = SaveProcs; if (TempNode != NULL) { while (TempNode->Next != NULL) { TempNode = TempNode->Next; #ifndef _UNICODE if (!stricmp(TempNode->Ext, Ext)) { // already registered #else if (!_wcsicmp(TempNode->Ext, Ext)) { #endif//_UNICODE return IL_TRUE; } } } NewNode = (iFormatS*)ialloc(sizeof(iFormatL)); if (NewNode == NULL) { return IL_FALSE; } if (SaveProcs == NULL) { SaveProcs = NewNode; } else { TempNode->Next = NewNode; } #ifndef _UNICODE NewNode->Ext = ilStrDup(Ext); #else NewNode->Ext = _wcsdup(Ext); #endif//_UNICODE NewNode->Save = Save; NewNode->Next = NULL; return IL_TRUE; } //! Unregisters a load extension - doesn't have to be called. ILboolean ILAPIENTRY ilRemoveLoad(const ILstring Ext) { iFormatL *TempNode = LoadProcs, *PrevNode = NULL; while (TempNode != NULL) { #ifndef _UNICODE if (!stricmp(Ext, TempNode->Ext)) { #else if (_wcsicmp(Ext, TempNode->Ext)) { #endif//_UNICODE if (PrevNode == NULL) { // first node in the list LoadProcs = TempNode->Next; ifree((void*)TempNode->Ext); ifree(TempNode); } else { PrevNode->Next = TempNode->Next; ifree((void*)TempNode->Ext); ifree(TempNode); } return IL_TRUE; } PrevNode = TempNode; TempNode = TempNode->Next; } return IL_FALSE; } //! Unregisters a save extension - doesn't have to be called. ILboolean ILAPIENTRY ilRemoveSave(const ILstring Ext) { iFormatS *TempNode = SaveProcs, *PrevNode = NULL; while (TempNode != NULL) { #ifndef _UNICODE if (!stricmp(Ext, TempNode->Ext)) { #else if (_wcsicmp(Ext, TempNode->Ext)) { #endif//_UNICODE if (PrevNode == NULL) { // first node in the list SaveProcs = TempNode->Next; ifree((void*)TempNode->Ext); ifree(TempNode); } else { PrevNode->Next = TempNode->Next; ifree((void*)TempNode->Ext); ifree(TempNode); } return IL_TRUE; } PrevNode = TempNode; TempNode = TempNode->Next; } return IL_FALSE; } // Automatically removes all registered formats. ILvoid ilRemoveRegistered() { iFormatL *TempNodeL = LoadProcs; iFormatS *TempNodeS = SaveProcs; while (LoadProcs != NULL) { TempNodeL = LoadProcs->Next; ifree((void*)LoadProcs->Ext); ifree(LoadProcs); LoadProcs = TempNodeL; } while (SaveProcs != NULL) { TempNodeS = SaveProcs->Next; ifree((void*)SaveProcs->Ext); ifree(SaveProcs); SaveProcs = TempNodeS; } return; } ILboolean iRegisterLoad(const ILstring FileName) { iFormatL *TempNode = LoadProcs; ILstring Ext = iGetExtension(FileName); ILenum Error; if (!Ext) return IL_FALSE; while (TempNode != NULL) { #ifndef _UNICODE if (!stricmp(Ext, TempNode->Ext)) { #else if (_wcsicmp(Ext, TempNode->Ext)) { #endif//_UNICODE Error = TempNode->Load(FileName); if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid. return IL_TRUE; } else { ilSetError(Error); return IL_FALSE; } } TempNode = TempNode->Next; } return IL_FALSE; } ILboolean iRegisterSave(const ILstring FileName) { iFormatS *TempNode = SaveProcs; ILstring Ext = iGetExtension(FileName); ILenum Error; if (!Ext) return IL_FALSE; while (TempNode != NULL) { #ifndef _UNICODE if (!stricmp(Ext, TempNode->Ext)) { #else if (_wcsicmp(Ext, TempNode->Ext)) { #endif//_UNICODE Error = TempNode->Save(FileName); if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid. return IL_TRUE; } else { ilSetError(Error); return IL_FALSE; } } TempNode = TempNode->Next; } return IL_FALSE; } // // "Reporting" functions // ILvoid ILAPIENTRY ilRegisterOrigin(ILenum Origin) { switch (Origin) { case IL_ORIGIN_LOWER_LEFT: case IL_ORIGIN_UPPER_LEFT: iCurImage->Origin = Origin; break; default: ilSetError(IL_INVALID_ENUM); } return; } ILvoid ILAPIENTRY ilRegisterFormat(ILenum Format) { switch (Format) { case IL_COLOUR_INDEX: case IL_RGB: case IL_RGBA: case IL_BGR: case IL_BGRA: case IL_LUMINANCE: case IL_LUMINANCE_ALPHA: iCurImage->Format = Format; break; default: ilSetError(IL_INVALID_ENUM); } return; } ILboolean ILAPIENTRY ilRegisterMipNum(ILuint Num) { ILimage *Next, *Prev; ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. ilCloseImage(iCurImage->Mipmaps); // Close any current mipmaps. iCurImage->Mipmaps = NULL; if (Num == 0) // Just gets rid of all the mipmaps. return IL_TRUE; iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1); if (iCurImage->Mipmaps == NULL) return IL_FALSE; Next = iCurImage->Mipmaps; Num--; while (Num) { Next->Next = ilNewImage(1, 1, 1, 1, 1); if (Next->Next == NULL) { // Clean up before we error out. Prev = iCurImage->Mipmaps; while (Prev) { Next = Prev->Next; ilCloseImage(Prev); Prev = Next; } return IL_FALSE; } Next = Next->Next; Num--; } return IL_TRUE; }
//@NEXT DestX,DestY,DestZ must be set to ILuint ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX, ILint DestY, ILint DestZ, ILuint SrcX, ILuint SrcY, ILuint SrcZ, ILuint Width, ILuint Height, ILuint Depth) { ILuint x, y, z, ConvBps, ConvSizePlane; ILimage *Dest,*Src; ILubyte *Converted; ILuint DestName = ilGetCurName(); ILuint c; ILuint StartX, StartY, StartZ; ILboolean DestFlipped = IL_FALSE; ILubyte *SrcTemp; ILfloat Back; // Check if the desiination image really exists if( DestName == 0 || iCurImage == NULL ) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } Dest = iCurImage; // set the destination image to upper left origin if( Dest->Origin == IL_ORIGIN_LOWER_LEFT ) { // Dest DestFlipped = IL_TRUE; ilFlipImage(); } //DestOrigin = Dest->Origin; ilBindImage(Source); // Check if the source image really exists if( iCurImage == NULL ) { ilSetError(IL_INVALID_PARAM); return IL_FALSE; } Src = iCurImage; //@TODO test if coordinates are inside the images (hard limit for source) // set the source image to upper left origin if (Src->Origin == IL_ORIGIN_LOWER_LEFT) { SrcTemp = iGetFlipped(iCurImage); if (SrcTemp == NULL) { ilBindImage(DestName); if (DestFlipped) ilFlipImage(); return IL_FALSE; } } else { SrcTemp = iCurImage->Data; } // convert source image to match the destination image type and format Converted = (ILubyte*)ilConvertBuffer(Src->SizeOfData, Src->Format, Dest->Format, Src->Type, Dest->Type, SrcTemp); if (Converted == NULL) return IL_FALSE; ConvBps = Dest->Bpp * Src->Width; ConvSizePlane = ConvBps * Src->Height; //@NEXT in next version this would have to be removed since Dest* will be unsigned StartX = DestX >= 0 ? 0 : -DestX; StartY = DestY >= 0 ? 0 : -DestY; StartZ = DestZ >= 0 ? 0 : -DestZ; // Limit the copy of data inside of the destination image if (Width + DestX > Dest->Width) Width = Dest->Width - DestX; if (Height + DestY > Dest->Height) Height = Dest->Height - DestY; if (Depth + DestZ > Dest->Depth) Depth = Dest->Depth - DestZ; //@TODO: non funziona con rgba if (Src->Format == IL_RGBA || Src->Format == IL_BGRA || Src->Format == IL_LUMINANCE_ALPHA) { const ILuint bpp_without_alpha = Dest->Bpp - 1; for (z = 0; z < Depth; z++) { for (y = 0; y < Height; y++) { for (x = 0; x < Width; x++) { const ILuint SrcIndex = (z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp; const ILuint DestIndex = (z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp; const ILuint AlphaIdx = SrcIndex + bpp_without_alpha; ILfloat Front = 0; switch (Dest->Type) { case IL_BYTE: case IL_UNSIGNED_BYTE: Front = Converted[AlphaIdx]/((float)IL_MAX_UNSIGNED_BYTE); break; case IL_SHORT: case IL_UNSIGNED_SHORT: Front = ((ILshort*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_SHORT); break; case IL_INT: case IL_UNSIGNED_INT: Front = ((ILint*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_INT); break; case IL_FLOAT: Front = ((ILfloat*)Converted)[AlphaIdx]; break; case IL_DOUBLE: Front = (ILfloat)(((ILdouble*)Converted)[AlphaIdx]); break; } Back = 1.0f - Front; // In case of Alpha channel, the data is blended. Keeps the original alpha. if (ilIsEnabled(IL_BLIT_BLEND)) { for (c = 0; c < bpp_without_alpha; c++) { Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c] * Front + Dest->Data[DestIndex + c] * Back); } } else { for (c = 0; c < Dest->Bpp; c++) { Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c]); } } } } } } else { for( z = 0; z < Depth; z++ ) { for( y = 0; y < Height; y++ ) { for( x = 0; x < Width; x++ ) { for( c = 0; c < Dest->Bpp; c++ ) { Dest->Data[(z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp + c] = Converted[(z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp + c]; } } } } } if (SrcTemp != iCurImage->Data) ifree(SrcTemp); ilBindImage(DestName); if (DestFlipped) ilFlipImage(); ifree(Converted); return IL_TRUE; }