HaloMap.RawData.ParsedBitmap.DecodeBitm C# (CSharp) Method

DecodeBitm() public static method

The decode bitm.
/// ///
public static DecodeBitm ( byte bitmBytes, int height, int width, int depth, int bitsPerPixel, BitmapType type, BitmapFormat format, bool swizzle, Map map, int visualchunkindex, int ident ) : Bitmap
bitmBytes byte The bitm bytes.
height int The height.
width int The width.
depth int The depth.
bitsPerPixel int The bits per pixel.
type BitmapType The type.
format BitmapFormat The format.
swizzle bool The swizzle.
map HaloMap.Map.Map The map.
visualchunkindex int The visualchunkindex.
ident int The ident.
return System.Drawing.Bitmap
        public static Bitmap DecodeBitm(
            byte[] bitmBytes, 
            int height, 
            int width, 
            int depth, 
            int bitsPerPixel, 
            BitmapType type, 
            BitmapFormat format, 
            bool swizzle, 
            Map map, 
            int visualchunkindex, 
            int ident)
        {
            int stride = 0;

            #region Volume Textures / 3D
            if (type == BitmapType.BITM_TYPE_3D)
            {
                List<Bitmap> images = new List<Bitmap>();
                Bitmap finalImage = null;
                List<IntPtr> tPtr = new List<IntPtr>();
                if (swizzle)
                {
                    bitmBytes = Swizzler.Swizzle(bitmBytes, width, height, depth, bitsPerPixel, true);
                }

                try
                {
                    // Make our new image large enough to handle a square of all the images together with a 2 pixel pad between
                    int imageSize = width * height * bitsPerPixel >> 3;
                    int rCount = (int)(Math.Sqrt(depth) + 0.5);
                    int tWidth = rCount * (width + 1);
                    int tHeight = (int)Math.Round(depth / rCount + 0.5f, MidpointRounding.AwayFromZero) * (height + 2);

                    // Display 3D bitmaps combined as a 2D bitmap
                    if (visualchunkindex == 0)
                    {
                        for (int i = 0; i < depth; i++)
                        {
                            byte[] tempBytes = new byte[imageSize];
                            Array.Copy(bitmBytes, i * imageSize, tempBytes, 0, imageSize);

                            stride = DecodeBitmap(
                                ref tempBytes,
                                height,
                                width,
                                1,
                                bitsPerPixel,
                                type,
                                format,
                                false,
                                map,
                                visualchunkindex,
                                ident);

                            tPtr.Add(Marshal.AllocHGlobal(tempBytes.Length));
                            RtlMoveMemory(tPtr[tPtr.Count - 1], tempBytes, tempBytes.Length);
                            Bitmap bitmap = new Bitmap(
                                width, height, stride, PixelFormat.Format32bppArgb, tPtr[tPtr.Count - 1]);

                            images.Add(bitmap);
                        }
                    }
                    // Display only one of the 3D images
                    else
                    {
                        byte[] tempBytes = new byte[imageSize];
                        Array.Copy(bitmBytes, (visualchunkindex - 1) * imageSize, tempBytes, 0, imageSize);

                        stride = DecodeBitmap(
                            ref tempBytes,
                            height,
                            width,
                            1,
                            bitsPerPixel,
                            type,
                            format,
                            false,
                            map,
                            visualchunkindex,
                            ident);
                        tPtr.Add(Marshal.AllocHGlobal(tempBytes.Length));
                        RtlMoveMemory(tPtr[tPtr.Count - 1], tempBytes, tempBytes.Length);
                        images.Add(new Bitmap(width, height, stride, PixelFormat.Format32bppArgb, tPtr[tPtr.Count - 1]));
                        tWidth = width;
                        tHeight = height;
                    }

                    // create a bitmap to hold the combined image
                    finalImage = new Bitmap(tWidth, tHeight);

                    // get a graphics object from the image so we can draw on it
                    using (Graphics g = Graphics.FromImage(finalImage))
                    {
                        // set background color
                        g.Clear(Color.Empty);

                        // go through each image and draw it on the final image
                        int offset = 0;
                        foreach (Bitmap image in images)
                        {
                            g.DrawImage(
                                image,
                                new Rectangle(
                                    offset % tWidth, (offset / tWidth) * (image.Height + 1), image.Width, image.Height));
                            offset += image.Width + 1;
                        }
                    }
                    return finalImage;

                }
                catch (Exception ex)
                {
                    if (finalImage != null)
                    {
                        finalImage.Dispose();
                    }

                    throw ex;
                    //Global.ShowErrorMsg("Error loading bitmap", ex);
                }
                finally
                {
                    // clean up memory
                    foreach (Bitmap image in images)
                    {
                        image.Dispose();
                    }

                    foreach (IntPtr p in tPtr)
                    {
                        Marshal.FreeHGlobal(p);
                    }
                }
            }
            #endregion
            #region Cubemap
            else if (type == BitmapType.BITM_TYPE_CUBEMAP)
            {
                // stride = DecodeBitmap(ref bitmBytes, height, width, 1, bitsPerPixel, type, format, swizzle, map, visualchunkindex, ident);
                List<Bitmap> images = new List<Bitmap>();
                Bitmap finalImage = null;
                List<IntPtr> tPtr = new List<IntPtr>();

                // Don't think any cubemaps are swizzled, but...
                if (swizzle)
                {
                    int imageSize = bitmBytes.Length / 6; // width * height * bitsPerPixel >> 3;
                    for (int i = 0; i < 6; i++)
                    {
                        bitmBytes = Swizzler.Swizzle(bitmBytes, i * imageSize, width, height, depth, bitsPerPixel, true);
                    }
                }

                try
                {
                    // Make our new image large enough to handle a square of all the images together with a 2 pixel pad between
                    //int tWidth = 2 * (width + 2) + 10; // Add some extras..
                    int tWidth = 4 * width; // Add some extras..
                    int tHeight = 3 * height;
                    int imageSize = width * height * (bitsPerPixel >> 3);

                    // Total image size has each image (including it's mipmaps) padded to 256
                    int tImageSize = bitmBytes.Length / 6;

                    // Unused, just divide stream size by 6 as above
                    int ttImageSize = imageSize +
                                      ((imageSize / 6) % 256 == 0 ? 0 : ((256 * 6) - (imageSize % (256 * 6))));

                    // All cubemaps should be DXT1...
                    switch (format)
                    {
                        case BitmapFormat.BITM_FORMAT_DXT1:
                            imageSize = Math.Max(imageSize / 8, 8);
                            break;
                        case BitmapFormat.BITM_FORMAT_DXT2AND3:
                        case BitmapFormat.BITM_FORMAT_DXT4AND5:
                            imageSize = Math.Max(imageSize / 4, 16);
                            break;
                    }

                    //int mipmaps = 0;
                    for (int i = 0; i < 6; i++)
                    {
                        int tw = width;
                        int th = height;
                        int tempSize = imageSize;
                        int offset = 0;
                        //while (tw > 2 & th > 2)
                        {
                            byte[] tempBytes = new byte[tempSize];

                            Array.Copy(bitmBytes, i * tImageSize + offset, tempBytes, 0, tempSize);

                            stride = DecodeBitmap(
                                ref tempBytes,
                                th,
                                tw,
                                1,
                                bitsPerPixel,
                                type,
                                format,
                                false,
                                map,
                                visualchunkindex,
                                ident);

                            tPtr.Add(Marshal.AllocHGlobal(tempBytes.Length));
                            RtlMoveMemory(tPtr[tPtr.Count - 1], tempBytes, tempBytes.Length);
                            Bitmap bitmap = new Bitmap(
                                tw, th, stride, PixelFormat.Format32bppArgb, tPtr[tPtr.Count - 1]);

                            images.Add(bitmap);
                            offset += tempSize;
                            tempSize /= 4;
                            tw /= 2;
                            th /= 2;
                        }
                    }

                    // create a bitmap to hold the combined image
                    finalImage = new Bitmap(tWidth, tHeight);

                    // get a graphics object from the image so we can draw on it
                    using (Graphics g = Graphics.FromImage(finalImage))
                    {
                        // set background color
                        g.Clear(Color.Empty);

                        //
                        int[] crossX = new int[6] { 2, 0, 1, 1, 1, 3 }; // Right, Left, Top, Bottom, Front, Back
                        int[] crossY = new int[6] { 1, 1, 0, 2, 1, 1 }; // Right, Left, Top, Bottom, Front, Back
                        // go through each image and draw it on the final image
                        int xOffset = 0;
                        int yOffset = 0;
                        int tempCount = 0;
                        foreach (Bitmap image in images)
                        {
                            /*
                            if (mipmapCount == 0)
                            {
                                xOffset = 0;
                                yOffset += image.Height + 2;
                                mipmapCount = images.Count / 6;
                            }
                            */
                            xOffset = crossX[tempCount] * image.Width;
                            yOffset = crossY[tempCount] * image.Height;

                            g.DrawImage(image, new Rectangle(xOffset, yOffset, image.Width, image.Height));
                            tempCount++;
                        }
                    }

                    return finalImage;
                }
                catch (Exception ex)
                {
                    if (finalImage != null)
                    {
                        finalImage.Dispose();
                    }

                    throw ex;
                    //Global.ShowErrorMsg("Error while processing bitmap", ex);
                }
                finally
                {
                    // clean up memory
                    foreach (Bitmap image in images)
                    {
                        image.Dispose();
                    }

                    foreach (IntPtr p in tPtr)
                    {
                        Marshal.FreeHGlobal(p);
                    }
                }
            }
            #endregion
            #region 2D Textures
            else
            {
                stride = DecodeBitmap(
                    ref bitmBytes, height, width, 1, bitsPerPixel, type, format, swizzle, map, visualchunkindex, ident);
            }
            #endregion

            /*
            // This creates a memory leaks from HGlobal
            IntPtr intPtr = Marshal.AllocHGlobal(bitmBytes.Length);
            RtlMoveMemory(intPtr, bitmBytes, bitmBytes.Length);
            Bitmap temp = new Bitmap(width, height, stride, PixelFormat.Format32bppArgb, intPtr);
            temp.Tag = intPtr; // This NEEDS to be released when disposed
            */

            Bitmap temp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            Rectangle rect = new Rectangle( 0, 0, width, height);
            BitmapData data = null;
            try
            {
                data = temp.LockBits(rect, ImageLockMode.WriteOnly, temp.PixelFormat);
                System.Runtime.InteropServices.Marshal.Copy(bitmBytes, 0, data.Scan0, Math.Min(bitmBytes.Length, data.Width * data.Height * 4));
            }
            finally
            {
                if (data != null)
                    temp.UnlockBits(data);
            }
            return temp;
        }