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);”否则我得到的数字是巨大的负数。