Ejemplo n.º 1
0
void*
get_params (dt_lib_module_t *self, int *size)
{
    // concat storage and format, size is max + header
    dt_imageio_module_format_t  *mformat  = dt_imageio_get_format();
    dt_imageio_module_storage_t *mstorage = dt_imageio_get_storage();
    if(!mformat || !mstorage) return NULL;

    int32_t fsize = 0, ssize = 0;
    // size will be only as large as to remove random pointers from params (stored at the end).
    dt_imageio_module_data_t *fdata = mformat->get_params(mformat, &fsize);
    void *sdata = mstorage->get_params(mstorage, &ssize);
    // we allow null pointers (plugin not ready for export in current state), and just dont copy back the settings later:
    if(!sdata) ssize = 0;
    if(!fdata) fsize = 0;
    if(fdata)
    {
        // clean up format global params (need to set all bytes to reliably detect which preset is active).
        // we happen to want to set it all to 0
        memset(fdata, 0, sizeof(dt_imageio_module_data_t));
    }

    // FIXME: also the web preset has to be applied twice to be known as preset! (other dimension magic going on here?)
    // TODO: get this stuff from gui and not from conf, so it will be sanity-checked (you can never delete an insane preset)?
    // also store icc profile/intent here.
    int32_t iccintent = dt_conf_get_int("plugins/lighttable/export/iccintent");
    int32_t max_width  = dt_conf_get_int ("plugins/lighttable/export/width");
    int32_t max_height = dt_conf_get_int ("plugins/lighttable/export/height");
    gchar *iccprofile = dt_conf_get_string("plugins/lighttable/export/iccprofile");
    gchar *style = dt_conf_get_string("plugins/lighttable/export/style");

    if (fdata) {
        strncpy(fdata->style, style, 128);
    }

    if(!iccprofile)
    {
        iccprofile = (char *)g_malloc(1);
        iccprofile[0] = '\0';
    }

    char *fname = mformat->plugin_name, *sname = mstorage->plugin_name;
    int32_t fname_len = strlen(fname), sname_len = strlen(sname);
    *size = fname_len + sname_len + 2 + 2*sizeof(int32_t) + fsize + ssize + 3*sizeof(int32_t) + strlen(iccprofile) + 1;

    char *params = (char *)malloc(*size);
    memset(params, 0, *size);
    int pos = 0;
    memcpy(params+pos, &max_width, sizeof(int32_t));
    pos += sizeof(int32_t);
    memcpy(params+pos, &max_height, sizeof(int32_t));
    pos += sizeof(int32_t);
    memcpy(params+pos, &iccintent, sizeof(int32_t));
    pos += sizeof(int32_t);
    memcpy(params+pos, iccprofile, strlen(iccprofile)+1);
    pos += strlen(iccprofile) + 1;
    memcpy(params+pos, fname, fname_len+1);
    pos += fname_len+1;
    memcpy(params+pos, sname, sname_len+1);
    pos += sname_len+1;
    memcpy(params+pos, &fsize, sizeof(int32_t));
    pos += sizeof(int32_t);
    memcpy(params+pos, &ssize, sizeof(int32_t));
    pos += sizeof(int32_t);
    if(fdata != NULL) // otherwise fsize == 0, but clang doesn't like it ...
    {
        memcpy(params+pos, fdata, fsize);
        pos += fsize;
    }
    if(sdata != NULL) // see above
    {
        memcpy(params+pos, sdata, ssize);
        pos += ssize;
    }
    g_assert(pos == *size);

    g_free(iccprofile);
    g_free(style);

    if(fdata) mformat->free_params(mformat, fdata);
    if(sdata) mstorage->free_params(mstorage, sdata);
    return params;
}
Ejemplo n.º 2
0
int32_t dt_control_export_job_run(dt_job_t *job)
{
  long int imgid = -1;
  dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param;
  GList *t = t1->index;
  const int total = g_list_length(t);
  int size = 0;
  dt_imageio_module_format_t  *mformat  = dt_imageio_get_format();
  g_assert(mformat);
  dt_imageio_module_storage_t *mstorage = dt_imageio_get_storage();
  g_assert(mstorage);

  // Get max dimensions...
  uint32_t w,h,fw,fh,sw,sh;
  fw=fh=sw=sh=0;
  mstorage->dimension(mstorage, &sw,&sh);
  mformat->dimension(mformat, &fw,&fh);

  if( sw==0 || fw==0) w=sw>fw?sw:fw;
  else w=sw<fw?sw:fw;

  if( sh==0 || fh==0) h=sh>fh?sh:fh;
  else h=sh<fh?sh:fh;

  // get shared storage param struct (global sequence counter, one picasa connection etc)
  dt_imageio_module_data_t *sdata = mstorage->get_params(mstorage, &size);
  if(sdata == NULL)
  {
    dt_control_log(_("failed to get parameters from storage module, aborting export.."));
    return 1;
  }
  dt_control_log(ngettext ("exporting %d image..", "exporting %d images..", total), total);
  char message[512]= {0};
  snprintf(message, 512, ngettext ("exporting %d image to %s", "exporting %d images to %s", total), total, mstorage->name() );
  
  /* create a cancellable bgjob ui template */
  const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message );
  dt_control_backgroundjobs_set_cancellable(darktable.control, jid, job);
  const dt_control_t *control = darktable.control;

  double fraction=0;
#ifdef _OPENMP
  // limit this to num threads = num full buffers - 1 (keep one for darkroom mode)
  // use min of user request and mipmap cache entries
  const int full_entries = dt_conf_get_int ("parallel_export");
  // GCC won't accept that this variable is used in a macro, considers
  // it set but not used, which makes for instance Fedora break.
  const __attribute__((__unused__)) int num_threads = MAX(1, MIN(full_entries, 8));
#if !defined(__SUNOS__)
#pragma omp parallel default(none) private(imgid, size) shared(control, fraction, w, h, stderr, mformat, mstorage, t, sdata, job, jid, darktable) num_threads(num_threads) if(num_threads > 1)
#else
#pragma omp parallel private(imgid, size) shared(control, fraction, w, h, mformat, mstorage, t, sdata, job, jid, darktable) num_threads(num_threads) if(num_threads > 1)
#endif
  {
#endif
    // get a thread-safe fdata struct (one jpeg struct per thread etc):
    dt_imageio_module_data_t *fdata = mformat->get_params(mformat, &size);
    fdata->max_width  = dt_conf_get_int ("plugins/lighttable/export/width");
    fdata->max_height = dt_conf_get_int ("plugins/lighttable/export/height");
    fdata->max_width = (w!=0 && fdata->max_width >w)?w:fdata->max_width;
    fdata->max_height = (h!=0 && fdata->max_height >h)?h:fdata->max_height;
    int num = 0;
    // Invariant: the tagid for 'darktable|changed' will not change while this function runs. Is this a sensible assumption?
    guint tagid = 0;
    dt_tag_new("darktable|changed",&tagid);

    while(t && dt_control_job_get_state(job) != DT_JOB_STATE_CANCELLED)
    {
#ifdef _OPENMP
      #pragma omp critical
#endif
      {
        if(!t) 
          imgid = 0; 
        else
        {
          imgid = (long int)t->data;
          t = g_list_delete_link(t, t);
          num = total - g_list_length(t);
        }
      }
      // remove 'changed' tag from image
      dt_tag_detach(tagid, imgid);
      // check if image still exists:
      char imgfilename[1024];
      const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, (int32_t)imgid);
      if(image)
      {
        dt_image_full_path(image->id, imgfilename, 1024);
        if(!g_file_test(imgfilename, G_FILE_TEST_IS_REGULAR))
        {
          dt_control_log(_("image `%s' is currently unavailable"), image->filename);
          fprintf(stderr, _("image `%s' is currently unavailable"), imgfilename);
          // dt_image_remove(imgid);
          dt_image_cache_read_release(darktable.image_cache, image);
        }
        else
        {
          dt_image_cache_read_release(darktable.image_cache, image);
          mstorage->store(sdata, imgid, mformat, fdata, num, total);
        }
      }
#ifdef _OPENMP
      #pragma omp critical
#endif
      {
        fraction+=1.0/total;
        dt_control_backgroundjobs_progress(control, jid, fraction);
      }
    }
#ifdef _OPENMP
    #pragma omp barrier
    #pragma omp master
#endif
    {
      dt_control_backgroundjobs_destroy(control, jid);
      if(mstorage->finalize_store) mstorage->finalize_store(mstorage, sdata);
      mstorage->free_params(mstorage, sdata);
    }
    // all threads free their fdata
    mformat->free_params (mformat, fdata);
#ifdef _OPENMP
  }
#endif
  return 0;
}