These examples demonstrate basic API usage. To build them, see the examples subdirectory in the FCam source package.
#include <stdlib.h> #include <stdio.h> #include <assert.h> #include <vector> // Select the platform #include <FCam/N900.h> namespace Plat = FCam::N900; /***********************************************************/ /* A program that takes a single shot */ /* */ /* This example is a simple demonstration of the usage of */ /* the FCam API. */ /***********************************************************/ void errorCheck(); int main(int argc, char **argv) { // Make the image sensor Plat::Sensor sensor; // Make a new shot std::vector<FCam::Shot> shot(3); for (size_t i = 0; i < shot.size(); i++) { shot[i].exposure = 50000; // 50 ms exposure shot[i].gain = 1.0f; // minimum ISO } // Specify the output resolution and format, and allocate storage for the resulting image shot[0].image = FCam::Image(2592, 1968, FCam::RAW); shot[1].image = FCam::Image(1296, 984, FCam::RAW); shot[2].image = FCam::Image(648, 492, FCam::RAW); // Order the sensor to capture the shots sensor.capture(shot); // Check for errors errorCheck(); assert(sensor.shotsPending() == shot.size()); // There should be exactly this many shots // Retrieve the frame from the sensor std::vector<FCam::Frame> frame(shot.size()); for (size_t i = 0; i < shot.size(); i++) { frame[i] = sensor.getFrame(); } sensor.stop(); errorCheck(); // Each frame should be the result of the shot we made for (size_t i = 0; i < shot.size(); i++) { printf("Checking frame %d\n", i); assert(frame[i].shot().id == shot[i].id); // This frame should be valid too assert(frame[i].valid()); assert(frame[i].image().valid()); printf("Frame %d OK!\n", i); } // Save the frames FCam::saveDNG(frame[0], "/home/user/MyDocs/DCIM/frame0.dng"); FCam::saveDNG(frame[1], "/home/user/MyDocs/DCIM/frame1.dng"); FCam::saveDNG(frame[2], "/home/user/MyDocs/DCIM/frame2.dng"); // Check that the pipeline is empty assert(sensor.framesPending() == 0); assert(sensor.shotsPending() == 0); return 0; } void errorCheck() { // Make sure FCam is running properly by looking for DriverError FCam::Event e; while (FCam::getNextEvent(&e, FCam::Event::Error)) { printf("Error: %s\n", e.description.c_str()); if (e.data == FCam::Event::DriverMissingError) { printf("example1: FCam can't find its driver. Did you install " "fcam-drivers on your platform, and reboot the device " "after installation?\n"); exit(1); } if (e.data == FCam::Event::DriverLockedError) { printf("example1: Another FCam program appears to be running " "already. Only one can run at a time.\n"); exit(1); } } }
#include <stdlib.h> #include <stdio.h> #include <assert.h> #include <FCam/N900.h> // Select the platform namespace Plat = FCam::N900; // namespace Plat = FCam::F2; /***********************************************************/ /* Flash / No-flash */ /* */ /* This example demonstrates capturing multiple shots with */ /* possibly different settings. */ /***********************************************************/ int main(int argc, char **argv) { // Devices Plat::Sensor sensor; Plat::Flash flash; sensor.attach(&flash); // Attach the flash to the sensor // Make two shots std::vector<FCam::Shot> shot(2); // Set the first shot parameters (to be done with flash) shot[0].exposure = 80000; shot[0].gain = 1.0f; shot[0].image = FCam::Image(2592, 1968, FCam::UYVY); // Set the second shot parameters (to be done without flash) shot[1].exposure = 80000; shot[1].gain = 1.0f; shot[1].image = FCam::Image(2592, 1968, FCam::UYVY); // Make an action to fire the flash Plat::Flash::FireAction fire(&flash); fire.duration = flash.minDuration(); // flash briefly fire.time = shot[0].exposure - fire.duration; // at the end of the exposure fire.brightness = flash.maxBrightness(); // at full power // Attach the action to the first shot shot[0].addAction(fire); // Order the sensor to capture the two shots sensor.capture(shot); assert(sensor.shotsPending() == 2); // There should be exactly two shots // Retrieve the first frame FCam::Frame frame = sensor.getFrame(); assert(sensor.shotsPending() == 1); // There should be one shot pending assert(frame.shot().id == shot[0].id); // Check the source of the request // Write out file if needed if (argc > 1) { FCam::saveJPEG(frame, argv[1]); } // Retrieve the second frame frame = sensor.getFrame(); assert(frame.shot().id == shot[1].id); // Check the source of the request // Write out file FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example2.jpg"); // Check the pipeline is empty assert(sensor.framesPending() == 0); assert(sensor.shotsPending() == 0); }
#include <stdlib.h> #include <stdio.h> #include <math.h> #include <assert.h> #include <FCam/N900.h> // Select the platform namespace Plat = FCam::N900; // namespace Plat = FCam::F2; /***********************************************************/ /* Focus sweep */ /* */ /* This example demonstrates moving the lens during an */ /* exposure via the use of Lens::FocusAction. It also */ /* shows how to use the metadata tagged by the devices. */ /* Because the lens on the N900 zooms slightly when it */ /* focuses, you'll also get a zoom-blur effect. */ /***********************************************************/ int main(int argc, char **argv) { // Devices Plat::Sensor sensor; Plat::Lens lens; // Attach the lens to the sensor sensor.attach(&lens); // First focus near with maximal speed lens.setFocus(lens.nearFocus(), lens.maxFocusSpeed()); while (lens.focusChanging()) { ; } // Wait to be done // Now make a shot that will sweep the lens FCam::Shot shot1; FCam::Lens::FocusAction sweep(&lens); // Set the parameters of this action sweep.time = 0; sweep.focus = lens.farFocus(); sweep.speed = lens.maxFocusSpeed()/4; // Calculate how long it takes to move the lens to the desired // location in microseconds float duration = 1000000.0f * (lens.nearFocus() - lens.farFocus()) / sweep.speed; printf("The lens will sweep from near to far in %f milliseconds\n", duration / 1000.0); // Set the shot parameter accordingly shot1.exposure = duration; shot1.gain = 1.0f; // Use a lower resolution to minimize rolling shutter effects shot1.image = FCam::Image(640, 480, FCam::UYVY); // Attach the action to the shot shot1.addAction(sweep); // Order the sensor to capture the shot sensor.capture(shot1); assert(sensor.shotsPending() == 1); // There should be exactly one shot // Retrieve the frame FCam::Frame frame = sensor.getFrame(); assert(frame.shot().id == shot1.id); // Check the source of the request // Print out some metadata const FCam::Lens::Tags lensTags(frame); printf("Aperture : %.4f\n", lensTags.aperture); printf("Initial focus : %.4f\n", lensTags.initialFocus); printf("Final focus : %.4f\n", lensTags.finalFocus); // Save the resulting file FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example3.jpg"); assert(sensor.framesPending() == 0); assert(sensor.shotsPending() == 0); }
#include <stdlib.h> #include <stdio.h> #include <math.h> #include <assert.h> #include <FCam/N900.h> #include <FCam/AutoExposure.h> #include <FCam/AutoWhiteBalance.h> // Select the platform namespace Plat = FCam::N900; // namespace Plat = FCam::F2; /***********************************************************/ /* Autoexposure */ /* */ /* This example shows how to request streams and deal with */ /* the incoming frames, and also uses the provided */ /* auto-exposure and auto-white-balance routines. */ /***********************************************************/ int main(int argc, char **argv) { // Make a sensor Plat::Sensor sensor; // Shot FCam::Shot stream1; // Set the shot parameters stream1.exposure = 33333; stream1.gain = 1.0f; // We don't bother to set frameTime in this example. It defaults // to zero, which the implementation will clamp to the minimum // possible value given the exposure time. // Request an image size and allocate storage stream1.image = FCam::Image(640, 480, FCam::UYVY); // Enable the histogram unit stream1.histogram.enabled = true; stream1.histogram.region = FCam::Rect(0, 0, 640, 480); // We will stream until the exposure stabilizes int count = 0; // # of frames streamed int stableCount = 0; // # of consecutive frames with stable exposure float exposure; // total exposure for the current frame (exposure time * gain) float lastExposure = 0; // total exposure for the previous frame FCam::Frame frame; do { // Ask the sensor to stream with the given parameters sensor.stream(stream1); // Retrieve a frame, make sure it's the latest frame = sensor.getFrame(); assert(frame.shot().id == stream1.id); // Check the source of the request // Calculate the total exposure used (including gain) exposure = frame.exposure() * frame.gain(); // Call the autoexposure algorithm. It will update stream1 // using this frame's histogram. autoExpose(&stream1, frame); // Call the auto white-balance algorithm. It will similarly // update the white balance using the histogram. autoWhiteBalance(&stream1, frame); // Increment stableCount if the exposure is within 5% of the // previous one if (fabs(exposure - lastExposure) < 0.05f * lastExposure) { stableCount++; } else { // Reset stableCount to less than zero to account for latency through the pipeline // Otherwise, we might assume we're stable before we see the results of the latest // updates. stableCount = -sensor.shotsPending(); } // Update lastExposure lastExposure = exposure; // Increment frame counter count++; } while (stableCount < 5); // Terminate when stable for 5 frames // Order the sensor to stop the pipeline and discard any frames still in it. sensor.stop(); printf("Processed %d frames until stable for 5 frames!\n", count); printf("Final exposure: %.2f ms. Final gain: %.2f\n", frame.exposure()/1000.f, frame.gain()); printf("Final color temperature: %d K\n", frame.whiteBalance()); // Write out the last, well-exposed frame FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example4.jpg"); // Check that the pipeline is empty assert(sensor.framesPending() == 0); assert(sensor.shotsPending() == 0); }
#include <stdlib.h> #include <stdio.h> #include <assert.h> #include <FCam/N900.h> #include <FCam/AutoFocus.h> // Select the platform namespace Plat = FCam::N900; // namespace Plat = FCam::F2; /***********************************************************/ /* Autofocus */ /* */ /* This example shows how to request streams and deal with */ /* the incoming frames, and also uses the provided */ /* autofocus routine. */ /***********************************************************/ int main(int argc, char **argv) { // Devices Plat::Sensor sensor; Plat::Lens lens; sensor.attach(&lens); // Attach the lens to the sensor // Autofocus supplied by FCam API FCam::AutoFocus autoFocus(&lens); // Shot FCam::Shot stream1; // Set the shot parameters stream1.exposure = 50000; stream1.gain = 1.0f; // Request a resolution, and allocate storage stream1.image = FCam::Image(640, 480, FCam::UYVY); // Enable the sharpness unit stream1.sharpness.enabled = true; // We will stream until the focus stabilizes int count = 0; // # of frames streamed // Order the sensor to stream sensor.stream(stream1); // Ask the autofocus algorithm to start sweeping the lens autoFocus.startSweep(); // Stream until autofocus algorithm completes FCam::Frame frame; do { // Retrieve a frame frame = sensor.getFrame(); assert(frame.shot().id == stream1.id); // Check the source of the request // The lens has tagged each frame with where it was focused // during that frame. Let's retrieve it so we can print it out. float diopters = frame["lens.focus"]; printf("Lens focused at %2.0f cm\n", 100/diopters); // The sensor has attached a sharpness map to each frame. // Let's sum up all the values in it so we can print out // the total sharpness of this frame. int totalSharpness = 0; for (int y = 0; y < frame.sharpness().height(); y++) { for (int x = 0; x < frame.sharpness().width(); x++) { totalSharpness += frame.sharpness()(x, y); } } printf("Total sharpness is %d\n\n", totalSharpness); // Call the autofocus algorithm autoFocus.update(frame); // Increment frame counter count++; } while (!autoFocus.idle()); printf("Autofocus chose to focus at %2.0f cm\n\n", 100/lens.getFocus()); // Order the sensor to shut down sensor.stop(); printf("Processed %d frames until autofocus completed!\n", count); // Write out the focused frame FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example5.jpg"); // Check that the pipeline is empty assert(sensor.framesPending() == 0); assert(sensor.shotsPending() == 0); }
#include <stdlib.h> #include <stdio.h> #include <assert.h> #include <FCam/N900.h> #include "SoundPlayer.h" // Select the platform namespace Plat = FCam::N900; // namespace Plat = FCam::F2; /***********************************************************/ /* Shutter sound */ /* */ /* This example shows how to declare and attach a device, */ /* and write the appropriate actions. In this example, the */ /* camera will trigger two actions at the beginning of the */ /* exposure: a flash, and a shutter sound. */ /* See SoundPlayer class for more information. */ /***********************************************************/ int main(int argc, char **argv) { // Devices Plat::Sensor sensor; Plat::Flash flash; // We defined a custom device to play a sound during the // exposure. See SoundPlayer.h/cpp for details. SoundPlayer audio; sensor.attach(&flash); // Attach the flash to the sensor sensor.attach(&audio); // Attach the sound player to the sensor // Set the shot parameters FCam::Shot shot1; shot1.exposure = 400000; shot1.gain = 1.0f; shot1.image = FCam::Image(2592, 1968, FCam::UYVY); // Action (Flash) FCam::Flash::FireAction fire(&flash); fire.time = 0; fire.duration = 60000; fire.brightness = flash.maxBrightness(); // Action (Sound) SoundPlayer::SoundAction click(&audio); click.time = 0; // Start at the beginning of the exposure click.setWavFile("/usr/share/sounds/camera_snd_title_1.wav"); // Attach actions shot1.addAction(fire); shot1.addAction(click); // Order the sensor to capture a shot. // The flash and the shutter sound should happen simultaneously. sensor.capture(shot1); assert(sensor.shotsPending() == 1); // There should be exactly one shot // Retrieve the frame from the sensor FCam::Frame frame = sensor.getFrame(); assert(frame.shot().id == shot1.id); // Check the source of the request // Write out the file FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example6.jpg"); // Check that the pipeline is empty assert(sensor.framesPending() == 0); assert(sensor.shotsPending() == 0); }