static void
capture_to_file(Camera *canon, GPContext *canoncontext, char *fn) {
	int fd, retval;
	CameraFile *canonfile;
	CameraFilePath camera_file_path;

	printf("Capturing.\n");

	/* NOP: This gets overridden in the library to /capt0000.jpg */
	strcpy(camera_file_path.folder, "/");
	strcpy(camera_file_path.name, "foo.jpg");

	retval = gp_camera_capture(canon, GP_CAPTURE_IMAGE, &camera_file_path, canoncontext);
	printf("  Retval: %d\n", retval);

	printf("Pathname on the camera: %s/%s\n", camera_file_path.folder, camera_file_path.name);

	fd = open(fn, O_CREAT | O_WRONLY, 0644);
	retval = gp_file_new_from_fd(&canonfile, fd);
	printf("  Retval: %d\n", retval);
	retval = gp_camera_file_get(canon, camera_file_path.folder, camera_file_path.name,
		     GP_FILE_TYPE_NORMAL, canonfile, canoncontext);
	printf("  Retval: %d\n", retval);

	printf("Deleting.\n");
	retval = gp_camera_file_delete(canon, camera_file_path.folder, camera_file_path.name,
			canoncontext);
	printf("  Retval: %d\n", retval);

	gp_file_free(canonfile);
}
Пример #2
0
static void
capture_to_file(Camera *canon, GPContext *canoncontext, char *fn) {
	int fd, retval;
	CameraFile *canonfile;
	CameraFilePath camera_file_path;

	printf("Capturing.\n");

	retval = gp_camera_capture(canon, GP_CAPTURE_IMAGE, &camera_file_path, canoncontext);
	printf("  Retval: %d\n", retval);

	printf("Pathname on the camera: %s/%s\n", camera_file_path.folder, camera_file_path.name);

	fd = open(fn, O_CREAT | O_WRONLY | O_BINARY, 0644);
	retval = gp_file_new_from_fd(&canonfile, fd);
	printf("  Retval: %d\n", retval);
	retval = gp_camera_file_get(canon, camera_file_path.folder, camera_file_path.name,
		     GP_FILE_TYPE_NORMAL, canonfile, canoncontext);
	printf("  Retval: %d\n", retval);

	printf("Deleting.\n");
	retval = gp_camera_file_delete(canon, camera_file_path.folder, camera_file_path.name,
			canoncontext);
	printf("  Retval: %d\n", retval);

	gp_file_free(canonfile);
}
Пример #3
0
void Camera::save_file(const std::string& folder, const std::string& name,
		const std::string& localfile, bool delete_from_cam) {
    std::lock_guard<std::mutex> g(mutex);
	int ret;

	// TODO smart handle
	int fd = open(localfile.c_str(), O_CREAT | O_WRONLY, 0644);
	if (fd == -1)
		throw std::runtime_error("open() failed: " + std::to_string(errno));

	CameraFile *filep;
	if ((ret = gp_file_new_from_fd(&filep, fd)) < GP_OK) {
		close(fd);
		throw Exception("gp_file_new_from_fd", ret);
	}
	std::unique_ptr<CameraFile, int (*)(CameraFile*)> file(filep, gp_file_unref);

	if ((ret = gp_camera_file_get(camera, folder.c_str(), name.c_str(),
			 GP_FILE_TYPE_NORMAL, filep, ctx->context)) < GP_OK) {
		close(fd);
		throw Exception("gp_camera_file_get", ret);
	}

	if (delete_from_cam) {
		if ((ret = gp_camera_file_delete(camera, folder.c_str(),
						name.c_str(), ctx->context)) < GP_OK) {
			close(fd);
			throw Exception("gp_camera_file_delete", ret);
		}
	}

	close(fd);
}
Пример #4
0
void dt_camctl_import(const dt_camctl_t *c,const dt_camera_t *cam,GList *images,gboolean delete_orginals)
{
  //dt_camctl_t *camctl=(dt_camctl_t *)c;
  _camctl_lock(c,cam);

  GList *ifile=g_list_first(images);

  const char *output_path=_dispatch_request_image_path(c,cam);
  if(ifile)
    do
    {
      // Split file into folder and filename
      char *eos;
      char folder[4096]= {0};
      char filename[4096]= {0};
      char *file=(char *)ifile->data;
      eos=file+strlen(file);
      while( --eos>file && *eos!='/' );
      char *_file = g_strndup(file, eos-file);
      g_strlcat(folder, _file, 4096);
      g_strlcat(filename, eos+1, 4096);
      g_free(_file);

      const char *fname = _dispatch_request_image_filename(c,filename,cam);
      if(!fname) fname=filename;

      char *output = g_build_filename(output_path,fname,(char *)NULL);

      // Now we have filenames lets download file and notify listener of image download
      CameraFile *destination;
      int handle = open( output, O_CREAT | O_WRONLY,0666);
      if( handle > 0 )
      {
        gp_file_new_from_fd( &destination , handle );
        if( gp_camera_file_get( cam->gpcam, folder , filename, GP_FILE_TYPE_NORMAL, destination,  c->gpcontext) == GP_OK)
        {
          close( handle );
          _dispatch_camera_image_downloaded(c,cam,output);
          if( delete_orginals )
            gp_camera_file_delete(cam->gpcam, folder, filename, c->gpcontext);
        }
        else
          dt_print(DT_DEBUG_CAMCTL,"[camera_control] failed to download file %s\n",output);


      }
    }
    while( (ifile=g_list_next(ifile)) );

  _dispatch_control_status(c,CAMERA_CONTROL_AVAILABLE);
  _camctl_unlock(c);
}
Пример #5
0
bool Image_GPhoto::capture()
{
    lock_guard<recursive_mutex> lock(_gpMutex);

    if (_selectedCameraIndex == -1)
    {
        Log::get() << Log::WARNING << "Image_GPhoto::" << __FUNCTION__ << " - A camera must be selected before trying to capture" << Log::endl;
        return false;
    }

    GPhotoCamera camera = _cameras[_selectedCameraIndex];

    CameraFilePath filePath{};
    int res;
    if ((res = gp_camera_capture(camera.cam, GP_CAPTURE_IMAGE, &filePath, _gpContext)) == GP_OK)
    {
        if (string(filePath.name).find(".jpg") != string::npos || string(filePath.name).find(".JPG") != string::npos)
        {
            CameraFile* destination;
            int handle = open((string("/tmp/") + string(filePath.name)).c_str(), O_CREAT | O_WRONLY, 0666);
            if (handle != -1)
            {
                gp_file_new_from_fd(&destination, handle);
                if (gp_camera_file_get(camera.cam, filePath.folder, filePath.name, GP_FILE_TYPE_NORMAL, destination, _gpContext) == GP_OK)
                    Log::get() << Log::DEBUGGING << "Image_GPhoto::" << __FUNCTION__ << " - Sucessfully downloaded file " << string(filePath.folder) << "/" << string(filePath.name)
                               << Log::endl;
                close(handle);
            }

            // Read the downloaded file
            readFile(string("/tmp/") + string(filePath.name));
        }
        else
        {
            Log::get() << Log::WARNING << "Image_GPhoto::" << __FUNCTION__ << " - Captured image filetype is not jpeg. Maybe the camera is set to RAW?" << Log::endl;
            res = GP_ERROR;
        }

        gp_camera_file_delete(camera.cam, filePath.folder, filePath.name, _gpContext);

        // Delete the file
        if (remove((string("/tmp/") + string(filePath.name)).c_str()) == -1)
            Log::get() << Log::WARNING << "Image_GPhoto::" << __FUNCTION__ << " - Unable to delete file /tmp/" << filePath.name << Log::endl;
    }

    if (res != GP_OK)
        return false;
    else
        return true;
}
Пример #6
0
	int capture_to_file(std::string file_prefix, float exposure,
			std::string iso="1600", std::string aperture="0",
			bool gen_fits=true) {
		int aborted = 0;
		int fd, retval;
		CameraFile *canonfile;
		CameraFilePath camera_file_path;
		set_config_value_string(camera, "iso", iso.c_str(), context);
		if (aperture=="0")
			set_config_value_index(camera, "aperture", 0, context);
		else
			set_config_value_string(camera, "aperture", aperture.c_str(), context);

		printf("Capturing.\n");
		//press shutter, wait for "exposure" seconds, release shutter
		CameraEventType eventtype;
		void* eventdata;
		set_config_value_string(camera, "eosremoterelease", "Press Full", context);
		usleep(exposure*1e6);
		if (errno == EINTR) aborted = 1;
		set_config_value_string(camera, "eosremoterelease", "Release Full", context);

		std::cout << "Waiting for file...\n";
		eventtype = GP_EVENT_UNKNOWN;
		while (eventtype != GP_EVENT_FILE_ADDED) {
			gp_camera_wait_for_event(camera, TIMEOUT, &eventtype, &eventdata, context);
		}
		camera_file_path = *((CameraFilePath*) eventdata);

		printf("Pathname on the camera: %s/%s\n", camera_file_path.folder,
				camera_file_path.name);

		fd = open((file_prefix+".cr2").c_str(),
				O_CREAT | O_WRONLY, 0644);
		retval = gp_file_new_from_fd(&canonfile, fd);
		if (retval != GP_OK) return retval;

		retval = gp_camera_file_get(camera, camera_file_path.folder,
				camera_file_path.name, GP_FILE_TYPE_NORMAL, canonfile,
				context);
		if (retval != GP_OK) return retval;

		retval = gp_camera_file_delete(camera, camera_file_path.folder,
				camera_file_path.name, context);
		if (retval != GP_OK) return retval;

		gp_file_free(canonfile);
		if (gen_fits) produce_fits(file_prefix, aborted);
		return GP_OK;
	}
Пример #7
0
bool photo_camera::photo_camera_capture_to_file( std::string filename )
{
  int fd, error_code;
  CameraFile *photo_file;
  CameraFilePath photo_file_path;

  // NOP: This gets overridden in the library to /capt0000.jpg
  strcpy( photo_file_path.folder, "/");
  strcpy( photo_file_path.name, "foo.jpg");

  error_code = gp_camera_capture( camera_, GP_CAPTURE_IMAGE, &photo_file_path, context_ );
  if( error_code < GP_OK )
  {
    photo_reporter::error( "gp_camera_capture()" );
    gp_context_error( context_, "Could not capture image  (error code %d)\n", error_code );
    return false;
  }

  fd = open( filename.c_str(), O_CREAT|O_WRONLY, 0644 );
  error_code = gp_file_new_from_fd( &photo_file, fd );
  if( error_code < GP_OK )
  {
    photo_reporter::error( "gp_file_new_from_fd()" );
    gp_context_error( context_, "Could not create a new image file from %s%s (error code %d)\n", photo_file_path.folder, photo_file_path.name, error_code );
    gp_file_free( photo_file );
    return false;
  }

  error_code = gp_camera_file_get( camera_, photo_file_path.folder, photo_file_path.name, GP_FILE_TYPE_NORMAL, photo_file, context_ );
  if( error_code < GP_OK )
  {
    photo_reporter::error( "gp_camera_file_get()" );
    gp_context_error( context_, "Could not get file %s%s (error code %d)\n", photo_file_path.folder, photo_file_path.name, error_code );
    gp_file_free( photo_file );
    return false;
  }

  error_code = gp_camera_file_delete( camera_, photo_file_path.folder, photo_file_path.name, context_ );
  if( error_code < GP_OK )
  {
    photo_reporter::error( "gp_camera_file_delete()" );
    gp_context_error( context_, "Could delete file %s%s  (error code %d)\n", photo_file_path.folder, photo_file_path.name, error_code );
    gp_file_free( photo_file );
    return false;
  }

  gp_file_free( photo_file );
  return true;
}
Пример #8
0
void _camera_poll_events(const dt_camctl_t *c,const dt_camera_t *cam)
{
  CameraEventType event;
  gpointer data;
  if( gp_camera_wait_for_event( cam->gpcam, 30, &event, &data, c->gpcontext ) == GP_OK )
  {
    if( event == GP_EVENT_UNKNOWN )
    {
      /* this is really some undefined behavior, seems like its
      camera driver dependent... very ugly! */
      if( strstr( (char *)data, "4006" ) || // Nikon PTP driver
        (strstr((char *)data, "PTP Property") && strstr((char *)data, "changed"))  // Some Canon driver maybe all ??
      )
      {
        // Property change event occured on camera
        // let's update cache and signalling
        dt_print(DT_DEBUG_CAMCTL, "[camera_control] Camera configuration change event, lets update internal configuration cache.\n");
        _camera_configuration_update(c,cam);
      }
    }
    else if( event == GP_EVENT_FILE_ADDED )
    {
      if( cam->is_tethering )
      {
        dt_print(DT_DEBUG_CAMCTL,"[camera_control] Camera file added event\n");
        CameraFilePath *fp = (CameraFilePath *)data;
        CameraFile *destination;
        const char *output_path = _dispatch_request_image_path(c,cam);
        if( !output_path ) output_path="/tmp";
        const char *fname = _dispatch_request_image_filename(c,fp->name,cam);
        if( !fname ) fname=fp->name;

        char *output = g_build_filename(output_path,fname,(char *)NULL);

        int handle = open( output, O_CREAT | O_WRONLY,0666);
        gp_file_new_from_fd( &destination , handle );
        gp_camera_file_get( cam->gpcam, fp->folder , fp->name, GP_FILE_TYPE_NORMAL, destination,  c->gpcontext);
        close( handle );

        // Notify listerners of captured image
        _dispatch_camera_image_downloaded(c,cam,output);
        g_free(output);
      }
    }
  }
}
Пример #9
0
bool photo_camera::photo_camera_capture( photo_image* image )
{
  int fd, error_code;
  CameraFile *photo_file;
  CameraFilePath photo_file_path;
  char temp_file_name[20];

  // NOP: This gets overridden in the library to /capt0000.jpg
  strcpy( photo_file_path.folder, "/" );
  strcpy( photo_file_path.name, "foo.jpg" );

  error_code = gp_camera_capture( camera_, GP_CAPTURE_IMAGE, &photo_file_path, context_ );
  if( error_code < GP_OK )
  {
    photo_reporter::error( "gp_camera_capture()" );
    gp_context_error( context_, "Could not capture image  (error code %d)\n", error_code );
    return false;
  }

  // create temporary file
  strcpy( temp_file_name, "tmpfileXXXXXX" );
  fd = mkstemp( temp_file_name );
  error_code = gp_file_new_from_fd( &photo_file, fd );
  if( error_code < GP_OK )
  {
    close( fd );
    unlink( temp_file_name );

    photo_reporter::error( "gp_file_new_from_fd()" );
    gp_context_error( context_, "Could not create a new image file from %s%s (error code %d)\n", photo_file_path.folder, photo_file_path.name, error_code );
    gp_file_free( photo_file );
    return false;
  }

  // get image from camera and store in temporary file
  error_code = gp_camera_file_get( camera_, photo_file_path.folder, photo_file_path.name, GP_FILE_TYPE_NORMAL, photo_file, context_ );
  if( error_code < GP_OK )
  {
    gp_file_unref( photo_file );
    unlink( temp_file_name );
    photo_reporter::error( "gp_camera_file_get()" );
    gp_context_error( context_, "Could not get file %s%s (error code %d)\n", photo_file_path.folder, photo_file_path.name, error_code );
    return false;
  }

  // delete image from camera's memory
  error_code = gp_camera_file_delete( camera_, photo_file_path.folder, photo_file_path.name, context_ );
  if( error_code < GP_OK )
  {
    unlink( temp_file_name );
    photo_reporter::error( "gp_camera_file_delete()" );
    gp_context_error( context_, "Could delete file %s%s  (error code %d)\n", photo_file_path.folder, photo_file_path.name, error_code );
    gp_file_free( photo_file );
    return false;
  }

  // load image from temporary file
  if( image->photo_image_read( std::string(temp_file_name) ) == true )
  {
    gp_file_free( photo_file );
    unlink( temp_file_name );
    return true;
  }

  photo_reporter::error( "photo_image_read()" );
  gp_file_free( photo_file );
  unlink( temp_file_name );
  return false;
}
Пример #10
0
static void _camera_process_job(const dt_camctl_t *c,const dt_camera_t *camera, gpointer job)
{
  dt_camera_t *cam=(dt_camera_t *)camera;
  _camctl_camera_job_t *j = (_camctl_camera_job_t *)job;
  switch( j->type )
  {

    case _JOB_TYPE_EXECUTE_CAPTURE:
    {
      dt_print (DT_DEBUG_CAMCTL,"[camera_control] executing remote camera capture job\n");
      CameraFilePath fp;
      int res=GP_OK;
      if( (res = gp_camera_capture (camera->gpcam, GP_CAPTURE_IMAGE,&fp, c->gpcontext)) == GP_OK )
      {
        CameraFile *destination;
        const char *output_path = _dispatch_request_image_path(c,camera);
        if( !output_path ) output_path="/tmp";
        const char *fname = _dispatch_request_image_filename(c,fp.name,cam);
        if( !fname ) fname=fp.name;

        char *output = g_build_filename (output_path,fname,(char *)NULL);

        int handle = open (output, O_CREAT | O_WRONLY,0666);
        gp_file_new_from_fd (&destination , handle);
        gp_camera_file_get (camera->gpcam, fp.folder , fp.name, GP_FILE_TYPE_NORMAL, destination,  c->gpcontext);
        close (handle);

        // Notify listerners of captured image
        _dispatch_camera_image_downloaded (c,camera,output);
        g_free (output);
      }
      else
        dt_print (DT_DEBUG_CAMCTL,"[camera_control] capture job failed to capture image: %s\n",gp_result_as_string(res));


    }
    break;

    case _JOB_TYPE_EXECUTE_LIVE_VIEW:
    {
      CameraFile *fp = NULL;
      int res = GP_OK;
      const gchar* data = NULL;
      unsigned long int data_size = 0;

      gp_file_new(&fp);

      if( (res = gp_camera_capture_preview (cam->gpcam, fp, c->gpcontext)) != GP_OK )
      {
        dt_print (DT_DEBUG_CAMCTL,"[camera_control] live view failed to capture preview: %s\n", gp_result_as_string(res));
      }
      else if( (res = gp_file_get_data_and_size(fp, &data, &data_size)) != GP_OK )
      {
        dt_print (DT_DEBUG_CAMCTL,"[camera_control] live view failed to get preview data: %s\n", gp_result_as_string(res));
      }
      else
      {
        // everything worked
        GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
        if(gdk_pixbuf_loader_write(loader, (guchar*)data, data_size, NULL) == TRUE)
        {
          dt_pthread_mutex_lock(&cam->live_view_pixbuf_mutex);
          if(cam->live_view_pixbuf != NULL)
            g_object_unref(cam->live_view_pixbuf);
          cam->live_view_pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
          dt_pthread_mutex_unlock(&cam->live_view_pixbuf_mutex);
        }
        gdk_pixbuf_loader_close(loader, NULL);
      }
      if(fp)
        gp_file_free(fp);
      dt_pthread_mutex_unlock(&cam->live_view_synch);
      dt_control_queue_redraw_center();
    }
    break;

    case _JOB_TYPE_SET_PROPERTY:
    {
      _camctl_camera_set_property_job_t *spj=(_camctl_camera_set_property_job_t *)job;
      dt_print(DT_DEBUG_CAMCTL,"[camera_control] executing set camera config job %s=%s\n",spj->name,spj->value);

      CameraWidget *config; // Copy of camera configuration
      CameraWidget *widget;
      gp_camera_get_config( cam->gpcam, &config, c->gpcontext );
      if(  gp_widget_get_child_by_name ( config, spj->name, &widget) == GP_OK)
      {
        gp_widget_set_value ( widget , spj->value);
        gp_camera_set_config( cam->gpcam, config, c->gpcontext );
      }
      /* dt_pthread_mutex_lock( &cam->config_lock );
       CameraWidget *widget;
       if(  gp_widget_get_child_by_name ( camera->configuration, spj->name, &widget) == GP_OK) {
      	 gp_widget_set_value ( widget , spj->value);
      	 //gp_widget_set_changed( widget, 1 );
      	 cam->config_changed=TRUE;
       }

       dt_pthread_mutex_unlock( &cam->config_lock);*/
    }
    break;

    default:
      dt_print(DT_DEBUG_CAMCTL,"[camera_control] process of unknown job type %lx\n",(unsigned long int)j->type);
      break;
  }

  g_free(j);
}
Пример #11
0
bool GPCamera::downloadItem(const QString& folder, const QString& itemName,
                            const QString& saveFile)
{
#ifdef HAVE_GPHOTO2
    int         errorCode;
    CameraFile* cfile = 0;

    d->status->cancel = false;
    QFile file(saveFile);

    if (!file.open(QIODevice::ReadWrite))
    {
        qCDebug(DIGIKAM_IMPORTUI_LOG) << "Failed to open file" << file.fileName() << file.errorString();
        return false;
    }

    // dup fd, passing fd control to gphoto2 later
    int handle = dup(file.handle());

    if (handle == -1)
    {
        qCDebug(DIGIKAM_IMPORTUI_LOG) << "Failed to dup file descriptor";
        return false;
    }

    errorCode = gp_file_new_from_fd(&cfile, handle);

    if (errorCode != GP_OK)
    {
        qCDebug(DIGIKAM_IMPORTUI_LOG) << "Failed to get camera item!";
        printGphotoErrorDescription(errorCode);
        return false;
    }

    errorCode = gp_camera_file_get(d->camera, QFile::encodeName(folder).constData(),
                                   QFile::encodeName(itemName).constData(),
                                   GP_FILE_TYPE_NORMAL, cfile,
                                   d->status->context);

    if (errorCode != GP_OK)
    {
        qCDebug(DIGIKAM_IMPORTUI_LOG) << "Failed to get camera item!";
        printGphotoErrorDescription(errorCode);
        gp_file_unref(cfile);
        return false;
    }

    time_t mtime;
    errorCode = gp_file_get_mtime(cfile, &mtime);

    if (errorCode == GP_OK && mtime)
    {
        struct utimbuf ut;
        ut.modtime = mtime;
        ut.actime  = mtime;
        ::utime(QFile::encodeName(saveFile).constData(), &ut);
    }

    file.close();

    gp_file_unref(cfile);
    return true;
#else
    Q_UNUSED(folder);
    Q_UNUSED(itemName);
    Q_UNUSED(saveFile);
    return false;
#endif /* HAVE_GPHOTO2 */
}
Пример #12
0
bool photoController::capture(const char *filename) 
{
	if(checkCameraDetection() == false)
	{
		DEBUG_PRINTF(V_WARNING, "No camera detected.\n");
		return false;
	}
	int fd, retval;
	CameraFile *file;
	CameraFilePath camera_file_path;
	START_CHRONOMETER();
	DEBUG_PRINTF(V_MESSAGE, "Deleting old files.\n");
	retval = gp_camera_folder_delete_all(camera, "/", context);
	if(retval != GP_OK) // Error.
	{
		DEBUG_PRINTF(V_WARNING, "ERROR: Couldn't delete old files in camera memory. Code: %d\n", retval);
		return false;
	}
	DEBUG_PRINTF(V_MESSAGE, "Camera capture.\n");

	retval = gp_camera_capture(camera, GP_CAPTURE_IMAGE, &camera_file_path, context);
	if(retval != GP_OK) // Error.
	{
		if(retval == GP_ERROR_NOT_SUPPORTED)
			DEBUG_PRINTF(V_WARNING, "ERROR: This camera can not capture.\n");
		else
		{
			DEBUG_PRINTF(V_WARNING, "ERROR: Unexpected gp_camera_capture return. Code: %d\n", retval);
			releaseCamera(&camera, context);
			camera_detected = false;
			initCamera();
		}
		return false;
	}
	DEBUG_PRINTF(V_MESSAGE, "camera_file_path.folder %s!\n", camera_file_path.folder);
	DEBUG_PRINTF(V_MESSAGE, "Open %s!\n", filename);
	fd = open(filename, O_CREAT | O_WRONLY, 0644);
	if(fd < 0)  // Error.
	{
		DEBUG_PRINTF(V_WARNING, "Error opening file: %s!\n", strerror(errno));
		return false;
	}
	DEBUG_PRINTF(V_MESSAGE, "Create new CameraFile object from a file descriptor FD: %d.\n", fd);
	retval = gp_file_new_from_fd(&file, fd);
	if(retval != GP_OK) // Error.
	{
		DEBUG_PRINTF(V_WARNING, "ERROR: Unexpected gp_file_new_from_fd return. Code: %d\n", retval);
		gp_file_free(file);
		close(fd);
		return false;
	}
	if(checkCameraDetection() == false)
	{
		DEBUG_PRINTF(V_WARNING, "No camera detected 2.\n");
		gp_file_free(file);
		close(fd);
		return false;
	}
	DEBUG_PRINTF(V_MESSAGE, "Copy file from camera.\n");
	retval = gp_camera_file_get(camera, camera_file_path.folder, camera_file_path.name, GP_FILE_TYPE_NORMAL, file, context);
	if(retval != GP_OK) // Error.
	{
		if(retval == GP_ERROR_DIRECTORY_NOT_FOUND)
			DEBUG_PRINTF(V_WARNING, "Photo directory not found.\n");
		else if(retval == GP_ERROR_FILE_NOT_FOUND)
			DEBUG_PRINTF(V_WARNING, "Photo file name not found.\n");
		else
			DEBUG_PRINTF(V_WARNING, "ERROR: Unexpected gp_camera_file_get return. Code: %d\n", retval);
		gp_file_free(file);
		close(fd);
		return false;
	}
	if(checkCameraDetection() == false)
	{
		DEBUG_PRINTF(V_WARNING, "No camera detected 3.\n");
		gp_file_free(file);
		close(fd);
		return false;
	}
	DEBUG_PRINTF(V_MESSAGE, "Delete file from camera.\n");
	retval = gp_camera_file_delete(camera, camera_file_path.folder, camera_file_path.name, context);
	if(retval != GP_OK) // Error.
	{
		DEBUG_PRINTF(V_WARNING, "ERROR: Unexpected gp_camera_file_delete return. Code: %d\n", retval);
		gp_file_free(file);
		close(fd);
		return false;
	}

	DEBUG_PRINTF(V_MESSAGE, "Free CameraFile object.\n");
	gp_file_unref(file);
	close(fd);

	cv::Mat raw = cv::imread(filename);
	if(raw.data == NULL)
	{
		DEBUG_PRINTF(V_WARNING, "ERROR: OpenCV failed to open image file.\n");
		return false;
	}
	cv::Size raw_size = raw.size();
	DEBUG_PRINTF(V_MESSAGE, "capture() cv::Mat total=%u width=%d height=%d refcount=%d\n", raw.total(), raw_size.width, raw_size.height, (int)(void*)raw.refcount);
	crop(raw);
	raw.release();

	STOP_CHRONOMETER("Capture");
	return true;
}