// Internal function used to check if the HEADER is a valid DICOM header. ILboolean iCheckDicom(DICOMHEAD *Header) { // Always has the signature "DICM" at position 0x80. if (strncmp((const char*)Header->Signature, "DICM", 4)) return IL_FALSE; // Does not make sense to have any dimension = 0. if (Header->Width == 0 || Header->Height == 0 || Header->Depth == 0) return IL_FALSE; // We can only deal with images that have byte-aligned data. //@TODO: Take care of any others? if (Header->BitsAllocated % 8) return IL_FALSE; // Check for an invalid format being set (or not set at all). if (ilGetBppFormat(Header->Format) == 0) return IL_FALSE; // Check for an invalid type being set (or not set at all). if (ilGetBpcType(Header->Type) == 0) return IL_FALSE; return IL_TRUE; }
ILAPI void ILAPIENTRY il2SetPixels(ILimage* image, ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data) { void *Converted; if (image == NULL) { il2SetError(IL_ILLEGAL_OPERATION); return; } if (Data == NULL) { il2SetError(IL_INVALID_PARAM); return; } if (Format == image->Format && Type == image->Type) { Converted = (void*)Data; } else { Converted = ilConvertBuffer(Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type), Format, image->Format, Type, image->Type, NULL, Data); if (!Converted) return; } if (YOff + Height <= 1) { ilSetPixels1D(image, XOff, Width, Converted); } else if (ZOff + Depth <= 1) { ilSetPixels2D(image, XOff, YOff, Width, Height, Converted); } else { ilSetPixels3D(image, XOff, YOff, ZOff, Width, Height, Depth, Converted); } if (Format == image->Format && Type == image->Type) { return; } if (Converted != Data) ifree(Converted); return; }
// Internal function used to load the DICOM. ILboolean iLoadDicomInternal(void) { DICOMHEAD Header; ILuint i; ILushort TempS, *ShortPtr; ILfloat TempF, *FloatPtr; ILboolean Swizzle = IL_FALSE; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } // Clear the header to all 0s to make checks later easier. memset(&Header, 0, sizeof(DICOMHEAD)); if (!iGetDicomHead(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!iCheckDicom(&Header)) return IL_FALSE; if (!ilTexImage(Header.Width, Header.Height, Header.Depth, ilGetBppFormat(Header.Format), Header.Format, Header.Type, NULL)) return IL_FALSE; //@TODO: Find out if the origin is always in the upper left. iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Header.DataLen may be larger than SizeOfData, since it has to be padded with a NULL if it is not an even length, // so we just test to make sure it is at least large enough. //@TODO: Do this check before ilTexImage call. if (Header.DataLen < iCurImage->SizeOfData) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // We may have to swap the order of the data. #ifdef __BIG_ENDIAN__ if (!Header.BigEndian) { if (Header.Format == IL_RGB) Header.Format = IL_BGR; else if (Header.Format == IL_RGBA) Swizzle = IL_TRUE; } #else // Little endian if (Header.BigEndian) { if (Header.Format == IL_RGB) Header.Format = IL_BGR; if (Header.Format == IL_RGBA) Swizzle = IL_TRUE; } #endif switch (Header.Type) { case IL_UNSIGNED_BYTE: if (iread(iCurImage->Data, iCurImage->SizeOfData, 1) != 1) return IL_FALSE; // Swizzle the data from ABGR to RGBA. if (Swizzle) { for (i = 0; i < iCurImage->SizeOfData; i += 4) { iSwapUInt((ILuint*)(iCurImage->Data + i)); } } break; case IL_UNSIGNED_SHORT: for (i = 0; i < iCurImage->SizeOfData; i += 2) { *((ILushort*)(iCurImage->Data + i)) = GetShort(&Header, 0);//GetLittleUShort(); } // Swizzle the data from ABGR to RGBA. if (Swizzle) { ShortPtr = (ILushort*)iCurImage->Data; for (i = 0; i < iCurImage->SizeOfData / 2; i += 4) { TempS = ShortPtr[i]; ShortPtr[i] = ShortPtr[i+3]; ShortPtr[i+3] = TempS; } } break; case IL_FLOAT: for (i = 0; i < iCurImage->SizeOfData; i += 4) { *((ILfloat*)(iCurImage->Data + i)) = GetFloat(&Header, 0);//GetLittleFloat(); } // Swizzle the data from ABGR to RGBA. if (Swizzle) { FloatPtr = (ILfloat*)iCurImage->Data; for (i = 0; i < iCurImage->SizeOfData / 4; i += 4) { TempF = FloatPtr[i]; FloatPtr[i] = FloatPtr[i+3]; FloatPtr[i+3] = TempF; } } break; } return ilFixImage(); }
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; }
ILAPI ILuint ILAPIENTRY il2CopyPixels(ILimage* image, ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data) { void *Converted = NULL; ILubyte *TempBuff = NULL; ILuint SrcSize, DestSize; if (image == NULL) { il2SetError(IL_ILLEGAL_OPERATION); return 0; } DestSize = Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type); if (DestSize == 0) { return DestSize; } if (Data == NULL || Format == IL_COLOUR_INDEX) { il2SetError(IL_INVALID_PARAM); return 0; } SrcSize = Width * Height * Depth * image->Bpp * image->Bpc; if (Format == image->Format && Type == image->Type) { TempBuff = (ILubyte*)Data; } else { TempBuff = (ILubyte*)ialloc(SrcSize); if (TempBuff == NULL) { return 0; } } if (YOff + Height <= 1) { if (!ilCopyPixels1D(image, XOff, Width, TempBuff)) { goto failed; } } else if (ZOff + Depth <= 1) { if (!ilCopyPixels2D(image, XOff, YOff, Width, Height, TempBuff)) { goto failed; } } else { if (!ilCopyPixels3D(image, XOff, YOff, ZOff, Width, Height, Depth, TempBuff)) { goto failed; } } if (Format == image->Format && Type == image->Type) { return DestSize; } Converted = ilConvertBuffer(SrcSize, image->Format, Format, image->Type, Type, &image->Pal, TempBuff); if (Converted == NULL) goto failed; memcpy(Data, Converted, DestSize); ifree(Converted); if (TempBuff != Data) ifree(TempBuff); return DestSize; failed: if (TempBuff != Data) ifree(TempBuff); ifree(Converted); return 0; }