Iphone 获取图像大小而不加载到内存中
我有几个Iphone 获取图像大小而不加载到内存中,iphone,cocoa,cocoa-touch,uikit,core-graphics,Iphone,Cocoa,Cocoa Touch,Uikit,Core Graphics,我有几个.png图像(ETA:但格式也可以是JPEG或其他格式),我将在UITableViewCells中显示。现在,为了获得行高度,我加载图像,获取它们的大小属性,并使用该属性计算行的高度(计算沿途的任何必要更改,因为大多数图像在显示之前都会调整大小)。为了加快速度并减少内存使用,我希望能够在不加载图像的情况下获得大小。有办法做到这一点吗 注意:我知道有很多快捷方式可以解决这个问题,但由于一些原因,我无法提前调整图像大小或收集图像大小,迫使我在运行时获取这些信息。这应该很简单。对(实际上是一个
.png
图像(ETA:但格式也可以是JPEG或其他格式),我将在UITableViewCell
s中显示。现在,为了获得行高度,我加载图像,获取它们的大小
属性,并使用该属性计算行的高度(计算沿途的任何必要更改,因为大多数图像在显示之前都会调整大小)。为了加快速度并减少内存使用,我希望能够在不加载图像的情况下获得大小。有办法做到这一点吗
注意:我知道有很多快捷方式可以解决这个问题,但由于一些原因,我无法提前调整图像大小或收集图像大小,迫使我在运行时获取这些信息。这应该很简单。对(实际上是一个文件)进行了解释。节包含有关图像尺寸的信息
所以你要做的就是读入PNG的“魔法值”,然后读入两个四字节的整数,分别是宽度和高度。您可能还需要对这些值中的位进行重新排序(不确定它们是如何存储的),但一旦您弄明白了这一点,这将非常简单。尝试使用and函数。我不知道他们是否足够懒惰,也不知道JPEG是否可能做到这一点,但值得一试。这在Perl中很好地实现了大约十几种格式,包括PNG和JPEG。为了在Objective 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只长几行。低技术解决方案:
如果您事先知道图像是什么,请将图像大小及其文件名存储在XML文件或plist(或您喜欢的任何方式)中,然后在中读取这些属性
如果您不知道图像是什么(即,它们将在运行时定义),那么您必须在某个时间加载图像。第一次加载时,请将其高度和宽度保存在文件中,以便以后访问。注意:此功能不适用于iPhone压缩PNG,此压缩由XCode自动执行并更改图像标题,请参阅此处的更多详细信息以及如何禁用此功能:
PSFramework的未来版本也将解释此标题,请继续关注
看看这个函数,她就是这么做的。仅读取PNG文件的30个字节并返回大小(CGSize)。此函数是处理图像的框架PSFramework()的一部分。尚未为其他图像格式实现,欢迎开发人员。该项目是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 );
}
CGSize PSPNGSizeFromMetaData(NSString*anFileName){
//包路径中的文件名。
NSString*fullFileName=[NSString stringWithFormat:@“%@/%@”,[[NSBundle mainBundle]bundlePath],anFileName];
//文件名转换为C字符串。
常量字符*文件名=[fullFileName UTF8String];
/*源文件*/
文件*填充;
//检查是否可以打开该文件。
if((infle=fopen(文件名,“rb”))==NULL)
{
NSLog(@“PSFramework Warning>>(PSPNGSizeFromMetaData)无法打开文件:%@),anFileName;
返回cgizezero;
}
////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //////
//缓冲区长度。
#定义字节长度30
//字节缓冲区。
无符号字符缓冲区[字节长度];
//只抓取第一个字节。
fread(缓冲区,1,字节长度,填充);
//关闭文件。
fclose(infle);
////// ////// ////// ////// //////
//PNG签名。
无符号字符png_签名[8]={137,80,78,71,13,10,26,10};
//比较文件签名。
if((int)(memcmp(&buffer[0],&png_签名[0,8])){
NSLog(@“PSFramework Warning>>(PSPNGSizeFromMetaData):文件(%@)不是一个PNG文件。”,anFileName);
返回cgizezero;
}
////// ////// ////// ////// ////// ////// ////// ////// ////// //////
//计算大小。仅隔离每个大小(宽度、高度)的四个字节。
整数宽度[4];
整数高度[4];
对于(int d=16;d<(16+4);d++){
宽度[d-16]=缓冲区[d];
高度[d-16]=缓冲器[d+4];
}
//将字节转换为长(整数)
long resultWidth=(宽度[0]//这是C的一个快速脏端口#
public static Size PNGSize(string fileName)
{
// PNG Signature.
byte[] png_signature = {137, 80, 78, 71, 13, 10, 26, 10};
try
{
using (FileStream stream = File.OpenRead(fileName))
{
byte[] buf = new byte[30];
if (stream.Read(buf, 0, 30) == 30)
{
int i = 0;
int imax = png_signature.Length;
for (i = 0; i < imax; i++)
{
if (buf[i] != png_signature[i])
break;
}
// passes sig test
if (i == imax)
{
// Calc Sizes. Isolate only four bytes of each size (width, height).
// Convert bytes to integer
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];
// Return Size.
return new Size( resultWidth, resultHeight );
}
}
}
}
catch
{
}
return new Size(0, 0);
公共静态大小PNGSize(字符串文件名)
{
//PNG签名。
字节[]png_签名={137,80,78,71,13,10,26,10}
尝试
{
使用(FileStream-stream=File.OpenRead(文件名))
{
字节[]buf=新字节[30];
if(stream.Read(buf,0,30)==30)
{
int i=0;
int imax=png_signature.Length;
对于(i=0;i int resultWidth=buf[16]从iOS SDK 4.0开始,这个任务可以通过ImageIO框架(CGImageSource…
)来完成。我已经回答了。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];
}
好主意,除了我忘了提到它可能不是PNG,这正是我现在碰巧拥有的(编辑后反映了这一点)。我至少也应该支持JPEG,尽管我想我可以用与您描述的类似的方式来实现。CGImageSource是实现这一点的完美API,但令人恼火的是它在iPhone上不可用。您可能需要自己实现它。也就是说,请记住UIImage将