获取图像的大小,而无需加载到内存中(Get size of image without loadin

2019-07-22 01:19发布

我有几个.png图片(ETA:但格式也可以是JPEG或别的东西),我要在显示UITableViewCell秒。 眼下,为了得到该行的高度,我在加载图像,得到他们的size属性,并用它来找出如何高,使行(计算沿途进行必要的修改,因为大多数的图像得到调整大小前正在显示)。 为了加快速度,减少内存使用情况,我希望能够得到size不加载图像。 有没有办法做到这一点?

注:我知道有一些快捷方式我可以实现消除这个问题,但有以下几个原因,我不能提前调整图像或收集的图像尺寸提前,迫使我在运行时获取这些信息。

Answer 1:

由于iOS的SDK 4.0,这个任务可以用的ImageIO框架内进行( CGImageSource... )。 我已经回答了这里过类似的问题 。



Answer 2:

它应该是非常简单的。 PNG规范具有的解释PNG数据流 (这实际上是一个文件)。 IHDR部分包含有关图像尺寸的信息。

所以,你必须做的是在读取PNG “魔力值”,然后读出两个四字节的整数,这将是宽度和高度分别。 您可能还需要在这些值重新排序位(不知道他们是如何保存),但一旦你明白这一点,这将是非常简单的。



Answer 3:

注:此功能不能与iPhone压缩的PNG工作,这种压缩是由的XCode自动执行和更改图像头,在这里看到更多的细节和如何禁用此功能: http://discussions.apple.com/thread.jspa ?线程ID = 1751896

PSFramework的未来版本将解释这头太,敬请期待。


看到这个功能,她做到了这一点。 只读取30个字节的PNG文件,并返回该尺寸(CGSize)。 该功能被称为PSFramework(用于处理图像的框架的一部分http://sourceforge.net/projects/photoshopframew/ )。 尚未对其他图像格式来实现,开发者的欢迎。 该项目是GNU许可证下开源。

CGSize PSPNGSizeFromMetaData( NSString* anFileName ) {

    // File Name from Bundle Path.
    NSString *fullFileName = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] bundlePath], anFileName ];

    // File Name to C String.
    const char* fileName = [fullFileName UTF8String];

    /* source file */ 
    FILE * infile;    

    // Check if can open the file.
    if ((infile = fopen(fileName, "rb")) == NULL) 
    {
        NSLog(@"PSFramework Warning >> (PSPNGSizeFromMetaData) can't open the file: %@", anFileName );
        return CGSizeZero;

    }

    //////  //////  //////  //////  //////  //////  //////  //////  //////  //////  ////// 

    // Lenght of Buffer.
    #define bytesLenght 30

    // Bytes Buffer.
    unsigned char buffer[bytesLenght];

    // Grab Only First Bytes.
    fread(buffer, 1, bytesLenght, infile);

    // Close File.
    fclose(infile);

    //////  //////  //////  //////  ////// 

    // PNG Signature.
    unsigned char png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};

    // Compare File signature.
    if ((int)(memcmp(&buffer[0], &png_signature[0], 8))) {

        NSLog(@"PSFramework Warning >> (PSPNGSizeFromMetaData) : The file (%@) don't is one PNG file.", anFileName);    
        return CGSizeZero;

    }

    //////  //////  //////  //////  ////// //////   //////  //////  //////  ////// 

    // Calc Sizes. Isolate only four bytes of each size (width, height).
    int width[4];
    int height[4];
    for ( int d = 16; d < ( 16 + 4 ); d++ ) {
        width[ d-16] = buffer[ d ];
        height[d-16] = buffer[ d + 4];
    }

    // Convert bytes to Long (Integer)
    long resultWidth = (width[0] << (int)24) | (width[1] << (int)16) | (width[2] << (int)8) | width[3]; 
    long resultHeight = (height[0] << (int)24) | (height[1] << (int)16) | (height[2] << (int)8) | height[3]; 

    // Return Size.
    return CGSizeMake( resultWidth, resultHeight );

}



Answer 4:

//这里有一个快速和肮脏的端口C#

 public static Size PNGSize(string fileName) { // PNG Signature. byte[] png_signature = {137, 80, 78, 71, 13, 10, 26, 10}; 

尝试使用{(的FileStream流= File.OpenRead(文件名)){字节[] buf中=新的字节[30]; 如果(stream.Read(BUF,0,30)== 30){INT I = 0; int imax = png_signature.Length; INT IMAX = png_signature.Length; for (i = 0; i < imax; i++) { if (buf[i] != png_signature[i]) break; 对于(I = 0; I <IMAX;我++){如果(BUF [I] = png_signature [I]!)打破; } // passes sig test if (i == imax) { // Calc Sizes. } //通过SIG测试,如果(I == IMAX){//计算值大小。 隔离仅四个字节每个尺寸(宽度,高度)的。 //转换字节整数的INT resultWidth = BUF [16] << 24 | BUF [17] << 16 | BUF [18] << 8 | BUF [19]; INT resultHeight = BUF [20] << 24 | BUF [21] << 16 | BUF [22] << 8 | BUF [23]; //返回尺寸。 返回新的大小(resultWidth,resultHeight); }}}}捕获{}返回新尺寸(0,0);

}



Answer 5:

这是在Perl的很好的实现图片::尺寸模块约十几格式-包括PNG和JPEG。 为了重新实现它的目标C只是把Perl代码,并把它读作伪;-)

例如,pngsize()被定义为

# pngsize : gets the width & height (in pixels) of a png file
# cor this program is on the cutting edge of technology! (pity it's blunt!)
#
# Re-written and tested by tmetro@vl.com
sub pngsize
{
    my $stream = shift;

    my ($x, $y, $id) = (undef, undef, "could not determine PNG size");
    my ($offset, $length);

    # Offset to first Chunk Type code = 8-byte ident + 4-byte chunk length + 1
    $offset = 12; $length = 4;
    if (&$read_in($stream, $length, $offset) eq 'IHDR')
    {
        # IHDR = Image Header
        $length = 8;
        ($x, $y) = unpack("NN", &$read_in($stream, $length));
        $id = 'PNG';
    }

    ($x, $y, $id);
}

jpegsize是只有几行更长的时间。



Answer 6:

imageURL表示一个NSURL,还导入的ImageIO / ImageIO.h用<>周围。

CGImageSourceRef imageSourceRef = CGImageSourceCreateWithURL((CFURLRef)imageUrl, NULL);

if (!imageSourceRef)
    return;

CFDictionaryRef props = CGImageSourceCopyPropertiesAtIndex(imageSourceRef, 0, NULL);

NSDictionary *properties = (NSDictionary*)CFBridgingRelease(props);

if (!properties) {
    return;
}

NSNumber *height = [properties objectForKey:@"PixelHeight"];
NSNumber *width = [properties objectForKey:@"PixelWidth"];
int height = 0;
int width = 0;

if (height) {
    height = [height intValue];
}
if (width) {
    width = [width intValue];
}


Answer 7:

尝试使用CGImageCreateWithPNGDataProvider和CGImageCreateWithJPEGDataProvider功能。 我不知道他们是否有足够或不懒,还是这甚至有可能为JPEG,但它是值得一试。



Answer 8:

低科技的解决方案:

如果你知道图片是什么事前,保存的图像尺寸以及它们在一个XML文件或plist中(或任何方式,您喜欢),只是在阅读这些属性的文件名。

如果你不知道该图像是什么(即他们会在运行时定义的),那么你一定有在同一时间或其他加载的图像。 在你第一次做有他们加载,挽救他们的高度和宽度在一个文件中,以便以后可以访问它。



文章来源: Get size of image without loading in to memory