简体   繁体   中英

OpenGL ES: Screenshot shows different between device and simulator

I've tried to create a screenshot by using UIActivityViewController and saved into Photos in iPhone/iPad device. However, in simulator everything shows correctly, but when I switched to device, it only shows part. Here is the screenshot:

  1. In simulator (You can see there is one background, one green line and one star image)

在此处输入图片说明

  1. In real device (You can see there is only one star image, and everything else is gone)

在此处输入图片说明

I merged all of those three different UIImages into one image so that I can take a screenshot.

  1. I first merge the background image (bridge UIImage) with star image.

     -(UIImage*)mergeUIImageView:(UIImage*)bkgound FrontPic:(UIImage*)fnt FrontPicX:(CGFloat)xPos FrontPicY:(CGFloat)yPos FrontPicWidth:(CGFloat)picWidth FrontPicHeight:(CGFloat)picHeight FinalSize:(CGSize)finalSize { UIGraphicsBeginImageContext(CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width)); // bkgound - is the bridge image [bkgound drawInRect:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width)]; // fnt - is the star image [fnt drawInRect:CGRectMake(xPos, yPos, picWidth, picHeight)]; // merged image UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 
  2. Then I merged this picture with opengl rendered picture which is the green line.

a) I first change the opengGL image to UIImage by using this function

    -(UIImage *) glToUIImage {

     float scaleFactor = [[UIScreen mainScreen] scale];
     CGRect screen = [[UIScreen mainScreen] bounds];
     CGFloat image_height = screen.size.width * scaleFactor;
     CGFloat image_width = screen.size.height * scaleFactor;

     NSInteger myDataLength = image_width * image_height * 4;

     // allocate array and read pixels into it.
     GLubyte *buffer = (GLubyte *) malloc(myDataLength);
     glReadPixels(0, 0, image_width, image_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

     // gl renders "upside down" so swap top to bottom into new array.
     // there's gotta be a better way, but this works.
     GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
     for(int y = 0; y < image_height; y++)
     {
        for(int x = 0; x < image_width * 4; x++)
        {
           buffer2[(int)((image_height - 1 - y) * image_width * 4 + x)] = buffer[(int)(y * 4 * image_width + x)];
         }
      }

      // make data provider with data.
      CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);

      // prep the ingredients
      int bitsPerComponent = 8;
      int bitsPerPixel = 32;
      int bytesPerRow = 4 * image_width;
      CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
      CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
      CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

      // make the cgimage
      CGImageRef imageRef = CGImageCreate(image_width, image_height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

       // then make the uiimage from that
       UIImage *myImage = [UIImage imageWithCGImage:imageRef];

       return myImage;
     }

b)Then I merge this opengl image with my above image(bridge + star) by using the same function above

    -(UIImage*)screenshot
    {
        // get opengl image from above function
        UIImage *image = [self glToUIImage];

        CGRect pos = CGRectMake(0, 0, image.size.width, image.size.height);
        UIGraphicsBeginImageContext(image.size);
        [image drawInRect:pos];
        [self.background.image drawInRect:pos];
        UIImage* final = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return final;
     }

And it works great in (iPhone, iPad, iPhone with retina and iPad with retina)simulator (version 6.0). However, when I switched to real device (iPhone 4/4s/5, iPad (2/mini/retina)) it only shows star image. The xcode version is 4.6.3 and base SDK is latest IOS(IOS 6.1) and IOS deployment target is 5.0. Could you guys tell me how to fix it? Thanks.

The problem is IOS 6.0 will not keep the buffer all the time, it will erase it. However, when you do screenshot, you are getting data from buffer so that's why I keep getting black background. So add category to let device keep buffer image instead will solve this problem.

 @interface CAEAGLLayer (Retained)
 @end

 @implementation CAEAGLLayer (Retained)
 - (NSDictionary*) drawableProperties
 {
    return @{kEAGLDrawablePropertyRetainedBacking : @(YES)};
 }
 @end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM