locked
Getting component can not be found error when loading bitmap bytes into an image control?

    Question

  • I have a Windows Store App that receives JPEG frames over a StreamSocket from another computer.  I am getting a "component can not be found" exception when I load the decoded JPEG data bytes into an Image control.  That exception usually means that there is a problem with the image format.  Yet the bitmap decoder doesn't complain about the JPEG bytes at all when it decodes the JPEG image.  What is the problem with my code?

    Also, it seems like I'm having to execute an awkwardly large number of steps to go from the incoming JPEG frame to get to the bitmap bytes.  Is there a less convoluted way of doing this? 

    Below is the code.  Note, the sending computer does send the length of the JPEG frame before it sends the frame itself (the bytes for the frame).

                       // Receive video on this channel.  First 4 bytes should be the length of the incoming frame.
                        DataReader dr = new DataReader(args.Socket.InputStream);
    
                        // Load the data into the stream socket buffer.
                        uint numBytesLoaded = await dr.LoadAsync(4);
    
                        if (numBytesLoaded == 0)
                        {
                            Debug.WriteLine(string.Format("Disconnected (from {0})", args.Socket.Information.RemoteHostName.DisplayName));
                            return;
                        }
    
                        // Get the size of the JPEG frame.
                        int jpegLength = dr.ReadInt32();
    
                        // Request the number of bytes for the JPEG frame from the strema socket.
                        uint numJpegBytes = await dr.LoadAsync((uint)jpegLength);
    
                        IBuffer buffer = dr.ReadBuffer(numJpegBytes);
    
                        using (IRandomAccessStream ras = new InMemoryRandomAccessStream())
                        {
                            await ras.WriteAsync(buffer);
    
                            // Show the frame.  Has to be done on the URI thread.
                            await imgVideo.Dispatcher.RunAsync(
                                Windows.UI.Core.CoreDispatcherPriority.Normal,
                                async () =>
                                {
                                    // Create a bitmap decoder to decode the JPEG bytes to a bitmap.
                                    BitmapDecoder decoder = null;
    
                                    decoder = 
                                        await BitmapDecoder.CreateAsync(
                                                    BitmapDecoder.JpegDecoderId, ras);
    
                                    BitmapFrame bitmapFrame =
                                        await decoder.GetFrameAsync(0);
    
                                    byte[] aryBitmapBytes = (await bitmapFrame.GetPixelDataAsync()).DetachPixelData().ToArray();
    
                                    using (IRandomAccessStream ras2 = new InMemoryRandomAccessStream())
                                    {
                                        ras2.AsStreamForWrite().Write(aryBitmapBytes, 0, aryBitmapBytes.Length);
    
                                        BitmapImage bmi = new BitmapImage();
    
                                        bmi.DecodePixelHeight = (int)decoder.PixelHeight;
                                        bmi.DecodePixelWidth = (int)decoder.PixelWidth;
    
                                        await bmi.SetSourceAsync(ras2);
    
                                        imgVideo.Source = bmi;
                                    } 
                                });
                        } // using (IRandomAccessStream ras = new InMemoryRandomAccessStream())


    -- roschler

    Friday, May 30, 2014 5:36 AM

Answers

  • Kind of bypassing the question, but why not put the byte[] into a WriteableBitmap? That will be a cleaner transition, and since WriteableBitmaps are ImageSources just like BitmapImages you can use them the same way in almost all situations.

    --Rob

    • Marked as answer by roschler Saturday, May 31, 2014 4:23 AM
    Saturday, May 31, 2014 3:02 AM
    Owner

All replies

  • Kind of bypassing the question, but why not put the byte[] into a WriteableBitmap? That will be a cleaner transition, and since WriteableBitmaps are ImageSources just like BitmapImages you can use them the same way in almost all situations.

    --Rob

    • Marked as answer by roschler Saturday, May 31, 2014 4:23 AM
    Saturday, May 31, 2014 3:02 AM
    Owner
  • Thanks, that's what I ended up doing and it worked.  Too bad though that you have to work with WriteableBitmap objects on the UI thread.  Creates a whole set of problems of its own.

    --roschler


    -- roschler

    Saturday, May 31, 2014 4:24 AM