Saving a picture from Camera to a file


#1

I have build a program where a picture from the camera is saved to a file. I use 2 buttons. One for the snapshot and one for the saving of data. The structure is identical to the CameraDemo.  

The save the picture to a file consist of the following:

if (b == &button1)

{

String filenaam = "something";

FileOutputStream stream (File::getSpecialLocation(File::userDocumentsDirectory).getChildFile (filenaam));

JPEGImageFormat jpgWriter;

jpgWriter.writeImageToStream(lastSnapshot.getImage(), stream);

}

I expected the picture that is showed as preview to be written down as a file. The strange thing happening is that it makes a new picture and store that in a file.

I want the preview to be stored as a file. What do I do wrong?

 

Kind regards,

 

Harrie 

 

 


#2

Don't fully understand what you mean about previews, but the code you have there will append the image data to the end of the file if it already exists - could that be what's confusing you? You should delete the file first if you want to be sure of overwriting it.


#3

I hope to make it more clear:

 

A picture is made by the snapshot button:

 

if (cameraDevice != nullptr)

{

if (b == &snapshotButton)

{

cameraDevice->addListener (this);

}

}

 

This triggers:

 // This is called by the camera device when a new image arrives

void imageReceived (const Image& image) override

{

// In this app we just want to take one image, so as soon as this happens,

// we'll unregister ourselves as a listener.

if (cameraDevice != nullptr)

cameraDevice->removeListener (this);

// This callback won't be on the message thread, so to get the image back to

// the message thread, we'll stash a pointer to it (which is reference-counted in

// a thead-safe way), and trigger an async callback which will then display the

// new image..

incomingImage = image; triggerAsyncUpdate();

}

 

void handleAsyncUpdate() override

{

if (incomingImage.isValid()) lastSnapshot.setImage (incomingImage);

}

The lastsnapshot is displayed by

~addAndMakeVisible (&lastSnapshot);

and

~lastSnapshot.setBounds (r);

 

I guessed that I should store lastSnapshot to the file, but the strange thing is that not the picture that I see on screen, but the camera makes a new picture and stores it in the file.


#4

Well yes.. the code you've written will keep getting new images and storing them in that variable.. (?)


#5

The

cameraDevice->removeListener (this);

inside the

void imageReceived (const Image& image) override

does not stop the Images from getting in the variable "lastSnapshot"??

 


#6

I didn't notice that in your unformatted mess of code!

But seriously, haven't you tried debugging it to see when these things are getting called??


#7

I could not get the formated code with crtl-C / crtl-V in this forum. I'll try the debugger.


#8

The debugger tells me that the functions get called like I expected. The

FileOutputStream stream (File::getSpecialLocation(File::userDocumentsDirectory).getChildFile (filenaam));

JPEGImageFormat jpgWriter;

jpgWriter.writeImageToStream(imageCache.getFromHashCode(0), stream);

is recapturing the Image. It can take some time between the captured picture and the pressing of the second button. So I guessed I should try an ImageCache.  I am trying to fill an ImageCache, but get errors:

 ~1>c:\inspector\source\projectdemo.cpp(1020): error C2248: 'juce::ImageCache::ImageCache' : cannot access private member declared in class 'juce::ImageCache'

I declared a public

ImageCache imageCache;

I added this part:

void handleAsyncUpdate() override

{

   if (incomingImage.isValid())

   imageCache.addImageToCache(incomingImage,0);

}

 

And try to write it to a file

FileOutputStream stream (File::getSpecialLocation(File::userDocumentsDirectory).getChildFile (filenaam));

JPEGImageFormat jpgWriter;

jpgWriter.writeImageToStream(imageCache.getFromHashCode(0), stream);

I'll probably be missing something simple. Should this help me with the correct version of the picture?

 


#9

One thing to note is that the ImageCache only has static methods so you shouldn't be creating an instance of one anywhere. That could be your problem if you're not using the same cache object.

Your handling of the Image looks a bit strange as well. When you recieve the image from the camera callback just write it to a file and then use that File to retrieve a cahced version using ImageCache::getFromFile (fileYouJustSaved);

Do you even need to use the ImageCache though? Can't you just keep the last Image object as a member variable?


#10

Thanks, I just figured out that adding

if (cameraDevice != nullptr)

cameraDevice->removeListener (this);

to the void handleAsyncUpdate() override

is doing the trick without a cache. Maybe an idea to place it this way in the CameraDemo.