0

これは別の投稿に多少関連していますが、その投稿はちょっとめちゃくちゃになったので、ゼロから始めます。

巨大な画像 (5780x6700px) を含む CAtiledLayer があります。

タイル レイヤーはスクロールビューにあります。スクロールし始めると、明らかにレンダリングされたタイルが多すぎるところまでは問題ありません。次に、メモリ警告が表示され、アプリがクラッシュします。

メモリの警告が表示されたときにビューから tiledlayer を削除しようとしました。その内容をクリアし (rootLayer.contents = nil AND tiledLayer.contents = nil)、ビューに空の状態で再アタッチしました。うまくいきませんでした...

任意の入力に感謝します...

編集:

これまでのヒントをありがとう。私の仮定のいくつかは間違っているようです。画像を関数にロードして保持しました。これは、CATiledLayer の動作と矛盾していると思います。さらに、UIImage imageNamed:いくつかのエラーも発生しているようです。次に、画像を読み込み、それdrawLayer:(CALayer *) inContentext(CGContextRef) ctxを使用UIImage imageWithContentsOfFile:して読み込みます。

これは、メモリが少なくなることなく動作するようです。

ただし、タイルの描画は非常に遅くなります:(

tiledLayer のセットアップは次のとおりです。

-(CATiledLayer *)initTiledLayers: (int)level{

    //[tiledLayer release];

    CGRect pageRect;

    CATiledLayer *myLayer = [CATiledLayer layer];
    myLayer.delegate = self;

    if(level == 1){     
        pageRect = CGRectMake(0,  0,  690, 800);
        myLayer.tileSize = CGSizeMake(800, 800);
        myLayer.levelsOfDetail = 10;
        myLayer.levelsOfDetailBias = 2;
    }else if(level == 2){
        pageRect = CGRectMake(0,  0,  1445, 1675);
        myLayer.tileSize = CGSizeMake(600, 600);
        myLayer.levelsOfDetail = 8;
        myLayer.levelsOfDetailBias = 2;
    }else if(level == 3){   
        pageRect = CGRectMake(0,  0,  2890, 3350);
        myLayer.tileSize = CGSizeMake(400, 400);
        myLayer.levelsOfDetail = 4;
        myLayer.levelsOfDetailBias = 1;
    }else if(level == 4){
        pageRect = CGRectMake(0,  0, 5780, 6700);
        myLayer.tileSize = CGSizeMake(150, 150);
        myLayer.levelsOfDetail = 4;
        myLayer.levelsOfDetailBias = 0;
    }

    myLayer.frame = pageRect;

    return myLayer;
    [myLayer release];
}

(int)level は、使用する画像を示します (特定のズームレベルで画像を切り替えています)。Level4は最大の画像です...

そして、ここに drawLayer 関数があります:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx));
CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
CGContextClearRect(ctx, CGRectMake(0,0,layer.bounds.size.width, layer.bounds.size.height));
CGContextScaleCTM(ctx, 1.0, -1.0);

    UIImage *map = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d", actLevel] ofType:@"jpg"]];
    UIImage *wanderwege = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_wanderwege", actLevel] ofType:@"png"]];
    UIImage *rhb = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_rhb", actLevel] ofType:@"png"]];
    UIImage *abstecher = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_abstecher", actLevel] ofType:@"png"]];

    CGRect imageRect = CGRectMake (0.0, 0.0, map.size.width, map.size.height);
    CGContextDrawImage (ctx, imageRect, [map CGImage]);

    imageRect = CGRectMake (0.0, 0.0, wanderwege.size.width, wanderwege.size.height);
    CGContextDrawImage (ctx, imageRect, [wanderwege CGImage]);

    imageRect = CGRectMake (0.0, 0.0, rhb.size.width, rhb.size.height);
    CGContextDrawImage (ctx, imageRect, [rhb CGImage]);

    imageRect = CGRectMake (0.0, 0.0, abstecher.size.width, abstecher.size.height);
    CGContextDrawImage (ctx, imageRect, [abstecher CGImage]);

}

ええ - 知っています - 私は実際にコンテキストに 4 つの画像を描画します。PNGは、メイン画像に動的に追加する必要があるオーバーレイです...

画像を1つにマージしようとしましたが、これはさらにメモリ/ CPUを消費するようです;)

さらに助けていただければ幸いです。

4

3 に答える 3

2

デリゲート コールバックですべての画像を描画するのはなぜですか?

問題は、CATiledLayer がすべてのコンテンツを長方形に分割し、クリップされたコンテキストをデリゲート コールバックに渡すことです: - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

これはすべての長方形で発生し、それらの数が多く、描画する画像が大きくて時間がかかるため、全体的なプロセスは「何年も」続きます。

私の練習では、クリッピングされたコンテキストによって定義されたフレーム内に表示される場合にのみレンダリングされる小さなオブジェクトがたくさんありました。

あなたの場合(1つの大きなpdf)、画像の一部のみを描画しようとします。とにかく役立つかどうかはわかりません:)

于 2010-08-27T12:55:31.020 に答える
1

iOS は画像を圧縮せずにメモリに保持する必要があるため、大きな画像を分割する必要があります。画像サイズにピクセルあたり 4 バイトを掛けると、膨大な量の RAM が消費されます。

どういうわけか、それらを半分と 4 分の 1 に事前に分割し、これらをディスクにキャッシュしてから、そこからタイルを表示する必要があります。それをスムーズに行う方法を示す WWDC 2010 scrollview talk を参照してください。

于 2011-06-20T10:28:51.697 に答える
0

tiledLayer を正しく使用していないことがわかりました。また、PNG をオーバーレイとして使用していたため、黒い画面を取り除くために tiledLayer のブレンド モードを正しく設定する必要がありました...

[編集] 忘れないように (Andrew が以下で言及しているように)、大きな画像をタイルに分割する必要があります (たとえば、PSD のズーム化)。1枚の大きな画像でタイルレイヤーを使うと上手くいかない…

于 2010-08-21T01:31:44.280 に答える