0

画像を取得して、バックグラウンド スレッドの一時ディレクトリに保存しています。保存する前に、この UIImage に小さな白い境界線を追加したいと思います。私はこれをやっています:

    - (UIImage *)imageWithBorder:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width, image.size.height);
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale); {
        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextBeginTransparencyLayer (context, NULL);
        //Draw
        [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextStrokeRectWithWidth(context, rect, 10);
        CGContextEndTransparencyLayer(context);
    }
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

すべて問題ありません。一時ディレクトリからその画像をロードした後、画像の境界線が表示されますが、コンソールではinvalid context 0x0、以下のコードが実装されているときに取得しています。ここで何が問題なのですか?


更新 01

- (UIImage *)imageWithBorder:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width, image.size.height);
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale); {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextDrawImage (context, rect, [image CGImage]);
        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextStrokeRectWithWidth(context, rect, 10);
    }
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}
4

2 に答える 2

1

変更してみてください:

[image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];

CGContextDrawImage (context, rect, [image CGImage]);

また、なぜ透明レイヤーを使用するのですか? アルファが 1 に設定されているので、元の画像を上書きできますね。

編集:アプリで同じコードをバックグラウンドで実行したところ、問題なく動作しました:

- (UIImage *)imageWithBorder:(UIImage *)image
{
    NSLog(@"Thread %@", [NSThread currentThread]);

    CGSize newSize = CGSizeMake(image.size.width, image.size.height);
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    //Draw
    CGContextDrawImage(context, rect, [image CGImage]);
    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextStrokeRectWithWidth(context, rect, 10);
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
assert(result);
    return result;
}

viewDidAppear でこれを行うと: (しかし、小さな画像ですが、サイズが関係している可能性がありますか?)

dispatch_async(dispatch_get_global_queue(0, 0), ^{ [self imageWithBorder:[UIImage imageNamed:@"02-redo.png"]] ; } );

ログに表示されるのはこれだけです。

2012-08-27 13:48:04.679 Searcher[32825:11103] Thread <NSThread: 0x6d30e30>{name = (null), num = 4}

したがって、コードで何か他のことが起こっています。Xcode 4.4.1 でビルドしています。展開ターゲットは 5.1 です

編集:あなたのブロックでは、セルは一時的なものであるため、「セル」を参照することはできません-リサイクルすると、表示されない場合もあります。したがって、画像名はローカルの NSString を介してルーティングされ、最後に、セルの indexPath と共に、画像を投稿できる別のメソッドが必要になります。そのメソッドは、その indexPath がテーブルの visibleCells にあるかどうかを確認し、そうである場合は画像を更新し、そうでない場合は画像を保存して tableView で使用できるようにし、次にセルを要求します。

EDIT2: このコード:

dispatch_async(queue, ^{ 
  UIImage *image = [_thumbnailMaster thumbnailForItemWithFilename:cell.label.text];
  dispatch_sync(dispatch_get_main_queue(), ^{ cell.thumbnailView.image = image; }); 
});

cell は範囲外になるか、別のインデックスで使用される可能性があるため (リサイクルを想定)、「cell」を含まないものに変換する必要があります。このようなもの:

NSString *text = cell.label.text;
NSIndexPath *path = ...;

dispatch_async(queue, ^{ 
  UIImage *image = [_thumbnailMaster thumbnailForItemWithFilename:text];  
   dispatch_sync(dispatch_get_main_queue(), ^{ [self updateCellImage:image withPath"path]; }); 
});

メソッドは、そのセルが表示されているかどうかを判断し、表示されている場合は画像を更新し、表示されていない場合は保存して、次に必要になったときにそれを取得します。

于 2012-08-27T17:20:59.460 に答える
1

UIGraphicsGetCurrentContext 現在のグラフィック コンテキストを返します。

CGContextRef UIGraphicsGetCurrentContext ( void ); 戻り値 現在のグラフィック コンテキスト。

考察 現在のグラフィックス コンテキストはデフォルトでは nil です。ビュー オブジェクトは、その drawRect: メソッドを呼び出す前に、有効なコンテキストをスタックにプッシュして、現在のコンテキストにします。ただし、UIView オブジェクトを使用して描画を行っていない場合は、UIGraphicsPushContext 関数を使用して、有効なコンテキストを手動でスタックにプッシュする必要があります。

この関数は、アプリケーションのメイン スレッドからのみ呼び出す必要があります。

これはUIKit Function Referenceからのものです

于 2012-08-27T17:12:40.173 に答える