2009-10-11 3 views
7

У меня есть несколько изображений .png (ETA:, но формат также может быть JPEG или что-то еще), который я собираюсь отобразить в UITableViewCell. Прямо сейчас, чтобы получить высоту строки, я загружаю изображения, получаю их свойства size и использую это для определения того, насколько высок для создания строк (вычисление любых необходимых изменений на этом пути, поскольку большая часть изображений изменяется в размерах перед отображением). Чтобы ускорить работу и уменьшить использование памяти, я бы хотел получить size без загрузки изображений. Есть ли способ сделать это?Получить размер изображения без загрузки в память

Примечание: Я знаю, что существует целый ряд ярлыков я мог бы осуществить, чтобы устранить эту проблему, но по нескольким причинам я не могу изменить размер изображения заранее или собирать размеры изображения заранее, заставляя меня, чтобы получить это info во время выполнения.

+1

CGImageSource - идеальный API для этого, но досадно, что он недоступен на iPhone. Вам, вероятно, придется реализовать его самостоятельно. Тем не менее, имейте в виду, что UIImage очистит свои данные, если вы используете + imageWithContentsOfFile: это должно устранить проблемы с использованием памяти. –

ответ

4

В ИО SDK 4.0, эта задача может быть выполнена с каркасом ImageIO (CGImageSource...). Я ответил a similar question here.

6

Это должно быть довольно просто. PNG spec имеет описание PNG datastream (что фактически является файлом). IHDR раздел содержит информацию о размерах изображения.

Итак, вам нужно прочитать «0», а затем прочитать два четырехбайтовых целых числа, которые будут иметь ширину и высоту соответственно. Вам также может потребоваться изменить порядок бит в этих значениях (не уверен, как они хранятся), но как только вы это выясните, это будет очень просто.

+0

Хорошая идея, за исключением того, что я забыл упомянуть, что это может быть не PNG, это то, что у меня сейчас есть (отредактированный пост, чтобы отразить это). По крайней мере, я должен поддерживать JPEG, хотя, я полагаю, я мог бы сделать это аналогично тому, что вы описываете. –

1

Это хорошо реализовано в Perl's Image::Size module для примерно десятка форматов - включая 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 [email protected] 
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 всего несколько строк больше ,

0

низкие решения технологий:

, если вы знаете, что изображения заранее, хранящие изображение размеров вместе с их именами файлов в файле XML или PLIST (или в зависимости от того, как вы предпочитаете) и просто прочитать эти свойства в

.

Если вы не знаете, что такое изображения (то есть они будут определены во время выполнения), тогда у вас должны были быть загружены изображения в тот или иной момент. в первый раз, когда вы загрузите их, сохраните их высоту и ширину в файле, чтобы вы могли получить к ней доступ позже.

1

Примечание: Эта функция не работает с iPhone сжатых в формате PNG, это сжатие выполняется автоматически с помощью XCode и изменить заголовок изображения, подробнее здесь и как отключить эту функцию: http://discussions.apple.com/thread.jspa?threadID=1751896

Будущие версии PSFramework также интерпретирует эти заголовки, следите за обновлениями.


Просмотреть эту функцию, она делает именно это. Читает только 30 байт файла PNG и возвращает размер (CGSize). Эта функция является частью структуры для обработки изображений под названием PSFramework (http://sourceforge.net/projects/photoshopframew/). Разработчики приветствуются не для других форматов изображений.Проект является Open Source по лицензии 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); 

} 

1

// Вот быстрый & грязный порт 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);

}

1

imageUrl - это NSURL, также импортируйте ImageIO/ImageIO.h с помощью <> вокруг него.

Смежные вопросы