在图像上添加文本

时间:2012-10-23 10:55:07

标签: c# silverlight windows-phone-7

我正在尝试在相机的照片上添加一些文本,这是我正在使用的方法,但不幸的是我得到了一个closedStream错误,或者当我尝试使用时有跨线程访问调度员。有人可以解释一下我出了什么问题吗?

    void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
    {
        DateTime dt = DateTime.Now;
        string fileName = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Second.ToString() + ".jpg";

        try
        {  
            // Save picture to the library camera roll.
            library.SavePictureToCameraRoll(fileName, e.ImageStream);

            // Set the position of the stream back to start
            e.ImageStream.Seek(0, SeekOrigin.Begin);

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                // load photo to writable bitmap 
                WriteableBitmap writeableBitmap = PictureDecoder.DecodeJpeg(e.ImageStream);
                writeableBitmap.Invalidate();
                var renderText = new TextBlock
                {
                    Text = "Hello World",
                    FontSize = 72,
                    Foreground = new SolidColorBrush(Colors.White),
                    FontWeight = FontWeights.Black,
                    Width = 500,
                    Height = 100
                };

                writeableBitmap.Render(renderText, new TranslateTransform() { X = 100, Y = 300 });
                writeableBitmap.Invalidate();

                using (var ms = new MemoryStream())
                {
                    writeableBitmap.SaveJpeg(ms, 1024, 768, 0, 100);
                    ms.Seek(0, SeekOrigin.Begin);

                    library.SavePicture("x" + fileName, ms);
                }

                // e.ImageStream.Close();
            });

            // Save picture as JPEG to isolated storage.
            using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
                {
                    // Initialize the buffer for 4KB disk pages.
                    byte[] readBuffer = new byte[4096];
                    int bytesRead = -1;

                    // Copy the image to isolated storage. 
                    while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                    {
                        targetStream.Write(readBuffer, 0, bytesRead);
                    }
                }
            }
        }
        finally
        {
            // Close image stream
            e.ImageStream.Close();
        }
    }

使用上面的代码我收到以下错误:无法访问已关闭的流。

如果我删除Dispatcher,我会收到此错误:无效的跨线程访问。

感谢。

2 个答案:

答案 0 :(得分:0)

在调度员范围之外放置更少的代码。

或将e.ImageStream保存到其他流可以在调度程序范围内获取。

答案 1 :(得分:0)

首先,发生了什么?

Dispatcher.BeginInvoke推迟了你的代码并告诉UI线程只要它可用就执行它。因此,您的e.ImageStream.Close();行会在BeginInvoke内的代码之前执行。因此,当您尝试读取流的内容时,它已经关闭。

解决这个问题的两种方法:

  1. e.ImageStream.Close();块中删除finally。但我不知道该流是否会保持开放状态。
  2. 如果1.不起作用,请将流的内容复制到MemoryStream,然后使用此流创建WriteableBitmap

    var stream = new MemoryStream();
    e.ImageStream.CopyTo(stream);
    
  3. 在这两种情况下,请勿忘记在创建WriteableBitmap后关闭流。