Answered My jpeg are partially scrambled

All Replies

  • Friday, February 03, 2012 10:30 AM
     
      Has Code

    Here is the code that reproduce the bug :(

    My interop code come from this post : http://weblogs.asp.net/bleroy/archive/2010/05/03/the-fastest-way-to-resize-images-from-asp-net-and-it-s-more-supported-ish.aspx

     

    Can someone tell me what is wrong ? I'm running a Win2008 R2, and should be in an MTA.

     

     class Program
        {
            static void Main(string[] args)
            {
                Parallel.For(1, 200, c =>
                {
    
                    {
                        Stream fStream = File.OpenRead("par6803327_2_1_0.jpg");
                        try
                        {
    <span style="white-space:pre">			</span>Resize(new Size(170, 170), 94, 94, true, ref fStream);
                            fStream.Position = 0;
                            byte[] buffer = new byte[fStream.Length];
                            fStream.Read(buffer, 0, buffer.Length);
                            if (buffer.Length < 20000)
                                File.WriteAllBytes(".\\Out\\" + Path.GetRandomFileName() + ".wic.jpg", buffer);
                            //else Thread.Sleep(05);
                        }
                        catch (Exception e)
                        {
                            File.WriteAllText(".\\Out\\" + Path.GetRandomFileName() + ".wic.log", e.ToString());
    
                            try
                            {
                                fStream.Position = 0;
    
                               // Mdf.Medias.Tools.Transformations.WPF.TranformationsWPF.Resize(
                             //  new Size(170, 170), 94, 94, true, ref fStream);
                                
                            }
                            catch (Exception ee)
                            {
                                File.WriteAllText(".\\Out\\" + Path.GetRandomFileName() + ".wpf.log", ee.ToString());
                            }
                            byte[] buffer1 = new byte[fStream.Length];
                            fStream.Read(buffer1, 0, buffer1.Length);
                            File.WriteAllBytes(".\\Out\\" + Thread.CurrentThread.ManagedThreadId + ".wpf.jpg", buffer1);
                            //fStream.Position = 0;
                            fStream = File.OpenRead("par6803327_2_1_0.jpg");
                        }
    
                        //    try {
    
    
                    }
                })
            ;
    
    
                return;
    }
    
    
     static readonly IWICComponentFactory factory = (IWICComponentFactory)new WICImagingFactory();
               
            public static Size Resize(Size size, int quality, int compression, bool boxed, ref Stream outputContent, bool removeMetadata = false)
            {
                
                MemoryStream memoryStream = null;
                if (!(outputContent is MemoryStream))
                {
                    memoryStream = new MemoryStream();
                    outputContent.Position = 0;
                    outputContent.CopyTo(memoryStream);
                    outputContent = memoryStream;
                }
                else
                    memoryStream = (MemoryStream)outputContent;
                memoryStream.Position = 0;
    
                IWICBitmapFrameDecode frame = null;
               // lock (lockResizeObject)
                {
                
                var inputStream = factory.CreateStream();
                byte[] buffer = new byte[memoryStream.Length];
                memoryStream.Position = 0;
                outputContent.Read(buffer, 0, buffer.Length);
                inputStream.InitializeFromMemory(buffer, (uint)buffer.Length);
                var decoder = factory.CreateDecoderFromStream(inputStream, null,
                                                              WICDecodeOptions.WICDecodeMetadataCacheOnLoad);
                
                 frame = decoder.GetFrame(0);
                }
               
                uint frameWidth = 0;
                uint frameHeight = 0;
                frame.GetSize(out frameWidth, out frameHeight);
                //////////
    
                double heightRatio = (size.Height / (float)frameHeight);
                double widthRatio = (size.Width / (float)frameWidth);
    
                double ratio = Math.Min(heightRatio, widthRatio);
    
                double newWidth = 0;
                double newHeight = 0;
    
                if ((size.Height == frameHeight && size.Width >= frameWidth) ||
                    (size.Width == frameWidth && size.Height >= frameHeight))
                {
                    outputContent.Position = 0;
                    return new Size((int)frameWidth, (int)frameHeight);
                }
    
                if ((!boxed && ratio == widthRatio) || (boxed && ratio == heightRatio))
                {
                    newWidth = size.Width;
                    newHeight = (int)(newWidth / ((float)frameWidth / frameHeight));
                }
                else
                {
                    newHeight = size.Height;
                    newWidth = (int)(newHeight * ((float)frameWidth / frameHeight));
                }
    
    
                //////////
                PropVariant metadataValue = null;
                if (!removeMetadata)
                {
                    try
                    {
                        metadataValue = new PropVariant();
                        //Get All IPTC data
                        frame.GetMetadataQueryReader().GetMetadataByName("/app13/irb/8bimiptc/iptc", metadataValue);
                    }
                    catch (Exception e)
                    {
                        //No metadata were available
                        metadataValue = null;
                    }
                }
                
                    var outputStream = new MemoryIStream();
                    {
                       // lock (lockResizeObject)
                        {
                            // Prepare JPG encoder
                            var encoder = factory.CreateEncoder(Consts.GUID_ContainerFormatJpeg, null);
                            encoder.Initialize(outputStream, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);
    
                            // Prepare output frame
                            IWICBitmapFrameEncode outputFrame;
                            var arg = new IPropertyBag2[1];
                            encoder.CreateNewFrame(out outputFrame, arg);
    
                            var propBag = arg[0];
                            var propertyBagOption = new PROPBAG2[1];
                            propertyBagOption[0].pstrName = "ImageQuality";
                            propBag.Write(1, propertyBagOption, new object[] {(float) (quality == -1 ? 100 : quality)/100});
                            outputFrame.Initialize(propBag);
    
                            outputFrame.SetResolution(96, 96);
                            outputFrame.SetSize((uint) newWidth, (uint) newHeight);
    
                            try
                            {
                                //Write previously retrieved IPTC data
                                if (metadataValue != null)
                                    outputFrame.GetMetadataQueryWriter().SetMetadataByName("/app13/irb/8bimiptc/iptc",
                                                                                           metadataValue);
                            }
                            catch (ArgumentException)
                            {
                                //Value does not fall within the expected range. 
                                //:( unknown exception and don't know how to solve this
                                //Maybe metadata is not so important
                            }
                            // Prepare scaler
    
                            var scaler = factory.CreateBitmapScaler();
                            scaler.Initialize(frame, (uint) newWidth, (uint) newHeight,
                                              WICBitmapInterpolationMode.WICBitmapInterpolationModeCubic);
                            // Write the scaled source to the output frame
                            outputFrame.WriteSource(scaler,
                                                    new WICRect
                                                        {X = 0, Y = 0, Width = (int) newWidth, Height = (int) newHeight});
                            outputFrame.Commit();
                            encoder.Commit();
                        }
    
                        //outputContent.Position = 0;
                        //outputStream.Position = 0;
                        outputContent = outputStream;
                        outputContent.Position = 0;
                        //outputStream.Close();
                        return new Size((int)newWidth, (int)newHeight);
                    }
                
            }
    }
    


  • Wednesday, February 15, 2012 3:21 PM
     
      Has Code

    Here is the same problem with simplified code :

    static void Main(string[] args)
            {
                Parallel.For(1, 300, new ParallelOptions(){MaxDegreeOfParallelism = 8}, c =>
                {
    
                        Stream fStream = File.OpenRead("par6803327_2_1_0.jpg");
                        try
                        {
                            Stream res = Mdf.Medias.Tools.Transformations.WIC.TranformationsWIC.Test(
                                new Size(170, 170), 94, 94, true, fStream);
                            fStream.Position = 0;
                            byte[] buffer = new byte[res.Length];
                            res.Read(buffer, 0, buffer.Length);
                            //if (buffer.Length < 21000)
                                File.WriteAllBytes(".\\Out\\" + Path.GetRandomFileName() + ".wic.jpg", buffer);
                            //else Thread.Sleep(05);
                        }
                        catch (Exception e)
                        {
                            File.WriteAllText(".\\Out\\" + Path.GetRandomFileName() + ".wic.log", e.ToString());
                        }
    
                })
            ;
    
    
                return;
    }


     public static Stream Test(Size size, int quality, int compression, bool boxed, Stream outputContent, bool removeMetadata = false)
            {
    
                MemoryIStream memoryStream = null;
                if (!(outputContent is MemoryStream))
                {
                    memoryStream = new MemoryIStream();
                    outputContent.Position = 0;
                    outputContent.CopyTo(memoryStream);
                    outputContent = memoryStream;
                }
                else
                    memoryStream = (MemoryIStream)outputContent;
    
                IWICBitmapFrameDecode frame = null;
                IWICBitmapDecoder decoder = null;
                IWICComponentFactory factory2 = (IWICComponentFactory)new WICImagingFactory();
                var inputStream = factory2.CreateStream();
                
                    memoryStream.Position = 0;
    
                    inputStream.InitializeFromMemory(memoryStream.ToArray(), (uint)memoryStream.Length);
    
                    decoder = factory2.CreateDecoderFromStream(inputStream, null,
                                                            WICDecodeOptions.WICDecodeMetadataCacheOnLoad);
                    frame = decoder.GetFrame(0);
            
    
                using(var outputStream = new MemoryIStream())
                {
                        // Prepare JPG encoder
                        var encoder = factory2.CreateEncoder(Consts.GUID_ContainerFormatJpeg, null);
                        encoder.Initialize(outputStream, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);
    
                        // Prepare output frame
                        IWICBitmapFrameEncode outputFrame;
                        var arg = new IPropertyBag2[0];
                        encoder.CreateNewFrame(out outputFrame, arg);
                        
                        
                        outputFrame.Initialize(null);
                        
                        outputFrame.WriteSource(frame, null);
                        outputFrame.Commit();
                        encoder.Commit();
                        Marshal.ReleaseComObject(inputStream);
                        Marshal.ReleaseComObject(outputFrame);
                        Marshal.ReleaseComObject(frame);
                        Marshal.ReleaseComObject(encoder);
                        Marshal.ReleaseComObject(decoder);
                        Marshal.ReleaseComObject(factory2);
                        Marshal.CleanupUnusedObjectsInCurrentContext();
                        var array = outputStream.ToArray();
                        return new MemoryStream(array);
                }
    
            }

    The output is correct about 80% of time, but sometimes its corrupted like these.

    Can someone confirm that on other computers ? and maybe tell me what's wrong with this code ?

     


    • Edited by Alex AxSoft Wednesday, February 15, 2012 3:22 PM
    •  
  • Monday, February 20, 2012 11:19 AM
     
     Answered
    Proxy methods are the answer to this problem
    • Marked As Answer by Alex AxSoft Monday, February 20, 2012 11:19 AM
    •