获取UIImage的大小(字节数),而不是高度和宽度

68

我正在尝试获取UIImage的长度。 不是图像的宽度或高度,而是数据的大小。

12个回答

78
 UIImage *img = [UIImage imageNamed:@"sample.png"];
 NSData *imgData = UIImageJPEGRepresentation(img, 1.0); 
 NSLog(@"Size of Image(bytes):%d",[imgData length]);

25
应该将0替换为1.0;这是来自原始图像的质量。 - Denis Kutlubaev
1
在UIImageJPEGRepresentation中传递的压缩质量应该是多少才合适?1.0会使得计算出来的大小比原始大小还要大。 - R3D3vil
1
@Nisarg,1.0 提供了最高质量和最少的压缩。尝试使用 0.6,它具有更好的质量和显著的压缩。 - Meet
1
NSData *imgData = UIImageJPEGRepresentation(img, 1);NSData *imgData = UIImageJPEGRepresentation(img, 1); - Fabio
5
如果想查看图像占用了多少内存,为什么要获取它的压缩大小?而且使用UIImageJPEGRepresentation会创建一个新图像,占用空间并复制位,如果您不想消耗更多内存或者性能受限,请勿这样做。 - mahboudz
显示剩余2条评论

38

UIImage的底层数据可能会有所不同,因此对于相同的“图像”,其数据大小可能会有所变化。您可以使用UIImagePNGRepresentationUIImageJPEGRepresentation来获取它们等效的NSData构造体,然后检查其大小。


正如我们所预期的那样,使用UIImageJPEGRepresentation可能会返回比使用UIImagePNGRepresentation小一半的大小。 - onmyway133
7
UIImageJPEGRepresentation和UIImagePNGRepresentation不会返回原始大小。 - NSLeader

16

使用UIImage的CGImage属性。然后结合CGImageGetBytesPerRow * CGImageGetHeight和UIImage的sizeof,你应该可以接近实际大小。

如果你想将其用于例如malloc以准备位图操作(假设像素格式为4字节,其中3字节为RGB和1字节为Alpha)等目的,则这将返回图像的未压缩大小。

int height = image.size.height,
    width = image.size.width;
int bytesPerRow = 4*width;
if (bytesPerRow % 16)
    bytesPerRow = ((bytesPerRow / 16) + 1) * 16;
int dataSize = height*bytesPerRow;

4
这里有几个问题;(1) image.size.heightimage.size.width 会给你CG单位的大小,不一定是像素。如果.scale属性不是1,你会得到错误的答案。(2)你假设每个像素占4个字节,这对于RGBA图像是正确的,但对于灰度图像不正确。 - Todd Lehman

13
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)editInfo
{
   UIImage *image=[editInfo valueForKey:UIImagePickerControllerOriginalImage];
   NSURL *imageURL=[editInfo valueForKey:UIImagePickerControllerReferenceURL];
   __block long long realSize;

   ALAssetsLibraryAssetForURLResultBlock resultBlock=^(ALAsset *asset)
   {
      ALAssetRepresentation *representation=[asset defaultRepresentation];
      realSize=[representation size];
   };

   ALAssetsLibraryAccessFailureBlock failureBlock=^(NSError *error)
   {
      NSLog(@"%@", [error localizedDescription]);
   };

   if(imageURL)
   {
      ALAssetsLibrary *assetsLibrary=[[[ALAssetsLibrary alloc] init] autorelease];
      [assetsLibrary assetForURL:imageURL resultBlock:resultBlock failureBlock:failureBlock];
   }
}

1
我认为这是处理UIImagePickerController时更优雅的解决方案。 - D33pN16h7
1
这是处理UIIImagePickerController最佳的解决方案。 - Pawan Sharma
1
惊人的解决方案兄弟...完美地工作着...每个人都建议使用JPEGRepresentation或PNGRepresentation...但这会导致不正确的图像大小...非常感谢...你节省了我很多时间。 - SURESH SANKE
你提供了一个不错的解决方案,使用imageURL来查找图像大小。是否有可能使用上述代码中的“image”从新捕获的图像中获取它? - SURESH SANKE

10

Swift 中的示例:

let img: UIImage? = UIImage(named: "yolo.png")
let imgData: NSData = UIImageJPEGRepresentation(img, 0)
println("Size of Image: \(imgData.length) bytes")

1
如果想查看图像占用了多少内存,为什么要获取它的压缩大小?而且使用UIImageJPEGRepresentation会创建一个新图像,占用空间并复制位;如果您不想消耗更多内存或者性能受限,请勿这样做。 - mahboudz

6
以下是最快、最干净、最通用且最不容易出错的方法来获得答案。在一个类别UIImage+MemorySize中:
#import <objc/runtime.h>

- (size_t) memorySize
{
  CGImageRef image = self.CGImage;
  size_t instanceSize = class_getInstanceSize(self.class);
  size_t pixmapSize = CGImageGetHeight(image) * CGImageGetBytesPerRow(image);
  size_t totalSize = instanceSize + pixmapSize;
  return totalSize;
}

如果你只需要实际的位图而不是UIImage实例容器,那么它真的很简单,只需按照以下步骤操作:
- (size_t) memorySize
{
  return CGImageGetHeight(self.CGImage) * CGImageGetBytesPerRow(self.CGImage);
}

4

Swift 3:

let image = UIImage(named: "example.jpg")
if let data = UIImageJPEGRepresentation(image, 1.0) {
    print("Size: \(data.count) bytes")
}

2

Swift 4&5:

extension UIImage {
    var sizeInBytes: Int {
        guard let cgImage = self.cgImage else {
            // This won't work for CIImage-based UIImages
            assertionFailure()
            return 0
        }
        return cgImage.bytesPerRow * cgImage.height
    }
}

1

我尝试使用以下代码获取图像大小

let imgData = image.jpegData(compressionQuality: 1.0)

但它给出的图像大小比实际大小小。然后我尝试使用PNG表示来获取大小。

let imageData = image.pngData()

但它给出的字节计数比实际图像大小要大。

对我来说,唯一完美运作的事情。

public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    var asset: PHAsset!
    if #available(iOS 11.0, *) {
      asset = info[UIImagePickerControllerPHAsset] as? PHAsset
    } else {
      if let url = info[UIImagePickerControllerReferenceURL] as? URL {
        asset = PHAsset.fetchAssets(withALAssetURLs: [url], options: .none).firstObject!
      }
    }

    if #available(iOS 13, *) {
      PHImageManager.default().requestImageDataAndOrientation(for: asset, options: .none) { data, string, orien, info in
        let imgData = NSData(data:data!)
        var imageSize: Int = imgData.count
        print("actual size of image in KB: %f ", Double(imageSize) / 1024.0)
      }
    } else {
      PHImageManager.default().requestImageData(for: asset, options: .none) { data, string, orientation, info in
        let imgData = NSData(data:data!)
        var imageSize: Int = imgData.count
        print("actual size of image in KB: %f ", Double(imageSize) / 1024.0)
      }
    }
  }

1

我不确定你的情况。如果你需要实际的字节大小,我认为你不需要这样做。你可以使用UIImagePNGRepresentation或UIImageJPEGRepresentation获取图像压缩数据的NSData对象。

我认为你想要获取未压缩图像(像素数据)的实际大小。你需要将UIImage*或CGImageRef转换为原始数据。这是一个将UIImage转换为IplImage(来自OpenCV)的示例。你只需要分配足够的内存并将指针传递给CGBitmapContextCreate的第一个参数即可。

UIImage *image = //Your image
CGImageRef imageRef = image.CGImage;

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
IplImage *iplimage = cvCreateImage(cvSize(image.size.width, image.size.height), IPL_DEPTH_8U, 4);
CGContextRef contextRef = CGBitmapContextCreate(iplimage->imageData, iplimage->width, iplimage->height,
                                                iplimage->depth, iplimage->widthStep,
                                                colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);
CGContextDrawImage(contextRef, CGRectMake(0, 0, image.size.width, image.size.height), imageRef);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);

IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, 3);
cvCvtColor(iplimage, ret, CV_RGBA2BGR);
cvReleaseImage(&iplimage);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接