ImageIO

ImageIO

在阅读有关gif编解码相关的内容时,有见到使用ImageIO相关的内容

参考Accessing Image Properties Without Loading the Image Into Memory提到其一些应用

比如说你想获取图片的一些属性,比如图片的尺寸和一些其他的元数据,但是这张图片你并不需要再屏幕上显示。最简单的方式就是使用UIImage

UIImage *image = [UIImage imageWithContentsOfFile:...];
CGSize imageSize = image.size;
...

这样做所带来的问题是整张图片都会被加载到内存中。由于在内存中是未压缩的,所以一个512 × 512 的图片就有1M

此时就可以使用ImageIO.framework

如下的例子,获取一张网络上的图片,输出图片的大小:

    NSString *urlStr = @"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524748621307&di=46209fd530717b3c1621468c5e22e063&imgtype=0&src=http%3A%2F%2Fa.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F0ff41bd5ad6eddc4c984b29335dbb6fd52663372.jpg";

    NSURL *imageFileURL = [NSURL URLWithString:urlStr];
    CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageFileURL, NULL);
    if (imageSource == NULL) {
        // Error loading image

        return;
    }

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:NO], (NSString *)kCGImageSourceShouldCache,
                             nil];
    CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (CFDictionaryRef)options);
    if (imageProperties) {
        NSNumber *width = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
        NSNumber *height = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
        NSLog(@"Image dimensions: %@ x %@ px", width, height);
        CFRelease(imageProperties);
    }
    CFRelease(imageSource);

输出结果为:

Image dimensions: 1280 x 1920 px

CGImageSourceCopyPropertiesAtIndex()返回的字典包含许多信息

如下可以获取拍摄的日期、相机的模式和GPS信息等:

        CFDictionaryRef exif = CFDictionaryGetValue(imageProperties, kCGImagePropertyExifDictionary);
        if (exif) {
            NSString *dateTakenString = (NSString *)CFDictionaryGetValue(exif, kCGImagePropertyExifDateTimeOriginal);
            NSLog(@"Date Taken: %@", dateTakenString);
        }

        CFDictionaryRef tiff = CFDictionaryGetValue(imageProperties, kCGImagePropertyTIFFDictionary);
        if (tiff) {
            NSString *cameraModel = (NSString *)CFDictionaryGetValue(tiff, kCGImagePropertyTIFFModel);
            NSLog(@"Camera Model: %@", cameraModel);
        }

        CFDictionaryRef gps = CFDictionaryGetValue(imageProperties, kCGImagePropertyGPSDictionary);
        if (gps) {
            NSString *latitudeString = (NSString *)CFDictionaryGetValue(gps, kCGImagePropertyGPSLatitude);
            NSString *latitudeRef = (NSString *)CFDictionaryGetValue(gps, kCGImagePropertyGPSLatitudeRef);
            NSString *longitudeString = (NSString *)CFDictionaryGetValue(gps, kCGImagePropertyGPSLongitude);
            NSString *longitudeRef = (NSString *)CFDictionaryGetValue(gps, kCGImagePropertyGPSLongitudeRef);
            NSLog(@"GPS Coordinates: %@ %@ / %@ %@", longitudeString, longitudeRef, latitudeString, latitudeRef);
        }

Programming iOS 10 Dive Deep into Views View Controllers and Frameworks一书中,就有这样的使用形式:

        let url = Bundle.main.url(forResource:"colson", withExtension: "jpg")!
        let src = CGImageSourceCreateWithURL(url as CFURL, nil)!
        let result = CGImageSourceCopyPropertiesAtIndex(src, 0, nil)!
        let d = result as! [AnyHashable:Any] // :) works because CFString is now AnyHashable
        print(d)
        // just proving it really is a dictionary
        let width = d[kCGImagePropertyPixelWidth] as! CGFloat
        let height = d[kCGImagePropertyPixelHeight] as! CGFloat
        print("\(width) by \(height)")

        // another way; no one in his right mind would do this, though
        do {
            let result = CGImageSourceCopyPropertiesAtIndex(src, 0, nil)!
            let key = kCGImagePropertyPixelWidth // CFString
            let p1 = Unmanaged.passUnretained(key).toOpaque() // UnsafeMutableRawPointer
            let p2 = CFDictionaryGetValue(result, p1) // UnsafeRawPointer
            let n = Unmanaged<CFNumber>.fromOpaque(p2!).takeUnretainedValue() // CFNumber
            var width : CGFloat = 0
            CFNumberGetValue(n, .cgFloatType, &width) // width is now 640.0
            print(width)
        }

缩略图
如果你在显示某个图片的时候,不关心原始的图片数据,缩率图thumbnail正是你所需要的

使用CGImageSourceCreateThumbnailAtIndex时传递一个字典。需要注意的是我们使用的CGImage是实际的像素,所以要考虑到设备的scale

        let url = Bundle.main.url(forResource:"colson", withExtension: "jpg")!
        let src = CGImageSourceCreateWithURL(url as CFURL, nil)!
        let scale = UIScreen.main.scale
        let w = self.iv.bounds.width * scale
        let d : [AnyHashable:Any] = [
            kCGImageSourceShouldAllowFloat : true,
            kCGImageSourceCreateThumbnailWithTransform : true,
            kCGImageSourceCreateThumbnailFromImageAlways : true,
            kCGImageSourceThumbnailMaxPixelSize : w
        ]
        let imref = CGImageSourceCreateThumbnailAtIndex(src, 0, d as CFDictionary)!
        let im = UIImage(cgImage: imref, scale: scale, orientation: .up)
        self.iv.image = im
        print(im)
        print(im.size)

缩略图

保存图片为特定的格式

需要使用到image destination,如下的例子,保存为TIFF

        let url = Bundle.main.url(forResource:"colson", withExtension: "jpg")!
        let src = CGImageSourceCreateWithURL(url as CFURL, nil)!
        let fm = FileManager.default
        let suppurl = try! fm.url(for:.applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let tiff = suppurl.appendingPathComponent("mytiff.tiff")
        let dest = CGImageDestinationCreateWithURL(tiff as CFURL, kUTTypeTIFF, 1, nil)!
        CGImageDestinationAddImageFromSource(dest, src, 0, nil)
        let ok = CGImageDestinationFinalize(dest)
        if ok {
            print("tiff image written to disk")
        } else {
            print("something went wrong")
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值