// Does not account for converting luminance... BITMAP* ILAPIENTRY ilutConvertToAlleg(PALETTE Pal) { BITMAP *Bitmap; ILimage *TempImage; ILuint i = 0, j = 0; ilutCurImage = ilGetCurImage(); if (ilutCurImage == NULL) { ilSetError(ILUT_ILLEGAL_OPERATION); return NULL; } // Should be IL_BGR(A), but Djgpp screws up somewhere along the line. if (ilutCurImage->Format == IL_RGB || ilutCurImage->Format == IL_RGBA) { iluSwapColours(); } if (ilutCurImage->Origin == IL_ORIGIN_LOWER_LEFT) iluFlipImage(); if (ilutCurImage->Type > IL_UNSIGNED_BYTE) {} // Can't do anything about this right now... if (ilutCurImage->Type == IL_BYTE) {} // Can't do anything about this right now... Bitmap = create_bitmap_ex(ilutCurImage->Bpp * 8, ilutCurImage->Width, ilutCurImage->Height); if (Bitmap == NULL) { return IL_FALSE; } memcpy(Bitmap->dat, ilutCurImage->Data, ilutCurImage->SizeOfData); // Should we make this toggleable? if (ilutCurImage->Bpp == 8 && ilutCurImage->Pal.PalType != IL_PAL_NONE) { // Use the image's palette if there is one // ilConvertPal is destructive to the original image // @TODO: Use new ilCopyPal!!! TempImage = ilNewImage(ilutCurImage->Width, ilutCurImage->Height, ilutCurImage->Depth, ilutCurImage->Bpp, 1); ilCopyImageAttr(TempImage, ilutCurImage); ilSetCurImage(TempImage); if (!ilConvertPal(IL_PAL_RGB24)) { destroy_bitmap(Bitmap); ilSetError(ILUT_ILLEGAL_OPERATION); return NULL; } for (; i < ilutCurImage->Pal.PalSize && i < 768; i += 3, j++) { Pal[j].r = TempImage->Pal.Palette[i+0]; Pal[j].g = TempImage->Pal.Palette[i+1]; Pal[j].b = TempImage->Pal.Palette[i+2]; Pal[j].filler = 255; } ilCloseImage(TempImage); ilSetCurImage(ilutCurImage); } return Bitmap; }
ILboolean ILAPIENTRY ilApplyPal(ILconst_string FileName) { ILimage Image, *CurImage = iCurImage; ILubyte *NewData; ILuint *PalInfo, NumColours, NumPix, MaxDist, DistEntry=0, i, j; ILint Dist1, Dist2, Dist3; ILboolean Same; ILenum Origin; // COL_CUBE *Cubes; if( iCurImage == NULL || (iCurImage->Format != IL_BYTE || iCurImage->Format != IL_UNSIGNED_BYTE) ) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } NewData = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth); if (NewData == NULL) { return IL_FALSE; } iCurImage = &Image; imemclear(&Image, sizeof(ILimage)); // IL_PAL_RGB24, because we don't want to make parts transparent that shouldn't be. if (!ilLoadPal(FileName) || !ilConvertPal(IL_PAL_RGB24)) { ifree(NewData); iCurImage = CurImage; return IL_FALSE; } NumColours = Image.Pal.PalSize / 3; // RGB24 is 3 bytes per entry. PalInfo = (ILuint*)ialloc(NumColours * sizeof(ILuint)); if (PalInfo == NULL) { ifree(NewData); iCurImage = CurImage; return IL_FALSE; } NumPix = CurImage->SizeOfData / ilGetBppFormat(CurImage->Format); switch (CurImage->Format) { case IL_COLOUR_INDEX: iCurImage = CurImage; if (!ilConvertPal(IL_PAL_RGB24)) { ifree(NewData); ifree(PalInfo); return IL_FALSE; } NumPix = iCurImage->Pal.PalSize / ilGetBppPal(iCurImage->Pal.PalType); for (i = 0; i < NumPix; i++) { for (j = 0; j < Image.Pal.PalSize; j += 3) { // No need to perform a sqrt. Dist1 = (ILint)iCurImage->Pal.Palette[i] - (ILint)Image.Pal.Palette[j]; Dist2 = (ILint)iCurImage->Pal.Palette[i+1] - (ILint)Image.Pal.Palette[j+1]; Dist3 = (ILint)iCurImage->Pal.Palette[i+2] - (ILint)Image.Pal.Palette[j+2]; PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3; } MaxDist = UINT_MAX; DistEntry = 0; for (j = 0; j < NumColours; j++) { if (PalInfo[j] < MaxDist) { DistEntry = j; MaxDist = PalInfo[j]; } } iCurImage->Pal.Palette[i] = DistEntry; } for (i = 0; i < iCurImage->SizeOfData; i++) { NewData[i] = iCurImage->Pal.Palette[iCurImage->Data[i]]; } break; case IL_RGB: case IL_RGBA: /*Cube = (COL_CUBE*)ialloc(NumColours * sizeof(COL_CUBE)); // @TODO: Check if ialloc failed here! for (i = 0; i < NumColours; i++) memcpy(&Cubes[i].Val, Image.Pal.Palette[i * 3], 3); for (j = 0; j < 3; j++) { qsort(Cubes, NumColours, sizeof(COL_CUBE), sort_func); Cubes[0].Min = 0; Cubes[NumColours-1] = UCHAR_MAX; NumColours--; for (i = 1; i < NumColours; i++) { Cubes[i].Min[CurSort] = Cubes[i-1].Val[CurSort] + 1; Cubes[i-1].Max[CurSort] = Cubes[i].Val[CurSort] - 1; } CurSort++; NumColours++; }*/ for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) { Same = IL_TRUE; if (i != 0) { for (j = 0; j < CurImage->Bpp; j++) { if (CurImage->Data[i-CurImage->Bpp+j] != CurImage->Data[i+j]) { Same = IL_FALSE; break; } } } if (Same) { NewData[i / CurImage->Bpp] = DistEntry; continue; } for (j = 0; j < Image.Pal.PalSize; j += 3) { // No need to perform a sqrt. Dist1 = (ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j]; Dist2 = (ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j+1]; Dist3 = (ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j+2]; PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3; } MaxDist = UINT_MAX; DistEntry = 0; for (j = 0; j < NumColours; j++) { if (PalInfo[j] < MaxDist) { DistEntry = j; MaxDist = PalInfo[j]; } } NewData[i / CurImage->Bpp] = DistEntry; } break; case IL_BGR: case IL_BGRA: for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) { for (j = 0; j < NumColours; j++) { // No need to perform a sqrt. PalInfo[j] = ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) * ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) + ((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) * ((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) + ((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]) * ((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]); } MaxDist = UINT_MAX; DistEntry = 0; for (j = 0; j < NumColours; j++) { if (PalInfo[j] < MaxDist) { DistEntry = j; MaxDist = PalInfo[j]; } } NewData[i / CurImage->Bpp] = DistEntry; } break; case IL_LUMINANCE: case IL_LUMINANCE_ALPHA: for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp ) { for (j = 0; j < NumColours; j++) { // No need to perform a sqrt. PalInfo[j] = ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) * ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) * ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]) * ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]); } MaxDist = UINT_MAX; DistEntry = 0; for (j = 0; j < NumColours; j++) { if (PalInfo[j] < MaxDist) { DistEntry = j; MaxDist = PalInfo[j]; } } NewData[i] = DistEntry; } break; default: // Should be no other! ilSetError(IL_INTERNAL_ERROR); return IL_FALSE; } iCurImage = CurImage; Origin = iCurImage->Origin; if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NewData)) { ifree(Image.Pal.Palette); ifree(PalInfo); ifree(NewData); return IL_FALSE; } iCurImage->Origin = Origin; iCurImage->Pal.Palette = Image.Pal.Palette; iCurImage->Pal.PalSize = Image.Pal.PalSize; iCurImage->Pal.PalType = Image.Pal.PalType; ifree(PalInfo); ifree(NewData); return IL_TRUE; }
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; 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; }
ILboolean ILAPIENTRY ilSavePal(ILconst_string FileName) { ILstring Ext = iGetExtension(FileName); if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } #ifndef _UNICODE if (FileName == NULL || strlen(FileName) < 1 || Ext == NULL) { #else if (FileName == NULL || wcslen(FileName) < 1 || Ext == NULL) { #endif//_UNICODE ilSetError(IL_INVALID_PARAM); return IL_FALSE; } if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType == IL_PAL_NONE) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!iStrCmp(Ext, IL_TEXT("pal"))) { return ilSaveJascPal(FileName); } ilSetError(IL_INVALID_EXTENSION); return IL_FALSE; } //! Saves a Paint Shop Pro formatted palette (.pal) file. ILboolean ilSaveJascPal(ILconst_string FileName) { FILE *PalFile; ILuint i, PalBpp, NumCols = ilGetInteger(IL_PALETTE_NUM_COLS); ILubyte *CurPal; if (iCurImage == NULL || NumCols == 0 || NumCols > 256) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } #ifndef _UNICODE if (FileName == NULL || strlen(FileName) < 5) { #else if (FileName == NULL || wcslen(FileName) < 5) { #endif//_UNICODE ilSetError(IL_INVALID_VALUE); return IL_FALSE; } if (!iCheckExtension(FileName, IL_TEXT("pal"))) { ilSetError(IL_INVALID_EXTENSION); return IL_FALSE; } if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { if (iFileExists(FileName)) { ilSetError(IL_FILE_ALREADY_EXISTS); return IL_FALSE; } } // Create a copy of the current palette and convert it to RGB24 format. CurPal = iCurImage->Pal.Palette; iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); if (!iCurImage->Pal.Palette) { iCurImage->Pal.Palette = CurPal; return IL_FALSE; } memcpy(iCurImage->Pal.Palette, CurPal, iCurImage->Pal.PalSize); if (!ilConvertPal(IL_PAL_RGB24)) { ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = CurPal; return IL_FALSE; } #ifndef _UNICODE PalFile = fopen(FileName, "wt"); #else PalFile = _wfopen(FileName, L"wt"); #endif//_UNICODE if (!PalFile) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } // Header needed on all .pal files fputs("JASC-PAL\n0100\n256\n", PalFile); PalBpp = ilGetBppPal(iCurImage->Pal.PalType); for (i = 0; i < iCurImage->Pal.PalSize; i += PalBpp) { fprintf(PalFile, "%d %d %d\n", iCurImage->Pal.Palette[i], iCurImage->Pal.Palette[i+1], iCurImage->Pal.Palette[i+2]); } NumCols = 256 - NumCols; for (i = 0; i < NumCols; i++) { fprintf(PalFile, "0 0 0\n"); } ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = CurPal; fclose(PalFile); return IL_TRUE; } //! Loads a Halo formatted palette (.pal) file. ILboolean ilLoadHaloPal(ILconst_string FileName) { ILHANDLE HaloFile; HALOHEAD HaloHead; ILushort *TempPal; ILuint i, Size; if (!iCheckExtension(FileName, IL_TEXT("pal"))) { ilSetError(IL_INVALID_EXTENSION); return IL_FALSE; } if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } HaloFile = iopenr(FileName); if (HaloFile == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } if (iread(&HaloHead, sizeof(HALOHEAD), 1) != 1) return IL_FALSE; if (HaloHead.Id != 'A' + ('H' << 8) || HaloHead.Version != 0xe3) { icloser(HaloFile); ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } Size = (HaloHead.MaxIndex + 1) * 3; TempPal = (ILushort*)ialloc(Size * sizeof(ILushort)); if (TempPal == NULL) { icloser(HaloFile); return IL_FALSE; } if (iread(TempPal, sizeof(ILushort), Size) != Size) { icloser(HaloFile); ifree(TempPal); return IL_FALSE; } if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = NULL; } iCurImage->Pal.PalType = IL_PAL_RGB24; iCurImage->Pal.PalSize = Size; iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); if (iCurImage->Pal.Palette == NULL) { icloser(HaloFile); return IL_FALSE; } for (i = 0; i < iCurImage->Pal.PalSize; i++, TempPal++) { iCurImage->Pal.Palette[i] = (ILubyte)*TempPal; } TempPal -= iCurImage->Pal.PalSize; ifree(TempPal); icloser(HaloFile); return IL_TRUE; }
void ilFConvertPal_(int *RetVal, int *DestFormat) { *RetVal = ilConvertPal(*DestFormat); }