• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

iOS 大图加载处理

武飞扬头像
键盘侠-弹壳
帮助1

ios需要理解图片原始数据metadata,图片显示内存区别;处理分辨率与图片大小关系,

位图的大小计算公式:

图片width x heigth x 4(ARGB)

对于大图下载需要理解,沙盒作用.

对于大图上传,不能一次性加载压缩等处理,可以使用分片算法再进行上传。

对于大图显示,可以采用gpu的模式性渲染显示。整体思维如下:

        先计算好原图片的每个分片CGRect,然后在根据设备获取到对应的缩放后的分片CGRect,缩放的比例也是根据设备来设定。

        缩放后的分片CGRect和 p1生成缩放后的小分片,并且绘制到屏幕,这样一直循环把原图片全部的每个小分片全部生成对应缩放的小分片,然后绘制。

        以上效果,最终加载出来的图片质量上虽然没有太大变化,但是图片分辨率(即大小width x heigth)变小了。所以如果大图片的显示可以这么处理。


    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
   
    sourceImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kImageFilename ofType:nil]];
    if( sourceImage == nil ) NSLog(@"input image not found!");
    
    sourceResolution.width = CGImageGetWidth(sourceImage.CGImage);
    sourceResolution.height = CGImageGetHeight(sourceImage.CGImage);
  
    sourceTotalPixels = sourceResolution.width * sourceResolution.height;
   
    sourceTotalMB = sourceTotalPixels / pixelsPerMB;
    
    imageScale = destTotalPixels / sourceTotalPixels;
   
    destResolution.width = (int)( sourceResolution.width * imageScale );
    destResolution.height = (int)( sourceResolution.height * imageScale );
  
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerRow = bytesPerPixel * destResolution.width;
    
    void* destBitmapData = malloc( bytesPerRow * destResolution.height );
    if( destBitmapData == NULL ) NSLog(@"failed to allocate space for the output image!");
   
    destContext = CGBitmapContextCreate( destBitmapData, destResolution.width, destResolution.height, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast );
  
    if( destContext == NULL ) {
        free( destBitmapData ); 
        NSLog(@"failed to create the output bitmap context!");
    }        
  
    CGColorSpaceRelease( colorSpace );
 
    CGContextTranslateCTM( destContext, 0.0f, destResolution.height );
    CGContextScaleCTM( destContext, 1.0f, -1.0f );
  
    sourceTile.size.width = sourceResolution.width;
    
    sourceTile.size.height = (int)( tileTotalPixels / sourceTile.size.width );     
    NSLog(@"source tile size: %f x %f",sourceTile.size.width, sourceTile.size.height);
    sourceTile.origin.x = 0.0f;
    
    destTile.size.width = destResolution.width;
    destTile.size.height = sourceTile.size.height * imageScale;        
    destTile.origin.x = 0.0f;
    NSLog(@"dest tile size: %f x %f",destTile.size.width, destTile.size.height);
    
    sourceSeemOverlap = (int)( ( destSeemOverlap / destResolution.height ) * sourceResolution.height );
    NSLog(@"dest seem overlap: %f, source seem overlap: %f",destSeemOverlap, sourceSeemOverlap);    
    CGImageRef sourceTileImageRef;
 
    int iterations = (int)( sourceResolution.height / sourceTile.size.height );
   
    int remainder = (int)sourceResolution.height % (int)sourceTile.size.height;
    if( remainder ) iterations ;
    
    float sourceTileHeightMinusOverlap = sourceTile.size.height;
    sourceTile.size.height = sourceSeemOverlap;
    destTile.size.height = destSeemOverlap;    
    NSLog(@"beginning downsize. iterations: %d, tile height: %f, remainder height: %d", iterations, sourceTile.size.height,remainder );
    for( int y = 0; y < iterations; y ) {
       
        NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init];
        NSLog(@"iteration %d of %d",y 1,iterations);
        sourceTile.origin.y = y * sourceTileHeightMinusOverlap sourceSeemOverlap; 
        destTile.origin.y = ( destResolution.height ) - ( ( y 1 ) * sourceTileHeightMinusOverlap * imageScale destSeemOverlap ); 
    
        sourceTileImageRef = CGImageCreateWithImageInRect( sourceImage.CGImage, sourceTile );
      
        if( y == iterations - 1 && remainder ) {
            float dify = destTile.size.height;
            destTile.size.height = CGImageGetHeight( sourceTileImageRef ) * imageScale;
            dify -= destTile.size.height;
            destTile.origin.y = dify;
        }

        CGContextDrawImage( destContext, destTile, sourceTileImageRef );

        CGImageRelease( sourceTileImageRef ); 


        [sourceImage release];
        // free all objects that were sent -autorelease within the scope of this loop.
        [pool2 drain];     
      
        if( y < iterations - 1 ) {            
            sourceImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:kImageFilename ofType:nil]];
            [self performSelectorOnMainThread:@selector(updateScrollView:) withObject:nil waitUntilDone:YES];
        }
    }
    NSLog(@"downsize complete.");
    [self performSelectorOnMainThread:@selector(initializeScrollView:) withObject:nil waitUntilDone:YES];
   
    CGContextRelease( destContext );
    [pool drain];
}

-(void)createImageFromContext {
   
    CGImageRef destImageRef = CGBitmapContextCreateImage( destContext );
    if( destImageRef == NULL ) NSLog(@"destImageRef is null.");
  
    self.destImage = [UIImage imageWithCGImage:destImageRef scale:1.0f orientation:UIImageOrientationDownMirrored];
   
    CGImageRelease( destImageRef );
    if( destImage == nil ) NSLog(@"destImage is nil.");

}

分片读取可以一下思想:

  1.  
    -(void)readDataWithChunk:(NSInteger)chunk file:(CNFile*)file{
  2.  
    总片数的获取方法:
  3.  
    int offset =1024*1024;(每一片的大小是1M)
  4.  
    NSInteger chunks = (file.fileSize%1024==0)?((int)(file.fileSize/1024*1024)):((int)(file.fileSize/(1024*1024) 1));
  5.  
    NSLog(@"chunks = %ld",(long)chunks);
  6.  
    将文件分片,读取每一片的数据:
  7.  
    NSData* data;
  8.  
    NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:file.filePath];
  9.  
    [readHandle seekToFileOffset:offset * chunk];
  10.  
    data = [readHandle readDataOfLength:offset];
  11.  
    }

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcaeei
系列文章
更多 icon
同类精品
更多 icon
继续加载