public void DumpErrors(string title) { int error = Il.ilGetError(); while (error != 0) { Console.WriteLine(title + ": Error #" + error + " Message: " + Ilu.iluErrorString(error)); error = Il.ilGetError(); } }
public static bool ReshapeToPowersOf2AndSave(Stream input, int size, string outputFileName) { InitializeIL(); InitializeILU(); // load the image ImageData data = new ImageData(); int imageID; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // create a temp buffer and copy the stream into it byte[] buffer = new byte[size]; int bytesRead = 0, byteOffset = 0, bytes = buffer.Length; do { bytesRead = input.Read(buffer, byteOffset, bytes); bytes -= bytesRead; byteOffset += bytesRead; } while (bytes > 0 && bytesRead > 0); Il.ilLoadL(Il.IL_TYPE_UNKNOWN, buffer, buffer.Length); // check errors int ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { throw new AxiomException("Error while loading image data: '{0}'", Ilu.iluErrorString(ilError)); } // determine dimensions & compute powers-of-2 reshape if needed int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); int newWidth = (int)Math.Pow(2, Math.Floor(Math.Log(width, 2))); int newHeight = (int)Math.Pow(2, Math.Floor(Math.Log(height, 2))); if (width != newWidth || height != newHeight) { // reshape // set the scale function filter & scale Ilu.iluImageParameter(Ilu.ILU_FILTER, Ilu.ILU_BILINEAR); // .ILU_SCALE_BSPLINE); Ilu.iluScale(newWidth, newHeight, 1); } // save Il.ilSetInteger(Il.IL_JPG_QUALITY, 50); Il.ilSaveImage(outputFileName); // drop image Il.ilDeleteImages(1, ref imageID); return(true); }
public Image(string filename) { // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // load the data into DevIL Il.ilLoadImage(filename); // check for an error int ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { throw new Exception(string.Format("Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError))); } format = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); bytesPerPixel = Math.Max(Il.ilGetInteger(Il.IL_IMAGE_BPC), Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL)); width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); stride = bytesPerPixel * width; // get the decoded data IntPtr ptr = Il.ilGetData(); // copy the data into the byte array pBuffer = (byte *)ptr; }
public TaoImage(string filename) { FileStream s = new FileStream(filename, FileMode.Open); int imageID; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // create a temp buffer and write the stream into it byte[] tmpBuffer = new byte[s.Length]; s.Read(tmpBuffer, 0, tmpBuffer.Length); // load the data into DevIL Il.ilLoadL(Il.IL_PNG, tmpBuffer, tmpBuffer.Length); // check for an error int ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { throw new Exception(string.Format("Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError))); } // flip the image so that the mosaics produced match what L3DT produces Ilu.iluFlipImage(); format = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); bytesPerPixel = Math.Max(Il.ilGetInteger(Il.IL_IMAGE_BPC), Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL)); Width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); Height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); // get the decoded data buffer = new byte[Width * Height * bytesPerPixel]; IntPtr ptr = Il.ilGetData(); // copy the data into the byte array unsafe { byte *pBuffer = (byte *)ptr; for (int i = 0; i < buffer.Length; i++) { buffer[i] = pBuffer[i]; } } // we won't be needing this anymore Il.ilDeleteImages(1, ref imageID); }
public override Codec.DecodeResult Decode(Stream input) { var imgData = new ImageData(); var output = new MemoryStream(); int imageID; int imageFormat, bytesPerPixel; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // create a temp buffer and write the stream into it var buffer = new byte[input.Length]; input.Read(buffer, 0, buffer.Length); // Put it right side up Il.ilEnable(Il.IL_ORIGIN_SET); Il.ilSetInteger(Il.IL_ORIGIN_MODE, Il.IL_ORIGIN_UPPER_LEFT); // Keep DXTC(compressed) data if present Il.ilSetInteger(Il.IL_KEEP_DXTC_DATA, Il.IL_TRUE); // load the data into DevIL Il.ilLoadL(this._ilType, buffer, buffer.Length); // check for an error var ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { throw new AxiomException("Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError)); } imageFormat = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); var imageType = Il.ilGetInteger(Il.IL_IMAGE_TYPE); // Convert image if imageType is incompatible with us (double or long) if (imageType != Il.IL_BYTE && imageType != Il.IL_UNSIGNED_BYTE && imageType != Il.IL_FLOAT && imageType != Il.IL_UNSIGNED_SHORT && imageType != Il.IL_SHORT) { Il.ilConvertImage(imageFormat, Il.IL_FLOAT); imageType = Il.IL_FLOAT; } // Converted paletted images if (imageFormat == Il.IL_COLOR_INDEX) { Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE); imageFormat = Il.IL_BGRA; imageType = Il.IL_UNSIGNED_BYTE; } // populate the image data bytesPerPixel = Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL); imgData.format = ILUtil.Convert(imageFormat, imageType); imgData.width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); imgData.height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); imgData.depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); imgData.numMipMaps = Il.ilGetInteger(Il.IL_NUM_MIPMAPS); if (imgData.format == PixelFormat.Unknown) { throw new AxiomException("Unsupported devil format ImageFormat={0} ImageType={1}", imageFormat, imageType); } // Check for cubemap var numFaces = Il.ilGetInteger(Il.IL_NUM_IMAGES) + 1; if (numFaces == 6) { imgData.flags |= ImageFlags.CubeMap; } else { numFaces = 1; // Support only 1 or 6 face images for now } // Keep DXT data (if present at all and the GPU supports it) var dxtFormat = Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT); if (dxtFormat != Il.IL_DXT_NO_COMP && Root.Instance.RenderSystem.Capabilities.HasCapability(Axiom.Graphics.Capabilities.TextureCompressionDXT)) { imgData.format = ILUtil.Convert(dxtFormat, imageType); imgData.flags |= ImageFlags.Compressed; // Validate that this devil version loads DXT mipmaps if (imgData.numMipMaps > 0) { Il.ilBindImage(imageID); Il.ilActiveMipmap(1); if ((uint)Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT) != dxtFormat) { imgData.numMipMaps = 0; LogManager.Instance.Write( "Warning: Custom mipmaps for compressed image were ignored because they are not loaded by this DevIL version."); } } } // Calculate total size from number of mipmaps, faces and size imgData.size = Image.CalculateSize(imgData.numMipMaps, numFaces, imgData.width, imgData.height, imgData.depth, imgData.format); // get the decoded data BufferBase BufferHandle; // Dimensions of current mipmap var width = imgData.width; var height = imgData.height; var depth = imgData.depth; // Transfer data for (var mip = 0; mip <= imgData.numMipMaps; ++mip) { for (var i = 0; i < numFaces; ++i) { Il.ilBindImage(imageID); if (numFaces > 1) { Il.ilActiveImage(i); } if (imgData.numMipMaps > 0) { Il.ilActiveMipmap(mip); } // Size of this face var imageSize = PixelUtil.GetMemorySize(width, height, depth, imgData.format); buffer = new byte[imageSize]; if ((imgData.flags & ImageFlags.Compressed) != 0) { // Compare DXT size returned by DevIL with our idea of the compressed size if (imageSize == Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat)) { // Retrieve data from DevIL using (BufferHandle = BufferBase.Wrap(buffer)) { Il.ilGetDXTCData(BufferHandle.Pin(), imageSize, dxtFormat); BufferHandle.UnPin(); } } else { LogManager.Instance.Write("Warning: compressed image size mismatch, devilsize={0} oursize={1}", Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat), imageSize); } } else { // Retrieve data from DevIL using (BufferHandle = BufferBase.Wrap(buffer)) { var dst = new PixelBox(width, height, depth, imgData.format, BufferHandle); ILUtil.ConvertFromIL(dst); } } // write the decoded data to the output stream output.Write(buffer, 0, buffer.Length); } // Next mip if (width != 1) { width /= 2; } if (height != 1) { height /= 2; } if (depth != 1) { depth /= 2; } } // Restore IL state Il.ilDisable(Il.IL_ORIGIN_SET); Il.ilDisable(Il.IL_FORMAT_SET); Il.ilDeleteImages(1, ref imageID); return(new DecodeResult(output, imgData)); }
public override void EncodeToFile(Stream input, string outFileName, Codec.CodecData codecData) { int imageID; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); var buffer = new byte[input.Length]; input.Read(buffer, 0, buffer.Length); var imgData = (ImageData)codecData; PixelBox src; using (var bufHandle = BufferBase.Wrap(buffer)) { src = new PixelBox(imgData.width, imgData.height, imgData.depth, imgData.format, bufHandle); } try { // Convert image from Axiom to current IL image ILUtil.ConvertToIL(src); } catch (Exception ex) { LogManager.Instance.Write("IL Failed image conversion :", ex.Message); } // flip the image Ilu.iluFlipImage(); // save the image to file Il.ilSaveImage(outFileName); var error = Il.ilGetError(); if (error != Il.IL_NO_ERROR) { LogManager.Instance.Write("IL Error, could not save file: {0} : {1}", outFileName, Ilu.iluErrorString(error)); } Il.ilDeleteImages(1, ref imageID); }
// create the texture and call the callback public void Notify() { Debug.Assert(Done); bool loaded = false; // need these in the callback for scaling images into picture frames (friendworld) int initialWidth = 0; int initialHeight = 0; try { if (sourceBuffer != null) { int imageID; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // Put it right side up Il.ilEnable(Il.IL_ORIGIN_SET); Il.ilSetInteger(Il.IL_ORIGIN_MODE, Il.IL_ORIGIN_UPPER_LEFT); // Keep DXTC(compressed) data if present Il.ilSetInteger(Il.IL_KEEP_DXTC_DATA, Il.IL_TRUE); // load the data into DevIL Il.ilLoadL(this.ilImageType, sourceBuffer, sourceBuffer.Length); // check for an error int ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { log.ErrorFormat("TextureFetcher: Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError)); throw new Exception("TextureFetcher: Error while decoding image data: " + Ilu.iluErrorString(ilError)); } int ilFormat = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); int imageType = Il.ilGetInteger(Il.IL_IMAGE_TYPE); // force conversion to 24-bit RGB image if ((imageType != Il.IL_BYTE && imageType != Il.IL_UNSIGNED_BYTE) || ilFormat != Il.IL_BGR) { ilFormat = Il.IL_BGR; imageType = Il.IL_UNSIGNED_BYTE; Il.ilConvertImage(ilFormat, imageType); } PixelFormat format = PixelFormat.R8G8B8; int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); int depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); int numMipMaps = Il.ilGetInteger(Il.IL_NUM_MIPMAPS) + 1; int numFaces = Il.ilGetInteger(Il.IL_NUM_IMAGES) + 1; initialWidth = width; initialHeight = height; if (numFaces > 1 || numMipMaps > 1) { log.WarnFormat("TextureFetcher: ignoring extra faces or mipmaps: faces={0}: mipmaps={1}", numFaces, numMipMaps); } if (destHeight == 0) { destHeight = height; } if (destWidth == 0) { destWidth = width; } int scaleX; int scaleY; int topFill = 0; int bottomFill = 0; int leftFill = 0; int rightFill = 0; if (keepAspect) { float scaleWidthFactor = (float)width / (float)destWidth; float scaleHeightFactor = (float)height / (float)destHeight; if (scaleWidthFactor > scaleHeightFactor) { scaleX = destWidth; scaleY = (int)(height / scaleWidthFactor); topFill = (destHeight - scaleY) / 2; bottomFill = destHeight - scaleY - topFill; } else { scaleX = (int)(width / scaleHeightFactor); scaleY = destHeight; leftFill = (destWidth - scaleX) / 2; rightFill = destWidth - scaleX - leftFill; } } else { scaleX = destWidth; scaleY = destWidth; } // scale the image if ((scaleX != width) || (scaleY != height)) { DoScale(scaleX, scaleY); width = scaleX; height = scaleY; } int imageSize = PixelUtil.GetMemorySize(destWidth, destHeight, depth, format); // set up buffer for the decoded data byte[] buffer = new byte[imageSize]; byte fillRed = (byte)(fillColor.r * 255.0); byte fillGreen = (byte)(fillColor.g * 255.0); byte fillBlue = (byte)(fillColor.b * 255.0); if (keepAspect) { // fill top for (int y = 0; y < topFill; y++) { int offset = y * destWidth * 3; for (int x = 0; x < destWidth; x++) { buffer[offset++] = fillBlue; buffer[offset++] = fillGreen; buffer[offset++] = fillRed; } } // copy the data IntPtr srcPtr = Il.ilGetData(); int srcOffset = 0; unsafe { byte *srcBytes = (byte *)srcPtr.ToPointer(); for (int y = topFill; y < topFill + height; y++) { int offset = y * destWidth * 3; for (int x = 0; x < leftFill; x++) { buffer[offset++] = fillBlue; buffer[offset++] = fillGreen; buffer[offset++] = fillRed; } for (int x = 0; x < width; x++) { buffer[offset++] = srcBytes[srcOffset++]; buffer[offset++] = srcBytes[srcOffset++]; buffer[offset++] = srcBytes[srcOffset++]; } for (int x = 0; x < rightFill; x++) { buffer[offset++] = fillBlue; buffer[offset++] = fillGreen; buffer[offset++] = fillRed; } } } // fill bottom for (int y = topFill + height; y < destHeight; y++) { int offset = y * destWidth * 3; for (int x = 0; x < destWidth; x++) { buffer[offset++] = fillBlue; buffer[offset++] = fillGreen; buffer[offset++] = fillRed; } } } else { // copy the data IntPtr srcPtr = Il.ilGetData(); unsafe { byte *srcBytes = (byte *)srcPtr.ToPointer(); for (int i = 0; i < imageSize; i++) { buffer[i] = srcBytes[i]; } } } // Restore IL state Il.ilDisable(Il.IL_ORIGIN_SET); Il.ilDisable(Il.IL_FORMAT_SET); // we won't be needing this anymore Il.ilDeleteImages(1, ref imageID); Image resultImage = Image.FromDynamicImage(buffer, destWidth, destHeight, depth, format); TextureManager.Instance.LoadImage(textureName, resultImage); loaded = true; resultImage.Dispose(); } } catch (Exception ex) { LogUtil.LogUtil.ExceptionLog.ErrorFormat("TextureFetcher: exception while decoding image: {0}", ex); } finally { doneHandler(textureName, initialWidth, initialHeight, loaded); } return; }
public override object Decode(Stream input, Stream output, params object[] args) { ImageData data = new ImageData(); int imageID; int format, bytesPerPixel, imageType; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // Put it right side up Il.ilEnable(Il.IL_ORIGIN_SET); Il.ilSetInteger(Il.IL_ORIGIN_MODE, Il.IL_ORIGIN_UPPER_LEFT); // Keep DXTC(compressed) data if present Il.ilSetInteger(Il.IL_KEEP_DXTC_DATA, Il.IL_TRUE); // create a temp buffer and write the stream into it byte[] buffer = new byte[input.Length]; input.Read(buffer, 0, buffer.Length); // load the data into DevIL Il.ilLoadL(this.ILType, buffer, buffer.Length); // check for an error int ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { throw new AxiomException("Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError)); } format = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); imageType = Il.ilGetInteger(Il.IL_IMAGE_TYPE); //bytesPerPixel = Math.Max(Il.ilGetInteger(Il.IL_IMAGE_BPC), // Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL)); // Convert image if ImageType is incompatible with us (double or long) if (imageType != Il.IL_BYTE && imageType != Il.IL_UNSIGNED_BYTE && imageType != Il.IL_FLOAT && imageType != Il.IL_UNSIGNED_SHORT && imageType != Il.IL_SHORT) { Il.ilConvertImage(format, Il.IL_FLOAT); imageType = Il.IL_FLOAT; } // Converted paletted images if (format == Il.IL_COLOUR_INDEX) { Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE); format = Il.IL_BGRA; imageType = Il.IL_UNSIGNED_BYTE; } bytesPerPixel = Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL); // populate the image data data.format = ILUtil.ConvertFromILFormat(format, imageType); data.width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); data.height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); data.depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); data.numMipMaps = Il.ilGetInteger(Il.IL_NUM_MIPMAPS); data.flags = 0; if (data.format == PixelFormat.Unknown) { Il.ilDeleteImages(1, ref imageID); throw new AxiomException("Unsupported DevIL format: ImageFormat = {0:x} ImageType = {1:x}", format, imageType); } // Check for cubemap // int cubeflags = Il.ilGetInteger(Il.IL_IMAGE_CUBEFLAGS); int numFaces = Il.ilGetInteger(Il.IL_NUM_IMAGES) + 1; if (numFaces == 6) { data.flags |= ImageFlags.CubeMap; } else { numFaces = 1; // Support only 1 or 6 face images for now } // Keep DXT data (if present at all and the GPU supports it) int dxtFormat = Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT); if (dxtFormat != Il.IL_DXT_NO_COMP && Root.Instance.RenderSystem.Caps.CheckCap(Axiom.Graphics.Capabilities.TextureCompressionDXT)) { data.format = ILUtil.ConvertFromILFormat(dxtFormat, imageType); data.flags |= ImageFlags.Compressed; // Validate that this devil version saves DXT mipmaps if (data.numMipMaps > 0) { Il.ilBindImage(imageID); Il.ilActiveMipmap(1); if (Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT) != dxtFormat) { data.numMipMaps = 0; LogManager.Instance.Write("Warning: Custom mipmaps for compressed image were ignored because they are not loaded by this DevIL version"); } } } // Calculate total size from number of mipmaps, faces and size data.size = Image.CalculateSize(data.numMipMaps, numFaces, data.width, data.height, data.depth, data.format); // set up buffer for the decoded data buffer = new byte[data.size]; // Pin the buffer, so we can use our PixelBox methods on it GCHandle bufGCHandle = new GCHandle(); bufGCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr bufPtr = bufGCHandle.AddrOfPinnedObject(); int offset = 0; // Dimensions of current mipmap int width = data.width; int height = data.height; int depth = data.depth; // Transfer data for (int mip = 0; mip <= data.numMipMaps; ++mip) { for (int i = 0; i < numFaces; ++i) { Il.ilBindImage(imageID); if (numFaces > 1) { Il.ilActiveImage(i); } if (data.numMipMaps > 0) { Il.ilActiveMipmap(mip); } /// Size of this face int imageSize = PixelUtil.GetMemorySize(width, height, depth, data.format); if ((data.flags & ImageFlags.Compressed) != 0) { // Compare DXT size returned by DevIL with our idea of the compressed size if (imageSize == Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat)) { // Retrieve data from DevIL byte[] tmpBuffer = new byte[imageSize]; Il.ilGetDXTCData(tmpBuffer, imageSize, dxtFormat); // Copy the data into our output buffer Array.Copy(tmpBuffer, 0, buffer, offset, tmpBuffer.Length); } else { LogManager.Instance.Write("Warning: compressed image size mismatch, devilsize={0} oursize={1}", Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat), imageSize); } } else { /// Retrieve data from DevIL PixelBox dst = new PixelBox(width, height, depth, data.format, bufPtr); dst.Offset = offset; ILUtil.ToAxiom(dst); } offset += imageSize; } /// Next mip if (width != 1) { width /= 2; } if (height != 1) { height /= 2; } if (depth != 1) { depth /= 2; } } // Restore IL state Il.ilDisable(Il.IL_ORIGIN_SET); Il.ilDisable(Il.IL_FORMAT_SET); // we won't be needing this anymore Il.ilDeleteImages(1, ref imageID); output.Write(buffer, 0, buffer.Length); // Free the buffer we allocated for the conversion. // I used bufPtr to store my data while I converted it. // I need to free it here. This invalidates bufPtr. // My data has already been copied to output. if (bufGCHandle.IsAllocated) { bufGCHandle.Free(); } return(data); }