module image.DevilLoader; private { import image.Image; import image.Loader; import derelict.devil.il; import utils.Memory; import std.stdio : writefln; static import std.file; } class DevilLoader : Loader { // TODO: 1d, 3d and cube textures // TODO: convert to fileWrapper override Image load(char[] filename) { writefln("DevilLoader.load(\"%s\")", filename); // TODO: generalize this ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT); Image result = new Image; ILuint ilId; { if (!std.file.exists(filename)) { writefln("File not found: '%s'", filename); return null; } void[] rawData = std.file.read(filename); ilGenImages(1, &ilId); ilBindImage(ilId); ilLoadL(IL_TYPE_UNKNOWN, &rawData[0], rawData.length); delete rawData; } result.dataFormat = DataFormat.Byte; uint w = ilGetInteger(IL_IMAGE_WIDTH); uint h = ilGetInteger(IL_IMAGE_HEIGHT); uint bpp = ilGetInteger(IL_IMAGE_BITS_PER_PIXEL); if (32 == bpp) { ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE); result.imageFormat = ImageFormat.RGBA; } else if (8 == bpp) { ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE); result.imageFormat = ImageFormat.Grayscale; } else { ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); result.imageFormat = ImageFormat.RGB; bpp = 24; } ImagePlane imgPlane = new ImagePlane; { void[] tmp = (cast(ubyte*)ilGetData())[0 .. w * h * bpp / 8]; imgPlane.data.alloc(tmp.length); imgPlane.data[] = tmp[]; } ilDeleteImages(1, &ilId); imgPlane.opaque = true; imgPlane.source = filename; imgPlane.width = w; imgPlane.height = h; imgPlane.depth = 1; // check if the image is opaque if (32 == bpp) { assert (imgPlane.data.length); foreach (uint i, ubyte a; cast(ubyte[])imgPlane.data) { if (i & 3 != 3) continue; // only check alpha if (a != 255) { imgPlane.opaque = false; break; } } } result.planes ~= imgPlane; return result; } this() { if (ilInit is null) { DerelictIL.load(); ilInit(); } } }