예제 #1
0
        //-----------------------------------------------------------------------
        public static void ToAxiom(PixelBox dst)
        {
            if (!dst.Consecutive)
            {
                throw new NotImplementedException("Destination must currently be consecutive");
            }
            if (dst.Width != Il.ilGetInteger(Il.IL_IMAGE_WIDTH) ||
                dst.Height != Il.ilGetInteger(Il.IL_IMAGE_HEIGHT) ||
                dst.Depth != Il.ilGetInteger(Il.IL_IMAGE_DEPTH))
            {
                throw new AxiomException("Destination dimensions must equal IL dimension");
            }

            int ilfmt = Il.ilGetInteger(Il.IL_IMAGE_FORMAT);
            int iltp  = Il.ilGetInteger(Il.IL_IMAGE_TYPE);

            // Check if in-memory format just matches
            // If yes, we can just copy it and save conversion
            ILFormat ifmt = ILUtil.ConvertToILFormat(dst.Format);

            if (ifmt.format == ilfmt && ILabs(ifmt.type) == ILabs(iltp))
            {
                int size = Il.ilGetInteger(Il.IL_IMAGE_SIZE_OF_DATA);
                // Copy from the IL structure to our buffer
                PixelUtil.CopyBytes(dst.Data, dst.Offset, Il.ilGetData(), 0, size);
                return;
            }
            // Try if buffer is in a known OGRE format so we can use OGRE its
            // conversion routines
            PixelFormat bufFmt = ILUtil.ConvertFromILFormat(ilfmt, iltp);

            ifmt = ILUtil.ConvertToILFormat(bufFmt);

            if (ifmt.format == ilfmt && ILabs(ifmt.type) == ILabs(iltp))
            {
                // IL format matches another OGRE format
                PixelBox src = new PixelBox(dst.Width, dst.Height, dst.Depth, bufFmt, Il.ilGetData());
                PixelUtil.BulkPixelConversion(src, dst);
                return;
            }

#if NOT
            // The extremely slow method
            if (iltp == Il.IL_UNSIGNED_BYTE || iltp == Il.IL_BYTE)
            {
                ilToOgreInternal(static_cast <uint8 *>(dst.data), dst.format, (uint8)0x00, (uint8)0x00, (uint8)0x00, (uint8)0xFF);
            }
            else if (iltp == IL_FLOAT)
            {
                ilToOgreInternal(static_cast <uint8 *>(dst.data), dst.format, 0.0f, 0.0f, 0.0f, 1.0f);
            }
            else if (iltp == IL_SHORT || iltp == IL_UNSIGNED_SHORT)
            {
                ilToOgreInternal(static_cast <uint8 *>(dst.data), dst.format,
                                 (uint16)0x0000, (uint16)0x0000, (uint16)0x0000, (uint16)0xFFFF);
            }
            else
            {
                OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE,
                            "Cannot convert this DevIL type",
                            "ILUtil::ilToOgre");
            }
#else
            throw new NotImplementedException("Cannot convert this DevIL type");
#endif
        }
        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);
        }