合并/合并两个图像时,由于内存警告,iPad应用程序崩溃 [英] iPad app crashed due to memory warning while combining/merging two images

查看:106
本文介绍了合并/合并两个图像时,由于内存警告,iPad应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在执行图像处理时,由于大量使用内存,我的应用程序崩溃了.

My app is crashing due to heavy use of memory while I am doing image processing.

基本上,我的整个应用程序都依赖于以下方法,其中使用了用于组合图像的逻辑,另一种方法是我从捆绑软件中加载图像.

Basically my whole app depends on following method in which logic for combining images are used another method i used for loading images from bundle.

+ (UIImage*)imageByCombiningImages:(UIImage*)firstImage withImage:(UIImage*)secondImage
{
    @autoreleasepool
    {
        UIImage *image = nil;

        CGSize newImageSize = CGSizeMake(MAX(firstImage.size.width, secondImage.size.width), MAX(firstImage.size.height, secondImage.size.height));
        if (UIGraphicsBeginImageContextWithOptions != NULL)
        {
            UIGraphicsBeginImageContextWithOptions(newImageSize, NO, [[UIScreen mainScreen] scale]);
        }
        else
        {
            UIGraphicsBeginImageContext(newImageSize);
        }

        [firstImage drawAtPoint:CGPointMake(roundf((newImageSize.width-firstImage.size.width)/2), roundf((newImageSize.height-firstImage.size.height)/2))];

        firstImage =nil;
        [secondImage drawAtPoint:CGPointMake(roundf((newImageSize.width-secondImage.size.width)/2), roundf((newImageSize.height-secondImage.size.height)/2))];


        secondImage=nil;

        image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
}

- (UIImage*) getImage:(NSString*)imagename
{
    NSString *fileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:imagename];
    UIImage *image = [UIImage imageWithContentsOfFile:fileName];
    return image;
}

上述方法多次被以下方法调用

the above methods are called from following method numerous times

- (void) applyMaterialWithValue:(NSDictionary*)dict
{

    @synchronized(self)
    {

        NSString *materialName = [dict valueForKey:@"material"];
        NSString *optionName = [dict valueForKey:@"option"];
        //NSString *preset_Name = [dict valueForKey:@"preset"];
        NSString *name = [dict valueForKey:@"name"];
        if([[GlobalIntVariable getCMFScheme] isEqualToString:@"preset1"])

        {
            if(!isMetalPressed)
            {

                [GlobalIntVariable setCurrentMaterialName:@"Preset 1 Metal Plating"];
            }
            if(!isLeatherPressed)
            {
                [GlobalIntVariable setCurrentPresetName:@"preset1"];

            }

        }
        if([[GlobalIntVariable getCMFScheme] isEqualToString:@"preset2"])

        {

            if(!isMetalPressed)
            {

                [GlobalIntVariable setCurrentMaterialName:@"Preset 2 Metal Plating"];
            }
            if(!isLeatherPressed)
            {
                [GlobalIntVariable setCurrentPresetName:@"preset2"];

            }

        }

        if ([materialName isEqualToString:AREAD4METALCOMPONENET ]|| [materialName isEqualToString:AREA8METALCOMPONENET])
        {
            [GlobalIntVariable setCurrentMaterialName:name];
        }


        if([optionName isEqualToString:OPTION0])
        {
            @autoreleasepool
            {

                UIImage *presetImg1L1Standard = [APP_DEL getImage:[dict valueForKey:@"image1L1Standard"]];
                imgView1Layout1Standard.image = [ImageOperations imageByCombiningImages:imgView1Layout1Standard.image withImage:presetImg1L1Standard];
                imgView1Layout1StandardPSUOn.image = [ImageOperations imageByCombiningImages:imgView1Layout1StandardPSUOn.image withImage:presetImg1L1Standard];
                 presetImg1L1Standard=nil;



                UIImage *presetImg1L1Premium = [APP_DEL getImage:[dict valueForKey:@"image1L1Premium"]];
                imgView1Layout1Premium.image = [ImageOperations imageByCombiningImages:imgView1Layout1Premium.image withImage:presetImg1L1Premium];
                imgView1Layout1PremiumPSUOn.image = [ImageOperations imageByCombiningImages:imgView1Layout1PremiumPSUOn.image withImage:presetImg1L1Premium];
                presetImg1L1Premium=nil;

                UIImage *presetImg1L2Standard = [APP_DEL getImage:[dict valueForKey:@"image1L2Standard"]];
                imgView1Layout2Standard.image = [ImageOperations imageByCombiningImages:imgView1Layout2Standard.image withImage:presetImg1L2Standard];
                imgView1Layout2StandardPSUOn.image = [ImageOperations imageByCombiningImages:imgView1Layout2StandardPSUOn.image withImage:presetImg1L2Standard];
                presetImg1L2Standard=nil;

                UIImage *presetImg1L2Premium = [APP_DEL getImage:[dict valueForKey:@"image1L2Premium"]];
                imgView1Layout2Premium.image = [ImageOperations imageByCombiningImages:imgView1Layout2Premium.image withImage:presetImg1L2Premium];
                imgView1Layout2PremiumPSUOn.image = [ImageOperations imageByCombiningImages:imgView1Layout2PremiumPSUOn.image withImage:presetImg1L2Premium];
                presetImg1L2Premium=nil;

            }

            @autoreleasepool
            {

                UIImage *presetImg2L1Standard = [APP_DEL getImage:[dict valueForKey:@"image2L1Standard"]];
                imgView2Layout1Standard.image = [ImageOperations imageByCombiningImages:imgView2Layout1Standard.image withImage:presetImg2L1Standard];
                imgView2Layout1StandardPSUOn.image = [ImageOperations imageByCombiningImages:imgView2Layout1StandardPSUOn.image withImage:presetImg2L1Standard];
                presetImg2L1Standard=nil;

                UIImage *presetImg2L1Premium = [APP_DEL getImage:[dict valueForKey:@"image2L1Premium"]];
                imgView2Layout1Premium.image = [ImageOperations imageByCombiningImages:imgView2Layout1Premium.image withImage:presetImg2L1Premium];
                imgView2Layout1PremiumPSUOn.image = [ImageOperations imageByCombiningImages:imgView2Layout1PremiumPSUOn.image withImage:presetImg2L1Premium];
                presetImg2L1Premium=nil;

                UIImage *presetImg2L2Standard = [APP_DEL getImage:[dict valueForKey:@"image2L2Standard"]];
                imgView2Layout2Standard.image = [ImageOperations imageByCombiningImages:imgView2Layout2Standard.image withImage:presetImg2L2Standard];
                imgView2Layout2StandardPSUOn.image = [ImageOperations imageByCombiningImages:imgView2Layout2StandardPSUOn.image withImage:presetImg2L2Standard];
                presetImg2L2Standard=nil;

                UIImage *presetImg2L2Premium = [APP_DEL getImage:[dict valueForKey:@"image2L2Premium"]];
                imgView2Layout2Premium.image = [ImageOperations imageByCombiningImages:imgView2Layout2Premium.image withImage:presetImg2L2Premium];
                imgView2Layout2PremiumPSUOn.image = [ImageOperations imageByCombiningImages:imgView2Layout2PremiumPSUOn.image withImage:presetImg2L2Premium];
                presetImg2L2Premium=nil;


            }

            @autoreleasepool
            {

                UIImage *presetImg3L1Standard = [APP_DEL getImage:[dict valueForKey:@"image3L1Standard"]];
                imgView3Layout1Standard.image = [ImageOperations imageByCombiningImages:imgView3Layout1Standard.image withImage:presetImg3L1Standard];
                imgView3Layout1StandardPSUOn.image = [ImageOperations imageByCombiningImages:imgView3Layout1StandardPSUOn.image withImage:presetImg3L1Standard];
                presetImg3L1Standard=nil;

                UIImage *presetImg3L1Premium = [APP_DEL getImage:[dict valueForKey:@"image3L1Premium"]];
                imgView3Layout1Premium.image = [ImageOperations imageByCombiningImages:imgView3Layout1Premium.image withImage:presetImg3L1Premium];
                imgView3Layout1PremiumPSUOn.image = [ImageOperations imageByCombiningImages:imgView3Layout1PremiumPSUOn.image withImage:presetImg3L1Premium];
                presetImg3L1Premium=nil;

                UIImage *presetImg3L2Standard = [APP_DEL getImage:[dict valueForKey:@"image3L2Standard"]];
                imgView3Layout2Standard.image = [ImageOperations imageByCombiningImages:imgView3Layout2Standard.image withImage:presetImg3L2Standard];
                imgView3Layout2StandardPSUOn.image = [ImageOperations imageByCombiningImages:imgView3Layout2StandardPSUOn.image withImage:presetImg3L2Standard];
                presetImg3L2Standard=nil;


                UIImage *presetImg3L2Premium = [APP_DEL getImage:[dict valueForKey:@"image3L2Premium"]];
                imgView3Layout2Premium.image = [ImageOperations imageByCombiningImages:imgView3Layout2Premium.image withImage:presetImg3L2Premium];
                imgView3Layout2PremiumPSUOn.image = [ImageOperations imageByCombiningImages:imgView3Layout2PremiumPSUOn.image withImage:presetImg3L2Premium];
                presetImg3L2Premium=nil;

            }



        }

        @autoreleasepool
        {
            UIImage *presetImg4Standard = [APP_DEL getImage:[dict valueForKey:@"image4Standard"]];
            mainImageView4.image=[ImageOperations imageByCombiningImages:mainImageView4.image withImage:presetImg4Standard];
            presetImg4Standard=nil;

            UIImage *presetImg5Standard = [APP_DEL getImage:[dict valueForKey:@"image5Standard"]];
            mainImageView5.image=[ImageOperations imageByCombiningImages:mainImageView5.image withImage:presetImg5Standard];
             presetImg5Standard=nil;
        }

        @autoreleasepool
        {
            UIImage *presetImg1Detail1 = [APP_DEL getImage:[dict valueForKey:@"image1DetailView1"]];
            imgView1Detail.image = [ImageOperations imageByCombiningImages:imgView1Detail.image withImage:presetImg1Detail1];
             presetImg1Detail1=nil;

            UIImage *presetImg2Detail2 = [APP_DEL getImage:[dict valueForKey:@"image2DetailView2"]];
            imgView2Detail.image = [ImageOperations imageByCombiningImages:imgView2Detail.image withImage:presetImg2Detail2];
            presetImg2Detail2=nil;

             UIImage *presetImg3Detail3 = [APP_DEL getImage:[dict valueForKey:@"image3DetailView3"]];
            imgView3Detail.image = [ImageOperations imageByCombiningImages:imgView3Detail.image withImage:presetImg3Detail3];
            presetImg3Detail3=nil;

        }


        [self setMaterialReflection];

        NSString *strShowIndicator = [dict valueForKey:@"hideIndicator"];
        if ([strShowIndicator isEqualToString:@"YES"]) {
            [appDelegate hideIndicator];
        }



    }
}

当上述称为内存使用量的方法超过400 mb&时,问题就出在这里.我在控制台& ;;中收到2-3次收到的内存警告消息之后我的应用程序崩溃了.

the issue is this when above method called the memory usage goes beyond 400 mb & i receive 2 - 3 times received memory warning message in console & my app is crashed after that.

,即使您在上述方法中看到的情况下,执行内存中的上述方法始终增加,我也没有所有uiimage对象&还使用了@autorelese块,但内存没有释放.

in runtime when above method in execution memory always increasing even as you see in above method i have nil all the uiimage objects & also used @autorelese block but memory is not releasing.

我想在每次调用以下方法后减少内存.

i want to decrease memory after each call of following method.

  • (UIImage *)imageByCombiningImages:(UIImage *)firstImage与Image:(UIImage *)secondImage
  • (UIImage*)imageByCombiningImages:(UIImage*)firstImage withImage:(UIImage*)secondImage

在上述方法中,我将两个图像合并为一个图像&我项目中的所有图像平均大小为2 MB.

in above method i am combining two images in to one image & all images in my projects are of average size of 2 MB.

如果我降低图像分辨率,而应用程序的质量却在降低,则我将图像大小减小到2 mb,而之前只有4 mb.那不是我想要的.

i have decreased size of images to 2 mb average before it was of 4 mb, if i reduce images resolution than quality of app is decreasing & that is not what i want.

我对此做了一个Google搜索&也尝试在堆栈溢出时找到解决方案,但仍然一无所获,因此请引导我解决此问题.

i have done a google about it & tried to find solution on stack overflow also but still got nothing, so please guide me through this issue.

请建议我如何改善图像合成方法? &我如何优化上述方法?,以便可以减少内存使用量&;我的应用程序可以顺利运行.

please suggest me how can i improve method of image combining ? & how can i optimize above methods ?,so that memory usage can be reduced & my app can run smoothly.

推荐答案

我建议的一件事是不要每次都绘制以从图形上下文中捕获图像.

One thing I can suggest is don't draw each and every time to capture the image from graphic context.

尝试以下步骤:

  1. 将字典传递给方法imageByCombiningImages:
  2. 计算框架
  3. 迭代字典中的所有图像并绘制
  4. 仅捕获一次最终图像.

编辑方法:

    + (UIImage*)imageByCombiningImages:(NSDictionary *)imageDict
    {
     UIImage *image = nil;

            CGSize newImageSize = CGSizeZero;
    NSArray *allImages = [imageDict allValues];
    for (UIImage *image in allImages) {
    newImageSize  = CGSizeMake(MAX(image.size.width, newImageSize.size.width), MAX(image.size.height, newImageSize.size.height));
    }


            if (UIGraphicsBeginImageContextWithOptions != NULL)
            {
                UIGraphicsBeginImageContextWithOptions(newImageSize, NO, [[UIScreen mainScreen] scale]);
            }
            else
            {
                UIGraphicsBeginImageContext(newImageSize);
            }

    for (UIImage *image in allImages) {
            [image drawAtPoint:CGPointMake(roundf((newImageSize.width-image.size.width)/2), roundf((newImageSize.height-image.size.height)/2))];
    }

image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;

    }

当您使用 UIGraphicsGetImageFromCurrentImageContext()创建图像时,核心图形会在内部创建 cg栅格数据以创建位图图像.它将消耗更多的内存.

when you create image using UIGraphicsGetImageFromCurrentImageContext(), internally cg raster data is created by the core graphics to create the bitmap image. it will consume more memory.

您可以通过延迟顺序的方法调用来合并图像来避免出现内存警告.

you can avoid memory warning by delaying sequential method calls to merge the image.

修改的图像合并方法:

- (void)imageByCombiningImages:(UIImage*)firstImage withImage:(UIImage*)secondImage
{

        UIImage *image = nil;

        CGSize newImageSize = CGSizeMake(MAX(firstImage.size.width, secondImage.size.width), MAX(firstImage.size.height, secondImage.size.height));
        if (UIGraphicsBeginImageContextWithOptions != NULL)
        {
            UIGraphicsBeginImageContextWithOptions(newImageSize, NO, [[UIScreen mainScreen] scale]);
        }
        else
        {
            UIGraphicsBeginImageContext(newImageSize);
        }

        [firstImage drawAtPoint:CGPointMake(roundf((newImageSize.width-firstImage.size.width)/2), roundf((newImageSize.height-firstImage.size.height)/2))];

        firstImage =nil;
        [secondImage drawAtPoint:CGPointMake(roundf((newImageSize.width-secondImage.size.width)/2), roundf((newImageSize.height-secondImage.size.height)/2))];


        secondImage=nil;

        image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

[self performSelector:@selector(merge:) withObject:image afterDelay:1]; // modify the delay which will work out for you

}

将所有图像键添加到数组中并调用方法,

Add all the image keys in array and call the method,

- (void)merge:(UIImage *)image {

    switch (rowIndex) {
        case 0: {
            UIImage *presetImg1L1Standard = [APP_DEL getImage:[dict valueForKey:[imagesArray objectAtIndex:rowIndex]]];
            switch (sectionIndex) {
                case 0:
                    [ImageOperations imageByCombiningImages:imgView1Layout1Standard.image withImage:presetImg1L1Standard];
                    sectionIndex++;
                    break;
                  case 1:
                    imgView1Layout1Standard.image = image;
                    [ImageOperations imageByCombiningImages:imgView1Layout1StandardPSUOn.image withImage:presetImg1L1Standard];
                    rowIndex ++;
                    sectionIndex = 0;
                    break;
                default:
                    break;
            }
        }
            break;
        case 1: {
            UIImage *image = [APP_DEL getImage:[dict valueForKey:[imagesArray objectAtIndex:rowIndex]]];
            switch (sectionIndex) {
                case 0:
                    imgView1Layout1StandardPSUOn.image = image;
                    [ImageOperations imageByCombiningImages:imgView1Layout1Premium.image withImage:image];
                    sectionIndex++;
                    break;
                case 1:
                    imgView1Layout1Premium.image = image;
                    [ImageOperations imageByCombiningImages:imgView1Layout1Premium.image withImage:presetImg1L1Premium];
                    rowIndex ++;
                    sectionIndex = 0;
                    break;
                default:
                        break;
                }
            }
                break;
// ................. and so on
            default:
                break;
        }
    }

希望这会给您一个想法.

hope this will give you an idea.

这篇关于合并/合并两个图像时,由于内存警告,iPad应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆