Saving Image on SD

I had a similar post 6 months back, but then had to put that part of the project aside until now. So I thought I should start a new thread.

I am trying to capture an image from a Serial Camera L2 and save it to SD card for processing on a PC.

I can capture the image, convert it to a file and save it. It appears on the SD card and has some content. However when I try to load the file on the PC it says it is corrupted.

I am using the workaround ConvertToFile published long ago on the forum as Bitmaps.ConvertToFile still seems broken.

Running on a Cobra2 with version 4.3.6.

The following is my test program:

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;
using System.IO;
using GTM = Gadgeteer.Modules.GHIElectronics;
using GT = Gadgeteer;
using GHI.Utilities;

namespace CameraTest
{
    public partial class Program
    {
        private GT.Timer timer;
        Microsoft.SPOT.Bitmap image = null;

        void ProgramStarted()
        {
            this.camera.ImageResolution = GTM.SerialCameraL2.Resolution.QQVGA;
            this.camera.StartStreaming();


            this.timer = new GT.Timer(1);
            timer.Behavior = GT.Timer.BehaviorType.RunOnce;
            this.timer.Tick += this.timer_Tick;

            System.Threading.Thread t = new System.Threading.Thread(cameraThread);
            t.Start();
        }

        private void cameraThread()
        {
            while(true)
            {
                camera.StartStreaming();
                while (!camera.NewImageReady) Thread.Sleep(10);
                if (image != null) image.Dispose();
                image = camera.GetImage();
                camera.StopStreaming();
                timer.Start();
                Thread.Sleep(2);                //Lets timer run so I can see image

                VolumeInfo[] vi2 = VolumeInfo.GetVolumes();
                if (vi2[0].IsFormatted)
                {
                    try
                    {
                        int fileSize = image.Height * image.Width * 3 + 54;
                        LargeBuffer data = new LargeBuffer(fileSize);
                        ConvertToFile(image, data.Bytes);
                        string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
                        string imageName = rootDirectory + @ "\Test_" + DateTime.Now.Ticks.ToString() + ".bmp";
                        FileStream FileHandle = new FileStream(imageName, FileMode.Create);
                        FileHandle.Write(data.Bytes, 0, fileSize);
                        FileHandle.Close();
                        VolumeInfo[] vi = VolumeInfo.GetVolumes();
                        for (int i = 0; i < vi.Length; i++) vi[i].FlushAll();

                    }
                    catch (Exception exp)
                    {
                        Debug.Print(exp.Message.ToString());
                    }
                }
                else
                {
                    Debug.Print("Storage is not formatted. " + "Format on PC with FAT32/FAT16 first!");
                }

                System.Threading.Thread.Sleep(30000);
            }
        }
        private void timer_Tick(GT.Timer timer)
        {
            this.displayTE35.SimpleGraphics.DisplayImage(image, 0, 0);          //will not run anywhere but in a timer routine
        }

        private void ConvertToFile(Bitmap bitmap, byte[] outputBuffer)          //From old post since Bitmaps.ConvertToFile still seems broken
        {
            var inputBuffer = bitmap.GetBitmap();
            var width = (uint)bitmap.Width;
            var height = (uint)bitmap.Height;

            if (outputBuffer.Length != width * height * 3 + 54) throw new System.ArgumentException("outputBuffer.Length must be width * height * 3 + 54.", "outputSize");

            System.Array.Clear(outputBuffer, 0, outputBuffer.Length);

            Utility.InsertValueIntoArray(outputBuffer, 0, 2, 1977);
            Utility.InsertValueIntoArray(outputBuffer, 2, 4, width * height * 3 + 54);
            Utility.InsertValueIntoArray(outputBuffer, 10, 4, 54);
            Utility.InsertValueIntoArray(outputBuffer, 14, 4, 40);
            Utility.InsertValueIntoArray(outputBuffer, 18, 4, width);
            Utility.InsertValueIntoArray(outputBuffer, 22, 4, (uint)(-height));
            Utility.InsertValueIntoArray(outputBuffer, 26, 2, 1);
            Utility.InsertValueIntoArray(outputBuffer, 28, 2, 24);

            for (int i = 0, j = 54; i < width * height * 4; i += 4, j += 3)
            {
                outputBuffer[j + 0] = inputBuffer[i + 2];
                outputBuffer[j + 1] = inputBuffer[i + 1];
                outputBuffer[j + 2] = inputBuffer[i + 0];
            }
        }
    }
}

I’ve never unmounted the SD card and never had a problem as long as the file was closed and the volume flushed. Or at least for small text files there has never been a problem.

In any case I added an unmount and set a breakpoint at the brace after the sleep and it did not make any difference:

.Name);
System.Threading.Thread.Sleep(30000);
}

I found the issue:

In the post on the workarround for ConvertToFile, my browser (Chrome) displays a fragement of C code of an 8 followed by a ) as 8). When I copied and pasted the code, I translated this back incorrectly to source code.

So the line I had as:



Should be:


```cs]Utility.InsertValueIntoArray(outputBuffer, 0, 2, 19778);[/code


Ah!!!!!  See what I mean.

Maybe without the code attribute?

Utility.InsertValueIntoArray(outputBuffer, 0, 2, 19778);

Nope!.  Anyway the constant is 19778.

Sigh.  The stupid things always are the hardest.

How do we report a bug in the forum itself?