3

以下のコードを使用して、PDF ページのプレビューをレンダリングしています。ただし、大量のメモリ (ページあたり 2 ~ 3MB) を使用しています。

デバイスのログに次のように表示されます。

<Error>: CGBitmapContextInfoCreate: unable to allocate 2851360 bytes for bitmap data

ビットマップをカラー チャネルあたり 8 ビットでレンダリングする必要はありません。コードを変更して、グレースケールまたはチャネルあたりのビット数を減らすにはどうすればよいですか?

ビットマップが x/y の最大解像度でレンダリングされ、結果の画像が要求されたサイズにズームされるソリューションでも問題ありません。PDF は後で aCATiledLayerとにかく詳細にレンダリングされます。

また、Apple のドキュメントによると、CGBitmapContextCreate()(メモリが原因で) コンテキストを作成できない場合は NIL を返します。しかし、MonoTouch ではコンテキストを作成するコンストラクタしかないため、作成が失敗したかどうかを確認できません。できれば、ふりをしている画像をスキップできます。

UIImage oBackgroundImage= null;
using(CGColorSpace oColorSpace = CGColorSpace.CreateDeviceRGB())
// This is the line that is causing the issue.
using(CGBitmapContext oContext = new CGBitmapContext(null, iWidth, iHeight, 8, iWidth * 4, oColorSpace, CGImageAlphaInfo.PremultipliedFirst))
{
    // Fill background white.
    oContext.SetFillColor(1f, 1f, 1f, 1f);
    oContext.FillRect(oTargetRect);

    // Calculate the rectangle to fit the page into. 
    RectangleF oCaptureRect = new RectangleF(0, 0, oTargetRect.Size.Width / fScaleToApply, oTargetRect.Size.Height / fScaleToApply);
    // GetDrawingTransform() doesn't scale up, that's why why let it calculate the transformation for a smaller area
    // if the current page is smaller than the area we have available (fScaleToApply > 1). Afterwards we scale up again.
    CGAffineTransform oDrawingTransform = oPdfPage.GetDrawingTransform(CGPDFBox.Media, oCaptureRect, 0, true);

    // Now scale context up to final size.
    oContext.ScaleCTM(fScaleToApply, fScaleToApply);
    // Concat the PDF transformation.
    oContext.ConcatCTM(oDrawingTransform);
    // Draw the page.
    oContext.InterpolationQuality = CGInterpolationQuality.Medium;
    oContext.SetRenderingIntent (CGColorRenderingIntent.Default);
    oContext.DrawPDFPage(oPdfPage);

    // Capture an image.
    using(CGImage oImage = oContext.ToImage())
    {
        oBackgroundImage = UIImage.FromImage( oImage );
    }
}
4

2 に答える 2

2

私は本当にビットマップをカラーチャンネルごとに8ビットでレンダリングする必要はありません。

..。

using(CGColorSpace oColorSpace = CGColorSpace.CreateDeviceRGB())

別の色空間を提供しようとしましたか?

ここで、ビットマップはx/yの最大解像度でレンダリングされます

..。

using(CGBitmapContext oContext = new CGBitmapContext(null, iWidth, iHeight, 8, iWidth * 4, oColorSpace, CGImageAlphaInfo.PremultipliedFirst))

ビットマップのサイズや、ビットマップに必要なメモリ量に直接影響するその他のパラメータも制御できます。

また、Appleのドキュメントによると、コンテキストを作成できない場合(メモリのため)、CGBitmapContextCreate()はNILを返します。

無効なオブジェクト(などnull)が返された場合、C#インスタンスのHandle値は。になりIntPtr.Zeroます。これは、すべてのObjCオブジェクトに当てはまります。これは、initを返すことnilができ、.NETコンストラクターがを返すことができないためnullです。

于 2012-05-15T14:05:13.787 に答える
2

また、Apple のドキュメントによると、(メモリが原因で) コンテキストを作成できない場合、CGBitmapContextCreate() は NIL を返します。しかし、MonoTouch ではコンテキストを作成するコンストラクタしかないため、作成が失敗したかどうかを確認できません。できれば、ふりをしている画像をスキップできます。

これは実際には簡単です:

CGBitmapContext context;
try {
    context = new CGBitmapContext (...);
} catch (Exception ex) {
    context = null;
}

if (context != null) {
    using (context) {
        ...
    }
}

または、例外ハンドラで using 句全体を囲むこともできます。

try {
    using (var context = new CGBitmapContext (...)) {
        ...
    }
} catch {
    // we failed
    oBackgroundImage = null;
}
于 2012-05-16T10:27:25.443 に答える