ILboolean ILAPIENTRY ilApplyPal(const ILstring 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 ) { 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! break; } 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; }
//! Pushes the states indicated by Bits onto the state stack ILvoid ILAPIENTRY ilPushAttrib(ILuint Bits) { // Should we check here to see if ilCurrentPos is negative? if (ilCurrentPos >= IL_ATTRIB_STACK_MAX - 1) { ilCurrentPos = IL_ATTRIB_STACK_MAX - 1; ilSetError(IL_STACK_OVERFLOW); return; } ilCurrentPos++; // memcpy(&ilStates[ilCurrentPos], &ilStates[ilCurrentPos - 1], sizeof(IL_STATES)); ilDefaultStates(); if (Bits & IL_ORIGIN_BIT) { ilStates[ilCurrentPos].ilOriginMode = ilStates[ilCurrentPos-1].ilOriginMode; ilStates[ilCurrentPos].ilOriginSet = ilStates[ilCurrentPos-1].ilOriginSet; } if (Bits & IL_FORMAT_BIT) { ilStates[ilCurrentPos].ilFormatMode = ilStates[ilCurrentPos-1].ilFormatMode; ilStates[ilCurrentPos].ilFormatSet = ilStates[ilCurrentPos-1].ilFormatSet; } if (Bits & IL_TYPE_BIT) { ilStates[ilCurrentPos].ilTypeMode = ilStates[ilCurrentPos-1].ilTypeMode; ilStates[ilCurrentPos].ilTypeSet = ilStates[ilCurrentPos-1].ilTypeSet; } if (Bits & IL_FILE_BIT) { ilStates[ilCurrentPos].ilOverWriteFiles = ilStates[ilCurrentPos-1].ilOverWriteFiles; } if (Bits & IL_PAL_BIT) { ilStates[ilCurrentPos].ilAutoConvPal = ilStates[ilCurrentPos-1].ilAutoConvPal; } if (Bits & IL_LOADFAIL_BIT) { ilStates[ilCurrentPos].ilDefaultOnFail = ilStates[ilCurrentPos-1].ilDefaultOnFail; } if (Bits & IL_COMPRESS_BIT) { ilStates[ilCurrentPos].ilCompression = ilStates[ilCurrentPos-1].ilCompression; } if (Bits & IL_FORMAT_SPECIFIC_BIT) { ilStates[ilCurrentPos].ilTgaCreateStamp = ilStates[ilCurrentPos-1].ilTgaCreateStamp; ilStates[ilCurrentPos].ilJpgQuality = ilStates[ilCurrentPos-1].ilJpgQuality; ilStates[ilCurrentPos].ilPngInterlace = ilStates[ilCurrentPos-1].ilPngInterlace; ilStates[ilCurrentPos].ilTgaRle = ilStates[ilCurrentPos-1].ilTgaRle; ilStates[ilCurrentPos].ilBmpRle = ilStates[ilCurrentPos-1].ilBmpRle; ilStates[ilCurrentPos].ilSgiRle = ilStates[ilCurrentPos-1].ilSgiRle; ilStates[ilCurrentPos].ilJpgFormat = ilStates[ilCurrentPos-1].ilJpgFormat; ilStates[ilCurrentPos].ilDxtcFormat = ilStates[ilCurrentPos-1].ilDxtcFormat; ilStates[ilCurrentPos].ilPcdPicNum = ilStates[ilCurrentPos-1].ilPcdPicNum; ilStates[ilCurrentPos].ilPngAlphaIndex = ilStates[ilCurrentPos-1].ilPngAlphaIndex; // Strings if (ilStates[ilCurrentPos].ilTgaId) ifree(ilStates[ilCurrentPos].ilTgaId); if (ilStates[ilCurrentPos].ilTgaAuthName) ifree(ilStates[ilCurrentPos].ilTgaAuthName); if (ilStates[ilCurrentPos].ilTgaAuthComment) ifree(ilStates[ilCurrentPos].ilTgaAuthComment); if (ilStates[ilCurrentPos].ilPngAuthName) ifree(ilStates[ilCurrentPos].ilPngAuthName); if (ilStates[ilCurrentPos].ilPngTitle) ifree(ilStates[ilCurrentPos].ilPngTitle); if (ilStates[ilCurrentPos].ilPngDescription) ifree(ilStates[ilCurrentPos].ilPngDescription); //2003-09-01: added tif strings if (ilStates[ilCurrentPos].ilTifDescription) ifree(ilStates[ilCurrentPos].ilTifDescription); if (ilStates[ilCurrentPos].ilTifHostComputer) ifree(ilStates[ilCurrentPos].ilTifHostComputer); if (ilStates[ilCurrentPos].ilTifDocumentName) ifree(ilStates[ilCurrentPos].ilTifDocumentName); if (ilStates[ilCurrentPos].ilTifAuthName) ifree(ilStates[ilCurrentPos].ilTifAuthName); if (ilStates[ilCurrentPos].ilCHeader) ifree(ilStates[ilCurrentPos].ilCHeader); ilStates[ilCurrentPos].ilTgaId = ilStrDup(ilStates[ilCurrentPos-1].ilTgaId); ilStates[ilCurrentPos].ilTgaAuthName = ilStrDup(ilStates[ilCurrentPos-1].ilTgaAuthName); ilStates[ilCurrentPos].ilTgaAuthComment = ilStrDup(ilStates[ilCurrentPos-1].ilTgaAuthComment); ilStates[ilCurrentPos].ilPngAuthName = ilStrDup(ilStates[ilCurrentPos-1].ilPngAuthName); ilStates[ilCurrentPos].ilPngTitle = ilStrDup(ilStates[ilCurrentPos-1].ilPngTitle); ilStates[ilCurrentPos].ilPngDescription = ilStrDup(ilStates[ilCurrentPos-1].ilPngDescription); //2003-09-01: added tif strings ilStates[ilCurrentPos].ilTifDescription = ilStrDup(ilStates[ilCurrentPos-1].ilTifDescription); ilStates[ilCurrentPos].ilTifHostComputer = ilStrDup(ilStates[ilCurrentPos-1].ilTifHostComputer); ilStates[ilCurrentPos].ilTifDocumentName = ilStrDup(ilStates[ilCurrentPos-1].ilTifDocumentName); ilStates[ilCurrentPos].ilTifAuthName = ilStrDup(ilStates[ilCurrentPos-1].ilTifAuthName); ilStates[ilCurrentPos].ilCHeader = ilStrDup(ilStates[ilCurrentPos-1].ilCHeader); } return; }
// Internal function used to save the Jpeg. ILboolean iSaveJpegInternal(ILimage* image) { struct jpeg_compress_struct JpegInfo; struct jpeg_error_mgr Error; JSAMPROW row_pointer[1]; ILimage *TempImage; ILubyte *TempData; ILenum Type = 0; if (image == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } /*if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) Quality = 85; // Not sure how low we should dare go... else Quality = 99;*/ if ((image->Format != IL_RGB && image->Format != IL_LUMINANCE) || image->Bpc != 1) { TempImage = iConvertImage(image, IL_RGB, IL_UNSIGNED_BYTE); if (TempImage == NULL) { return IL_FALSE; } } else { TempImage = image; } if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { TempData = iGetFlipped(TempImage); if (TempData == NULL) { if (TempImage != image) ilCloseImage(TempImage); return IL_FALSE; } } else { TempData = TempImage->Data; } JpegInfo.err = jpeg_std_error(&Error); // Now we can initialize the JPEG compression object. jpeg_create_compress(&JpegInfo); //jpeg_stdio_dest(&JpegInfo, JpegFile); devil_jpeg_write_init(&JpegInfo); JpegInfo.image_width = TempImage->Width; // image width and height, in pixels JpegInfo.image_height = TempImage->Height; JpegInfo.input_components = TempImage->Bpp; // # of color components per pixel // John Villar's addition if (TempImage->Bpp == 1) JpegInfo.in_color_space = JCS_GRAYSCALE; else JpegInfo.in_color_space = JCS_RGB; jpeg_set_defaults(&JpegInfo); /*#ifndef IL_USE_JPEGLIB_UNMODIFIED Type = iGetInt(IL_JPG_SAVE_FORMAT); if (Type == IL_EXIF) { JpegInfo.write_JFIF_header = FALSE; JpegInfo.write_EXIF_header = TRUE; } else if (Type == IL_JFIF) { JpegInfo.write_JFIF_header = TRUE; JpegInfo.write_EXIF_header = FALSE; } //EXIF not present in libjpeg... #else*/ Type = Type; JpegInfo.write_JFIF_header = TRUE; //#endif//IL_USE_JPEGLIB_UNMODIFIED // Set the quality output jpeg_set_quality(&JpegInfo, iGetInt(IL_JPG_QUALITY), IL_TRUE); // Sets progressive saving here if (ilGetBoolean(IL_JPG_PROGRESSIVE)) jpeg_simple_progression(&JpegInfo); jpeg_start_compress(&JpegInfo, IL_TRUE); //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer while (JpegInfo.next_scanline < JpegInfo.image_height) { // jpeg_write_scanlines expects an array of pointers to scanlines. // Here the array is only one element long, but you could pass // more than one scanline at a time if that's more convenient. row_pointer[0] = &TempData[JpegInfo.next_scanline * TempImage->Bps]; (void) jpeg_write_scanlines(&JpegInfo, row_pointer, 1); } // Step 6: Finish compression jpeg_finish_compress(&JpegInfo); // Step 7: release JPEG compression object // This is an important step since it will release a good deal of memory. jpeg_destroy_compress(&JpegInfo); if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) ifree(TempData); if (TempImage != image) ilCloseImage(TempImage); return IL_TRUE; }
// From the DTE sources (mostly by Denton Woods with corrections by Randy Heit) ILboolean iLoadDoomInternal() { ILshort width, height, graphic_header[2], column_loop, row_loop; ILint column_offset, pointer_position, first_pos; ILubyte post, topdelta, length; ILubyte *NewData; ILuint i; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } first_pos = itell(); // Needed to go back to the offset table width = GetLittleShort(); height = GetLittleShort(); graphic_header[0] = GetLittleShort(); // Not even used graphic_header[1] = GetLittleShort(); // Not even used if (!ilTexImage(width, height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE); if (iCurImage->Pal.Palette == NULL) { return IL_FALSE; } iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE; iCurImage->Pal.PalType = IL_PAL_RGB24; memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE); // 247 is always the transparent colour (usually cyan) memset(iCurImage->Data, 247, iCurImage->SizeOfData); for (column_loop = 0; column_loop < width; column_loop++) { column_offset = GetLittleInt(); pointer_position = itell(); iseek(first_pos + column_offset, IL_SEEK_SET); while (1) { if (iread(&topdelta, 1, 1) != 1) return IL_FALSE; if (topdelta == 255) break; if (iread(&length, 1, 1) != 1) return IL_FALSE; if (iread(&post, 1, 1) != 1) return IL_FALSE; // Skip extra byte for scaling for (row_loop = 0; row_loop < length; row_loop++) { if (iread(&post, 1, 1) != 1) return IL_FALSE; if (row_loop + topdelta < height) iCurImage->Data[(row_loop+topdelta) * width + column_loop] = post; } iread(&post, 1, 1); // Skip extra scaling byte } iseek(pointer_position, IL_SEEK_SET); } // Converts palette entry 247 (cyan) to transparent. if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4); if (NewData == NULL) { return IL_FALSE; } for (i = 0; i < iCurImage->SizeOfData; i++) { NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0; } if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, 4, IL_RGBA, iCurImage->Type, NewData)) { ifree(NewData); return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; ifree(NewData); } ilFixImage(); return IL_TRUE; }
ILboolean GifGetData(ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, GFXCONTROL *Gfx) { ILubyte *sp; ILint code, fc, oc; ILubyte DisposalMethod = 0; ILint c, size; ILuint i = 0, Read = 0; if (!Gfx->Used) DisposalMethod = (Gfx->Packed & 0x1C) >> 2; if((size = igetc()) == IL_EOF) return IL_FALSE; if (size < 2 || 9 < size) { return IL_FALSE; } stack = (ILubyte*)ialloc(MAX_CODES + 1); suffix = (ILubyte*)ialloc(MAX_CODES + 1); prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1)); if (!stack || !suffix || !prefix) { ifree(stack); ifree(suffix); ifree(prefix); return IL_FALSE; } curr_size = size + 1; top_slot = 1 << curr_size; clear = 1 << size; ending = clear + 1; slot = newcodes = ending + 1; navail_bytes = nbits_left = 0; oc = fc = 0; sp = stack; success = IL_TRUE; while ((c = get_next_code()) != ending && Read < Height) { if (c == clear) { curr_size = size + 1; slot = newcodes; top_slot = 1 << curr_size; while ((c = get_next_code()) == clear); if (c == ending) break; if (c >= slot) c = 0; oc = fc = c; if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0) i++; else Data[i++] = c; if (i == Width) { Data += Stride; i = 0; Read += 1; } } else { code = c; if (code >= slot) { code = oc; *sp++ = fc; } while (code >= newcodes) { *sp++ = suffix[code]; code = prefix[code]; } *sp++ = (ILbyte)code; if (slot < top_slot) { fc = code; suffix[slot] = fc; prefix[slot++] = oc; oc = c; } if (slot >= top_slot && curr_size < 12) { top_slot <<= 1; curr_size++; } while (sp > stack) { sp--; if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0) i++; else Data[i++] = *sp; if (i == Width) { Data += Stride; i = 0; Read += 1; } } } } ifree(stack); ifree(suffix); ifree(prefix); return success; }
IDirect3DTexture9* ILAPIENTRY ilutD3D9Texture(IDirect3DDevice9 *Device) { IDirect3DTexture9 *Texture; // D3DLOCKED_RECT Rect; D3DFORMAT Format; ILimage *Image; ILenum DXTCFormat; ILuint Size; ILubyte *Buffer; Image = ilutCurImage = ilGetCurImage(); if (ilutCurImage == NULL) { ilSetError(ILUT_ILLEGAL_OPERATION); return NULL; } if (!FormatsDX9Checked) CheckFormatsDX9(Device); if (ilutGetBoolean(ILUT_D3D_USE_DXTC) && FormatsDX9supported[3] && FormatsDX9supported[4] && FormatsDX9supported[5]) { if (ilutCurImage->DxtcData != NULL && ilutCurImage->DxtcSize != 0) { ILuint dxtcFormat = ilutGetInteger(ILUT_DXTC_FORMAT); Format = D3DGetDXTCNumDX9(ilutCurImage->DxtcFormat); ilutSetInteger(ILUT_DXTC_FORMAT, ilutCurImage->DxtcFormat); Texture = iD3DMakeTexture(Device, ilutCurImage->DxtcData, ilutCurImage->DxtcSize, ilutCurImage->Width, ilutCurImage->Height, Format, ilutGetInteger(ILUT_D3D_POOL) == D3DPOOL_DEFAULT ? D3DPOOL_SYSTEMMEM : ilutGetInteger(ILUT_D3D_POOL), ilutGetInteger(ILUT_D3D_MIPLEVELS)); if (!Texture) return NULL; iD3D9CreateMipmaps(Texture, Image); if (ilutGetInteger(ILUT_D3D_POOL) == D3DPOOL_DEFAULT) { IDirect3DTexture9 *SysTex = Texture; // copy texture to device memory if (FAILED(IDirect3DDevice9_CreateTexture(Device, ilutCurImage->Width, ilutCurImage->Height, ilutGetInteger(ILUT_D3D_MIPLEVELS), 0, Format, D3DPOOL_DEFAULT, &Texture, NULL))) { IDirect3DTexture9_Release(SysTex); return NULL; } if (FAILED(IDirect3DDevice9_UpdateTexture(Device, (LPDIRECT3DBASETEXTURE9)SysTex, (LPDIRECT3DBASETEXTURE9)Texture))) { IDirect3DTexture9_Release(SysTex); return NULL; } IDirect3DTexture9_Release(SysTex); } ilutSetInteger(ILUT_DXTC_FORMAT, dxtcFormat); goto success; } if (ilutGetBoolean(ILUT_D3D_GEN_DXTC)) { DXTCFormat = ilutGetInteger(ILUT_DXTC_FORMAT); /* Image = MakeD3D9Compliant(Device, &Format); if (Image == NULL) { if (Image != ilutCurImage) ilCloseImage(Image); return NULL; } */ Size = ilGetDXTCData(NULL, 0, DXTCFormat); if (Size != 0) { Buffer = (ILubyte*)ialloc(Size); if (Buffer == NULL) return NULL; Size = ilGetDXTCData(Buffer, Size, DXTCFormat); if (Size == 0) { ifree(Buffer); return NULL; } Format = D3DGetDXTCNumDX9(DXTCFormat); Texture = iD3DMakeTexture(Device, Buffer, Size, ilutCurImage->Width, ilutCurImage->Height, Format, ilutGetInteger(ILUT_D3D_POOL) == D3DPOOL_DEFAULT ? D3DPOOL_SYSTEMMEM : ilutGetInteger(ILUT_D3D_POOL), ilutGetInteger(ILUT_D3D_MIPLEVELS)); if (!Texture) return NULL; iD3D9CreateMipmaps(Texture, Image); if (ilutGetInteger(ILUT_D3D_POOL) == D3DPOOL_DEFAULT) { IDirect3DTexture9 *SysTex = Texture; if (FAILED(IDirect3DDevice9_CreateTexture(Device, ilutCurImage->Width, ilutCurImage->Height, ilutGetInteger(ILUT_D3D_MIPLEVELS), 0, Format, D3DPOOL_DEFAULT, &Texture, NULL))) { IDirect3DTexture9_Release(SysTex); return NULL; } if (FAILED(IDirect3DDevice9_UpdateTexture(Device, (LPDIRECT3DBASETEXTURE9)SysTex, (LPDIRECT3DBASETEXTURE9)Texture))) { IDirect3DTexture9_Release(SysTex); return NULL; } IDirect3DTexture9_Release(SysTex); } goto success; } } } Image = MakeD3D9Compliant(Device, &Format); if (Image == NULL) { if (Image != ilutCurImage) ilCloseImage(Image); return NULL; } Texture = iD3DMakeTexture(Device, Image->Data, Image->SizeOfPlane, Image->Width, Image->Height, Format, ilutGetInteger(ILUT_D3D_POOL) == D3DPOOL_DEFAULT ? D3DPOOL_SYSTEMMEM : ilutGetInteger(ILUT_D3D_POOL), ilutGetInteger(ILUT_D3D_MIPLEVELS)); if (!Texture) return NULL; iD3D9CreateMipmaps(Texture, Image); if (ilutGetInteger(ILUT_D3D_POOL) == D3DPOOL_DEFAULT) { IDirect3DTexture9 *SysTex = Texture; // create texture in system memory if (FAILED(IDirect3DDevice9_CreateTexture(Device, Image->Width, Image->Height, ilutGetInteger(ILUT_D3D_MIPLEVELS), 0, Format, ilutGetInteger(ILUT_D3D_POOL), &Texture, NULL))) { IDirect3DTexture9_Release(SysTex); return NULL; } if (FAILED(IDirect3DDevice9_UpdateTexture(Device, (LPDIRECT3DBASETEXTURE9)SysTex, (LPDIRECT3DBASETEXTURE9)Texture))) { IDirect3DTexture9_Release(SysTex); return NULL; } IDirect3DTexture9_Release(SysTex); } // if (Image != ilutCurImage) // ilCloseImage(Image); success: if (Image != ilutCurImage) ilCloseImage(Image); return Texture; }
ILboolean iLoadXpmInternal() { #define BUFFER_SIZE 2000 ILubyte Buffer[BUFFER_SIZE], *Data; ILint Size, Pos, Width, Height, NumColours, i, x, y; ILint CharsPerPixel; #ifndef XPM_DONT_USE_HASHTABLE XPMHASHENTRY **HashTable; #else XpmPixel *Colours; ILint Offset; #endif Size = XpmGetsInternal(Buffer, BUFFER_SIZE); if (strncmp("/* XPM */", (char*)Buffer, strlen("/* XPM */"))) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } Size = XpmGets(Buffer, BUFFER_SIZE); // @TODO: Actually check the variable name here. Size = XpmGets(Buffer, BUFFER_SIZE); Pos = 0; Width = XpmGetInt(Buffer, Size, &Pos); Height = XpmGetInt(Buffer, Size, &Pos); NumColours = XpmGetInt(Buffer, Size, &Pos); CharsPerPixel = XpmGetInt(Buffer, Size, &Pos); #ifdef XPM_DONT_USE_HASHTABLE if (CharsPerPixel != 1) { ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } #endif if (CharsPerPixel > XPM_MAX_CHAR_PER_PIXEL || Width*CharsPerPixel > BUFFER_SIZE) { ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } #ifndef XPM_DONT_USE_HASHTABLE HashTable = XpmCreateHashTable(); if (HashTable == NULL) return IL_FALSE; #else Colours = ialloc(256 * sizeof(XpmPixel)); if (Colours == NULL) return IL_FALSE; #endif for (i = 0; i < NumColours; i++) { Size = XpmGets(Buffer, BUFFER_SIZE); #ifndef XPM_DONT_USE_HASHTABLE if (!XpmGetColour(Buffer, Size, CharsPerPixel, HashTable)) { XpmDestroyHashTable(HashTable); #else if (!XpmGetColour(Buffer, Size, CharsPerPixel, Colours)) { ifree(Colours); #endif return IL_FALSE; } } if (!ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { #ifndef XPM_DONT_USE_HASHTABLE XpmDestroyHashTable(HashTable); #else ifree(Colours); #endif return IL_FALSE; } Data = iCurImage->Data; for (y = 0; y < Height; y++) { Size = XpmGets(Buffer, BUFFER_SIZE); for (x = 0; x < Width; x++) { #ifndef XPM_DONT_USE_HASHTABLE XpmGetEntry(HashTable, &Buffer[1 + x*CharsPerPixel], CharsPerPixel, &Data[(x << 2)]); #else Offset = (x << 2); Data[Offset + 0] = Colours[Buffer[x + 1]][0]; Data[Offset + 1] = Colours[Buffer[x + 1]][1]; Data[Offset + 2] = Colours[Buffer[x + 1]][2]; Data[Offset + 3] = Colours[Buffer[x + 1]][3]; #endif } Data += iCurImage->Bps; } //added 20040218 iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; #ifndef XPM_DONT_USE_HASHTABLE XpmDestroyHashTable(HashTable); #else ifree(Colours); #endif return IL_TRUE; #undef BUFFER_SIZE }
// Internal function used to load the Tiff. ILboolean iLoadTiffInternal() { TIFF *tif; uint16 w, h, d, photometric, planarconfig; uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; ILubyte *pImageData; ILuint i, ProfileLen, DirCount = 0; ILvoid *Buffer; ILimage *Image; ILushort si; //TIFFRGBAImage img; //char emsg[1024]; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } TIFFSetWarningHandler(NULL); TIFFSetErrorHandler(NULL); //for debugging only //TIFFSetWarningHandler(warningHandler); //TIFFSetErrorHandler(errorHandler); tif = iTIFFOpen("r"); if (tif == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } do { DirCount++; } while (TIFFReadDirectory(tif)); /* if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { TIFFClose(tif); return IL_FALSE; } Image = iCurImage; for (i = 1; i < DirCount; i++) { Image->Next = ilNewImage(1, 1, 1, 1, 1); if (Image->Next == NULL) { TIFFClose(tif); return IL_FALSE; } Image = Image->Next; } iCurImage->NumNext = DirCount - 1; */ Image = NULL; for (i = 0; i < DirCount; i++) { TIFFSetDirectory(tif, (tdir_t)i); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &bitspersample); TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); //added 2003-08-31 //1 bpp tiffs are not neccessarily greyscale, they can //have a palette (photometric == 3)...get this information TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); if (samplesperpixel - extrasamples == 1) { //luminance or palette ILubyte* strip; tsize_t stripsize; ILuint y; uint32 rowsperstrip; if(!Image) { if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) { TIFFClose(tif); return IL_FALSE; } iCurImage->NumNext = 0; Image = iCurImage; } else { Image->Next = ilNewImage(w, h, 1, 1, 1); if(Image->Next == NULL) { TIFFClose(tif); return IL_FALSE; } Image = Image->Next; iCurImage->NumNext++; } TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); stripsize = TIFFStripSize(tif); strip = ialloc(stripsize); for(y = 0; y < h; y += rowsperstrip) { //if(y + rowsperstrip > h) // stripsize = (stripsize*(h - y))/rowsperstrip; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { ilSetError(IL_LIB_TIFF_ERROR); ifree(strip); TIFFClose(tif); return IL_FALSE; } } ifree(strip); } else {//rgb or rgba if(!Image) { if(!ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { TIFFClose(tif); return IL_FALSE; } iCurImage->NumNext = 0; Image = iCurImage; } else { Image->Next = ilNewImage(w, h, 1, 4, 1); if(Image->Next == NULL) { TIFFClose(tif); return IL_FALSE; } Image = Image->Next; iCurImage->NumNext++; } if (samplesperpixel == 4) { TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); if (!sampleinfo || sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED) { si = EXTRASAMPLE_ASSOCALPHA; TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &si); } } /* if (!ilResizeImage(Image, Image->Width, Image->Height, 1, 4, 1)) { TIFFClose(tif); return IL_FALSE; }*/ Image->Format = IL_RGBA; Image->Type = IL_UNSIGNED_BYTE; // Siigron: added u_long cast to shut up compiler warning //2003-08-31: changed flag from 1 (exit on error) to 0 (keep decoding) //this lets me view text.tif, but can give crashes with unsupported //tiffs... //2003-09-04: keep flag 1 for official version for now if (!TIFFReadRGBAImage(tif, Image->Width, Image->Height, (uint32*)Image->Data, 1)) { TIFFClose(tif); ilSetError(IL_LIB_TIFF_ERROR); return IL_FALSE; } } //else rgb or rgba if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &ProfileLen, &Buffer)) { if (Image->Profile && Image->ProfileSize) ifree(Image->Profile); Image->Profile = (ILubyte*)ialloc(ProfileLen); if (Image->Profile == NULL) { TIFFClose(tif); return IL_FALSE; } memcpy(Image->Profile, Buffer, ProfileLen); Image->ProfileSize = ProfileLen; //removed on 2003-08-24 as explained in bug 579574 on sourceforge //_TIFFfree(Buffer); } Image->Origin = IL_ORIGIN_LOWER_LEFT; // eiu...dunno if this is right /* Image = Image->Next; if (Image == NULL) // Should never happen except when we reach the end, but check anyway. break;*/ } //for tiff directories //TODO: put switch into the loop?? switch (samplesperpixel) { case 1: //added 2003-08-31 to keep palettized tiffs colored /* if(photometric != 3) ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE); else //strip alpha as tiff supports no alpha palettes ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);*/ break; case 3: //TODO: why the ifdef?? #ifdef __LITTLE_ENDIAN__ ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); #endif break; case 4: pImageData = iCurImage->Data; //removed on 2003-08-26...why was this here? libtiff should and does //take care of these things??? /* //invert alpha #ifdef __LITTLE_ENDIAN__ pImageData += 3; #endif for (i = iCurImage->Width * iCurImage->Height; i > 0; i--) { *pImageData ^= 255; pImageData += 4; } */ break; } TIFFClose(tif); ilFixImage(); return IL_TRUE; }
// Internal function used to save the Tiff. ILboolean iSaveTiffInternal(char *Filename) { ILenum Format; ILenum Compression; ILuint ixLine; TIFF *File; char Description[512]; ILimage *TempImage; if(iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) Compression = COMPRESSION_PACKBITS; else Compression = COMPRESSION_NONE; if (iCurImage->Format == IL_COLOUR_INDEX) { if (ilGetBppPal(iCurImage->Pal.PalType) == 4) // Preserve the alpha. TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); else TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); if (TempImage == NULL) { return IL_FALSE; } } else { TempImage = iCurImage; } File = TIFFOpen(Filename, "w"); //File = iTIFFOpen("w"); if (File == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } sprintf(Description, "Tiff generated by %s", ilGetString(IL_VERSION_NUM)); TIFFSetField(File, TIFFTAG_IMAGEWIDTH, TempImage->Width); TIFFSetField(File, TIFFTAG_IMAGELENGTH, TempImage->Height); TIFFSetField(File, TIFFTAG_COMPRESSION, Compression); TIFFSetField(File, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField(File, TIFFTAG_BITSPERSAMPLE, TempImage->Bpc << 3); TIFFSetField(File, TIFFTAG_SAMPLESPERPIXEL, TempImage->Bpp); TIFFSetField(File, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(File, TIFFTAG_ROWSPERSTRIP, 1); TIFFSetField(File, TIFFTAG_SOFTWARE, ilGetString(IL_VERSION_NUM)); /*TIFFSetField(File, TIFFTAG_DOCUMENTNAME, iGetString(IL_TIF_DOCUMENTNAME_STRING) ? iGetString(IL_TIF_DOCUMENTNAME_STRING) : FileName);*/ if (iGetString(IL_TIF_DOCUMENTNAME_STRING)) TIFFSetField(File, TIFFTAG_DOCUMENTNAME, iGetString(IL_TIF_DOCUMENTNAME_STRING)); if (iGetString(IL_TIF_AUTHNAME_STRING)) TIFFSetField(File, TIFFTAG_ARTIST, iGetString(IL_TIF_AUTHNAME_STRING)); if (iGetString(IL_TIF_HOSTCOMPUTER_STRING)) TIFFSetField(File, TIFFTAG_HOSTCOMPUTER, iGetString(IL_TIF_HOSTCOMPUTER_STRING)); if (iGetString(IL_TIF_DESCRIPTION_STRING)) TIFFSetField(File, TIFFTAG_IMAGEDESCRIPTION, iGetString(IL_TIF_DESCRIPTION_STRING)); TIFFSetField(File, TIFFTAG_DATETIME, iMakeString()); // 24/4/2003 // Orientation flag is not always supported ( Photoshop, ...), orient the image data // and set it always to normal view TIFFSetField(File, TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT ); if( TempImage->Origin != IL_ORIGIN_UPPER_LEFT ) { ILubyte *Data = iGetFlipped(TempImage); ifree( (void*)TempImage->Data ); TempImage->Data = Data; } /* TIFFSetField(File, TIFFTAG_ORIENTATION, TempImage->Origin == IL_ORIGIN_UPPER_LEFT ? ORIENTATION_TOPLEFT : ORIENTATION_BOTLEFT); */ Format = TempImage->Format; if (Format == IL_BGR || Format == IL_BGRA) ilSwapColours(); for (ixLine = 0; ixLine < TempImage->Height; ++ixLine) { if (TIFFWriteScanline(File, TempImage->Data + ixLine * TempImage->Bps, ixLine, 0) < 0) { TIFFClose(File); ilSetError(IL_LIB_TIFF_ERROR); return IL_FALSE; } } if (Format == IL_BGR || Format == IL_BGRA) ilSwapColours(); if (TempImage != iCurImage) ilCloseImage(TempImage); TIFFClose(File); return IL_TRUE; }
// Internal function used to load the Tiff. ILboolean iLoadTiffInternal() { TIFF *tif; uint16 w, h, d, photometric, planarconfig, orientation; uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; uint32 linesize, tilewidth, tilelength; ILubyte *pImageData; ILuint i, ProfileLen, DirCount = 0; ILvoid *Buffer; ILimage *Image, *TempImage; ILushort si; //TIFFRGBAImage img; //char emsg[1024]; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } TIFFSetWarningHandler(NULL); TIFFSetErrorHandler(NULL); //for debugging only //TIFFSetWarningHandler(warningHandler); //TIFFSetErrorHandler(errorHandler); tif = iTIFFOpen("r"); if (tif == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } do { DirCount++; } while (TIFFReadDirectory(tif)); /* if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { TIFFClose(tif); return IL_FALSE; } Image = iCurImage; for (i = 1; i < DirCount; i++) { Image->Next = ilNewImage(1, 1, 1, 1, 1); if (Image->Next == NULL) { TIFFClose(tif); return IL_FALSE; } Image = Image->Next; } iCurImage->NumNext = DirCount - 1; */ Image = NULL; for (i = 0; i < DirCount; i++) { TIFFSetDirectory(tif, (tdir_t)i); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); //TODO: d is ignored... TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation); linesize = TIFFScanlineSize(tif); //added 2003-08-31 //1 bpp tiffs are not neccessarily greyscale, they can //have a palette (photometric == 3)...get this information TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); #if 1 //special-case code for frequent data cases that may be read more //efficiently than with the TIFFReadRGBAImage() interface. //added 2004-05-12 //Get tile sizes and use TIFFReadRGBAImage() for tiled images for now tilewidth = w; tilelength = h; TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tilewidth); TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength); if (extrasamples == 0 && samplesperpixel == 1 //luminance or palette && (bitspersample == 8 || bitspersample == 1) && (photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_PALETTE) && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) && tilewidth == w && tilelength == h ) { ILubyte* strip; tsize_t stripsize; ILuint y; uint32 rowsperstrip, j, linesread; //TODO: 1 bit/pixel images should not be stored as 8 bits... //(-> add new format) if (!Image) { int type = IL_UNSIGNED_BYTE; if ( bitspersample == 16) type = IL_UNSIGNED_SHORT; if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) { TIFFClose(tif); return IL_FALSE; } iCurImage->NumNext = 0; Image = iCurImage; } else { Image->Next = ilNewImage(w, h, 1, 1, 1); if(Image->Next == NULL) { TIFFClose(tif); return IL_FALSE; } Image = Image->Next; iCurImage->NumNext++; } if (photometric == PHOTOMETRIC_PALETTE) { //read palette uint16 *red, *green, *blue; ILboolean is16bitpalette = IL_FALSE; ILubyte *entry; uint32 count = 1 << bitspersample, j; TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); Image->Format = IL_COLOUR_INDEX; Image->Pal.PalSize = (count)*3; Image->Pal.PalType = IL_PAL_RGB24; Image->Pal.Palette = ialloc(Image->Pal.PalSize); entry = Image->Pal.Palette; for (j = 0; j < count; ++j) { entry[0] = (ILubyte)(red[j] >> 8); entry[1] = (ILubyte)(green[j] >> 8); entry[2] = (ILubyte)(blue[j] >> 8); entry += 3; } } TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); stripsize = TIFFStripSize(tif); strip = ialloc(stripsize); if (bitspersample == 8) { ILubyte *dat = Image->Data; for (y = 0; y < h; y += rowsperstrip) { //the last strip may contain less data if the image //height is not evenly divisible by rowsperstrip if (y + rowsperstrip > h) { stripsize = linesize*(h - y); linesread = h - y; } else linesread = rowsperstrip; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { ilSetError(IL_LIB_TIFF_ERROR); ifree(strip); TIFFClose(tif); return IL_FALSE; } if (photometric == PHOTOMETRIC_MINISWHITE) { //invert channel uint32 k, t2; for (j = 0; j < linesread; ++j) { t2 = j*linesize; for (k = 0; k < w; ++k) dat[k] = ~strip[t2 + k]; dat += w; } } else for(j = 0; j < linesread; ++j) memcpy(&Image->Data[(y + j)*w], &strip[j*linesize], w); } } else if (bitspersample == 1) { //TODO: add a native format to devil, so we don't have to //unpack the values here ILubyte mask, curr, *dat = Image->Data; uint32 k, sx, t2; for (y = 0; y < h; y += rowsperstrip) { //the last strip may contain less data if the image //height is not evenly divisible by rowsperstrip if (y + rowsperstrip > h) { stripsize = linesize*(h - y); linesread = h - y; } else linesread = rowsperstrip; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { ilSetError(IL_LIB_TIFF_ERROR); ifree(strip); TIFFClose(tif); return IL_FALSE; } for (j = 0; j < linesread; ++j) { k = 0; sx = 0; t2 = j*linesize; while (k < w) { curr = strip[t2 + sx]; if (photometric == PHOTOMETRIC_MINISWHITE) curr = ~curr; for (mask = 0x80; mask != 0 && k < w; mask >>= 1){ if((curr & mask) != 0) dat[k] = 255; else dat[k] = 0; ++k; } ++sx; } dat += w; } } }
// Internal function to uncompress the .pcx (all .pcx files are rle compressed) ILboolean iUncompressPcx(PCXHEAD *Header) { //changed decompression loop 2003-09-01 //From the pcx spec: "There should always //be a decoding break at the end of each scan line. //But there will not be a decoding break at the end of //each plane within each scan line." //This is now handled correctly (hopefully ;) ) ILubyte ByteHead, Colour, *ScanLine /* For all planes */; ILuint ScanLineSize; ILuint c, i, x, y; if (Header->Bpp < 8) { /*ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE;*/ return iUncompressSmall(Header); } if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; switch (iCurImage->Bpp) { case 1: iCurImage->Format = IL_COLOUR_INDEX; iCurImage->Pal.PalType = IL_PAL_RGB24; iCurImage->Pal.PalSize = 256 * 3; // Need to find out for sure... iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); if (iCurImage->Pal.Palette == NULL) { return IL_FALSE; } break; //case 2: // No 16-bit images in the pcx format! case 3: iCurImage->Format = IL_RGB; iCurImage->Pal.Palette = NULL; iCurImage->Pal.PalSize = 0; iCurImage->Pal.PalType = IL_PAL_NONE; break; case 4: iCurImage->Format = IL_RGBA; iCurImage->Pal.Palette = NULL; iCurImage->Pal.PalSize = 0; iCurImage->Pal.PalType = IL_PAL_NONE; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } ScanLineSize = iCurImage->Bpp*Header->Bps; ScanLine = (ILubyte*)ialloc(ScanLineSize); if (ScanLine == NULL) { return IL_FALSE; } //changed 2003-09-01 //having the decoding code twice is error-prone, //so I made iUnCache() smart enough to grasp //if iPreCache() wasn't called and call it //anyways. if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) iPreCache(iCurImage->SizeOfData / 4); for (y = 0; y < iCurImage->Height; y++) { x = 0; //read scanline while (x < ScanLineSize) { if (iread(&ByteHead, 1, 1) != 1) { iUnCache(); goto file_read_error; } if ((ByteHead & 0xC0) == 0xC0) { ByteHead &= 0x3F; if (iread(&Colour, 1, 1) != 1) { iUnCache(); goto file_read_error; } if (x + ByteHead > ScanLineSize) { iUnCache(); goto file_read_error; } for (i = 0; i < ByteHead; i++) { ScanLine[x++] = Colour; } } else { ScanLine[x++] = ByteHead; } } //convert plane-separated scanline into index, rgb or rgba pixels. //there might be a padding byte at the end of each scanline... for (x = 0; x < iCurImage->Width; x++) { for(c = 0; c < iCurImage->Bpp; c++) { iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] = ScanLine[x + c * Header->Bps]; } } } iUnCache(); // Read in the palette if (Header->Version == 5 && iCurImage->Bpp == 1) { x = itell(); if (iread(&ByteHead, 1, 1) == 0) { // If true, assume that we have a luminance image. ilGetError(); // Get rid of the IL_FILE_READ_ERROR. iCurImage->Format = IL_LUMINANCE; if (iCurImage->Pal.Palette) ifree(iCurImage->Pal.Palette); iCurImage->Pal.PalSize = 0; iCurImage->Pal.PalType = IL_PAL_NONE; } else { if (ByteHead != 12) // Some Quake2 .pcx files don't have this byte for some reason. iseek(-1, IL_SEEK_CUR); if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) goto file_read_error; } } ifree(ScanLine); return IL_TRUE; file_read_error: ifree(ScanLine); //added 2003-09-01 ilSetError(IL_FILE_READ_ERROR); return IL_FALSE; }
EXPORT void IAfree( void *ptr, UINT attr ) { ifree(ptr, SelIMACB(attr)); }
// Internal function to uncompress the .dcx (all .dcx files are rle compressed) ILimage *iUncompressDcx(DCXHEAD *Header) { ILubyte ByteHead, Colour, *ScanLine = NULL /* Only one plane */; ILuint c, i, x, y;//, Read = 0; ILimage *Image = NULL; if (Header->Bpp < 8) { /*ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE;*/ return iUncompressDcxSmall(Header); } Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1); if (Image == NULL) return NULL; /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; }*/ Image->Origin = IL_ORIGIN_UPPER_LEFT; ScanLine = (ILubyte*)ialloc(Header->Bps); if (ScanLine == NULL) goto dcx_error; switch (Image->Bpp) { case 1: Image->Format = IL_COLOUR_INDEX; Image->Pal.PalType = IL_PAL_RGB24; Image->Pal.PalSize = 256 * 3; // Need to find out for sure... Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); if (Image->Pal.Palette == NULL) goto dcx_error; break; //case 2: // No 16-bit images in the dcx format! case 3: Image->Format = IL_RGB; Image->Pal.Palette = NULL; Image->Pal.PalSize = 0; Image->Pal.PalType = IL_PAL_NONE; break; case 4: Image->Format = IL_RGBA; Image->Pal.Palette = NULL; Image->Pal.PalSize = 0; Image->Pal.PalType = IL_PAL_NONE; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); goto dcx_error; } /*StartPos = itell(); Compressed = (ILubyte*)ialloc(Image->SizeOfData * 4 / 3); iread(Compressed, 1, Image->SizeOfData * 4 / 3); for (y = 0; y < Image->Height; y++) { for (c = 0; c < Image->Bpp; c++) { x = 0; while (x < Header->Bps) { ByteHead = Compressed[Read++]; if ((ByteHead & 0xC0) == 0xC0) { ByteHead &= 0x3F; Colour = Compressed[Read++]; for (i = 0; i < ByteHead; i++) { ScanLine[x++] = Colour; } } else { ScanLine[x++] = ByteHead; } } for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; } } } ifree(Compressed); iseek(StartPos + Read, IL_SEEK_SET);*/ //changed 2003-09-01 if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) iPreCache(iCurImage->SizeOfData); //TODO: because the .pcx-code was broken this //code is probably broken, too for (y = 0; y < Image->Height; y++) { for (c = 0; c < Image->Bpp; c++) { x = 0; while (x < Header->Bps) { if (iread(&ByteHead, 1, 1) != 1) { iUnCache(); goto dcx_error; } if ((ByteHead & 0xC0) == 0xC0) { ByteHead &= 0x3F; if (iread(&Colour, 1, 1) != 1) { iUnCache(); goto dcx_error; } for (i = 0; i < ByteHead; i++) { ScanLine[x++] = Colour; } } else { ScanLine[x++] = ByteHead; } } for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; } } } iUnCache(); ifree(ScanLine); // Read in the palette if (Image->Bpp == 1) { ByteHead = igetc(); // the value 12, because it signals there's a palette for some reason... // We should do a check to make certain it's 12... if (ByteHead != 12) iseek(-1, IL_SEEK_CUR); if (iread(Image->Pal.Palette, 1, Image->Pal.PalSize) != Image->Pal.PalSize) { ilCloseImage(Image); return NULL; } } return Image; dcx_error: ifree(ScanLine); ilCloseImage(Image); return NULL; }
ILboolean ILAPIENTRY ilApplyProfile(ILstring InProfile, ILstring OutProfile) { #ifndef IL_NO_LCMS cmsHPROFILE hInProfile, hOutProfile; cmsHTRANSFORM hTransform; ILubyte *Temp; ILint Format=0; #ifdef _UNICODE char AnsiName[512]; #endif//_UNICODE if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } switch (iCurImage->Type) { case IL_BYTE: case IL_UNSIGNED_BYTE: switch (iCurImage->Format) { case IL_LUMINANCE: Format = TYPE_GRAY_8; break; case IL_RGB: Format = TYPE_RGB_8; break; case IL_BGR: Format = TYPE_BGR_8; break; case IL_RGBA: Format = TYPE_RGBA_8; break; case IL_BGRA: Format = TYPE_BGRA_8; break; default: ilSetError(IL_INTERNAL_ERROR); return IL_FALSE; } break; case IL_SHORT: case IL_UNSIGNED_SHORT: switch (iCurImage->Format) { case IL_LUMINANCE: Format = TYPE_GRAY_16; break; case IL_RGB: Format = TYPE_RGB_16; break; case IL_BGR: Format = TYPE_BGR_16; break; case IL_RGBA: Format = TYPE_RGBA_16; break; case IL_BGRA: Format = TYPE_BGRA_16; break; default: ilSetError(IL_INTERNAL_ERROR); return IL_FALSE; } break; // These aren't supported right now. case IL_INT: case IL_UNSIGNED_INT: case IL_FLOAT: case IL_DOUBLE: ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (InProfile == NULL) { if (!iCurImage->Profile || !iCurImage->ProfileSize) { ilSetError(IL_INVALID_PARAM); return IL_FALSE; } hInProfile = iCurImage->Profile; } else { #ifndef _UNICODE hInProfile = cmsOpenProfileFromFile(InProfile, "r"); #else wcstombs(AnsiName, InProfile, 512); hInProfile = cmsOpenProfileFromFile(AnsiName, "r"); #endif//_UNICODE } #ifndef _UNICODE hOutProfile = cmsOpenProfileFromFile(OutProfile, "r"); #else wcstombs(AnsiName, OutProfile, 512); hOutProfile = cmsOpenProfileFromFile(AnsiName, "r"); #endif//_UNICODE hTransform = cmsCreateTransform(hInProfile, Format, hOutProfile, Format, INTENT_PERCEPTUAL, 0); Temp = (ILubyte*)ialloc(iCurImage->SizeOfData); if (Temp == NULL) { return IL_FALSE; } cmsDoTransform(hTransform, iCurImage->Data, Temp, iCurImage->SizeOfData / 3); ifree(iCurImage->Data); iCurImage->Data = Temp; cmsDeleteTransform(hTransform); if (InProfile != NULL) cmsCloseProfile(hInProfile); cmsCloseProfile(hOutProfile); #endif//IL_NO_LCMS return IL_TRUE; }
ILubyte *GetChannel(PspLoadState* state, ILimage* image) { BLOCKHEAD Block; CHANNEL_CHUNK Channel; ILubyte *CompData, *Data; ILuint ChunkSize, Padding; if (image->io.read(&image->io, &Block, 1, sizeof(Block)) != sizeof(Block)) return NULL; if (state->Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(&image->io); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { il2SetError(IL_ILLEGAL_FILE_VALUE); return NULL; } if (Block.BlockID != PSP_CHANNEL_BLOCK) { il2SetError(IL_ILLEGAL_FILE_VALUE); return NULL; } if (state->Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(&image->io); if (image->io.read(&image->io, &Channel, sizeof(Channel), 1) != 1) return NULL; Padding = (ChunkSize - 4) - sizeof(Channel); if (Padding > 0) image->io.seek(&image->io, Padding, IL_SEEK_CUR); } else { if (image->io.read(&image->io, &Channel, sizeof(Channel), 1) != 1) return NULL; } CompData = (ILubyte*)ialloc(Channel.CompLen); Data = (ILubyte*)ialloc(state->AttChunk.Width * state->AttChunk.Height); if (CompData == NULL || Data == NULL) { ifree(Data); ifree(CompData); return NULL; } if (image->io.read(&image->io, CompData, 1, Channel.CompLen) != Channel.CompLen) { ifree(CompData); ifree(Data); return NULL; } switch (state->AttChunk.Compression) { case PSP_COMP_NONE: ifree(Data); return CompData; break; case PSP_COMP_RLE: if (!UncompRLE(CompData, Data, Channel.CompLen)) { ifree(CompData); ifree(Data); return IL_FALSE; } break; default: ifree(CompData); ifree(Data); il2SetError(IL_INVALID_FILE_HEADER); return NULL; } ifree(CompData); return Data; }
// Needs some SERIOUS optimization. ILubyte *Filter(ILimage *Image, const ILint *matrix, ILint scale, ILint bias) { ILint x, y, c, LastX, LastY, Offsets[9]; ILuint i, Temp, z; ILubyte *Data, *ImgData, *NewData, *RegionMask; ILdouble Num; if (Image == NULL) { ilSetError(ILU_ILLEGAL_OPERATION); return NULL; } Data = (ILubyte*)ialloc(Image->SizeOfData); if (Data == NULL) { return NULL; } RegionMask = iScanFill(); // Preserve original data. ImgData = Image->Data; NewData = Data; for (z = 0; z < Image->Depth; z++) { LastX = Image->Width - 1; LastY = Image->Height - 1; for (y = 1; y < LastY; y++) { for (x = 1; x < LastX; x++) { Offsets[4] = ((y ) * Image->Width + (x )) * Image->Bpp; if (RegionMask) { if (!RegionMask[y * Image->Width + x]) { for (c = 0; c < Image->Bpp; c++) { Data[Offsets[4]+c] = Image->Data[Offsets[4]+c]; } continue; } } Offsets[0] = ((y-1) * Image->Width + (x-1)) * Image->Bpp; Offsets[1] = ((y-1) * Image->Width + (x )) * Image->Bpp; Offsets[2] = ((y-1) * Image->Width + (x+1)) * Image->Bpp; Offsets[3] = ((y ) * Image->Width + (x-1)) * Image->Bpp; Offsets[5] = ((y ) * Image->Width + (x+1)) * Image->Bpp; Offsets[6] = ((y+1) * Image->Width + (x-1)) * Image->Bpp; Offsets[7] = ((y+1) * Image->Width + (x )) * Image->Bpp; Offsets[8] = ((y+1) * Image->Width + (x-1)) * Image->Bpp; // Always has at least one, so get rid of all those +c's Num = Image->Data[Offsets[0]] * matrix[0] + Image->Data[Offsets[1]] * matrix[1]+ Image->Data[Offsets[2]] * matrix[2]+ Image->Data[Offsets[3]] * matrix[3]+ Image->Data[Offsets[4]] * matrix[4]+ Image->Data[Offsets[5]] * matrix[5]+ Image->Data[Offsets[6]] * matrix[6]+ Image->Data[Offsets[7]] * matrix[7]+ Image->Data[Offsets[8]] * matrix[8]; Temp = (ILuint)fabs((Num / (ILdouble)scale) + bias); if (Temp > 255) Data[Offsets[4]] = 255; else Data[Offsets[4]] = Temp; for (c = 1; c < Image->Bpp; c++) { Num = Image->Data[Offsets[0]+c] * matrix[0]+ Image->Data[Offsets[1]+c] * matrix[1]+ Image->Data[Offsets[2]+c] * matrix[2]+ Image->Data[Offsets[3]+c] * matrix[3]+ Image->Data[Offsets[4]+c] * matrix[4]+ Image->Data[Offsets[5]+c] * matrix[5]+ Image->Data[Offsets[6]+c] * matrix[6]+ Image->Data[Offsets[7]+c] * matrix[7]+ Image->Data[Offsets[8]+c] * matrix[8]; Temp = (ILuint)fabs((Num / (ILdouble)scale) + bias); if (Temp > 255) Data[Offsets[4]+c] = 255; else Data[Offsets[4]+c] = Temp; } } } // Copy 4 corners for (c = 0; c < Image->Bpp; c++) { Data[c] = Image->Data[c]; Data[Image->Bps - Image->Bpp + c] = Image->Data[Image->Bps - Image->Bpp + c]; Data[(Image->Height - 1) * Image->Bps + c] = Image->Data[(Image->Height - 1) * Image->Bps + c]; Data[Image->Height * Image->Bps - Image->Bpp + c] = Image->Data[Image->Height * Image->Bps - Image->Bpp + c]; } // If we only copy the edge pixels, then they receive no filtering, making them // look out of place after several passes of an image. So we filter the edge // rows/columns, duplicating the edge pixels for one side of the "matrix". // First row for (x = 1; x < (ILint)Image->Width-1; x++) { if (RegionMask) { if (!RegionMask[x]) { Data[y + x * Image->Bpp + c] = Image->Data[y + x * Image->Bpp + c]; continue; } } for (c = 0; c < Image->Bpp; c++) { Num = Image->Data[(x-1) * Image->Bpp + c] * matrix[0] + Image->Data[x * Image->Bpp + c] * matrix[1]+ Image->Data[(x+1) * Image->Bpp + c] * matrix[2]+ Image->Data[(x-1) * Image->Bpp + c] * matrix[3]+ Image->Data[x * Image->Bpp + c] * matrix[4]+ Image->Data[(x+1) * Image->Bpp + c] * matrix[5]+ Image->Data[(Image->Width + (x-1)) * Image->Bpp + c] * matrix[6]+ Image->Data[(Image->Width + (x )) * Image->Bpp + c] * matrix[7]+ Image->Data[(Image->Width + (x-1)) * Image->Bpp + c] * matrix[8]; Temp = (ILuint)fabs((Num / (ILdouble)scale) + bias); if (Temp > 255) Data[x * Image->Bpp + c] = 255; else Data[x * Image->Bpp + c] = Temp; } } // Last row y = (Image->Height - 1) * Image->Bps; for (x = 1; x < (ILint)Image->Width-1; x++) { if (RegionMask) { if (!RegionMask[(Image->Height - 1) * Image->Width + x]) { Data[y + x * Image->Bpp + c] = Image->Data[y + x * Image->Bpp + c]; continue; } } for (c = 0; c < Image->Bpp; c++) { Num = Image->Data[y - Image->Bps + (x-1) * Image->Bpp + c] * matrix[0] + Image->Data[y - Image->Bps + x * Image->Bpp + c] * matrix[1]+ Image->Data[y - Image->Bps + (x+1) * Image->Bpp + c] * matrix[2]+ Image->Data[y + (x-1) * Image->Bpp + c] * matrix[3]+ Image->Data[y + x * Image->Bpp + c] * matrix[4]+ Image->Data[y + (x+1) * Image->Bpp + c] * matrix[5]+ Image->Data[y + (x-1) * Image->Bpp + c] * matrix[6]+ Image->Data[y + x * Image->Bpp + c] * matrix[7]+ Image->Data[y + (x-1) * Image->Bpp + c] * matrix[8]; Temp = (ILuint)fabs((Num / (ILdouble)scale) + bias); if (Temp > 255) Data[y + x * Image->Bpp + c] = 255; else Data[y + x * Image->Bpp + c] = Temp; } } // Left side for (i = 1, y = Image->Bps; i < Image->Height-1; i++, y += Image->Bps) { if (RegionMask) { if (!RegionMask[y / Image->Bpp]) { Data[y + c] = Image->Data[y + c]; continue; } } for (c = 0; c < Image->Bpp; c++) { Num = Image->Data[y - Image->Bps + c] * matrix[0] + Image->Data[y - Image->Bps + Image->Bpp + c] * matrix[1]+ Image->Data[y - Image->Bps + 2 * Image->Bpp + c] * matrix[2]+ Image->Data[y + c] * matrix[3]+ Image->Data[y + Image->Bpp + c] * matrix[4]+ Image->Data[y + 2 * Image->Bpp + c] * matrix[5]+ Image->Data[y + Image->Bps + c] * matrix[6]+ Image->Data[y + Image->Bps + Image->Bpp + c] * matrix[7]+ Image->Data[y + Image->Bps + 2 * Image->Bpp + c] * matrix[8]; Temp = (ILuint)fabs((Num / (ILdouble)scale) + bias); if (Temp > 255) Data[y + c] = 255; else Data[y + c] = Temp; } } // Right side for (i = 1, y = Image->Bps * 2 - Image->Bpp; i < Image->Height-1; i++, y += Image->Bps) { if (RegionMask) { if (!RegionMask[y / Image->Bpp + (Image->Width - 1)]) { for (c = 0; c < Image->Bpp; c++) { Data[y + c] = Image->Data[y + c]; } continue; } } for (c = 0; c < Image->Bpp; c++) { Num = Image->Data[y - Image->Bps + c] * matrix[0] + Image->Data[y - Image->Bps + Image->Bpp + c] * matrix[1]+ Image->Data[y - Image->Bps + 2 * Image->Bpp + c] * matrix[2]+ Image->Data[y + c] * matrix[3]+ Image->Data[y + Image->Bpp + c] * matrix[4]+ Image->Data[y + 2 * Image->Bpp + c] * matrix[5]+ Image->Data[y + Image->Bps + c] * matrix[6]+ Image->Data[y + Image->Bps + Image->Bpp + c] * matrix[7]+ Image->Data[y + Image->Bps + 2 * Image->Bpp + c] * matrix[8]; Temp = (ILuint)fabs((Num / (ILdouble)scale) + bias); if (Temp > 255) Data[y + c] = 255; else Data[y + c] = Temp; } } // Go to next "plane". Image->Data += Image->SizeOfPlane; Data += Image->SizeOfPlane; } ifree(RegionMask); // Restore original data. Image->Data = ImgData; Data = NewData; return Data; }
ILboolean ReadLayerBlock(PspLoadState* state, ILuint BlockLen, ILimage* image) { BLOCKHEAD Block; LAYERINFO_CHUNK LayerInfo; LAYERBITMAP_CHUNK Bitmap; ILuint ChunkSize, Padding, i, j; ILushort NumChars; BlockLen; // Layer sub-block header if (image->io.read(&image->io, &Block, 1, sizeof(Block)) != sizeof(Block)) return IL_FALSE; if (state->Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(&image->io); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_FALSE; } if (Block.BlockID != PSP_LAYER_BLOCK) return IL_FALSE; if (state->Header.MajorVersion == 3) { image->io.seek(&image->io, 256, IL_SEEK_CUR); // We don't care about the name of the layer. image->io.read(&image->io, &LayerInfo, sizeof(LayerInfo), 1); if (image->io.read(&image->io, &Bitmap, sizeof(Bitmap), 1) != 1) return IL_FALSE; } else { // Header.MajorVersion >= 4 ChunkSize = GetLittleUInt(&image->io); NumChars = GetLittleUShort(&image->io); image->io.seek(&image->io, NumChars, IL_SEEK_CUR); // We don't care about the layer's name. ChunkSize -= (2 + 4 + NumChars); if (image->io.read(&image->io, &LayerInfo, IL_MIN(sizeof(LayerInfo), ChunkSize), 1) != 1) return IL_FALSE; // Can have new entries in newer versions of the spec (5.0). Padding = (ChunkSize) - sizeof(LayerInfo); if (Padding > 0) image->io.seek(&image->io, Padding, IL_SEEK_CUR); ChunkSize = GetLittleUInt(&image->io); if (image->io.read(&image->io, &Bitmap, sizeof(Bitmap), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4) - sizeof(Bitmap); if (Padding > 0) image->io.seek(&image->io, Padding, IL_SEEK_CUR); } state->Channels = (ILubyte**)ialloc(sizeof(ILubyte*) * Bitmap.NumChannels); if (state->Channels == NULL) { return IL_FALSE; } state->NumChannels = Bitmap.NumChannels; for (i = 0; i < state->NumChannels; i++) { state->Channels[i] = GetChannel(state, image); if (state->Channels[i] == NULL) { for (j = 0; j < i; j++) ifree(state->Channels[j]); return IL_FALSE; } } return IL_TRUE; }
// Could probably be optimized a bit...too many nested for loops. //! Pixelizes an image ILboolean ILAPIENTRY iluPixelize(ILuint PixSize) { ILuint x, y, z, i, j, k, c, r, Total, Tested; ILushort *ShortPtr; ILuint *IntPtr; ILdouble *DblPtr, DblTotal, DblTested; ILubyte *RegionMask; iluCurImage = ilGetCurImage(); if (iluCurImage == NULL) { ilSetError(ILU_ILLEGAL_OPERATION); return IL_FALSE; } if (PixSize == 0) PixSize = 1; r = 0; if (iluCurImage->Format == IL_COLOUR_INDEX) ilConvertImage(ilGetPalBaseType(iluCurImage->Pal.PalType), IL_UNSIGNED_BYTE); RegionMask = iScanFill(); switch (iluCurImage->Bpc) { case 1: for (z = 0; z < iluCurImage->Depth; z += PixSize) { for (y = 0; y < iluCurImage->Height; y += PixSize) { for (x = 0; x < iluCurImage->Width; x += PixSize) { for (c = 0; c < iluCurImage->Bpp; c++) { Total = 0; Tested = 0; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, Tested++) { Total += iluCurImage->Data[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c]; } } } Total /= Tested; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, Tested++) { if (RegionMask) { if (!RegionMask[(y+j) * iluCurImage->Width + (x+i)]) continue; } iluCurImage->Data[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c] = Total; } } } } } } } break; case 2: ShortPtr = (ILushort*)iluCurImage->Data; iluCurImage->Bps /= 2; for (z = 0; z < iluCurImage->Depth; z += PixSize) { for (y = 0; y < iluCurImage->Height; y += PixSize) { for (x = 0; x < iluCurImage->Width; x += PixSize, r += PixSize) { for (c = 0; c < iluCurImage->Bpp; c++) { Total = 0; Tested = 0; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, Tested++) { Total += ShortPtr[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c]; } } } Total /= Tested; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, Tested++) { if (RegionMask[r+i]) { ShortPtr[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c] = Total; } } } } } } } } iluCurImage->Bps *= 2; break; case 4: IntPtr = (ILuint*)iluCurImage->Data; iluCurImage->Bps /= 4; for (z = 0; z < iluCurImage->Depth; z += PixSize) { for (y = 0; y < iluCurImage->Height; y += PixSize) { for (x = 0; x < iluCurImage->Width; x += PixSize, r += PixSize) { for (c = 0; c < iluCurImage->Bpp; c++) { Total = 0; Tested = 0; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, Tested++) { Total += IntPtr[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c]; } } } Total /= Tested; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, Tested++) { if (RegionMask[r+i]) { IntPtr[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c] = Total; } } } } } } } } iluCurImage->Bps *= 4; break; case 8: DblPtr = (ILdouble*)iluCurImage->Data; iluCurImage->Bps /= 8; for (z = 0; z < iluCurImage->Depth; z += PixSize) { for (y = 0; y < iluCurImage->Height; y += PixSize) { for (x = 0; x < iluCurImage->Width; x += PixSize, r += PixSize) { for (c = 0; c < iluCurImage->Bpp; c++) { DblTotal = 0.0; DblTested = 0.0; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, DblTested++) { DblTotal += DblPtr[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c]; } } } DblTotal /= DblTested; for (k = 0; k < PixSize && z+k < iluCurImage->Depth; k++) { for (j = 0; j < PixSize && y+j < iluCurImage->Height; j++) { for (i = 0; i < PixSize && x+i < iluCurImage->Width; i++, DblTested++) { if (RegionMask[r+i]) { DblPtr[(z+k) * iluCurImage->SizeOfPlane + (y+j) * iluCurImage->Bps + (x+i) * iluCurImage->Bpp + c] = DblTotal; } } } } } } } } iluCurImage->Bps *= 8; break; } ifree(RegionMask); return IL_TRUE; }
ILboolean iD3D9CreateMipmaps(IDirect3DTexture9 *Texture, ILimage *Image) { D3DLOCKED_RECT Rect; D3DSURFACE_DESC Desc; ILuint NumMips, Width, Height, i; ILimage *CurImage, *MipImage, *Temp; ILenum DXTCFormat; ILuint Size; ILubyte *Buffer; ILboolean useDXTC = IL_FALSE; NumMips = IDirect3DTexture9_GetLevelCount(Texture); Width = Image->Width; Height = Image->Height; if (NumMips == 1) return IL_TRUE; CurImage = ilGetCurImage(); MipImage = Image; if (MipImage->NumMips != NumMips-1) { MipImage = ilCopyImage_(Image); ilSetCurImage(MipImage); if (!iluBuildMipmaps()) { ilCloseImage(MipImage); ilSetCurImage(CurImage); return IL_FALSE; } } // ilSetCurImage(CurImage); Temp = MipImage->Mipmaps; if (ilutGetBoolean(ILUT_D3D_USE_DXTC) && FormatsDX9supported[3] && FormatsDX9supported[4] && FormatsDX9supported[5]) useDXTC = IL_TRUE; // Counts the base texture as 1. for (i = 1; i < NumMips && Temp != NULL; i++) { ilSetCurImage(Temp); if (FAILED(IDirect3DTexture9_LockRect(Texture, i, &Rect, NULL, 0))) return IL_FALSE; Width = IL_MAX(1, Width / 2); Height = IL_MAX(1, Height / 2); IDirect3DTexture9_GetLevelDesc(Texture, i, &Desc); if (Desc.Width != Width || Desc.Height != Height) { IDirect3DTexture9_UnlockRect(Texture, i); return IL_FALSE; } if (useDXTC) { if (Temp->DxtcData != NULL && Temp->DxtcSize != 0) { memcpy(Rect.pBits, Temp->DxtcData, Temp->DxtcSize); } else if (ilutGetBoolean(ILUT_D3D_GEN_DXTC)) { DXTCFormat = ilutGetInteger(ILUT_DXTC_FORMAT); Size = ilGetDXTCData(NULL, 0, DXTCFormat); if (Size != 0) { Buffer = (ILubyte*)ialloc(Size); if (Buffer == NULL) { IDirect3DTexture9_UnlockRect(Texture, i); return IL_FALSE; } Size = ilGetDXTCData(Buffer, Size, DXTCFormat); if (Size == 0) { ifree(Buffer); IDirect3DTexture9_UnlockRect(Texture, i); return IL_FALSE; } memcpy(Rect.pBits, Buffer, Size); } else { IDirect3DTexture9_UnlockRect(Texture, i); return IL_FALSE; } } else { IDirect3DTexture9_UnlockRect(Texture, i); return IL_FALSE; } } else memcpy(Rect.pBits, Temp->Data, Temp->SizeOfData); IDirect3DTexture9_UnlockRect(Texture, i); Temp = Temp->Next; } if (MipImage != Image) ilCloseImage(MipImage); ilSetCurImage(CurImage); return IL_TRUE; }
/* * remove a file from the vfs: */ void rm(const char* pathname) { /* ensure present */ unsigned int dinode_no = namei(pathname); if (dinode_no == 0) { printf("No such file or directory\n"); return; } /* not a file but a directory */ struct inode_t* pinode = iget(dinode_no); if (pinode->type != 'f') { printf("Is a directory\n"); iput(pinode); return; } iput(pinode); /* release the inode */ /* * check the open_file[100] * if the file is being opened, denied to remove */ int i; for (i=0; i<100; i++) { if (open_file[i].count > 0 && open_file[i].pinode->dino == dinode_no) { printf("the file is already opened\n"); return; } } /* * get the current dir, then delete the target * dinode under the current directory by searching * all the nodes below it */ pinode = iget(cur_dir_dinode_no); struct directory_t dir; fseek(fd, pinode->addr[0] * SBLOCK, 0); fread(&dir, 1, sizeof(dir), fd); for (i=0; i<dir.size; i++) { if (dir.files[i].dino == dinode_no) { /* move the stack-top element to the dead one's * place, and the stack shrink */ dir.size--; dir.files[i] = dir.files[dir.size]; break; /* stop searching */ } } /* write back the current dir */ fseek(fd, pinode->addr[0] * SBLOCK, 0); fwrite(&dir, 1, sizeof(dir), fd); iput(pinode); /* free the blocks of the target file */ pinode = iget(dinode_no); for (i=0; i<pinode->size; i++) { bfree(pinode->addr[i]); } iput(pinode); /* finally free the d_inode */ ifree(dinode_no); return; }
// Internal function used to load the Jpeg2000 stream. ILboolean iLoadJp2Internal(jas_stream_t *Stream, ILimage *Image) { jas_image_t *Jp2Image = NULL; jas_matrix_t *origdata; ILuint x, y, c, Error; ILimage *TempImage; // Decode image Jp2Image = jas_image_decode(Stream, -1, 0); if (!Jp2Image) { ilSetError(IL_ILLEGAL_FILE_VALUE); jas_stream_close(Stream); return IL_FALSE; } // JasPer likes to buffer a lot, so it may try buffering past the end // of the file. iread naturally sets IL_FILE_READ_ERROR if it tries // reading past the end of the file, but this actually is not an error. Error = ilGetError(); // Put the error back if it is not IL_FILE_READ_ERROR. if (Error != IL_FILE_READ_ERROR) ilSetError(Error); // We're not supporting anything other than 8 bits/component yet. if (jas_image_cmptprec(Jp2Image, 0) != 8) { jas_image_destroy(Jp2Image); ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } switch (jas_image_numcmpts(Jp2Image)) { //@TODO: Can we do alpha data? jas_image_cmpttype always returns 0 for this case. case 1: // Assuming this is luminance data. if (Image == NULL) { ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); TempImage = iCurImage; } else { ifree(Image->Data); // @TODO: Not really the most efficient way to do this... ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); TempImage = Image; } break; case 2: // Assuming this is luminance-alpha data. if (Image == NULL) { ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL); TempImage = iCurImage; } else { ifree(Image->Data); // @TODO: Not really the most efficient way to do this... ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL); TempImage = Image; } break; case 3: if (Image == NULL) { ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); TempImage = iCurImage; } else { ifree(Image->Data); // @TODO: Not really the most efficient way to do this... ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); TempImage = Image; } break; case 4: if (Image == NULL) { ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); TempImage = iCurImage; } else { ifree(Image->Data); // @TODO: Not really the most efficient way to do this... ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); TempImage = Image; } break; default: jas_image_destroy(Jp2Image); ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } TempImage->Origin = IL_ORIGIN_UPPER_LEFT; // JasPer stores the data channels separately. // I am assuming RGBA format. Is it possible for other formats to be included? for (c = 0; c < TempImage->Bpp; c++) { origdata = jas_matrix_create(TempImage->Height, TempImage->Width); if (!origdata) { ilSetError(IL_LIB_JP2_ERROR); return IL_FALSE; // @TODO: Error } // Have to convert data into an intermediate matrix format. if (jas_image_readcmpt(Jp2Image, c, 0, 0, TempImage->Width, TempImage->Height, origdata)) { return IL_FALSE; } for (y = 0; y < TempImage->Height; y++) { for (x = 0; x < TempImage->Width; x++) { TempImage->Data[y * TempImage->Width * TempImage->Bpp + x * TempImage->Bpp + c] = origdata->data_[y * origdata->numcols_ + x]; } } jas_matrix_destroy(origdata); } jas_image_destroy(Jp2Image); return ilFixImage(); }
/* * remove a directory from the vfs */ void rmdir(const char* pathname) { /* refuse to remove the root dir */ if (strcmp("/", pathname) == 0) return; /* refuse to remove the upper layer dir */ if (strcmp("..", pathname) == 0) return; /* ensure present */ unsigned int dinode_no = namei(pathname); if (dinode_no == 0) { printf("No such file or directory\n"); return; } /* not a directory but a file */ struct inode_t* pinode = iget(dinode_no); if (pinode->type != 'd') { printf("Is a file\n"); iput(pinode); /* release inode */ return; } /* * make sure it is directory and count * the files under it. if it has two or * more files, refuse to remove it */ struct directory_t dir; fseek(fd, pinode->addr[0] * SBLOCK, 0); fread(&dir, 1, sizeof(dir), fd); if (dir.size > 1) { printf("Directory not empty\n"); iput(pinode); return; } iput(pinode); /* release the pinode */ /* * get current dir, then delete the target dinode * under the current directory by searching all * the nodes below it */ pinode = iget(cur_dir_dinode_no); fseek(fd, pinode->addr[0] * SBLOCK, 0); fread(&dir, 1, sizeof(dir), fd); int i; for (i=0; i<dir.size; i++) { if (dir.files[i].dino == dinode_no) { /* * move the stack-top element to the dead one's * place */ dir.size--; dir.files[i] = dir.files[dir.size]; break; /* stop searching */ } } /* write back the current dir */ fseek(fd, pinode->addr[0] * SBLOCK, 0); fwrite(&dir, 1, sizeof(dir), fd); iput(pinode); /* release the inode */ /* free the block of the target dir */ pinode = iget(dinode_no); bfree(pinode->addr[0]); /* free the #block_no */ iput(pinode); /* free the target dinode */ ifree(dinode_no); return; }
ILboolean iLoadIffInternal(void) { iff_chunk chunkInfo; // -- Header info. ILuint width, height; ILuint flags, compress; ILushort tiles; ILenum format; ILubyte bpp; ILboolean tileImageDataFound; // -- Initialize the top of the chunk stack. chunkDepth = -1; // -- File should begin with a FOR4 chunk of type CIMG chunkInfo = iff_begin_read_chunk(); if (chunkInfo.chunkType != IFF_TAG_CIMG) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } /* * Read the image header * OK, we have a FOR4 of type CIMG, look for the following tags * FVER * TBHD bitmap header, definition of size, etc. * AUTH * DATE */ while (1) { chunkInfo = iff_begin_read_chunk(); // -- Right now, the only info we need about the image is in TBHD // -- so search this level until we find it. if( chunkInfo.tag == IFF_TAG_TBHD ) { // -- Header chunk found width = GetBigUInt(); height = GetBigUInt(); GetBigShort(); // -- Don't support GetBigShort(); // -- Don't support flags = GetBigUInt(); GetBigShort(); // -- Don't support tiles = GetBigUShort(); compress = GetBigUInt(); iff_end_read_chunk(); if( compress > 1 ) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } break; } else iff_end_read_chunk(); } /* END find TBHD while loop */ if (!(flags & RGB_FLAG)) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (flags & ALPHA_FLAG) { format = IL_RGBA; bpp = 4; } else { format = IL_RGB; bpp = 3; } if (!ilTexImage(width, height, 1, bpp, format, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; tileImageDataFound = IL_FALSE; while (!tileImageDataFound) { ILuint tileImage; ILuint tileZ; chunkInfo = iff_begin_read_chunk(); /* * OK, we have a FOR4 of type TBMP, (embedded FOR4) * look for the following tags * RGBA color data, RLE compressed tiles of 32 bbp data * ZBUF z-buffer data, 32 bit float values * CLPZ depth map specific, clipping planes, 2 float values * ESXY depth map specific, eye x-y ratios, 2 float values * HIST * VERS * FOR4 <size> BLUR (twice embedded FOR4) */ if (chunkInfo.chunkType != IFF_TAG_TBMP) { iff_end_read_chunk(); continue; } tileImageDataFound = IL_TRUE; tileImage = 0; // Si no RGBA, tileImage = tiles... if (flags & ZBUFFER_FLAG) tileZ = 0; else tileZ = tiles; // Read tiles while ( (tileImage < tiles) || (tileZ < tiles)) { char *tileData; ILushort x1, x2, y1, y2, tile_width, tile_height; ILuint remainingDataSize; ILushort tile_area; ILuint tileCompressed; chunkInfo = iff_begin_read_chunk(); if ((chunkInfo.tag != IFF_TAG_RGBA) && (chunkInfo.tag != IFF_TAG_ZBUF)) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } x1 = GetBigUShort(); y1 = GetBigUShort(); x2 = GetBigUShort(); y2 = GetBigUShort(); remainingDataSize = chunkInfo.size - 4*sizeof(ILushort); tile_width = x2 - x1 + 1; tile_height = y2 - y1 + 1; tile_area = tile_width * tile_height; if ((ILint)remainingDataSize >= (tile_width * tile_height * bpp)) tileCompressed = 0; else tileCompressed = 1; if (chunkInfo.tag == IFF_TAG_RGBA) { if (tileCompressed) { char *data = iff_read_data(remainingDataSize); if (data) { tileData = iff_decompress_tile_rle(tile_width, tile_height, bpp, data, remainingDataSize); ifree(data); } } else { tileData = iffReadUncompressedTile(tile_width, tile_height, bpp); } if (tileData) { // Dump RGBA data to our data structure ILushort i; ILuint base; base = bpp*(width * y1 + x1); for (i = 0; i < tile_height; i++) { memcpy(&iCurImage->Data[base + bpp*i*width], &tileData[bpp*i*tile_width], tile_width*bpp*sizeof(char)); } ifree(tileData); tileData = NULL; iff_end_read_chunk(); tileImage++; } else return IL_FALSE; } else if (chunkInfo.tag == IFF_TAG_ZBUF) { tileZ++; iff_end_read_chunk(); } } } //ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Why was this here? return ilFixImage(); }
ILboolean PsdGetData(ILimage* image, PSDHEAD *Head, void *Buffer, ILboolean Compressed, ILushort& ChannelNum) { ILuint c, x, y, i, Size, ReadResult, NumChan; ILubyte *Channel = NULL; ILushort *ShortPtr; ILuint *ChanLen = NULL; // Added 01-07-2009: This is needed to correctly load greyscale and // paletted images. switch (Head->Mode) { case 1: case 2: NumChan = 1; break; default: NumChan = 3; } Channel = (ILubyte*)ialloc(Head->Width * Head->Height * image->Bpc); if (Channel == NULL) { return IL_FALSE; } ShortPtr = (ILushort*)Channel; // @TODO: Add support for this in, though I have yet to run across a .psd // file that uses this. if (Compressed && image->Type == IL_UNSIGNED_SHORT) { il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!Compressed) { if (image->Bpc == 1) { for (c = 0; c < NumChan; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height, 1) != 1) { ifree(Channel); return IL_FALSE; } for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { image->Data[y + x + c] = Channel[i]; } } } // Accumulate any remaining channels into a single alpha channel //@TODO: This needs to be changed for greyscale images. for (; c < Head->Channels; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height, 1) != 1) { ifree(Channel); return IL_FALSE; } for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { float curVal = ubyte_to_float(image->Data[y + x + 3]); float newVal = ubyte_to_float(Channel[i]); image->Data[y + x + 3] = float_to_ubyte(curVal * newVal); } } } } else { // image->Bpc == 2 for (c = 0; c < NumChan; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height * 2, 1) != 1) { ifree(Channel); return IL_FALSE; } image->Bps /= 2; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { #ifndef WORDS_BIGENDIAN iSwapUShort(ShortPtr+i); #endif ((ILushort*)image->Data)[y + x + c] = ShortPtr[i]; } } image->Bps *= 2; } // Accumulate any remaining channels into a single alpha channel //@TODO: This needs to be changed for greyscale images. for (; c < Head->Channels; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height * 2, 1) != 1) { ifree(Channel); return IL_FALSE; } image->Bps /= 2; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { float curVal = ushort_to_float(((ILushort*)image->Data)[y + x + 3]); float newVal = ushort_to_float(ShortPtr[i]); ((ILushort*)image->Data)[y + x + 3] = float_to_ushort(curVal * newVal); } } image->Bps *= 2; } } } else { ChanLen = GetCompChanLen(image, Head, ChannelNum); Size = Head->Width * Head->Height; for (c = 0; c < NumChan; c++) { ReadResult = ReadCompressedChannel(image, ChanLen[c], Size, Channel); if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) goto file_corrupt; else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) goto file_read_error; i = 0; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { image->Data[y + x + c] = Channel[i]; } } } // Initialize the alpha channel to solid //@TODO: This needs to be changed for greyscale images. if (Head->Channels >= 4) { for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp) { image->Data[y + x + 3] = 255; } } for (; c < Head->Channels; c++) { ReadResult = ReadCompressedChannel(image, ChanLen[c], Size, Channel); if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) goto file_corrupt; else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) goto file_read_error; i = 0; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { float curVal = ubyte_to_float(image->Data[y + x + 3]); float newVal = ubyte_to_float(Channel[i]); image->Data[y + x + 3] = float_to_ubyte(curVal * newVal); } } } } ifree(ChanLen); } ifree(Channel); return IL_TRUE; file_corrupt: ifree(ChanLen); ifree(Channel); il2SetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; file_read_error: ifree(ChanLen); ifree(Channel); return IL_FALSE; }
ILboolean iIcnsReadData(ILboolean *BaseCreated, ILboolean IsAlpha, ILint Width, ICNSDATA *Entry, ILimage **Image) { ILint Position = 0, RLEPos = 0, Channel, i; ILubyte RLERead, *Data = NULL; ILimage *TempImage = NULL; ILboolean ImageAlreadyExists = IL_FALSE; // The .icns format stores the alpha and RGB as two separate images, so this // checks to see if one exists for that particular size. Unfortunately, // there is no guarantee that they are in any particular order. if (*BaseCreated && iCurImage != NULL) { TempImage = iCurImage; while (TempImage != NULL) { if ((ILuint)Width == TempImage->Width) { ImageAlreadyExists = IL_TRUE; break; } TempImage = TempImage->Next; } } Data = (ILubyte*)ialloc(Entry->Size - 8); if (Data == NULL) return IL_FALSE; if (!ImageAlreadyExists) { if (!*BaseCreated) // Create base image { ilTexImage(Width, Width, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; *Image = iCurImage; *BaseCreated = IL_TRUE; } else // Create next image in list { (*Image)->Next = ilNewImage(Width, Width, 1, 4, 1); *Image = (*Image)->Next; (*Image)->Format = IL_RGBA; (*Image)->Origin = IL_ORIGIN_UPPER_LEFT; } TempImage = *Image; } if (IsAlpha) // Alpha is never compressed. { iread(Data, Entry->Size - 8, 1); // Size includes the header if (Entry->Size - 8 != Width * Width) { ifree(Data); return IL_FALSE; } for (i = 0; i < Width * Width; i++) { TempImage->Data[(i * 4) + 3] = Data[i]; } } else if (Width == 256 || Width == 512) // JPEG2000 encoded - uses JasPer { #ifndef IL_NO_JP2 iread(Data, Entry->Size - 8, 1); // Size includes the header if (ilLoadJp2LInternal(Data, Entry->Size - 8, TempImage) == IL_FALSE) { ifree(Data); ilSetError(IL_LIB_JP2_ERROR); return IL_TRUE; } #else // Cannot handle this size. ilSetError(IL_LIB_JP2_ERROR); //@TODO: Handle this better...just skip the data. return IL_FALSE; #endif//IL_NO_JP2 } else // RGB data { iread(Data, Entry->Size - 8, 1); // Size includes the header if (Width == 128) RLEPos += 4; // There are an extra 4 bytes here of zeros. //@TODO: Should we check to make sure they are all 0? if (Entry->Size - 8 == Width * Width * 4) // Uncompressed { //memcpy(TempImage->Data, Data, Entry->Size); for (i = 0; i < Width * Width; i++, Position += 4) { TempImage->Data[i * 4 + 0] = Data[Position+1]; TempImage->Data[i * 4 + 1] = Data[Position+2]; TempImage->Data[i * 4 + 2] = Data[Position+3]; } } else // RLE decoding { for (Channel = 0; Channel < 3; Channel++) { Position = 0; while (Position < Width * Width) { RLERead = Data[RLEPos]; RLEPos++; if (RLERead >= 128) { for (i = 0; i < RLERead - 125 && (Position + i) < Width * Width; i++) { TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos]; } RLEPos++; Position += RLERead - 125; } else { for (i = 0; i < RLERead + 1 && (Position + i) < Width * Width; i++) { TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos + i]; } RLEPos += RLERead + 1; Position += RLERead + 1; } } } } } ifree(Data); return IL_TRUE; }
ILboolean ReadIndexed(ILimage* image, PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo, NumEnt; ILushort Compressed; ILubyte *Palette = NULL, *Resources = NULL; ILushort ChannelNum; ColorMode = GetBigUInt(&image->io); // Skip over the 'color mode data section' if (ColorMode % 3 != 0) { il2SetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } Palette = (ILubyte*)ialloc(ColorMode); if (Palette == NULL) return IL_FALSE; if (image->io.read(&image->io, Palette, 1, ColorMode) != ColorMode) goto cleanup_error; ResourceSize = GetBigUInt(&image->io); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) { return IL_FALSE; } if (image->io.read(&image->io, Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(&image->io); if (image->io.eof(&image->io)) goto cleanup_error; image->io.seek(&image->io, MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(&image->io); if (image->io.eof(&image->io)) goto cleanup_error; if (Head->Channels != 1 || Head->Depth != 8) { il2SetError(IL_FORMAT_NOT_SUPPORTED); goto cleanup_error; } ChannelNum = Head->Channels; if (!il2TexImage(image, Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) goto cleanup_error; if (!image->Pal.use(ColorMode/3, NULL, IL_PAL_RGB24)) { goto cleanup_error; } NumEnt = image->Pal.getNumCols(); for (ILuint j = 0; j < NumEnt; j++) { image->Pal.setRGB(j, Palette[j], Palette[j+NumEnt], Palette[j+NumEnt*2]); } ifree(Palette); Palette = NULL; if (!PsdGetData(image, Head, image->Data, (ILboolean)Compressed, ChannelNum)) goto cleanup_error; ParseResources(image, ResourceSize, Resources); ifree(Resources); Resources = NULL; return IL_TRUE; cleanup_error: ifree(Palette); ifree(Resources); return IL_FALSE; }
ILvoid ILAPIENTRY ilSetString(ILenum Mode, const char *String) { if (String == NULL) { ilSetError(IL_INVALID_PARAM); return; } switch (Mode) { case IL_TGA_ID_STRING: if (ilStates[ilCurrentPos].ilTgaId) ifree(ilStates[ilCurrentPos].ilTgaId); ilStates[ilCurrentPos].ilTgaId = ilStrDup(String); break; case IL_TGA_AUTHNAME_STRING: if (ilStates[ilCurrentPos].ilTgaAuthName) ifree(ilStates[ilCurrentPos].ilTgaAuthName); ilStates[ilCurrentPos].ilTgaAuthName = ilStrDup(String); break; case IL_TGA_AUTHCOMMENT_STRING: if (ilStates[ilCurrentPos].ilTgaAuthComment) ifree(ilStates[ilCurrentPos].ilTgaAuthComment); ilStates[ilCurrentPos].ilTgaAuthComment = ilStrDup(String); break; case IL_PNG_AUTHNAME_STRING: if (ilStates[ilCurrentPos].ilPngAuthName) ifree(ilStates[ilCurrentPos].ilPngAuthName); ilStates[ilCurrentPos].ilPngAuthName = ilStrDup(String); break; case IL_PNG_TITLE_STRING: if (ilStates[ilCurrentPos].ilPngTitle) ifree(ilStates[ilCurrentPos].ilPngTitle); ilStates[ilCurrentPos].ilPngTitle = ilStrDup(String); break; case IL_PNG_DESCRIPTION_STRING: if (ilStates[ilCurrentPos].ilPngDescription) ifree(ilStates[ilCurrentPos].ilPngDescription); ilStates[ilCurrentPos].ilPngDescription = ilStrDup(String); break; //2003-09-01: added tif strings case IL_TIF_DESCRIPTION_STRING: if (ilStates[ilCurrentPos].ilTifDescription) ifree(ilStates[ilCurrentPos].ilTifDescription); ilStates[ilCurrentPos].ilTifDescription = ilStrDup(String); break; case IL_TIF_HOSTCOMPUTER_STRING: if (ilStates[ilCurrentPos].ilTifHostComputer) ifree(ilStates[ilCurrentPos].ilTifHostComputer); ilStates[ilCurrentPos].ilTifHostComputer = ilStrDup(String); break; case IL_TIF_DOCUMENTNAME_STRING: if (ilStates[ilCurrentPos].ilTifDocumentName) ifree(ilStates[ilCurrentPos].ilTifDocumentName); ilStates[ilCurrentPos].ilTifDocumentName = ilStrDup(String); break; case IL_TIF_AUTHNAME_STRING: if (ilStates[ilCurrentPos].ilTifAuthName) ifree(ilStates[ilCurrentPos].ilTifAuthName); ilStates[ilCurrentPos].ilTifAuthName = ilStrDup(String); break; case IL_CHEAD_HEADER_STRING: if (ilStates[ilCurrentPos].ilCHeader) ifree(ilStates[ilCurrentPos].ilCHeader); ilStates[ilCurrentPos].ilCHeader = ilStrDup(String); break; default: ilSetError(IL_INVALID_ENUM); } return; }
ILboolean ReadRGB(ILimage* image, PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo; ILushort Compressed; ILenum Format, Type; ILubyte *Resources = NULL; ILushort ChannelNum; ColorMode = GetBigUInt(&image->io); // Skip over the 'color mode data section' image->io.seek(&image->io, ColorMode, IL_SEEK_CUR); ResourceSize = GetBigUInt(&image->io); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) return IL_FALSE; if (image->io.read(&image->io, Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(&image->io); image->io.seek(&image->io, MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(&image->io); ChannelNum = Head->Channels; if (Head->Channels == 3) { Format = IL_RGB; } else if (Head->Channels == 4) { Format = IL_RGBA; } else if (Head->Channels >= 5) { // Additional channels are accumulated as a single alpha channel, since // if an image does not have a layer set as the "background", but also // has a real alpha channel, there will be 5 channels (or more). Format = IL_RGBA; } else { il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } switch (Head->Depth) { case 8: Type = IL_UNSIGNED_BYTE; break; case 16: Type = IL_UNSIGNED_SHORT; break; default: il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!il2TexImage(image, Head->Width, Head->Height, 1, (Format==IL_RGB) ? 3 : 4, Format, Type, NULL)) goto cleanup_error; if (!PsdGetData(image, Head, image->Data, (ILboolean)Compressed, ChannelNum)) goto cleanup_error; if (!ParseResources(image, ResourceSize, Resources)) goto cleanup_error; ifree(Resources); return IL_TRUE; cleanup_error: ifree(Resources); return IL_FALSE; }
// Internal function used to save the Jpeg. ILboolean iSaveJpegInternal(ILstring FileName, void *Lump, ILuint Size) { JPEG_CORE_PROPERTIES Image; ILuint Quality; ILimage *TempImage; ILubyte *TempData; imemclear(&Image, sizeof(JPEG_CORE_PROPERTIES)); if (image == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (FileName == NULL && Lump == NULL) { ilSetError(IL_INVALID_PARAM); return IL_FALSE; } if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) Quality = 85; // Not sure how low we should dare go... else Quality = 99; if (ijlInit(&Image) != IJL_OK) { ilSetError(IL_LIB_JPEG_ERROR); return IL_FALSE; } if ((image->Format != IL_RGB && image->Format != IL_RGBA && image->Format != IL_LUMINANCE) || image->Bpc != 1) { if (image->Format == IL_BGRA) Temp = iConvertImage(image, IL_RGBA, IL_UNSIGNED_BYTE); else Temp = iConvertImage(image, IL_RGB, IL_UNSIGNED_BYTE); if (Temp == NULL) { return IL_FALSE; } } else { Temp = image; } if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { TempData = iGetFlipped(TempImage); if (TempData == NULL) { if (TempImage != image) ilCloseImage(TempImage); return IL_FALSE; } } else { TempData = TempImage->Data; } // Setup DIB Image.DIBWidth = TempImage->Width; Image.DIBHeight = TempImage->Height; Image.DIBChannels = TempImage->Bpp; Image.DIBBytes = TempData; Image.DIBPadBytes = 0; // Setup JPEG Image.JPGWidth = TempImage->Width; Image.JPGHeight = TempImage->Height; Image.JPGChannels = TempImage->Bpp; switch (Temp->Bpp) { case 1: Image.DIBColor = IJL_G; Image.JPGColor = IJL_G; Image.JPGSubsampling = IJL_NONE; break; case 3: Image.DIBColor = IJL_RGB; Image.JPGColor = IJL_YCBCR; Image.JPGSubsampling = IJL_411; break; case 4: Image.DIBColor = IJL_RGBA_FPX; Image.JPGColor = IJL_YCBCRA_FPX; Image.JPGSubsampling = IJL_4114; break; } if (FileName != NULL) { Image.JPGFile = FileName; if (ijlWrite(&Image, IJL_JFILE_WRITEWHOLEIMAGE) != IJL_OK) { if (TempImage != image) ilCloseImage(TempImage); ilSetError(IL_LIB_JPEG_ERROR); return IL_FALSE; } } else { Image.JPGBytes = Lump; Image.JPGSizeBytes = Size; if (ijlWrite(&Image, IJL_JBUFF_WRITEWHOLEIMAGE) != IJL_OK) { if (TempImage != image) ilCloseImage(TempImage); ilSetError(IL_LIB_JPEG_ERROR); return IL_FALSE; } } ijlFree(&Image); if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) ifree(TempData); if (Temp != image) ilCloseImage(Temp); return IL_TRUE; }
//! Loads a Paint Shop Pro formatted palette (.pal) file. ILboolean ilLoadJascPal(const ILstring FileName) { FILE *PalFile; ILuint NumColours, i, c; ILubyte Buff[BUFFLEN]; ILboolean Error = IL_FALSE; ILpal *Pal = &iCurImage->Pal; if (!iCheckExtension(FileName, IL_TEXT("pal"))) { ilSetError(IL_INVALID_EXTENSION); return IL_FALSE; } if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } #ifndef _WIN32_WCE PalFile = fopen(FileName, "rt"); #else PalFile = _wfopen(FileName, L"rt"); #endif//_WIN32_WCE if (PalFile == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); 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; } iFgetw(Buff, BUFFLEN, PalFile); if (stricmp((ILbyte*)Buff, "JASC-PAL")) { Error = IL_TRUE; } iFgetw(Buff, BUFFLEN, PalFile); if (stricmp((ILbyte*)Buff, "0100")) { Error = IL_TRUE; } iFgetw(Buff, BUFFLEN, PalFile); NumColours = atoi((ILbyte*)Buff); if (NumColours == 0 || Error) { ilSetError(IL_INVALID_FILE_HEADER); fclose(PalFile); return IL_FALSE; } Pal->PalSize = NumColours * PALBPP; Pal->PalType = IL_PAL_RGB24; Pal->Palette = (ILubyte*)ialloc(NumColours * PALBPP); if (Pal->Palette == NULL) { fclose(PalFile); return IL_FALSE; } for (i = 0; i < NumColours; i++) { for (c = 0; c < PALBPP; c++) { iFgetw(Buff, BUFFLEN, PalFile); Pal->Palette[i * PALBPP + c] = atoi((ILbyte*)Buff); } } fclose(PalFile); return IL_TRUE; }