WCF:使用内存流在C#中传输位图

时间:2018-02-13 15:17:51

标签: c# wpf bitmap jpeg memorystream

我在同一台机器上使用WCF进行客户端和服务器程序之间的通信。之前我使用Bitmaps将视频帧传输到客户端。它在WCF上取得了成功,但我只有6兆字节/秒的局域网。每秒传输1.2Mb会阻塞LAN。我决定对从相机中捕获的位图进行JPEG编码。可以从位图或Memorystream将JPEG保存在磁盘上。我创建了一个

[MessageContract]
public class RemoteResponse
{
    [MessageBodyMember(Order = 1)]
    public System.IO.MemoryStream jpegImage;
}

我从(I)LiveImageService返回。 当我在客户端中找到它时:RemoteResponse ret = client.GetLiveImage();

MemoryStream returnedImage = returnedResponse.jpegImage;
returnedImage.Position = 0L;
returnedImage.Seek(0, SeekOrigin.Begin);
args.image = returnedImage;

我在事件处理程序中执行此操作:

args.image.Position = 0L;
args.image.Seek(0, SeekOrigin.Begin);
//bitmap = new Bitmap(args.image);
bitmap = (Bitmap)Image.FromStream(args.image);

它给了我一个"参数无效"例外。 我已经读过这是一个微软的错误解决方案。实际上是 转发的流被认为是21个字节长,因为有一个尾随 在前导" System.Drawing.Bitmap" \ 0结尾处为零\ 0。这就是为什么 停止处理图像。

我已经阅读了一个避免这种情况的解决方案:

byte[] arr = PdfReader.FlateDecode(PdfReader.GetStreamBytesRaw((PRStream)obj), true);

System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, pixelFormat);

System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new  System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);

Marshal.Copy(arr, 0, bmd.Scan0, arr.Length);
bmp.UnlockBits(bmd);

using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png); // here it is the trick
arr = ms.GetBuffer(); // now I replace my incorrect image format bytes for the correct ones
System.Drawing.Image image = System.Drawing.Image.FromStream(ms);
image.Save(path, System.Drawing.Imaging.ImageFormat.Png);
}

最后一个arr = ......有什么影响?以后不再使用了? 所以我不明白。

更新

在Microsoft网站上:https://social.msdn.microsoft.com/Forums/vstudio/en-US/f9e39595-04ca-42ae-a353-eb1a08602631/resolved-creating-image-file-parameter-is-not-valid?forum=netfxbcl

我重写了这个例子:

public static Bitmap DecodeJPEGFromMemoryStream(MemoryStream stream, int width, int height, PixelFormat pixelFormat)
{
    string content = System.Text.Encoding.UTF8.GetString(stream.ToArray());
    byte[] arr = Encoding.UTF8.GetBytes(content);
    //byte[] arr = PdfReader.FlateDecode(PdfReader.GetStreamBytesRaw((PRStream)obj), true);

    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, pixelFormat);
    System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new
    System.Drawing.Rectangle(0, 0, width, height),
    System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);

    Marshal.Copy(arr, 0, bmd.Scan0, arr.Length);
    bmp.UnlockBits(bmd);

    using (MemoryStream ms = new MemoryStream())
    {
        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // here it is the trick
        arr = ms.GetBuffer(); // now I replace my incorrect image format bytes for the correct ones
        System.Drawing.Image image = System.Drawing.Image.FromStream(ms);
        Bitmap ret = new Bitmap(image);
        return ret;
    }
}

我可以在Picturebox中看到图像,但它只有2行,闪烁。 如果我遮挡相机,我会发现它变暗了。所以现在数据来了。但我无法重建我的JPEG实时数据。

我能够解码JPEG数据,只需将其保存到磁盘即可。 所以我没有错误地得到了图像。我试图只保存图像 暂时删除后删除。

public static Bitmap DecodeJPEGFromMemoryStream(MemoryStream stream, int width, int height, PixelFormat pixelFormat)
{
    try
    {
        if(File.Exists("c:\\imagecache.jpg") == true)
                File.Delete("c:\\imagecache.jpg");

        //using (FileStream file = new FileStream("c:\\imagecache.jpg", FileMode.CreateNew, System.IO.FileAccess.ReadWrite))
        using (FileStream file = File.Open("c:\\imagecache.jpg", FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite))
        {
            stream.WriteTo(file);
            //JpegBitmapDecoder decoder = new JpegBitmapDecoder(file, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            file.Close();
            file.Dispose();
        }

        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();

        //BitmapSource bitmapSource = decoder.Frames[0];

        Bitmap jpeg;
        {
            {
                FileInfo info = new FileInfo("c:\\imagecache.jpg");

                if (info.Length == 0)
                {
                    File.Delete("c:\\imagecache.jpg");
                    return null;
                }
            }

            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();


            jpeg = (Bitmap)Image.FromFile("c:\\imagecache.jpg");  //the process cannot access the file...
        }

        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();

        if (File.Exists("c:\\imagecache.jpg") == true)
                File.Delete("c:\\imagecache.jpg");

        return jpeg;
    }
    catch(Exception ex)
    {
       return null;
    }
}

我得到异常:进程无法访问文件" imagecache.jpg", 因为它正被另一个进程使用。 FromFile有例外。

System.GC.Collect();
System.GC.WaitForPendingFinalizers();

Bitmap retImage = (Bitmap)jpeg.Clone();
jpeg.Dispose();

if (File.Exists("c:\\imagecache.jpg") == true)
{
    System.IO.FileInfo fi = new System.IO.FileInfo("c:\\imagecache.jpg");
    fi.Delete();
}

    return retImage;
}
catch (Exception ex)
{
    return null;
}
finally
{
    stream.Dispose();
}

这是固定的。 Image.FromFile:文件保持锁定状态,直到图像被丢弃。

所以我克隆了我的形象并处理了旧的。 在我看到我的影像之前,现在什么也看不见了。

0 个答案:

没有答案