Example #1
0
        public byte[] Read(Stream stream, out int x, out int y, out int comp, int req_comp)
        {
            _stream = stream;

            try
            {
                int xx, yy, ccomp;
                var result = StbImage.stbi_load_from_callbacks(_callbacks, null, &xx, &yy, &ccomp, req_comp);

                x    = xx;
                y    = yy;
                comp = ccomp;

                if (result == null)
                {
                    throw new Exception(StbImage.LastError);
                }

                // Convert to array
                var c    = req_comp != 0 ? req_comp : comp;
                var data = new byte[x * y * c];
                Marshal.Copy(new IntPtr(result), data, 0, data.Length);

                CRuntime.free(result);

                return(data);
            }
            finally
            {
                _stream = null;
            }
        }
Example #2
0
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            // Create white texture
            _white = new Texture2D(GraphicsDevice, 1, 1);
            _white.SetData(new[] { Color.White });

            // Load image data into memory
            var path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);

            path = Path.Combine(path, "image.jpg");
            var buffer = File.ReadAllBytes(path);

            var image = StbImage.LoadFromMemory(buffer, StbImage.STBI_rgb_alpha);

            _image = new Texture2D(GraphicsDevice, image.Width, image.Height, false, SurfaceFormat.Color);
            _image.SetData(image.Data);

            // Load ttf
            LoadFont();

            // Load ogg
            LoadSong();

            GC.Collect();
        }
Example #3
0
        /// <summary>
        /// Creates and loads and new image
        /// </summary>
        /// <param name="fileLocation">Location of the image</param>
        /// <param name="filp">Filp the image on load</param>
        /// <exception cref="FileNotFoundException"></exception>
        public Image(string fileLocation, bool filp)
        {
            if (!File.Exists(fileLocation))
            {
                throw new FileNotFoundException("Image doesn't exist!", fileLocation);
            }

            //Filp image on load, if we want to filp it
            if (filp)
            {
                StbImage.stbi_set_flip_vertically_on_load(1);
            }

            //Open stream
            FileStream imageStream = File.OpenRead(fileLocation);

            //Create image
            ImageResult image = ImageResult.FromStream(imageStream);

            Data   = image.Data;
            Width  = image.Width;
            Height = image.Height;

            //IDK if this was purposely done, but the enum number matches to the channels count of what the enum is
            Channels = (int)image.SourceComp;
        }
Example #4
0
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                using (var dlg = new OpenFileDialog())
                {
                    dlg.Filter =
                        "PNG Files (*.png)|*.png|JPEG Files (*.jpg)|*.jpg|BMP Files (*.bmp)|*.bmp|PSD Files (*.psd)|*.psd|TGA Files (*.tga)|*.tga|GIF Files (*.gif)|*.gif|All Files (*.*)|*.*";
                    if (dlg.ShowDialog() != DialogResult.OK)
                    {
                        return;
                    }

                    _fileName = dlg.FileName;

                    var bytes = File.ReadAllBytes(_fileName);

                    _loadedImage = StbImage.LoadFromMemory(bytes, StbImage.STBI_rgb_alpha);
                    SetImage();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error", ex.Message);
            }
        }
Example #5
0
        public static ImageResult LoadImage(string imgPath)
        {
#if DEBUG
            using Profiler fullProfiler = new Profiler(typeof(ImageHelper));
#endif
            StbImage.stbi_set_flip_vertically_on_load(1);
            return(ImageResult.FromMemory(ReadFile(imgPath), ColorComponents.RedGreenBlueAlpha));
        }
Example #6
0
        public void reloadtexture(string texturePath)
        {
            byte[] buffer = File.ReadAllBytes(texturePath);
            StbImage.stbi_set_flip_vertically_on_load(1);
            ImageResult image = ImageResult.FromMemory(buffer, ColorComponents.RedGreenBlueAlpha);

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Data);
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
        }
Example #7
0
        public AnimatedGifFrame[] ReadAnimatedGif(Stream stream, out int x, out int y, out int comp, int req_comp)
        {
            try
            {
                x = y = comp = 0;

                var res = new List <AnimatedGifFrame>();
                _stream = stream;

                var context = new StbImage.stbi__context();
                StbImage.stbi__start_callbacks(context, _callbacks, null);

                if (StbImage.stbi__gif_test(context) == 0)
                {
                    throw new Exception("Input stream is not GIF file.");
                }

                var g = new StbImage.stbi__gif();

                do
                {
                    int ccomp;
                    var result = StbImage.stbi__gif_load_next(context, g, &ccomp, req_comp);
                    if (result == null)
                    {
                        break;
                    }

                    comp = ccomp;
                    var c    = req_comp != 0 ? req_comp : comp;
                    var data = new byte[g.w * g.h * c];
                    Marshal.Copy(new IntPtr(result), data, 0, data.Length);
                    CRuntime.free(result);

                    var frame = new AnimatedGifFrame
                    {
                        Data  = data,
                        Delay = g.delay
                    };
                    res.Add(frame);
                } while (true);

                CRuntime.free(g._out_);

                if (res.Count > 0)
                {
                    x = g.w;
                    y = g.h;
                }

                return(res.ToArray());
            }
            finally
            {
                _stream = null;
            }
        }
Example #8
0
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            // Create white texture
            _white = new Texture2D(GraphicsDevice, 1, 1);
            _white.SetData(new[] { Color.White });

            // Load image data into memory
            var path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);

            path = Path.Combine(path, "image.jpg");
            var buffer = File.ReadAllBytes(path);

            var image = StbImage.LoadFromMemory(buffer, StbImage.STBI_rgb_alpha);

            _image = new Texture2D(GraphicsDevice, image.Width, image.Height, false, SurfaceFormat.Color);
            _image.SetData(image.Data);

            // Load ttf
            LoadFont();

            // Load ogg
            path   = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
            path   = Path.Combine(path, "Adeste_Fideles.ogg");
            buffer = File.ReadAllBytes(path);

            int chan, sampleRate;
            var audioShort = StbVorbis.decode_vorbis_from_memory(buffer, out sampleRate, out chan);

            byte[] audioData = new byte[audioShort.Length / 2 * 4];
            for (var i = 0; i < audioShort.Length; ++i)
            {
                if (i * 2 >= audioData.Length)
                {
                    break;
                }

                var b1 = (byte)(audioShort[i] >> 8);
                var b2 = (byte)(audioShort[i] & 256);

                audioData[i * 2 + 0] = b2;
                audioData[i * 2 + 1] = b1;
            }

            _effect = new DynamicSoundEffectInstance(sampleRate, AudioChannels.Stereo)
            {
                Volume = 0.5f
            };


            _effect.SubmitBuffer(audioData);

            GC.Collect();
        }
Example #9
0
        public static Softy.Texture LoadTexture(string fileName)
        {
            var bytes = File.ReadAllBytes(fileName);
            var image = StbImage.LoadFromMemory(bytes, StbImage.STBI_rgb_alpha);
            var cols  = new Softy.Color[image.Width * image.Height];

            for (int i = 0; i < cols.Length; ++i)
            {
                cols[i] = new Softy.Color(image.Data[i * 4 + 0], image.Data[i * 4 + 1], image.Data[i * 4 + 2], image.Data[i * 4 + 3]);
            }
            return(new Softy.Texture(cols, image.Width));
        }
Example #10
0
        public Image GetImage(string name)
        {
            var resFilestream = this.Assembly?.GetManifestResourceStream(IMAGE_BASE + name);

            if (resFilestream == null)
            {
                return(null);
            }

            byte[] bytes = new byte[resFilestream.Length];
            resFilestream.Read(bytes, 0, bytes.Length);
            return(StbImage.LoadFromMemory(bytes, StbImage.STBI_rgb_alpha));
        }
Example #11
0
        private int TextureFromFile(string path, bool gamma = false)
        {
            string fullPath = $"{Directory}/{path}";

            int texID = GL.GenTexture();

            StbImage.stbi_set_flip_vertically_on_load(0);
            var img = ImageResult.FromMemory(File.ReadAllBytes(fullPath));

            if (img != null)
            {
                PixelInternalFormat format   = 0;
                PixelFormat         pxFormat = 0;
                if (img.Comp == ColorComponents.Grey)
                {
                    format   = PixelInternalFormat.R8;
                    pxFormat = PixelFormat.Red;
                }
                else if (img.Comp == ColorComponents.RedGreenBlue)
                {
                    format   = PixelInternalFormat.Rgb;
                    pxFormat = PixelFormat.Rgb;
                }
                else if (img.Comp == ColorComponents.RedGreenBlueAlpha)
                {
                    format   = PixelInternalFormat.Rgba;
                    pxFormat = PixelFormat.Rgba;
                }
                GL.BindTexture(TextureTarget.Texture2D, texID);
                GL.TexImage2D(TextureTarget.Texture2D, 0, format, img.Width, img.Height, 0, pxFormat, PixelType.UnsignedByte, img.Data);
                GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
            }
            else
            {
                throw new Exception("Texture failed to load at " + fullPath);
            }
            return(texID);
        }
Example #12
0
        private static Texture2D LoadTextureFromFile(string texPath, bool alpha)
        {
            Texture2D tex = new Texture2D();

            if (alpha)
            {
                tex.InternalFormat = PixelInternalFormat.Rgba;
                tex.ImageFormat    = PixelFormat.Rgba;
            }

            StbImage.stbi_set_flip_vertically_on_load(0);
            var      img         = ImageResult.FromMemory(File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, texPath)), alpha ? ColorComponents.RedGreenBlueAlpha : ColorComponents.RedGreenBlue);
            GCHandle pinnedArray = GCHandle.Alloc(img.Data, GCHandleType.Pinned);
            IntPtr   pointer     = pinnedArray.AddrOfPinnedObject();

            tex.Generate(img.Width, img.Height, pointer);
            pinnedArray.Free();
            return(tex);
        }
Example #13
0
 public static unsafe Texture FromStream(Stream stream, bool flip = true)
 {
     if (DDS.StreamIsDDS(stream))
     {
         return(DDS.FromStream(stream));
     }
     else
     {
         /* Read full stream */
         int    len = (int)stream.Length;
         byte[] b   = new byte[len];
         int    pos = 0;
         int    r   = 0;
         while ((r = stream.Read(b, pos, len - pos)) > 0)
         {
             pos += r;
         }
         /* stb_image it */
         int x = 0, y = 0;
         StbImage.stbi_set_flip_vertically_on_load(flip ? 1 : 0);
         ImageResult image = ImageResult.FromMemory(b, ColorComponents.RedGreenBlueAlpha);
         x = image.Width;
         y = image.Height;
         var data       = image.Data;
         int dataLength = x * y * 4;
         int j          = 0;
         for (int i = 0; i < dataLength; i += 4)
         {
             var R = data[i];
             var G = data[i + 1];
             var B = data[i + 2];
             var A = data[i + 3];
             data[j++] = B;
             data[j++] = G;
             data[j++] = R;
             data[j++] = A;
         }
         var t = new Texture2D(x, y, false, SurfaceFormat.Color);
         t.SetData(data);
         return(t);
     }
 }
Example #14
0
        public Color[] Read(Stream stream, out int x, out int y, out int comp)
        {
            _stream = stream;

            try
            {
                int xx, yy, ccomp;
                var result = StbImage.stbi_load_from_callbacks(_callbacks, null, &xx, &yy, &ccomp, StbImage.STBI_rgb_alpha);

                x    = xx;
                y    = yy;
                comp = ccomp;

                if (result == null)
                {
                    throw new Exception(StbImage.LastError);
                }

                // Convert to color array
                var data = new Color[x * y];
                var src  = result;
                fixed(Color *dest = data)
                {
                    for (var i = 0; i < data.Length; ++i)
                    {
                        dest[i].R = *src++;
                        dest[i].G = *src++;
                        dest[i].B = *src++;
                        dest[i].A = *src++;
                    }
                }

                CRuntime.free(result);

                return(data);
            }
            finally
            {
                _stream = null;
            }
        }
Example #15
0
        public static LoadResult BytesFromStream(Stream stream, bool flip = false)
        {
            int len = (int)stream.Length;

            byte[] b   = new byte[len];
            int    pos = 0;
            int    r   = 0;

            while ((r = stream.Read(b, pos, len - pos)) > 0)
            {
                pos += r;
            }
            /* stb_image it */
            StbImage.stbi_set_flip_vertically_on_load(flip ? 1 : 0);
            ImageResult image = ImageResult.FromMemory(b, ColorComponents.RedGreenBlueAlpha);

            return(new LoadResult()
            {
                Width = image.Width, Height = image.Height, Data = image.Data
            });
        }
Example #16
0
        public static Texture loadFromFile(string path, bool useMipMaps = false)
        {
#if USE_STB
            var buffer = File.ReadAllBytes(path);
            var image  = StbImage.LoadFromMemory(buffer, StbImage.STBI_rgb_alpha);

            var tex = new Texture(TextureTarget.Texture2D, GL.GenTexture());
            tex.width  = image.Width;
            tex.height = image.Height;
            tex.setData(image.Data, image.Width, image.Height);
#elif USE_BITMAP
            var bmp = new Bitmap(path);
            var tex = new Texture(TextureTarget.Texture2D, GL.GenTexture());
            tex.width  = bmp.Width;
            tex.height = bmp.Height;
            tex.setData(bmp);
#else
            throw new Exception("Not supported")
#endif


            return(tex);
        }
 private static void StbLoadFromContext(TextureLoadingContext textureLoadingContext, ColorComponents requiredComponents = ColorComponents.Default)
 {
     try
     {
         StbImage.FromContext(requiredComponents, textureLoadingContext);
         if (textureLoadingContext.UnityTexture != null)
         {
             StbProcessTexture(textureLoadingContext);
         }
         textureLoadingContext.Stream.TryToDispose();
     }
     catch (Exception e)
     {
         if (textureLoadingContext.Context.Options.ShowLoadingWarnings)
         {
             if (textureLoadingContext.Texture != null)
             {
                 Debug.LogWarning($"Could not load texture {textureLoadingContext.Texture.Name ?? textureLoadingContext.Texture.Filename ?? "No-name"} :{e}");
             }
         }
         textureLoadingContext.Stream.TryToDispose();
     }
 }
Example #18
0
 public int StbSharp() => StbImage.LoadFromMemory(data, StbImage.STBI_rgb_alpha).Width;
Example #19
0
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            // Create white texture
            _white = new Texture2D(GraphicsDevice, 1, 1);
            _white.SetData(new[] { Color.White });

            // Load image data into memory
            var path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);

            path = Path.Combine(path, "image.jpg");
            var buffer = File.ReadAllBytes(path);

            var image = StbImage.LoadFromMemory(buffer, StbImage.STBI_rgb_alpha);

            _image = new Texture2D(GraphicsDevice, image.Width, image.Height, false, SurfaceFormat.Color);
            _image.SetData(image.Data);

            // Load ttf
            buffer = File.ReadAllBytes("Fonts/DroidSans.ttf");
            var buffer2 = File.ReadAllBytes("Fonts/DroidSansJapanese.ttf");

            var tempBitmap = new byte[FontBitmapWidth * FontBitmapHeight];

            var fontBaker = new FontBaker();

            fontBaker.Begin(tempBitmap, FontBitmapWidth, FontBitmapHeight);
            fontBaker.Add(buffer, 32, new []
            {
                FontBakerCharacterRange.BasicLatin,
                FontBakerCharacterRange.Latin1Supplement,
                FontBakerCharacterRange.LatinExtendedA,
                FontBakerCharacterRange.Cyrillic,
            });

            fontBaker.Add(buffer2, 32, new []
            {
                FontBakerCharacterRange.Hiragana,
                FontBakerCharacterRange.Katakana
            });

            _charData = fontBaker.End();

            // Offset by minimal offset
            float minimumOffsetY = 10000;

            foreach (var pair in _charData)
            {
                if (pair.Value.yoff < minimumOffsetY)
                {
                    minimumOffsetY = pair.Value.yoff;
                }
            }

            var keys = _charData.Keys.ToArray();

            foreach (var key in keys)
            {
                var pc = _charData[key];
                pc.yoff       -= minimumOffsetY;
                _charData[key] = pc;
            }


            var rgb = new Color[FontBitmapWidth * FontBitmapHeight];

            for (var i = 0; i < tempBitmap.Length; ++i)
            {
                var b = tempBitmap[i];
                rgb[i].R = b;
                rgb[i].G = b;
                rgb[i].B = b;

                rgb[i].A = b;
            }

            _fontTexture = new Texture2D(GraphicsDevice, FontBitmapWidth, FontBitmapHeight);
            _fontTexture.SetData(rgb);

            // Load ogg
            path   = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
            path   = Path.Combine(path, "Adeste_Fideles.ogg");
            buffer = File.ReadAllBytes(path);

            int chan, sampleRate;
            var audioShort = StbVorbis.decode_vorbis_from_memory(buffer, out sampleRate, out chan);

            byte[] audioData = new byte[audioShort.Length / 2 * 4];
            for (var i = 0; i < audioShort.Length; ++i)
            {
                if (i * 2 >= audioData.Length)
                {
                    break;
                }

                var b1 = (byte)(audioShort[i] >> 8);
                var b2 = (byte)(audioShort[i] & 256);

                audioData[i * 2 + 0] = b2;
                audioData[i * 2 + 1] = b1;
            }

            _effect = new DynamicSoundEffectInstance(sampleRate, AudioChannels.Stereo)
            {
                Volume = 0.5f
            };


            _effect.SubmitBuffer(audioData);

            GC.Collect();
        }
Example #20
0
        private static void ThreadProc(string f)
        {
            try
            {
                var sw = new Stopwatch();

                if (!f.EndsWith(".bmp") && !f.EndsWith(".jpg") && !f.EndsWith(".png") &&
                    !f.EndsWith(".jpg") && !f.EndsWith(".psd") && !f.EndsWith(".pic") &&
                    !f.EndsWith(".tga"))
                {
                    return;
                }

                Log(string.Empty);
                Log("{0} -- #{1}: Loading {2} into memory", DateTime.Now.ToLongTimeString(), filesProcessed, f);
                var data = File.ReadAllBytes(f);
                Log("----------------------------");

                Log("Loading From Stream");
                int    x = 0, y = 0, comp = 0;
                int    stbSharpPassed, stbNativePassed;
                byte[] parsed = new byte[0];
                ParseTest(
                    sw,
                    (out int xx, out int yy, out int ccomp) =>
                {
                    using (var ms = new MemoryStream(data))
                    {
                        var loader = new ImageReader();
                        var img    = loader.Read(ms);

                        parsed = img.Data;
                        xx     = img.Width;
                        yy     = img.Height;
                        ccomp  = img.SourceComp;

                        x    = xx;
                        y    = yy;
                        comp = ccomp;
                        return(parsed);
                    }
                },
                    (out int xx, out int yy, out int ccomp) =>
                {
                    using (var ms = new MemoryStream(data))
                    {
                        return(Native.load_from_stream(ms, out xx, out yy, out ccomp, StbImage.STBI_default));
                    }
                },
                    out stbSharpPassed, out stbNativePassed
                    );
                stbSharpLoadingFromStream  += stbSharpPassed;
                stbNativeLoadingFromStream += stbNativePassed;

                Log("Loading from memory");
                ParseTest(
                    sw,
                    (out int xx, out int yy, out int ccomp) =>
                {
                    var img = StbImage.LoadFromMemory(data);

                    var res = img.Data;
                    xx      = img.Width;
                    yy      = img.Height;
                    ccomp   = img.SourceComp;

                    x    = xx;
                    y    = yy;
                    comp = ccomp;
                    return(res);
                },
                    (out int xx, out int yy, out int ccomp) =>
                    Native.load_from_memory(data, out xx, out yy, out ccomp, StbImage.STBI_default),
                    out stbSharpPassed, out stbNativePassed
                    );
                stbSharpLoadingFromMemory  += stbSharpPassed;
                stbNativeLoadingFromMemory += stbNativePassed;

                var image = new Image
                {
                    Comp   = comp,
                    Data   = parsed,
                    Width  = x,
                    Height = y
                };

                for (var k = 0; k <= 4; ++k)
                {
                    Log("Saving as {0} with StbSharp", FormatNames[k]);

                    if (k < 4)
                    {
                        var           writer = new ImageWriter();
                        WriteDelegate wd     = null;
                        switch (k)
                        {
                        case 0:
                            wd = writer.WriteBmp;
                            break;

                        case 1:
                            wd = writer.WriteTga;
                            break;

                        case 2:
                            wd = writer.WriteHdr;
                            break;

                        case 3:
                            wd = writer.WritePng;
                            break;
                        }

                        byte[] save;
                        BeginWatch(sw);
                        using (var stream = new MemoryStream())
                        {
                            wd(image, stream);
                            save = stream.ToArray();
                        }

                        var passed = EndWatch(sw);
                        stbSharpWrite += passed;
                        Log("Span: {0} ms", passed);
                        Log("StbSharp Size: {0}", save.Length);

                        Log("Saving as {0} with Stb.Native", FormatNames[k]);
                        BeginWatch(sw);
                        byte[] save2;
                        using (var stream = new MemoryStream())
                        {
                            Native.save_to_stream(parsed, x, y, comp, k, stream);
                            save2 = stream.ToArray();
                        }

                        passed          = EndWatch(sw);
                        stbNativeWrite += passed;

                        Log("Span: {0} ms", passed);
                        Log("Stb.Native Size: {0}", save2.Length);

                        if (save.Length != save2.Length)
                        {
                            throw new Exception(string.Format("Inconsistent output size: StbSharp={0}, Stb.Native={1}",
                                                              save.Length, save2.Length));
                        }

                        for (var i = 0; i < save.Length; ++i)
                        {
                            if (save[i] != save2[i])
                            {
                                throw new Exception(string.Format("Inconsistent data: index={0}, StbSharp={1}, Stb.Native={2}",
                                                                  i,
                                                                  (int)save[i],
                                                                  (int)save2[i]));
                            }
                        }
                    }
                    else
                    {
                        for (var qi = 0; qi < JpgQualities.Length; ++qi)
                        {
                            var quality = JpgQualities[qi];
                            Log("Saving as JPG with StbSharp with quality={0}", quality);
                            byte[] save;
                            BeginWatch(sw);
                            using (var stream = new MemoryStream())
                            {
                                var writer = new ImageWriter();
                                writer.WriteJpg(image, stream, quality);
                                save = stream.ToArray();
                            }

                            var passed = EndWatch(sw);
                            stbSharpWrite += passed;

                            Log("Span: {0} ms", passed);
                            Log("StbSharp Size: {0}", save.Length);

                            Log("Saving as JPG with Stb.Native with quality={0}", quality);
                            BeginWatch(sw);
                            byte[] save2;
                            using (var stream = new MemoryStream())
                            {
                                Native.save_to_jpg(parsed, x, y, comp, stream, quality);
                                save2 = stream.ToArray();
                            }

                            passed          = EndWatch(sw);
                            stbNativeWrite += passed;

                            Log("Span: {0} ms", passed);
                            Log("Stb.Native Size: {0}", save2.Length);

                            if (save.Length != save2.Length)
                            {
                                throw new Exception(string.Format("Inconsistent output size: StbSharp={0}, Stb.Native={1}",
                                                                  save.Length, save2.Length));
                            }

                            for (var i = 0; i < save.Length; ++i)
                            {
                                if (save[i] != save2[i])
                                {
                                    throw new Exception(string.Format("Inconsistent data: index={0}, StbSharp={1}, Stb.Native={2}",
                                                                      i,
                                                                      (int)save[i],
                                                                      (int)save2[i]));
                                }
                            }
                        }
                    }
                }

                // Compressing
                Log("Performing DXT compression with StbSharp");
                image = StbImage.LoadFromMemory(data, StbImage.STBI_rgb_alpha);

                BeginWatch(sw);
                var compressed = StbDxt.stb_compress_dxt(image);
                stbSharpCompression += EndWatch(sw);

                Log("Performing DXT compression with Stb.Native");
                BeginWatch(sw);
                var compressed2 = Native.compress_dxt(image.Data, image.Width, image.Height, true);
                stbNativeCompression += EndWatch(sw);

                if (compressed.Length != compressed2.Length)
                {
                    throw new Exception(string.Format("Inconsistent output size: StbSharp={0}, Stb.Native={1}",
                                                      compressed.Length, compressed2.Length));
                }

                for (var i = 0; i < compressed.Length; ++i)
                {
                    if (compressed[i] != compressed2[i])
                    {
                        throw new Exception(string.Format("Inconsistent data: index={0}, StbSharp={1}, Stb.Native={2}",
                                                          i,
                                                          (int)compressed[i],
                                                          (int)compressed2[i]));
                    }
                }


                Log("Total StbSharp Loading From Stream Time: {0} ms", stbSharpLoadingFromStream);
                Log("Total Stb.Native Loading From Stream Time: {0} ms", stbNativeLoadingFromStream);
                Log("Total StbSharp Loading From memory Time: {0} ms", stbSharpLoadingFromMemory);
                Log("Total Stb.Native Loading From memory Time: {0} ms", stbNativeLoadingFromMemory);
                Log("Total StbSharp Write Time: {0} ms", stbSharpWrite);
                Log("Total Stb.Native Write Time: {0} ms", stbNativeWrite);
                Log("Total StbSharp Compression Time: {0} ms", stbSharpCompression);
                Log("Total Stb.Native Compression Time: {0} ms", stbNativeCompression);

                Log("GC Memory: {0}", GC.GetTotalMemory(true));

                ++filesProcessed;
                Log(DateTime.Now.ToLongTimeString() + " -- " + " Files processed: " + filesProcessed);
            }
            catch (Exception ex)
            {
                Log("Error: " + ex.Message);
            }
            finally
            {
                --tasksStarted;
            }
        }