我正在使用下面的代码创建一个基于UI元素的实时图块.它渲染uiElementa WriteableBitmap,保存位图+返回文件名.此方法在Windows Phone后台任务代理中运行,我正在运行内存限制.
private string CreateLiveTileImage(Canvas uiElement, int width, int heigth)
{
var wbmp = new WriteableBitmap(width, heigth);
try
{
wbmp.Render(uiElement, null);
wbmp.Invalidate();
var tileImageName = _liveTileStoreLocation;
using (var stream = new IsolatedStorageFileStream(tileImageName, FileMode.Create, FileAccess.Write, IsolatedStorageFile.GetUserStoreForApplication()))
{
wbmp.SaveJpeg(stream, width, heigth, 0, 100);
stream.Close();
}
uiElement = null;
wbmp = null;
GC.Collect();
return "isostore:" + tileImageName;
}
catch (Exception exception)
{
// ...
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
我做了一些测试,问题是:这个方法泄漏内存,但我不知道为什么/在哪里?!
我也做了一些测试运行 - 在第一次进入这个方法之前:
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
7.249.920 Bytes
Run Code Online (Sandbox Code Playgroud)
这是好的,因为附加了调试器,它使用大约2 MB的内存.
再做一些此方法的运行(在调试器中再次设置为run方法):
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage …Run Code Online (Sandbox Code Playgroud) 如何计算WriteableBitmap.WritePixels方法所需的缓冲区大小?
我使用带有四个参数的重载,第一个是Int32Rect,下一个是包含颜色的RGBA数字的字节数组,第三个是步幅(这是我的可写位图的宽度乘以每像素的位数除以通过8),最后一个是缓冲区(在Intellisense中称为偏移).
我在下面的代码中得到缓冲区大小不足够的运行时错误:
byte[] colourData = { 0, 0, 0, 0 };
var xCoordinate = 1;
var yCoordinate = 1;
var width = 2;
var height = 2;
var rect = new Int32Rect(xCoordinate, yCoordinate, width, height);
var writeableBitmap = new WriteableBitmap(MyImage.Source as BitmapSource);
var stride = width*writeableBitmap.Format.BitsPerPixel/8;
writeableBitmap.WritePixels(rect, colourData, stride,0);
Run Code Online (Sandbox Code Playgroud)
我需要使用什么公式来计算上面代码中所需的缓冲区值?
我试图在Windows Phone 7应用程序中的位图上呈现文本.
看起来或多或少类似于以下的代码在主线程上运行时可以正常工作:
public ImageSource RenderText(string text, double x, double y)
{
var canvas = new Canvas();
var textBlock = new TextBlock { Text = text };
canvas.Children.Add(textBloxk);
Canvas.SetLeft(textBlock, x);
Canvas.SetTop(textBlock, y);
var bitmap = new WriteableBitmap(400, 400);
bitmap.Render(canvas, null);
bitmap.Invalidate();
return bitmap;
}
Run Code Online (Sandbox Code Playgroud)
现在,由于我必须使用更复杂的东西渲染多个图像,我想在后台线程上渲染位图以避免无响应的UI.
当我使用a BackgroundWorker来执行此操作时,构造函数TextBlock会抛出UnauthorizedAccessException声称这是无效的跨线程访问.
我的问题是:如何在不阻塞UI的情况下在位图上呈现文本?
WriteableBitmap或UIElements,如果有另一种方式来呈现文本.编辑
另一个想法:有没有人知道是否应该可以在另一个线程中运行UI消息循环,然后让该线程完成工作?(而不是使用BackgroundWorker)?
编辑2
要考虑替代方案WriteableBitmap,我需要的功能是:
c# silverlight multithreading writeablebitmap windows-phone-7
我有:
WriteableBitmap bmp;
Run Code Online (Sandbox Code Playgroud)
我基本上想将它保存到磁盘上的文件中,如下所示:
C:\bmp.png
Run Code Online (Sandbox Code Playgroud)
我读了一些提到阅读的论坛:
bmp.Pixels
Run Code Online (Sandbox Code Playgroud)
并将这些像素保存到Bitmap当时使用的Bitmap.SaveImage()函数中.但是,我无法访问任何Pixels.显然我的WriteableBitmap名字没有任何属性Pixels.
我使用.NET Framework 4.0.
BitmapImage bitmapImage = new BitmapImage(new Uri("arka_projects_as_logo.png", UriKind.Relative));
Image uiElement = new Image() { Source = bitmapImage };
ScaleTransform t = new ScaleTransform() { ScaleX = 0.2, ScaleY = 0.2 };
WriteableBitmap writeableBitmap = new WriteableBitmap(uiElement,t);
Run Code Online (Sandbox Code Playgroud)
我想插入这个转换(WriteableBitmap的)的结果为System.Windows.Controls.Image.当我这样做:
Image arkaImage = new Image() { Source = writeableBitmap };
Run Code Online (Sandbox Code Playgroud)
arkaImage根本没有显示.有什么办法可以让它发挥作用?
有关WriteableBitmap 的简单MSDN示例.
它显示了如何通过在按下鼠标时更新一个像素并在WPF -Image Control上移动来用光标绘制手绘线.
writeableBitmap.Lock();
(...set the writeableBitmap.BackBuffers pixel value...)
writeableBitmap.AddDirtyRect(new Int32Rect(column, row, 1, 1));
writeableBitmap.Unlock();
Run Code Online (Sandbox Code Playgroud)
现在,我试图在非常快速地移动鼠标指针时理解以下行为:
如果图像/位图大小相对较小,例如800:600像素,那么最后绘制的像素总是与鼠标指针位置"同步",即没有延迟,对鼠标移动的反应非常快.
但是,如果位图变大,例如1300:1050像素,您可以注意到延迟,最后绘制的像素总是在移动鼠标指针后面稍微延迟.
因此在两种情况下只有一个像素用" AddDirtyRect" 更新,反应速度应该独立于位图大小!?但似乎Writeablebitmap在它的大小变大时会变慢.
或者整个位图在每次writeableBitmap.Unlock();调用时都会以某种方式转移到图形设备,而不仅仅是方法中指定的矩形区域AddDirtyRect?
弗里茨
前段时间我发布了一个与WriteableBitmap内存泄漏相关的问题,虽然我收到了与该问题相关的精彩提示,但我仍然认为有一个严重的错误/(我犯了错误)/(混乱)/(其他一些东西)这里.
所以,这是我的问题:
假设我们有一个带有图像和按钮的WPF应用程序.图像的源是一个非常大的位图(3600*4800像素),当它在运行时显示时,应用程序消耗~90 MB.
现在假设我希望从图像源(真正的大图像)实例化一个WriteableBitmap,当发生这种情况时,应用程序消耗大约220 MB.
现在到了棘手的部分,当对图像的修改(通过WriteableBitmap)结束时,对WriteableBitmap的所有引用(至少是我所知道的那些)都被销毁(在方法结束时或通过设置它们)为null)应释放writeableBitmap使用的内存,应用程序消耗应返回到~90 MB.问题是有时它会返回,有时却不会.
这是一个示例代码:
// The Image's source whas set previous to this event
private void buttonTest_Click(object sender, RoutedEventArgs e)
{
if (image.Source != null)
{
WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)image.Source);
bitmap.Lock();
bitmap.Unlock();
//image.Source = null;
bitmap = null;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,引用是本地的,并且应该在方法结束时释放内存(或者当垃圾收集器决定这样做时).但是,该应用程序可能消耗~224 MB直到宇宙结束.
任何帮助都会很棒.
嘿.我有480 x 800图像,并希望将其放在我的瓷砖地图上.我正在尝试将图像分割成网格(6 x 10)并为每个图块分配图像的特定部分.基本上,tilemap看起来像一个大图像,因为每个tile都附加了图像的相关部分.这样做的最佳方法是什么?我已经尝试浏览每个图块并将其绘制到WriteableBitmap,但所有图像都是相同的.
WriteableBitmap wb = new WriteableBitmap(80,80);
Rect src= new Rect(x*Width,y*Height, 80, 80);
Rect dest= new Rect(0, 0, 80, 80);
wb.Blit(dest, mainWb, src);
tile.SetImage(wb);
Run Code Online (Sandbox Code Playgroud)
(x和y)只是迭代tilemap时使用的索引,80是tile的高度和宽度,mainWb是我要分割的大图像.谢谢你的帮助.
编辑:完整循环代码:
var mainImage = Application.GetResourceStream(new Uri("MainImage.jpg", UriKind.Relative)).Stream;
WriteableBitmap mainWb = new WriteableBitmap(480, 800);
mainWb.SetSource(mainImage);
for (int x = 0; x < 6; x++)
{
for (int y = 0; y < 12; y++)
{
Tile tile = new Tile();
WriteableBitmap wb = new WriteableBitmap(80,80);
Rect src = new Rect(x*Width,y*Height, 80, …Run Code Online (Sandbox Code Playgroud) 是否可以直接读/写WriteableBitmap的像素数据?我目前正在使用WriteableBitmapEx,SetPixel()但速度很慢,我希望直接访问像素而不会产生任何开销.
我有一段时间没有使用过HTML5的画布,但是如果我没记错的话,你可以将它的图像数据作为单个数字数组获得,这就是我正在寻找的东西
提前致谢
在我的代码中,我从字节数组(依次从Kinect)接收WriteableBitmaps,我想把它们变成用于EmguCV的位图.目前这是我的代码:
// Copy the pixel data from the image to a temporary array
colorFrame.CopyPixelDataTo(this.colorPixels);
// Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * colorFrame.BytesPerPixel,
0);
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(colorBitmap));
MemoryStream ms = new MemoryStream();
encoder.Save(ms);
Bitmap b=new Bitmap(ms);
Image<Gray, Byte> img = new Image<Gray, Byte>(b);
img = img.ThresholdBinary(new Gray(200), new Gray(255));
Run Code Online (Sandbox Code Playgroud)
我从这里得到了代码的下半部分.代码编译和所有内容,但是在我尝试运行程序时挂起(它应该对图像执行一些操作然后将其转换回可以呈现的格式作为一个图像.)暂停我的代码,然后在VS 2013中使用IntelliTrace,我在Image<Gray, Byte> img = new Image<Gray, Byte>(b);"A System.ArgumentException被抛出时得到以下异常:不支持URI格式." 使用替代代码,从我直接从字节到位图的位置给出了同样的错误.(代码可以在这里找到.)
任何人都有关于如何解决此错误或其他方法转换为位图的提示?我是C#和EmguCV的新手,我非常感激.
writeablebitmap ×10
c# ×8
wpf ×4
silverlight ×3
bitmap ×1
bitmapimage ×1
buffer ×1
dispose ×1
emgucv ×1
image ×1
kinect ×1
live-tile ×1
memory ×1
pixel ×1