2009-10-11 27 views
7

Tôi có một số hình ảnh .png (ETA: nhưng định dạng cũng có thể là JPEG hoặc một thứ khác) mà tôi sẽ hiển thị trong UITableViewCell s. Ngay bây giờ, để có được chiều cao hàng, tôi tải các hình ảnh, lấy các thuộc tính size của chúng và sử dụng để tìm ra mức độ cao để tạo các hàng (tính toán bất kỳ thay đổi cần thiết nào, vì hầu hết các hình ảnh được đổi kích thước trước khi được hiển thị). Để tăng tốc độ và giảm thiểu mức sử dụng bộ nhớ, tôi muốn có thể nhận được size mà không cần tải hình ảnh. Có cách nào để làm việc này không?Lấy kích thước hình ảnh mà không tải vào bộ nhớ

Lưu ý: Tôi biết rằng có một số phím tắt tôi có thể thực hiện để loại bỏ vấn đề này, nhưng vì nhiều lý do tôi không thể thay đổi kích thước hình ảnh trước hoặc thu thập kích thước hình ảnh trước, buộc tôi thông tin tại thời gian chạy.

+1

CGImageSource là API hoàn hảo cho điều này, nhưng khó chịu nó không có sẵn trên iPhone. Có thể bạn sẽ phải tự mình thực hiện nó. Điều đó nói rằng, hãy nhớ rằng UIImage sẽ xóa dữ liệu của nó nếu bạn sử dụng + imageWithContentsOfFile: điều này sẽ loại bỏ các lo ngại về sử dụng bộ nhớ của bạn. –

Trả lời

4

Tính đến iOS SDK 4.0, nhiệm vụ này có thể được thực hiện với khuôn khổ ImageIO (CGImageSource...). Tôi đã trả lời a similar question here.

6

Nó sẽ khá đơn giản. PNG spec có giải thích về PNG datastream (đây là tệp có hiệu quả). IHDR phần chứa thông tin về kích thước hình ảnh.

Vì vậy, những gì bạn phải làm là để đọc trong PNG "giá trị ma thuật" và sau đó đọc hai số nguyên bốn byte, sẽ có chiều rộng và chiều cao, tương ứng. Bạn cũng có thể cần phải sắp xếp lại các bit trong các giá trị này (không chắc chắn chúng được lưu trữ như thế nào), nhưng một khi bạn tìm ra nó, nó sẽ rất đơn giản.

+0

Ý tưởng hay, ngoại trừ việc tôi quên đề cập rằng nó có thể không phải là một PNG, đó chỉ là những gì tôi tình cờ có ngay bây giờ (chỉnh sửa bài viết để phản ánh điều này). Tôi nên hỗ trợ JPEG quá, ít nhất, mặc dù tôi cho rằng tôi có thể làm điều đó theo cách tương tự như những gì bạn mô tả. –

1

Điều này được thực hiện độc đáo trong Perl's Image::Size module cho khoảng một chục định dạng - bao gồm PNG và JPEG. Để lại thực hiện nó trong Objective C chỉ mất mã perl và đọc nó như là giả ;-)

Ví dụ, pngsize() được định nghĩa là

# 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 chỉ là một vài dòng còn .

0

giải pháp thấp công nghệ:

nếu bạn biết những gì những hình ảnh trước đó, lưu trữ các hình ảnh kích thước cùng với tên tập tin của họ trong một tập tin XML hoặc plist (hoặc bất cứ cách nào bạn thích) và chỉ đọc những tài sản trong

.

nếu bạn không biết hình ảnh là gì (tức là chúng sẽ được xác định trong thời gian chạy), thì bạn phải có hình ảnh được tải cùng một lúc. lần đầu tiên bạn tải chúng, lưu chiều cao và chiều rộng của chúng trong một tệp để bạn có thể truy cập sau này.

1

Lưu ý: Chức năng này không làm việc với PNG iPhone nén, nén này được tự động thực hiện bởi XCode và thay đổi tiêu đề hình ảnh, xem chi tiết ở đây và làm thế nào để vô hiệu hóa tính năng này: http://discussions.apple.com/thread.jspa?threadID=1751896

phiên bản tương lai PSFramework cũng sẽ giải thích các tiêu đề này, hãy chú ý theo dõi.


Xem chức năng này, cô ấy thực hiện điều đó. Chỉ đọc 30 byte của tệp PNG và trả về kích thước (CGSize). Chức năng này là một phần của một khuôn khổ để xử lý hình ảnh được gọi là PSFramework (http://sourceforge.net/projects/photoshopframew/). Chưa được triển khai cho các định dạng hình ảnh khác, nhà phát triển được hoan nghênh.Dự án là Mã nguồn mở theo Giấy phép 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

// Dưới đây là một cách nhanh chóng & cổng bẩn để 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 là NSURL, cũng nhập ImageIO/ImageIO.h với <> xung quanh.

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]; 
} 
Các vấn đề liên quan