Page 1 of 1

[iOS] libpng failed to allocate memory when reading png files

Posted: 2018-10-25T19:26:25-07:00
by xsown
Hi there!

I'm using MagickWand in an iOS app to merge lots of png files into a single gif file. The memory keeps accumulating significantly on reading png files. At some point (memory usage in Xcode was 379MB) libpng began to throw "Memory allocation failed" error. I've set SetMagickResourceLimit(MemoryResource, 350 * 1024 * 1024) before, to limit the memory consumption. But it seems only working on magickwand itself, not libpng. Is there any way to solve this problem? Thanks!

iOS lib: ver 6.8.8-9 downloaded from https://imagemagick.org/download/iOS/

// The errors:

2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Coder [755]: png.c/MagickPNGErrorHandler/1803/Coder
libpng-1.6.10 error: Memory allocation failed
[MagickCore] MagickLogEvent: [10] 2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Coder [755]: png.c/MagickPNGErrorHandler/1803/Coder
libpng-1.6.10 error: Memory allocation failed
2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Exception [755]: png.c/MagickPNGErrorHandler/1806/Exception
Memory allocation failed `'
[MagickCore] MagickLogEvent: [100] 2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Exception [755]: png.c/MagickPNGErrorHandler/1806/Exception
Memory allocation failed `'
2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Coder [755]: png.c/ReadOnePNGImage/2320/Coder
exit ReadOnePNGImage() with error.
[MagickCore] MagickLogEvent: [10] 2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Coder [755]: png.c/ReadOnePNGImage/2320/Coder
exit ReadOnePNGImage() with error.
2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Coder [755]: png.c/ReadPNGImage/4074/Coder
exit ReadPNGImage() with error.
[MagickCore] MagickLogEvent: [10] 2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Coder [755]: png.c/ReadPNGImage/4074/Coder
exit ReadPNGImage() with error.
2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Exception [755]: png.c/ReadPNGImage/4077/Exception
CorruptImage `'
[MagickCore] MagickLogEvent: [100] 2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Exception [755]: png.c/ReadPNGImage/4077/Exception
CorruptImage `'
2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Cache [755]: cache.c/DestroyPixelCache/961/Cache
destroy [0]
[MagickCore] MagickLogEvent: [8] 2018-10-26T09:51:05+08:00 6:16.120 374.800u 6.8.8 Cache [755]: cache.c/DestroyPixelCache/961/Cache
destroy [0]

// My code (Objective-C):

Code: Select all

   MagickWand* gifWand = NewMagickWand();

   NSInteger frameIndex = 0;
   for (NSURL* fileURL in sortedSourceFileURLsArray) {

       MagickWand* pngWand = NewMagickWand();
       NSData* pngData = [[NSData alloc] initWithContentsOfURL:fileURL];
       if (MagickFalse == MagickReadImageBlob(pngWand, pngData.bytes, pngData.length)) {
            PRINT_ERROR(@"Failed to read image blob of file at: %s", fileName)
            DestroyMagickWand(pngWand);
            continue;
        }
       if (MagickFalse == MagickSetImageTicksPerSecond(pngWand, frameMeta.tps)) {
           PRINT_ERROR(@"Unable to set frame[%d] tps to: %d", frameIndex, frameMeta.tps)
           DestroyMagickWand(pngWand);
           continue;
       }
       if (MagickFalse == MagickSetImageDelay(pngWand, frameMeta.delay)) {
           PRINT_ERROR(@"Unable to set frame[%d] delay to: %d", frameIndex, frameMeta.tps)
           DestroyMagickWand(pngWand);
           continue;
       }
       if (MagickFalse == MagickAddImage(gifWand, pngWand)) {
           PRINT_ERROR(@"Failed to add image '%@' from pngWand to gifWand", fileURL.lastPathComponent)
           DestroyMagickWand(pngWand);
           continue;
       }
       DestroyMagickWand(pngWand);
       ++frameIndex;
   }
   
    size_t gifSize = 0;
    unsigned char* gifBytes = MagickGetImagesBlob(gifWand, &gifSize);
    DestroyMagickWand(gifWand);
    if (gifBytes == NULL || gifSize == 0) {
        PRINT_ERR(@"Failed to get images blog from gif wand.")
        return NO;
    }
    NSData* gifData = [[NSData alloc] initWithBytes:gifBytes length:gifSize];
    if (true == [gifData writeToURL:destFileURL atomically:true]) {
        return YES;
    }
    else {
        PRINT_ERROR(@"Failed to write image file at: %@", destFileURL)
        return NO;
    }