예제 #1
0
        /// <summary>
        /// Encode a <seealso cref="ManagedImage"/> object into a byte array
        /// </summary>
        /// <param name="image">The <seealso cref="ManagedImage"/> object to encode</param>
        /// <param name="lossless">true to enable lossless conversion, only useful for small images ie: sculptmaps</param>
        /// <returns>A byte array containing the encoded Image object</returns>
        public static byte[] Encode(ManagedImage image, bool lossless)
        {
            if (
                (image.Channels & ManagedImage.ImageChannels.Color) == 0 ||
                ((image.Channels & ManagedImage.ImageChannels.Bump) != 0 && (image.Channels & ManagedImage.ImageChannels.Alpha) == 0))
                throw new ArgumentException("JPEG2000 encoding is not supported for this channel combination");
            
            MarshalledImage marshalled = new MarshalledImage();

            // allocate and copy to input buffer
            marshalled.width = image.Width;
            marshalled.height = image.Height;
            marshalled.components = 3;
            if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) marshalled.components++;
            if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) marshalled.components++;

            if (!LibslAllocDecoded(ref marshalled))
                throw new Exception("LibslAllocDecoded failed");

            int n = image.Width * image.Height;

            if ((image.Channels & ManagedImage.ImageChannels.Color) != 0)
            {
                Marshal.Copy(image.Red, 0, marshalled.decoded, n);
                Marshal.Copy(image.Green, 0, (IntPtr)(marshalled.decoded.ToInt64() + n), n);
                Marshal.Copy(image.Blue, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 2), n);
            }

            if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) Marshal.Copy(image.Alpha, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 3), n);
            if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) Marshal.Copy(image.Bump, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 4), n);

            // codec will allocate output buffer
            if (!LibslEncode(ref marshalled, lossless))
                throw new Exception("LibslEncode failed");

            // copy output buffer
            byte[] encoded = new byte[marshalled.length];
            Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length);

            // free buffers
            LibslFree(ref marshalled);

            return encoded;
        }
예제 #2
0
        public static unsafe ManagedImage LoadTGAImage(System.IO.Stream source, bool mask)
        {
            byte[] buffer = new byte[source.Length];
            source.Read(buffer, 0, buffer.Length);

            System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);

            System.IO.BinaryReader br = new System.IO.BinaryReader(ms);

            tgaHeader header = new tgaHeader();
            header.Read(br);

            if (header.ImageSpec.PixelDepth != 8 &&
                header.ImageSpec.PixelDepth != 16 &&
                header.ImageSpec.PixelDepth != 24 &&
                header.ImageSpec.PixelDepth != 32)
                throw new ArgumentException("Not a supported tga file.");

            if (header.ImageSpec.AlphaBits > 8)
                throw new ArgumentException("Not a supported tga file.");

            if (header.ImageSpec.Width > 4096 ||
                header.ImageSpec.Height > 4096)
                throw new ArgumentException("Image too large.");

            byte[] decoded = new byte[header.ImageSpec.Width * header.ImageSpec.Height * 4];
            System.Drawing.Imaging.BitmapData bd = new System.Drawing.Imaging.BitmapData();

            fixed (byte* pdecoded = &decoded[0])
            {
                bd.Width = header.ImageSpec.Width;
                bd.Height = header.ImageSpec.Height;
                bd.PixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppPArgb;
                bd.Stride = header.ImageSpec.Width * 4;
                bd.Scan0 = (IntPtr)pdecoded;

                switch (header.ImageSpec.PixelDepth)
                {
                    case 8:
                        decodeStandard8(bd, header, br);
                        break;
                    case 16:
                        if (header.ImageSpec.AlphaBits > 0)
                            decodeSpecial16(bd, header, br);
                        else
                            decodeStandard16(bd, header, br);
                        break;
                    case 24:
                        if (header.ImageSpec.AlphaBits > 0)
                            decodeSpecial24(bd, header, br);
                        else
                            decodeStandard24(bd, header, br);
                        break;
                    case 32:
                        decodeStandard32(bd, header, br);
                        break;
                    default:
                        return null;
                }
            }

            int n = header.ImageSpec.Width * header.ImageSpec.Height;
            ManagedImage image;
            
            if (mask && header.ImageSpec.AlphaBits == 0 && header.ImageSpec.PixelDepth == 8)
            {
                image = new ManagedImage(header.ImageSpec.Width, header.ImageSpec.Height,
                    ManagedImage.ImageChannels.Alpha);
                int p = 3;

                for (int i = 0; i < n; i++)
                {
                    image.Alpha[i] = decoded[p];
                    p += 4;
                }
            }
            else
            {
                image = new ManagedImage(header.ImageSpec.Width, header.ImageSpec.Height,
                    ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                int p = 0;

                for (int i = 0; i < n; i++)
                {
                    image.Blue[i] = decoded[p++];
                    image.Green[i] = decoded[p++];
                    image.Red[i] = decoded[p++];
                    image.Alpha[i] = decoded[p++];
                }
            }

            br.Close();
            return image;
        }
예제 #3
0
 public ManagedImage Clone()
 {
     ManagedImage image = new ManagedImage(Width, Height, Channels);
     if (Red != null) image.Red = (byte[])Red.Clone();
     if (Green != null) image.Green = (byte[])Green.Clone();
     if (Blue != null) image.Blue = (byte[])Blue.Clone();
     if (Alpha != null) image.Alpha = (byte[])Alpha.Clone();
     if (Bump != null) image.Bump = (byte[])Bump.Clone();
     return image;
 }
예제 #4
0
        /// <summary>
        /// Encode a <seealso cref="System.Drawing.Bitmap"/> object into a byte array
        /// </summary>
        /// <param name="bitmap">The source <seealso cref="System.Drawing.Bitmap"/> object to encode</param>
        /// <param name="lossless">true to enable lossless decoding</param>
        /// <returns>A byte array containing the source Bitmap object</returns>
        public unsafe static byte[] EncodeFromImage(Bitmap bitmap, bool lossless)
        {
            BitmapData bd;
            ManagedImage decoded;

            int bitmapWidth = bitmap.Width;
            int bitmapHeight = bitmap.Height;
            int pixelCount = bitmapWidth * bitmapHeight;
            int i;

            if ((bitmap.PixelFormat & PixelFormat.Alpha) != 0 || (bitmap.PixelFormat & PixelFormat.PAlpha) != 0)
            {
                // Four layers, RGBA
                decoded = new ManagedImage(bitmapWidth, bitmapHeight,
                    ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                bd = bitmap.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight),
                    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                byte* pixel = (byte*)bd.Scan0;

                for (i = 0; i < pixelCount; i++)
                {
                    // GDI+ gives us BGRA and we need to turn that in to RGBA
                    decoded.Blue[i] = *(pixel++);
                    decoded.Green[i] = *(pixel++);
                    decoded.Red[i] = *(pixel++);
                    decoded.Alpha[i] = *(pixel++);
                }
            }
            else if (bitmap.PixelFormat == PixelFormat.Format16bppGrayScale)
            {
                // One layer
                decoded = new ManagedImage(bitmapWidth, bitmapHeight,
                    ManagedImage.ImageChannels.Color);
                bd = bitmap.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight),
                    ImageLockMode.ReadOnly, PixelFormat.Format16bppGrayScale);
                byte* pixel = (byte*)bd.Scan0;

                for (i = 0; i < pixelCount; i++)
                {
                    // Normalize 16-bit data down to 8-bit
                    ushort origVal = (byte)(*(pixel) + (*(pixel + 1) << 8));
                    byte val = (byte)(((double)origVal / (double)UInt32.MaxValue) * (double)Byte.MaxValue);

                    decoded.Red[i] = val;
                    decoded.Green[i] = val;
                    decoded.Blue[i] = val;
                    pixel += 2;
                }
            }
            else
            {
                // Three layers, RGB
                decoded = new ManagedImage(bitmapWidth, bitmapHeight,
                    ManagedImage.ImageChannels.Color);
                bd = bitmap.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight),
                    ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                byte* pixel = (byte*)bd.Scan0;

                for (i = 0; i < pixelCount; i++)
                {
                    decoded.Blue[i] = *(pixel++);
                    decoded.Green[i] = *(pixel++);
                    decoded.Red[i] = *(pixel++);
                }
            }

            bitmap.UnlockBits(bd);
            byte[] encoded = Encode(decoded, lossless);
            return encoded;
        }
예제 #5
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="encoded"></param>
        /// <param name="managedImage"></param>
        /// <returns></returns>
        public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage)
        {
            MarshalledImage marshalled = new MarshalledImage();

            // Allocate and copy to input buffer
            marshalled.length = encoded.Length;
            LibslAllocEncoded(ref marshalled);
            Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length);

            // Codec will allocate output buffer
            LibslDecode(ref marshalled);

            int n = marshalled.width * marshalled.height;

            switch (marshalled.components)
            {
                case 1: // Grayscale
                    managedImage = new ManagedImage(marshalled.width, marshalled.height,
                        ManagedImage.ImageChannels.Color);
                    Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                    Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n);
                    Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n);
                    break;

                case 2: // Grayscale + alpha
                    managedImage = new ManagedImage(marshalled.width, marshalled.height,
                        ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                    Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                    Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n);
                    Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Alpha, 0, n);
                    break;

                case 3: // RGB
                    managedImage = new ManagedImage(marshalled.width, marshalled.height,
                        ManagedImage.ImageChannels.Color);
                    Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n);
                    break;

                case 4: // RGBA
                    managedImage = new ManagedImage(marshalled.width, marshalled.height,
                        ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                    Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Alpha, 0, n);
                    break;

                case 5: // RGBBA
                    managedImage = new ManagedImage(marshalled.width, marshalled.height,
                        ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump);
                    Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n);
                    // Bump comes before alpha in 5 channel encode
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Bump, 0, n);
                    Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 4)), managedImage.Alpha, 0, n);
                    break;

                default:
                    Logger.Log("Decoded image with unhandled number of components: " + marshalled.components,
                        Helpers.LogLevel.Error);
                    LibslFree(ref marshalled);
                    managedImage = null;
                    return false;
            }

            LibslFree(ref marshalled);
            return true;
        }
예제 #6
0
        /// <summary>
        /// Decode JPEG2000 data to an <seealso cref="System.Drawing.Image"/> and
        /// <seealso cref="ManagedImage"/>
        /// </summary>
        /// <param name="encoded">JPEG2000 encoded data</param>
        /// <param name="managedImage">ManagedImage object to decode to</param>
        /// <param name="image">Image object to decode to</param>
        /// <returns>True if the decode succeeds, otherwise false</returns>
        public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage, out Image image)
        {
            managedImage = null;
            image = null;

            if (DecodeToImage(encoded, out managedImage))
            {
                try
                {
                    image = LoadTGAClass.LoadTGA(new MemoryStream(managedImage.ExportTGA()));
                    return true;
                }
                catch (Exception ex)
                {
                    Logger.Log("Failed to export and load TGA data from decoded image", Helpers.LogLevel.Error, ex);
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
예제 #7
0
 /// <summary>
 /// Encode a <seealso cref="ManagedImage"/> object into a byte array
 /// </summary>
 /// <param name="image">The <seealso cref="ManagedImage"/> object to encode</param>
 /// <returns>a byte array of the encoded image</returns>
 public static byte[] Encode(ManagedImage image)
 {
     return Encode(image, false);
 }
예제 #8
0
 public AssetTexture(ManagedImage image)
 {
     Image = image;
 }