Есть ли лучший способ для мозаичного изображения в iphone

В настоящее время мы пытаемся загрузить изображения через URL-адреса и разбить эти изображения на части так, как приложение PhotoScroller было сделано в магазине Apple. Самый большой размер изображения 4000*4000 и в формате RGB. Я разбиваю эти изображения на плитки размером 256 * 256. На разбиение изображения и запись файлов на диск уходит очень много времени. Искал лучший подход, если можно разбить файлы и загрузить их на iphone. Всего 4 вызова URL-адресов, и каждый вызов URL-адреса извлекает изображение, проходит через процесс мозаичного отображения и вызывает приложение PhotoScroller для запуска этих изображений на iphone.

Если кто-то сталкивался с такими проблемами и знает об этом больше, не могли бы вы поделиться некоторыми идеями.

-(void) startImageDownloading
{

if (!isImageRequested)
{
    isImageRequested = YES;
    self.responseData = [NSMutableData data];

    URL1 = @"http://www.abc.com/image_id=1&size=1"; 
    NSURLRequest *request1 = [NSURLRequest requestWithURL:[NSURL URLWithString:URL1]];
    self.connection1= [[[NSURLConnection alloc] initWithRequest:request1 delegate:self] autorelease];

    URL2 = @"http://www.abc.com/image_id=2&size=2"; 
    NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:URL2]];
    self.connection2= [[[NSURLConnection alloc] initWithRequest:request2 delegate:self] autorelease];

    URL3 = @"http://www.abc.com/image_id=3&size=3"; 
    NSURLRequest *request3 = [NSURLRequest requestWithURL:[NSURL URLWithString:URL3]];
    self.connection3= [[[NSURLConnection alloc] initWithRequest:request3 delegate:self] autorelease];


    URL4 = @"http://www.abc.com/image_id=4&size=4";     
    NSURLRequest *request4 = [NSURLRequest requestWithURL:[NSURL URLWithString:URL4]];
    self.connection4= [[[NSURLConnection alloc] initWithRequest:request4 delegate:self] autorelease];

}

}



- (void)saveTilesOfSize:(CGSize)size 
           forImage:(UIImage*)image 
        toDirectory:(NSString*)directoryPath 
        usingPrefix:(NSString*)prefix
   {

CGFloat cols = [image size].width / size.width;
CGFloat rows = [image size].height / size.height;

int fullColumns = floorf(cols);
int fullRows = floorf(rows);

CGFloat remainderWidth = [image size].width - (fullColumns * size.width);
CGFloat remainderHeight = [image size].height - (fullRows * size.height);


if (cols > fullColumns) fullColumns++;
if (rows > fullRows) fullRows++;

CGImageRef fullImage = [image CGImage];

for (int y = 0; y < fullRows; ++y) {
    for (int x = 0; x < fullColumns; ++x) {

        CGSize tileSize = size;

        if (x + 1 == fullColumns && remainderWidth > 0) {
            // Last column
            tileSize.width = remainderWidth;
        }
        if (y + 1 == fullRows && remainderHeight > 0) {
            // Last row
            tileSize.height = remainderHeight;
        }

        CGImageRef tileImage = CGImageCreateWithImageInRect(fullImage,(CGRect){{x*size.width, y*size.height},tileSize});

        NSData *imageData = UIImagePNGRepresentation([UIImage imageWithCGImage:tileImage]);
        CGImageRelease(tileImage);
        NSString *path = [NSString stringWithFormat:@"%@/%@%d_%d.png",directoryPath, prefix, x, y];

        [imageData writeToFile:path atomically:NO];

    }
}    
}

person lifemoveson    schedule 28.06.2011    source источник


Ответы (2)


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

Попробуйте этот подход:

  1. сохранять тайлы на диск, и параллельно,

  2. читать тайлы с диска и создавать их в памяти, рисуя их в контексте. Взгляните на UIGraphicsBeginImageContext и [UIImage drawInRect]. (Не уверен, что использование ресурсов лучше, чем CGImageCreateWithImageInRect)

  3. По завершении сохраните его на диск. См. UIGraphicsGetImageFromCurrentImageContext

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

Кроме того, я не видел в вашем коде, как вы отображаете изображение для отображения, но setNeedsDisplayInRect полезен для этого для отображения только на указанном прямоугольнике. Однако, если вы используете CATiledLayer, с этой комбинацией возникнут некоторые проблемы, попробуйте поиграть с ней еще или поискать решение, пока не получите именно то, что вам нужно.

person Manny    schedule 29.06.2011
comment
Спасибо, Мэнни. Я думаю, если я смогу сохранить файлы на диск, параллельно мне поможет решить проблему. Но не знаете, как сделать это параллельно? Вы хотите использовать NSOperationQueue? - person lifemoveson; 29.06.2011
comment
Я бы представил так: 4 асинхронных соединения для параллельного извлечения и сохранения на диск, а затем выполнения рендеринга в основном потоке. Извините за путаницу параллельно, я имел в виду, что более 1 потока будут получать данные с сервера и обрабатывать данные одновременно. - person Manny; 30.06.2011

Поскольку ваши изображения 4000 x 4000 и в RGB, загрузка и разбиение на мозаику наверняка займут много времени на iPhone, потому что это расчет с интенсивным использованием процессора.

Я заметил существенные улучшения для сохранения файла, переключившись с UIImagePNGRepresentation на UIImageJPEGRepresentation, чтобы вы могли попробовать это.

Для плитки лучший способ решить это - сделать это на сервере, а не на iphone.

person werner    schedule 29.06.2011
comment
Я попробовал UIImageJEPGRepresentation, и это не решило мою проблему. Я могу думать о плитке изображения на сервере, чем на iphone. - person lifemoveson; 29.06.2011
comment
размещение изображений на сервере будет вашим лучшим подходом, в блоге Джеффа Ламарша о размещении изображений здесь - person werner; 29.06.2011
comment
Спасибо Вернер. Но если мне нужно получить те мозаичные изображения, которые похожи на реальные данные, что означает, что изображения часто меняются и должны обновляться, как я могу этого добиться. Поскольку изображения, которые я получаю по URL-адресу, похожи на настоящие живые данные. И по этой причине я разбивал их каждый раз, когда получал обновленные данные с сервера. - person lifemoveson; 29.06.2011