iOSでUIWebViewのスクリーンショットを取る方法


■問題

iOSでisLoadingが常にYESを返す場合があり、完全にロードしたかどうかを判別できない場合があります。

■解決策

webViewDidFinishLoadが呼ばれた時点で、スクリーンショットを取り、白・黒の割合が90%未満だった場合にはロードされていると認識する。
※この方法では完全にとれない場合もあります。
※100%ロードしたものを表示したい場合には、timer等で以下の関数を処理を実行させて下さい。

■予備知識

UIViewからサムネイルを取得する方法
http://araking56.blog134.fc2.com/blog-entry-184.html

画像のピクセルから色を判別する方法
http://www.markj.net/iphone-uiimage-pixel-color/

■good

[objc]
– (void)webViewDidFinishLoad:(UIWebView *)webView {

BOOL isLoaded = [self isLoaded:webView];
if(isLoaded){
[self.imageView setHidden:NO];
}
}

-(BOOL)isLoaded:(UIWebView *)webView{

//画像を送る
CGRect screenRect = webView.frame;
UIGraphicsBeginImageContext(webView.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextFillRect(ctx, screenRect);
[webView.layer renderInContext:ctx];

UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//画像の内容を解析する
float percentage = [self getPercentageOfWhiteInImage:screenImage];

if (percentage > 0.9) {

NSLog(@"ほぼ真っ白 or 真っ黒なのでロードされていない");

}else{

NSLog(@"色がついているのでロード済み");

}
}

-(float)getPercentageOfWhiteInImage:(UIImage *)image{

CGImageRef inImage = image.CGImage;
CGContextRef cgctx = [self createARGBBitmapContextFromImage:inImage];
if (cgctx == NULL) { return 1.0; /* error */ }

size_t w = CGImageGetWidth(inImage);
size_t h = CGImageGetHeight(inImage);
CGRect rect = {{0,0},{w,h}};
CGContextDrawImage(cgctx, rect, inImage);

int startW = 0;
int startH = 0;
unsigned char* data = CGBitmapContextGetData (cgctx);

float result1 = [self getPercentageOfWhiteInPix:startW startH:startH data:data w:w h:h];
float result2 = [self getPercentageOfWhiteInPix:w/2-_estimateLengthstartH:h/2-_estimateLengthdata:data w:w h:h];
float result3 = [self getPercentageOfWhiteInPix:w-_estimateLengthstartH:h-_estimateLengthdata:data w:w h:h];

// When finished, release the context
CGContextRelease(cgctx);
// Free image data memory for the context
if (data) { free(data); }

return (result1+result2+result3)/(float)3;

}

-(float)getPercentageOfWhiteInPix:(int)startW startH:(int)startH data:(unsigned char *)data w:(size_t)w h:(size_t)h{

// Now we can get a pointer to the image data associated with the bitmap
// context.
int whiteCounter =0;
int blackCounter = 0;
int notWhiteCounter = 0;
//unsigned char* data = CGBitmapContextGetData (cgctx);
for (int width =0; width < _estimateLength ; width++) {

for (int height=0;height < _estimateLength; height++) {

if (data != NULL) {

//offset locates the pixel in the data from x,y.
//4 for 4 bytes of data per pixel, w is width of one row of data.
int offset = 4*((w*round(startH+height))+round(startW+width));
int alpha = data[offset];
int red = data[offset+1];
int green = data[offset+2];
int blue = data[offset+3];

if (red == 255 && green == 255 && blue == 255) {
whiteCounter++;
}else if(red ==0 && green==0 && blue==0){
blackCounter++;
}else {
notWhiteCounter++;
}
NSLog(@"offset: %i colors: RGB A %i %i %i %i",offset,red,green,blue,alpha);
//color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];

}

}

}

//大きい方を返す

if (whiteCounter > blackCounter) {

return (float)whiteCounter/(float)(notWhiteCounter+whiteCounter+blackCounter);

}else {

return (float)blackCounter/(float)(notWhiteCounter+whiteCounter+blackCounter);

}

}

– (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage {

CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;

size_t pixelsWide = CGImageGetWidth(inImage);
size_t pixelsHigh = CGImageGetHeight(inImage);

bitmapBytesPerRow = (pixelsWide * 4);
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);

colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL)
{
fprintf(stderr, "Error allocating color space\n");
return NULL;
}

bitmapData = malloc( bitmapByteCount );
if (bitmapData == NULL)
{
fprintf (stderr, "Memory not allocated!");
CGColorSpaceRelease( colorSpace );
return NULL;
}

context = CGBitmapContextCreate (bitmapData,
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst);
if (context == NULL)
{
free (bitmapData);
fprintf (stderr, "Context not created!");
}

// Make sure and release colorspace before returning
CGColorSpaceRelease( colorSpace );

return context;
}
[/objc]

SNSでもご購読できます。

コメント

コメントを残す

*