简体   繁体   中英

CGImageSourceCreateThumbnailAtIndex() giving different results in iOS11 and iOS12

CGImageRef        thumbnailImage = NULL;
CGImageSourceRef  imageSource = NULL;
CFDictionaryRef   createOptions = NULL;
CFStringRef       createKeys[3];
CFTypeRef         createValues[3];
CFNumberRef       thumbnailSize = 0;
UIImage * thumbnail;
NSData * squareData = UIImagePNGRepresentation(sourceImage);
NSData * thumbnailData = nil;

imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)squareData,NULL);
if (imageSource)
{
    thumbnailSize = CFNumberCreate(NULL, kCFNumberIntType, &imageSize);
    if (thumbnailSize)
    {
        createKeys[0] = kCGImageSourceCreateThumbnailWithTransform;
        createValues[0] = (CFTypeRef)kCFBooleanTrue;
        createKeys[1] = kCGImageSourceCreateThumbnailFromImageIfAbsent;
        createValues[1] = (CFTypeRef)kCFBooleanTrue;
        createKeys[2] = kCGImageSourceThumbnailMaxPixelSize;
        createValues[2] = (CFTypeRef)thumbnailSize;

        createOptions = CFDictionaryCreate(NULL, (const void **) createKeys,
                createValues, sizeof(createValues)/ sizeof(createValues[0]),
                &kCFTypeDictionaryKeyCallBacks,
                & kCFTypeDictionaryValueCallBacks);
        if (createOptions)
        {
            thumbnailImage = CGImageSourceCreateThumbnailAtIndex(imageSource,0,createOptions);
            if(thumbnailImage)
            {
                thumbnail = [UIImage imageWithCGImage:thumbnailImage];
                if (thumbnail)
                {
                    thumbnailData = UIImagePNGRepresentation(thumbnail);
                }
            }
        }
    }
}

Getting different thumbnailData.length value for the same image in iOS12. I am trying to create a thumbnail image using CGImageSourceCreateThumbnailAtIndex() and passing sourceImage as a parameter. Is it an iOS12 bug? Is there a workaround for it? I'm using iOS12 beta4.

The data size is different, but the resulting image is fine. They've clearly made some very modest changes to the algorithm. But there is no bug here.

Personally, I notice two changes:

  • In non-square images, the algorithm for determining the size of the thumbnail has obviously changed. Eg, with my sample 3500×2335px image, when I created a 100px thumbnail, it resulted in a 100×67px image in iOS 12.2, but was 100×66px in iOS 11.0.1.

  • In square images, the two iOS versions both generated suitably square thumbnails. Regarding the image, itself, I could not see much of any observable difference with the naked eye. In fact, I dropped this into Photoshop and analyzed the differences (where black == no difference), it first seemed to suggest no change at all:

    在此处输入图片说明

    Only when I started to really pixel-peep could I detect the very modest changes. The individual channels rarely differed by more than 1 or 2 (in these UInt8 values). Here is the same delta image, this time with the levels blown out so you can see the differences:

    在此处输入图片说明

Bottom line, there clearly is some change to the algorithm, but I wouldn't characterize it as a bug. It is just different, but it works fine.


In an unrelated observation, your code has some leaks. If a Core Foundation method has Create or Copy in the name, you are responsible for releasing it (or, in bridged types, transferring ownership to ARC, which isn't an option here). The static analyzer, shift + command + B , is excellent at identifying these issues.

FWIW, here's my rendition:

- (UIImage * _Nullable)resizedImage:(UIImage *)sourceImage to:(NSInteger)imageSize {
    NSData *squareData = UIImagePNGRepresentation(sourceImage);
    UIImage *thumbnail = nil;

    CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)squareData, NULL);
    if (imageSource) {
        NSDictionary *createOptions = @{
            (id)kCGImageSourceCreateThumbnailWithTransform: @true,
            (id)kCGImageSourceCreateThumbnailFromImageIfAbsent: @true,
            (id)kCGImageSourceThumbnailMaxPixelSize: @(imageSize)
        };
        CGImageRef thumbnailImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (CFDictionaryRef)createOptions);
        if (thumbnailImage) {
            thumbnail = [UIImage imageWithCGImage:thumbnailImage];
            if (thumbnail) {
                NSData *data = UIImagePNGRepresentation(thumbnail);
                // do something with `data` if you want
            }
            CFRelease(thumbnailImage);
        }
        CFRelease(imageSource);
    }

    return thumbnail;
}

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