我正在使用下面的代码来呈现PDF页面的预览。但它使用大量内存(每页2-3MB)。
在设备日志中,我看到:
<Error>: CGBitmapContextInfoCreate: unable to allocate 2851360 bytes for bitmap data
我真的不需要每个颜色通道以8位呈现位图。如何更改代码以使其以灰度或每通道更少的位数呈现?
我也可以使用一种解决方案,其中位图以x / y的最大分辨率渲染,然后将生成的图像缩放到所需的大小。无论如何,PDF将在CATiledLayer
之后详细呈现。
同样根据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 );
}
}
答案 0 :(得分: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
。
答案 1 :(得分: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;
}