Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何从objective c中的标题中提取PNG的宽度和高度?_Objective C_Image Processing_Header_Binary_Nsdata - Fatal编程技术网

Objective c 如何从objective c中的标题中提取PNG的宽度和高度?

Objective c 如何从objective c中的标题中提取PNG的宽度和高度?,objective-c,image-processing,header,binary,nsdata,Objective C,Image Processing,Header,Binary,Nsdata,我需要在线查找图像的尺寸,而无需下载它们。为了实现这一点,我做了以下工作: + (CGSize) getImageDimensions:(NSString *)url { // Send a synchronous request NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: url]]; NSString *rangeString

我需要在线查找图像的尺寸,而无需下载它们。为了实现这一点,我做了以下工作:

+ (CGSize) getImageDimensions:(NSString *)url {

   // Send a synchronous request
    NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: url]];
    NSString *rangeString = [url hasSuffix: @"png"] ? @"bytes=0-100" : @"bytes=0-1300";
    [urlRequest setValue:rangeString forHTTPHeaderField:@"Range"];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                          returningResponse:&response
                                                      error:&error];
    if (error == nil)
        return [UIImage imageWithData: data].size;
    else
        return CGSizeMake(0, 0);

}
这(下载前100个字节)出人意料地有效,我通过这种方式获得了PNG的正确尺寸

然而,我不认为这是一个非常优雅的方法。首先,我选择通过猜测和检查下载前100个字节,使其尽可能小,同时仍能正常工作

显然,在PNG文件中,标题中有一个叫做IHDR的东西,我必须找到它,紧接着是宽度和高度。这给我的印象是,我应该循环数据,找到这个IHDR并获得维度。问题是,当我记录数据时,我得到如下结果:

... 49484452 000003b7 000001a7 08060000 006c2da0 b100000a 41694343 50494343 2050726f 66696c65 ...
我不知道如何处理NSData对象上的循环并检测IHDR令牌,然后将其后面的内容转换为数字。我也不知道仅仅为一个PNG请求100个字节是否只是为了得到尺寸而请求太多,或者是请求的不够

根据报告:

PNG文件的第一个八个字节始终包含以下内容 (十进制)值:137 80 78 71 13 10 26 10

因此,你必须阅读这些文件,以确保你真的有一个PNG文件

那么

IHDR区块必须首先出现。它包括:

unsigned char buffer[24];
[data getBytes:buffer length:24];
宽度:4字节

高度:4字节

等等

因此,根据块的结构,首先必须读取表示块数据字段长度的4个字节,然后读取表示块名称的4个字节,然后读取表示宽度和高度的两个32位整数,总共8个字节

因此,为了确定宽度和高度,必须读取的确切最小字节数是8+4+4+8=24个字节

目标C代码 拥有NSData对象后,只需访问它包含的字节:

unsigned char buffer[24];
[data getBytes:buffer length:24];
或者,但我强烈建议您检查是否确实有PNG文件:

unsigned char png_header[] = {137, 80, 78, 71, 13, 10, 26, 10};
if (memcmp(buffer, png_header, 8)) {
     // this is not a PNG !
}
确保您有IHDR:

unsigned char ihdr_name[] = "IHDR";
if (memcmp(buffer+8+4, ihdr_name, 4)) {
    // not an IHDR chunk, invalid PNG file
}
宽度和高度可分别作为偏移量为24减去8和减去4字节的
big-endian
编码无符号整数进行访问:

unsigned int width = OSReadBigInt32(buffer + 24 - 8);
unsigned int height = OSReadBigInt32(buffer + 24 - 4);

编辑:固定缓冲区读取代码:PNG实际上以大端字节存储整数。

NSString*convertedData=[[NSString alloc]initWithData:someData编码:NSUTF8StringEncoding]好答案。您可以为
buffer
创建一个
struct
类型,以避免需要偏移量和大小常量。@robmayoff您认为您可以举一个这样做的例子吗?@user309641-Obj-C工具用于查找给定URI的图像的大小,提供了这样一个东西:请参考IGFastImageHelper。只有一件事,为什么要强制转换为带星号的“无符号int*)?我以为你只能用对象而不是原语的类型来做这件事。很抱歉所有的评论!我还必须将宽度和高度更改为“int32_t width=osreadbigin32(缓冲区,16);int32_t height=osreadbigin32(缓冲区,20);”否则我得到的数字是巨大的负数。