Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 图像大小优化导致内存使用率急剧下降_C#_Memory Leaks_Xamarin.ios_Uiimage - Fatal编程技术网

C# 图像大小优化导致内存使用率急剧下降

C# 图像大小优化导致内存使用率急剧下降,c#,memory-leaks,xamarin.ios,uiimage,C#,Memory Leaks,Xamarin.ios,Uiimage,我制作了一个函数,可以获取原始图像并将其调整为3种不同的缩放比例->16倍、10倍和4倍。为了更好地理解,请继续阅读本段。假设原始图像是1000x1000。我声明,在1x缩放时,其尺寸将为50x50。这意味着4倍变焦将是200x200,10倍变焦将是500x500,16倍变焦将是800x800。因此,我的函数需要将原来的1000x1000调整为800x800,然后调整为500x500,然后调整为200x200。请注意,我已经成功地完成了这项工作,我的问题是关于内存使用的 下面我有两种方法。这两种

我制作了一个函数,可以获取原始图像并将其调整为3种不同的缩放比例->16倍、10倍和4倍。为了更好地理解,请继续阅读本段。假设原始图像是1000x1000。我声明,在1x缩放时,其尺寸将为50x50。这意味着4倍变焦将是200x200,10倍变焦将是500x500,16倍变焦将是800x800。因此,我的函数需要将原来的1000x1000调整为800x800,然后调整为500x500,然后调整为200x200。请注意,我已经成功地完成了这项工作,我的问题是关于内存使用的

下面我有两种方法。这两种方法都有效,但其中一种会导致巨大的内存使用膨胀,使用的内存大约是另一种方法的3/4倍。。。我更喜欢第二种方法,因为它的加载速度明显快于第一种方法,因为它不是从原始图像调整3幅图像的大小,而是从先前调整大小的图像调整它们的大小

注意:我使用Xcode工具来测量内存使用情况。ImageResizer类包含一个名为“Resize”的函数,用于调整图像大小

方法1.)

public List InitImageList\u BFObjects(UIImage-image,SizeF-frameSize)
{
List listOfImages=新列表();
对于(int i=0;i<3;i++)
{
如果(i==0)
动物鳞片=16f;
else如果(i==1)
动物鳞片=10f;
else//if(i==2)
动物鳞片=4f;
Resizer=新图像Resizer(图像);
Resizer.Resize(frameSize.Width*缩放比例,frameSize.Height*缩放比例);
UIImage resizedImage=Resizer.ModifiedImage;
插入(0,大小图像);
}
返回图像列表;
}
方法1工作正常,占用的内存很少。我用一组大约20张图片来运行这个程序。加载后,我的应用程序的内存使用量约为14mb(使用Xcode工具检查内存使用情况)

方法2.)

public List InitImageList\u BFObjects(UIImage-image,SizeF-frameSize)
{
List listOfImages=新列表();
对于(int i=0;i<3;i++)
{
如果(i==0)
动物鳞片=16f;
else如果(i==1)
动物鳞片=10f;
else//if(i==2)
动物鳞片=4f;
if(listOfImages.Count==0)
{
Resizer=新图像Resizer(图像);
Resizer.Resize(frameSize.Width*缩放比例,frameSize.Height*缩放比例);
UIImage resizedImage=Resizer.ModifiedImage;
插入(0,大小图像);
}
其他的
{
//这一行包含方法1和方法2之间的主要区别
//请注意它是如何从listOfImages中的最新图像而不是原始图像调整大小的
Resizer=新的图像Resizer(listOfImages[0]);
Resizer.Resize(frameSize.Width*缩放比例,frameSize.Height*缩放比例);
UIImage resizedImage=Resizer.ModifiedImage;
插入(0,大小图像);
}
}
返回图像列表;
}
方法2可以工作,但内存使用率很高!我用同样的一组大约20张图片运行了这个。加载后,我的应用程序的内存使用量超过了60mb(使用Xcode仪器检查内存使用情况),为什么内存使用量如此之高?方法2的哪些方面导致内存急剧膨胀?这几乎就像一个变量没有得到正确的清理

*其他信息,ImageResizer类**

我从ImageResizer类中删除了不需要的函数,并将其重命名为“ImageResizer\u Abrided”。我甚至切换到使用这个类,以确保我没有意外地删除任何需要的内容

public class ImageResizer_Abridged
{
    UIImage originalImage  = null;
    UIImage modifiedImage = null;

    public ImageResizer_Abridged ( UIImage image )
    {
        this.originalImage = image;
        this.modifiedImage = image;
    }   

    /// <summary>
    /// strech resize
    /// </summary>
    public void Resize( float width, float height )
    {
        UIGraphics.BeginImageContext( new SizeF( width, height ) );
        //
        modifiedImage.Draw( new RectangleF( 0,0, width, height ) );
        modifiedImage = UIGraphics.GetImageFromCurrentImageContext();
        //
        UIGraphics.EndImageContext();
    }

    public UIImage OriginalImage 
    {
        get 
        {
            return this.originalImage;
        }
    }

    public UIImage ModifiedImage 
    {
        get 
        {
            return this.modifiedImage;
        }
    }
}
公共类ImageResizer\u节略
{
UIImage originalImage=null;
UIImage modifiedImage=null;
公共图像缩放器\u节略(UIImage图像)
{
this.originalImage=图像;
this.modifiedImage=图像;
}   
/// 
///拉伸调整大小
/// 
公共空心调整大小(浮动宽度、浮动高度)
{
BeginImageContext(新的SizeF(宽度、高度));
//
修改图像绘制(新矩形F(0,0,宽度,高度));
modifiedImage=UIGraphics.GetImageFromCurrentImageContext();
//
UIGraphics.EndImageContext();
}
公众形象原创
{
得到
{
返回此.originalImage;
}
}
公共图像修改图像
{
得到
{
返回此.modifiedImage;
}
}
}
我创建了一个简化的测试项目,显示了这个问题*

以下是指向该项目的dropbox链接:

以下是方法1的Xcode Instruments屏幕截图作为证据(9 mb内存使用):

以下是方法2的Xcode Instruments热屏作为证据(55 mb内存使用):

下面是运行测试项目所需的代码块

        // Initialize My List of Images
        ListOfImages = new List<UIImage>();

        for ( int i = 0; i < 30; i++ )
        {
            // Create a UIImage Containing my original Image
            UIImage originalImage = UIImage.FromFile ("b2Bomber.png");
            float newWidth = 100f;
            float newHeight = 40f;
            float zoomScale;
            float resizedWidth, resizedHeight;

            UIImage resizedImage1;
            UIImage resizedImage2;

            // Basically, I want to take the originalImage Image and resize it twice.  
            // Method 1.) Resize the originalImage and save it as ResizedImage1.  Resize the originalImage and save it as ResizedImage2.  We're finished!
            // Method 2.) Resize the originalImage and save it as ResizedImage1.  Resize ResizedImage1 and save it as ResizedImage2.  We're finished!

            // The pro to Method 1 is that we get the best possible quaility on all resized images.  The con is, this takes a long time if we're doing dozens of very large images
            // The pro to Method 2 is that it's faster than Method 1.  This is why I want to use Method 2, it's speed.  But it has a HUGE con, it's memory usage. 
            // Please run this project on an iPad connected to XCodes Instruments to monitor memory usage and see what I mean 

            zoomScale = 10f;
            resizedWidth = newWidth*zoomScale;
            resizedHeight = newHeight*zoomScale;
            UIGraphics.BeginImageContext( new SizeF( resizedWidth, resizedHeight ) );
            originalImage.Draw( new RectangleF( 0, 0, resizedWidth, resizedHeight ) );
            resizedImage1 = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();



            zoomScale = 4f;
            resizedWidth = newWidth*zoomScale;
            resizedHeight = newHeight*zoomScale;
            UIGraphics.BeginImageContext( new SizeF( resizedWidth, resizedHeight ) );

            // Run this project on an iPad and examine the memory usage in XCode's Instruments.  
            // The Real Memory Usage will be aroud 9 MB.  
            // Uncomment this "originalImage.Draw" line to see this happening, make sure to comment out the "resizedImage1.Draw" line

            // originalImage.Draw( new RectangleF( 0, 0, resizedWidth, resizedHeight ) );


            // Run this project on an iPad and examine the memory usage in XCode's Instruments.  
            // The Real Memory Usage will be aroud 55 MB!!  
            // My question is, why does the memory sky rocket when doing this, and how can I prevent the memory from sky rocketing??
            // My App requires me to resize around a hundred images and I want to be able to resize an already resized image (like in this example) without the memory usage sky rocketing like this...
            // Uncomment this "resizedImage1.Draw" line to see this happening, make sure to comment out the "originalImage.Draw" line

            resizedImage1.Draw( new RectangleF( 0, 0, resizedWidth, resizedHeight ) );
            resizedImage2 = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();


            // Add my resized images to the list of Images
            ListOfImages.Add (resizedImage1);
            ListOfImages.Add (resizedImage2);
        }
//初始化我的图像列表
ListOfImages=新列表();
对于(int i=0;i<30;i++)
{
//创建包含我的原始图像的UIImage
UIImage originalImage=UIImage.FromFile(“b2Bomber.png”);
浮动宽度=100f;
浮动高度=40f;
浮标动物鳞片;
float resizedWidth,resizedHeight;
UIImage resizedImage1;
UIImage resizedImage2;
//基本上,我想采取的原始图像,并调整它两次。
//方法1.)调整原始图像的大小并将其保存为ResizedImage1。调整原始图像的大小并将其保存为ResizedImage2。我们完成了
public class ImageResizer_Abridged
{
    UIImage originalImage  = null;
    UIImage modifiedImage = null;

    public ImageResizer_Abridged ( UIImage image )
    {
        this.originalImage = image;
        this.modifiedImage = image;
    }   

    /// <summary>
    /// strech resize
    /// </summary>
    public void Resize( float width, float height )
    {
        UIGraphics.BeginImageContext( new SizeF( width, height ) );
        //
        modifiedImage.Draw( new RectangleF( 0,0, width, height ) );
        modifiedImage = UIGraphics.GetImageFromCurrentImageContext();
        //
        UIGraphics.EndImageContext();
    }

    public UIImage OriginalImage 
    {
        get 
        {
            return this.originalImage;
        }
    }

    public UIImage ModifiedImage 
    {
        get 
        {
            return this.modifiedImage;
        }
    }
}
        // Initialize My List of Images
        ListOfImages = new List<UIImage>();

        for ( int i = 0; i < 30; i++ )
        {
            // Create a UIImage Containing my original Image
            UIImage originalImage = UIImage.FromFile ("b2Bomber.png");
            float newWidth = 100f;
            float newHeight = 40f;
            float zoomScale;
            float resizedWidth, resizedHeight;

            UIImage resizedImage1;
            UIImage resizedImage2;

            // Basically, I want to take the originalImage Image and resize it twice.  
            // Method 1.) Resize the originalImage and save it as ResizedImage1.  Resize the originalImage and save it as ResizedImage2.  We're finished!
            // Method 2.) Resize the originalImage and save it as ResizedImage1.  Resize ResizedImage1 and save it as ResizedImage2.  We're finished!

            // The pro to Method 1 is that we get the best possible quaility on all resized images.  The con is, this takes a long time if we're doing dozens of very large images
            // The pro to Method 2 is that it's faster than Method 1.  This is why I want to use Method 2, it's speed.  But it has a HUGE con, it's memory usage. 
            // Please run this project on an iPad connected to XCodes Instruments to monitor memory usage and see what I mean 

            zoomScale = 10f;
            resizedWidth = newWidth*zoomScale;
            resizedHeight = newHeight*zoomScale;
            UIGraphics.BeginImageContext( new SizeF( resizedWidth, resizedHeight ) );
            originalImage.Draw( new RectangleF( 0, 0, resizedWidth, resizedHeight ) );
            resizedImage1 = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();



            zoomScale = 4f;
            resizedWidth = newWidth*zoomScale;
            resizedHeight = newHeight*zoomScale;
            UIGraphics.BeginImageContext( new SizeF( resizedWidth, resizedHeight ) );

            // Run this project on an iPad and examine the memory usage in XCode's Instruments.  
            // The Real Memory Usage will be aroud 9 MB.  
            // Uncomment this "originalImage.Draw" line to see this happening, make sure to comment out the "resizedImage1.Draw" line

            // originalImage.Draw( new RectangleF( 0, 0, resizedWidth, resizedHeight ) );


            // Run this project on an iPad and examine the memory usage in XCode's Instruments.  
            // The Real Memory Usage will be aroud 55 MB!!  
            // My question is, why does the memory sky rocket when doing this, and how can I prevent the memory from sky rocketing??
            // My App requires me to resize around a hundred images and I want to be able to resize an already resized image (like in this example) without the memory usage sky rocketing like this...
            // Uncomment this "resizedImage1.Draw" line to see this happening, make sure to comment out the "originalImage.Draw" line

            resizedImage1.Draw( new RectangleF( 0, 0, resizedWidth, resizedHeight ) );
            resizedImage2 = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();


            // Add my resized images to the list of Images
            ListOfImages.Add (resizedImage1);
            ListOfImages.Add (resizedImage2);
        }
public class ImageResizer_Abridged
{
    private readonly UIImage originalImage;

    private UIImage modifiedImage;

    public ImageResizer_Abridged(UIImage image)
    {
        this.originalImage = image;
        this.modifiedImage = image;
    }

    /// <summary>
    /// stretch resize
    /// </summary>
    public void Resize(float width, float height)
    {
        UIGraphics.BeginImageContext(new SizeF(width, height));
        //
        var oldImage = this.modifiedImage;
        this.modifiedImage.Draw(new RectangleF(0, 0, width, height));
        this.modifiedImage = UIGraphics.GetImageFromCurrentImageContext();
        oldImage.Dispose();
        //
        UIGraphics.EndImageContext();
    }

    public UIImage OriginalImage
    {
        get
        {
            return this.originalImage;
        }
    }

    public UIImage ModifiedImage
    {
        get
        {
            return this.modifiedImage;
        }
    }
}