Пример #1
0
// transparent read method to load ldr image to dt_raw_image_t with exif and so on.
dt_imageio_retval_t
dt_imageio_open_ldr(
    dt_image_t *img,
    const char *filename,
    dt_mipmap_cache_allocator_t a)
{
  dt_imageio_retval_t ret;
  ret = dt_imageio_open_tiff(img, filename, a);
  if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
  {
    img->filters = 0;
    img->flags &= ~DT_IMAGE_RAW;
    img->flags &= ~DT_IMAGE_HDR;
    img->flags |= DT_IMAGE_LDR;
    return ret;
  }

  // jpeg stuff here:
  if(!img->exif_inited)
    (void) dt_exif_read(img, filename);
  const int orientation = dt_image_orientation(img);

  dt_imageio_jpeg_t jpg;
  if(dt_imageio_jpeg_read_header(filename, &jpg)) return DT_IMAGEIO_FILE_CORRUPTED;
  img->width  = (orientation & 4) ? jpg.height : jpg.width;
  img->height = (orientation & 4) ? jpg.width  : jpg.height;

  uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*jpg.width*jpg.height*4);
  if(dt_imageio_jpeg_read(&jpg, tmp))
  {
    free(tmp);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  img->bpp = 4*sizeof(float);
  void *buf = dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a);
  if(!buf)
  {
    free(tmp);
    return DT_IMAGEIO_CACHE_FULL;
  }

  dt_imageio_flip_buffers_ui8_to_float((float *)buf, tmp, 0.0f, 255.0f, 4, jpg.width, jpg.height, jpg.width, jpg.height, 4*jpg.width, orientation);

  free(tmp);

  img->filters = 0;
  img->flags &= ~DT_IMAGE_RAW;
  img->flags &= ~DT_IMAGE_HDR;
  img->flags |= DT_IMAGE_LDR;
  return DT_IMAGEIO_OK;
}
Пример #2
0
dt_imageio_retval_t dt_imageio_open_jpeg(dt_image_t *img,  const char *filename, dt_mipmap_cache_allocator_t a)
{
  const char *ext = filename + strlen(filename);
  while(*ext != '.' && ext > filename) ext--;
  if(strncmp(ext, ".jpg", 4) && strncmp(ext, ".JPG", 4) && strncmp(ext, ".jpeg", 5) && strncmp(ext, ".JPEG", 5))
    return DT_IMAGEIO_FILE_CORRUPTED;

  if(!img->exif_inited)
    (void) dt_exif_read(img, filename);

  const int orientation = dt_image_orientation(img);

  dt_imageio_jpeg_t jpg;
  if(dt_imageio_jpeg_read_header(filename, &jpg)) return DT_IMAGEIO_FILE_CORRUPTED;
  img->width  = (orientation & 4) ? jpg.height : jpg.width;
  img->height = (orientation & 4) ? jpg.width  : jpg.height;


  uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*jpg.width*jpg.height*4);
  if(dt_imageio_jpeg_read(&jpg, tmp))
  {
    free(tmp);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  img->bpp = 4*sizeof(float);
  void *buf = dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a);
  if(!buf)
  {
    free(tmp);
    return DT_IMAGEIO_CACHE_FULL;
  }

  dt_imageio_flip_buffers_ui8_to_float((float *)buf, tmp, 0.0f, 255.0f, 4, jpg.width, jpg.height, jpg.width, jpg.height, 4*jpg.width, orientation);

  free(tmp);

  return DT_IMAGEIO_OK;
}
Пример #3
0
uint32_t dt_image_import(const int32_t film_id, const char *filename, gboolean override_ignore_jpegs)
{
  if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
    return 0;
  const char *cc = filename + strlen(filename);
  for(; *cc!='.'&&cc>filename; cc--);
  if(!strcmp(cc, ".dt")) return 0;
  if(!strcmp(cc, ".dttags")) return 0;
  if(!strcmp(cc, ".xmp")) return 0;
  char *ext = g_ascii_strdown(cc+1, -1);
  if(override_ignore_jpegs == FALSE && (!strcmp(ext, "jpg") ||
                                        !strcmp(ext, "jpeg")) && dt_conf_get_bool("ui_last/import_ignore_jpegs"))
    return 0;
  int supported = 0;
  char **extensions = g_strsplit(dt_supported_extensions, ",", 100);
  for(char **i=extensions; *i!=NULL; i++)
    if(!strcmp(ext, *i))
    {
      supported = 1;
      break;
    }
  g_strfreev(extensions);
  if(!supported)
  {
    g_free(ext);
    return 0;
  }
  int rc;
  uint32_t id = 0;
  // select from images; if found => return
  gchar *imgfname;
  imgfname = g_path_get_basename((const gchar*)filename);
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select id from images where film_id = ?1 and filename = ?2",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_STATIC);
  if(sqlite3_step(stmt) == SQLITE_ROW)
  {
    id = sqlite3_column_int(stmt, 0);
    g_free(imgfname);
    sqlite3_finalize(stmt);
    g_free(ext);
    return id;
  }
  sqlite3_finalize(stmt);

  // also need to set the no-legacy bit, to make sure we get the right presets (new ones)
  uint32_t flags = dt_conf_get_int("ui_last/import_initial_rating");
  if(flags > 5)
  {
    flags = 1;
    dt_conf_set_int("ui_last/import_initial_rating", 1);
  }
  flags |= DT_IMAGE_NO_LEGACY_PRESETS;
  // insert dummy image entry in database
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "insert into images (id, film_id, filename, caption, description, "
                              "license, sha1sum, flags) values (null, ?1, ?2, '', '', '', '', ?3)",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname),
                             SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, flags);
  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) fprintf(stderr, "sqlite3 error %d\n", rc);
  sqlite3_finalize(stmt);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select id from images where film_id = ?1 and filename = ?2",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname),
                             SQLITE_STATIC);
  if(sqlite3_step(stmt) == SQLITE_ROW) id = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);

  // Try to find out if this should be grouped already.
  gchar *basename = g_strdup(imgfname);
  gchar *cc2 = basename + strlen(basename);
  for(; *cc2!='.'&&cc2>basename; cc2--);
  *cc2='\0';
  gchar *sql_pattern = g_strconcat(basename, ".%", NULL);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select group_id from images where film_id = ?1 and filename like ?2 and id != ?3", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, sql_pattern, -1, SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id);
  int group_id;
  if(sqlite3_step(stmt) == SQLITE_ROW) group_id = sqlite3_column_int(stmt, 0);
  else                                 group_id = id;
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update images set group_id = ?1 where id = ?2", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, group_id);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  // printf("[image_import] importing `%s' to img id %d\n", imgfname, id);

  // lock as shortly as possible:
  const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id);
  dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg);
  img->group_id = group_id;

  // read dttags and exif for database queries!
  (void) dt_exif_read(img, filename);
  char dtfilename[DT_MAX_PATH_LEN];
  g_strlcpy(dtfilename, filename, DT_MAX_PATH_LEN);
  dt_image_path_append_version(id, dtfilename, DT_MAX_PATH_LEN);
  char *c = dtfilename + strlen(dtfilename);
  sprintf(c, ".xmp");
  (void)dt_exif_xmp_read(img, dtfilename, 0);

  // write through to db, but not to xmp.
  dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED);
  dt_image_cache_read_release(darktable.image_cache, img);

  // add a tag with the file extension
  guint tagid = 0;
  char tagname[512];
  snprintf(tagname, 512, "darktable|format|%s", ext);
  g_free(ext);
  dt_tag_new(tagname, &tagid);
  dt_tag_attach(tagid,id);

  // Search for sidecar files and import them if found.
  glob_t *globbuf = g_malloc(sizeof(glob_t));

  // Add version wildcard
  gchar *fname = g_strdup(filename);
  gchar pattern[DT_MAX_PATH_LEN];
  g_snprintf(pattern, DT_MAX_PATH_LEN, "%s", filename);
  char *c1 = pattern + strlen(pattern);
  while(*c1 != '.' && c1 > pattern) c1--;
  snprintf(c1, pattern + DT_MAX_PATH_LEN - c1, "_*");
  char *c2 = fname + strlen(fname);
  while(*c2 != '.' && c2 > fname) c2--;
  snprintf(c1+2, pattern + DT_MAX_PATH_LEN - c1 - 2, "%s.xmp", c2);

  if (!glob(pattern, 0, NULL, globbuf))
  {
    for (int i=0; i < globbuf->gl_pathc; i++)
    {
      int newid = -1;
      newid = dt_image_duplicate(id);

      const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, newid);
      dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg);
      (void)dt_exif_xmp_read(img, globbuf->gl_pathv[i], 0);
      dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED);
      dt_image_cache_read_release(darktable.image_cache, img);
    }
    globfree(globbuf);
  }

  g_free(imgfname);
  g_free(fname);
  g_free(basename);
  g_free(sql_pattern);
  g_free(globbuf);

  dt_control_signal_raise(darktable.signals,DT_SIGNAL_IMAGE_IMPORT,id);
  return id;
}
Пример #4
0
// open a raw file, libraw path:
dt_imageio_retval_t
dt_imageio_open_raw(
    dt_image_t  *img,
    const char  *filename,
    dt_mipmap_cache_allocator_t a)
{
  if(!img->exif_inited)
    (void) dt_exif_read(img, filename);
  int ret;
  libraw_data_t *raw = libraw_init(0);
  libraw_processed_image_t *image = NULL;
  raw->params.half_size = 0; /* dcraw -h */
  raw->params.use_camera_wb = 0;
  raw->params.use_auto_wb = 0;
  raw->params.med_passes = 0;//img->raw_params.med_passes;
  raw->params.no_auto_bright = 1;
  // raw->params.filtering_mode |= LIBRAW_FILTERING_NOBLACKS;
  // raw->params.document_mode = 2; // no color scaling, no black, no max, no wb..?
  raw->params.document_mode = 2; // color scaling (clip,wb,max) and black point, but no demosaic
  raw->params.output_color = 0;
  raw->params.output_bps = 16;
  raw->params.user_flip = -1; // -1 means: use orientation from raw
  raw->params.gamm[0] = 1.0;
  raw->params.gamm[1] = 1.0;
  // raw->params.user_qual = img->raw_params.demosaic_method; // 3: AHD, 2: PPG, 1: VNG
  raw->params.user_qual = 0;
  // raw->params.four_color_rgb = img->raw_params.four_color_rgb;
  raw->params.four_color_rgb = 0;
  raw->params.use_camera_matrix = 0;
  raw->params.green_matching = 0;
  raw->params.highlight = 1;
  raw->params.threshold = 0;
  // raw->params.auto_bright_thr = img->raw_auto_bright_threshold;

  // raw->params.amaze_ca_refine = 0;
  raw->params.fbdd_noiserd    = 0;

  ret = libraw_open_file(raw, filename);
  HANDLE_ERRORS(ret, 0);
  raw->params.user_qual = 0;
  raw->params.half_size = 0;

  ret = libraw_unpack(raw);
  // img->black   = raw->color.black/65535.0;
  // img->maximum = raw->color.maximum/65535.0;
  img->bpp = sizeof(uint16_t);
  // printf("black, max: %d %d %f %f\n", raw->color.black, raw->color.maximum, img->black, img->maximum);
  HANDLE_ERRORS(ret, 1);
  ret = libraw_dcraw_process(raw);
  // ret = libraw_dcraw_document_mode_processing(raw);
  HANDLE_ERRORS(ret, 1);
  image = libraw_dcraw_make_mem_image(raw, &ret);
  HANDLE_ERRORS(ret, 1);

  // fallback for broken exif read in case of phase one H25
  if(!strncmp(img->exif_maker, "Phase One", 9))
    img->orientation = raw->sizes.flip;
  // filters seem only ever to take a useful value after unpack/process
  img->filters = raw->idata.filters;
  img->width  = (img->orientation & 4) ? raw->sizes.height : raw->sizes.width;
  img->height = (img->orientation & 4) ? raw->sizes.width  : raw->sizes.height;
  img->exif_iso = raw->other.iso_speed;
  img->exif_exposure = raw->other.shutter;
  img->exif_aperture = raw->other.aperture;
  img->exif_focal_length = raw->other.focal_len;
  g_strlcpy(img->exif_maker, raw->idata.make, sizeof(img->exif_maker));
  img->exif_maker[sizeof(img->exif_maker) - 1] = 0x0;
  g_strlcpy(img->exif_model, raw->idata.model, sizeof(img->exif_model));
  img->exif_model[sizeof(img->exif_model) - 1] = 0x0;
  dt_gettime_t(img->exif_datetime_taken, raw->other.timestamp);

  void *buf = dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a);
  if(!buf)
  {
    libraw_recycle(raw);
    libraw_close(raw);
    free(image);
    return DT_IMAGEIO_CACHE_FULL;
  }
#ifdef _OPENMP
  #pragma omp parallel for schedule(static) default(none) shared(img, image, raw, buf)
#endif
  for(int k=0; k<img->width*img->height; k++)
    ((uint16_t *)buf)[k] = CLAMPS((((uint16_t *)image->data)[k] - raw->color.black)*65535.0f/(float)(raw->color.maximum - raw->color.black), 0, 0xffff);
  // clean up raw stuff.
  libraw_recycle(raw);
  libraw_close(raw);
  free(image);
  raw = NULL;
  image = NULL;

  img->flags &= ~DT_IMAGE_LDR;
  img->flags &= ~DT_IMAGE_HDR;
  img->flags |= DT_IMAGE_RAW;
  return DT_IMAGEIO_OK;
}
Пример #5
0
dt_imageio_retval_t dt_imageio_open_png(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
{
  const char *ext = filename + strlen(filename);
  while(*ext != '.' && ext > filename) ext--;
  if(strncmp(ext, ".png", 4) && strncmp(ext, ".PNG", 4)) return DT_IMAGEIO_FILE_CORRUPTED;
  if(!img->exif_inited) (void)dt_exif_read(img, filename);

  dt_imageio_png_t image;
  uint8_t *buf = NULL;
  uint32_t width, height;
  uint16_t bpp;


  if(read_header(filename, &image) != 0) return DT_IMAGEIO_FILE_CORRUPTED;

  width = img->width = image.width;
  height = img->height = image.height;
  bpp = image.bit_depth;

  img->bpp = 4 * sizeof(float);

  float *mipbuf = (float *)dt_mipmap_cache_alloc(mbuf, img);
  if(!mipbuf)
  {
    fclose(image.f);
    png_destroy_read_struct(&image.png_ptr, &image.info_ptr, NULL);
    fprintf(stderr, "[png_open] could not alloc full buffer for image `%s'\n", img->filename);
    return DT_IMAGEIO_CACHE_FULL;
  }

  buf = dt_alloc_align(16, (size_t)width * height * 3 * (bpp < 16 ? 1 : 2));
  if(!buf)
  {
    fclose(image.f);
    png_destroy_read_struct(&image.png_ptr, &image.info_ptr, NULL);
    fprintf(stderr, "[png_open] could not alloc intermediate buffer for image `%s'\n", img->filename);
    return DT_IMAGEIO_CACHE_FULL;
  }

  if(read_image(&image, (void *)buf) != 0)
  {
    dt_free_align(buf);
    fprintf(stderr, "[png_open] could not read image `%s'\n", img->filename);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  for(size_t j = 0; j < height; j++)
  {
    if(bpp < 16)
      for(size_t i = 0; i < width; i++)
        for(int k = 0; k < 3; k++)
          mipbuf[4 * (j * width + i) + k] = buf[3 * (j * width + i) + k] * (1.0f / 255.0f);
    else
      for(size_t i = 0; i < width; i++)
        for(int k = 0; k < 3; k++)
          mipbuf[4 * (j * width + i) + k] = (256.0f * buf[2 * (3 * (j * width + i) + k)]
                                             + buf[2 * (3 * (j * width + i) + k) + 1]) * (1.0f / 65535.0f);
  }

  dt_free_align(buf);
  return DT_IMAGEIO_OK;
}
Пример #6
0
dt_imageio_retval_t
dt_imageio_open_gm(
  dt_image_t *img,
  const char *filename,
  dt_mipmap_cache_allocator_t a)
{
  int err = DT_IMAGEIO_FILE_CORRUPTED;
  float *buf = NULL;
  ExceptionInfo exception;
  Image *image = NULL;
  ImageInfo *image_info = NULL;
  uint32_t width, height, orientation;

  if(!_supported_image(filename)) return DT_IMAGEIO_FILE_CORRUPTED;

  if(!img->exif_inited)
    (void) dt_exif_read(img, filename);

  GetExceptionInfo(&exception);
  image_info=CloneImageInfo((ImageInfo *) NULL);

  g_strlcpy(image_info->filename,filename,sizeof(image_info->filename));

  image=ReadImage(image_info,&exception);
  if (exception.severity != UndefinedException)
    CatchException(&exception);
  if (!image)
  {
    fprintf(stderr, "[GraphicsMagick_open] image `%s' not found\n", img->filename);
    err = DT_IMAGEIO_FILE_NOT_FOUND;
    goto error;
  }

  width = image->columns;
  height = image->rows;
  orientation = image->orientation;

  if(orientation & 4)
  {
    img->width = height;
    img->height = width;
  }
  else
  {
    img->width = width;
    img->height = height;
  }

  img->bpp = 4*sizeof(float);

  float *mipbuf = (float *)dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a);
  if(!mipbuf)
  {
    fprintf(stderr, "[GraphicsMagick_open] could not alloc full buffer for image `%s'\n", img->filename);
    err = DT_IMAGEIO_CACHE_FULL;
    goto error;
  }

  buf = (float *)dt_alloc_align(16, width*img->bpp);
  if(!buf) goto error;

  const int ht2 = orientation & 4 ? img->width  : img->height; // pretend unrotated, rotate in write_pos
  const int wd2 = orientation & 4 ? img->height : img->width;

  for (uint32_t row = 0; row < height; row++)
  {
    int ret = DispatchImage(image, 0, row, width, 1, "RGBP", FloatPixel, (void *)buf, &exception);
    if (exception.severity != UndefinedException)
      CatchException(&exception);
    if(ret != MagickPass)
    {
      fprintf(stderr, "[GraphicsMagick_open] error reading image `%s'\n", img->filename);
      err = DT_IMAGEIO_FILE_CORRUPTED;
      goto error;
    }

    for(uint32_t i=0; i<width; i++)
      for(int k=0; k<4; k++) mipbuf[4*dt_imageio_write_pos(i, row, wd2, ht2, wd2, ht2, orientation) + k] = buf[4*i + k];
  }

  if(buf) dt_free_align(buf);
  if(image) DestroyImage(image);
  if(image_info) DestroyImageInfo(image_info);
  DestroyExceptionInfo(&exception);

  img->filters = 0;
  img->flags &= ~DT_IMAGE_RAW;
  img->flags &= ~DT_IMAGE_HDR;
  img->flags |= DT_IMAGE_LDR;

  return DT_IMAGEIO_OK;

error:
  if(buf) dt_free_align(buf);
  if(image) DestroyImage(image);
  if(image_info) DestroyImageInfo(image_info);
  DestroyExceptionInfo(&exception);
  return err;
}
Пример #7
0
// maybe this should be (partly) in common/imageio.[c|h]?
static void _lib_import_update_preview(GtkFileChooser *file_chooser, gpointer data)
{
  GtkWidget *preview;
  char *filename;
  GdkPixbuf *pixbuf = NULL;
  gboolean have_preview = FALSE, no_preview_fallback = FALSE;

  preview = GTK_WIDGET(data);
  filename = gtk_file_chooser_get_preview_filename(file_chooser);

  if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
  {
    no_preview_fallback = TRUE;
  }
  else
  {
    // don't create dng thumbnails to avoid crashes in libtiff when these are hdr:
    char *c = filename + strlen(filename);
    while(c > filename && *c != '.') c--;
    if(!strcasecmp(c, ".dng")) no_preview_fallback = TRUE;
  }

  // unfortunately we can not use following, because frequently it uses wrong orientation
  // pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL);

  have_preview = (pixbuf != NULL);
  if(!have_preview && !no_preview_fallback)
  {
    uint8_t *buffer = NULL;
    size_t size;
    char *mime_type = NULL;
    if(!dt_exif_get_thumbnail(filename, &buffer, &size, &mime_type))
    {
      // Scale the image to the correct size
      GdkPixbuf *tmp;
      GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
      if (!gdk_pixbuf_loader_write(loader, buffer, size, NULL)) goto cleanup;
      if (!(tmp = gdk_pixbuf_loader_get_pixbuf(loader))) goto cleanup;
      float ratio = 1.0 * gdk_pixbuf_get_height(tmp) / gdk_pixbuf_get_width(tmp);
      int width = 128, height = 128 * ratio;
      pixbuf = gdk_pixbuf_scale_simple(tmp, width, height, GDK_INTERP_BILINEAR);

      have_preview = TRUE;

    cleanup:
      gdk_pixbuf_loader_close(loader, NULL);
      free(mime_type);
      free(buffer);
      g_object_unref(loader); // This should clean up tmp as well
    }
  }
  if(have_preview && !no_preview_fallback)
  {
    // get image orientation
    dt_image_t img = { 0 };
    (void)dt_exif_read(&img, filename);

    // Rotate the image to the correct orientation
    GdkPixbuf *tmp = pixbuf;

    if(img.orientation == ORIENTATION_ROTATE_CCW_90_DEG)
    {
      tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
    }
    else if(img.orientation == ORIENTATION_ROTATE_CW_90_DEG)
    {
      tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
    }
    else if(img.orientation == ORIENTATION_ROTATE_180_DEG)
    {
      tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
    }

    if(pixbuf != tmp)
    {
      g_object_unref(pixbuf);
      pixbuf = tmp;
    }
  }
  if(no_preview_fallback || !have_preview)
  {
    guint8 *image_buffer = NULL;

    /* load the dt logo as a brackground */
    char filename[PATH_MAX] = { 0 };
    char datadir[PATH_MAX] = { 0 };
    char *logo;
    dt_logo_season_t season = get_logo_season();
    if(season != DT_LOGO_SEASON_NONE)
      logo = g_strdup_printf("%%s/pixmaps/idbutton-%d.svg", (int)season);
    else
      logo = g_strdup("%s/pixmaps/idbutton.svg");

    dt_loc_get_datadir(datadir, sizeof(datadir));
    snprintf(filename, sizeof(filename), logo, datadir);
    g_free(logo);
    RsvgHandle *svg = rsvg_handle_new_from_file(filename, NULL);
    if(svg)
    {
      cairo_surface_t *surface;
      cairo_t *cr;

      RsvgDimensionData dimension;
      rsvg_handle_get_dimensions(svg, &dimension);

      float svg_size = MAX(dimension.width, dimension.height);
      float final_size = 128;
      float factor = final_size / svg_size;
      float final_width = dimension.width * factor * darktable.gui->ppd,
            final_height = dimension.height * factor * darktable.gui->ppd;
      int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, final_width);

      image_buffer = (guint8 *)calloc(stride * final_height, sizeof(guint8));
      surface = dt_cairo_image_surface_create_for_data(image_buffer, CAIRO_FORMAT_ARGB32, final_width,
                                                       final_height, stride);
      if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
      {
        free(image_buffer);
        image_buffer = NULL;
      }
      else
      {
        cr = cairo_create(surface);
        cairo_scale(cr, factor, factor);
        rsvg_handle_render_cairo(svg, cr);
        cairo_surface_flush(surface);
        pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, final_width / darktable.gui->ppd,
                                             final_height / darktable.gui->ppd);
      }
      g_object_unref(svg);
    }

    have_preview = TRUE;
  }
  if(have_preview) gtk_image_set_from_pixbuf(GTK_IMAGE(preview), pixbuf);
  if(pixbuf) g_object_unref(pixbuf);
  g_free(filename);

  gtk_file_chooser_set_preview_widget_active(file_chooser, have_preview);
}
Пример #8
0
dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, dt_mipmap_cache_allocator_t a)
{
  opj_dparameters_t parameters;   /* decompression parameters */
  opj_event_mgr_t event_mgr;      /* event manager */
  opj_image_t *image = NULL;
  FILE *fsrc = NULL;
  unsigned char *src = NULL;
  int file_length;
  opj_dinfo_t* dinfo = NULL;      /* handle to a decompressor */
  opj_cio_t *cio = NULL;
  OPJ_CODEC_FORMAT codec;
  int ret = DT_IMAGEIO_FILE_CORRUPTED;

  int file_format = get_file_format(filename);
  if(file_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;

  if(!img->exif_inited)
    (void) dt_exif_read(img, filename);

  /* read the input file and put it in memory */
  /* ---------------------------------------- */
  fsrc = fopen(filename, "rb");
  if(!fsrc)
  {
    fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename);
    return DT_IMAGEIO_FILE_NOT_FOUND;
  }
  fseek(fsrc, 0, SEEK_END);
  file_length = ftell(fsrc);
  fseek(fsrc, 0, SEEK_SET);
  src = (unsigned char *) malloc(file_length);
  if(fread(src, 1, file_length, fsrc) != (size_t)file_length)
  {
    free(src);
    fclose(fsrc);
    fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n");
    return DT_IMAGEIO_FILE_NOT_FOUND;
  }
  fclose(fsrc);

  if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0)
  {
    file_format = JP2_CFMT; // just in case someone used the wrong extension
  }
  else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0)
  {
    file_format = J2K_CFMT; // just in case someone used the wrong extension
  }
  else // this will also reject jpt files.
  {
    free(src);
    fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  /* configure the event callbacks (not required) */
  memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
  event_mgr.error_handler = error_callback;
//   event_mgr.warning_handler = warning_callback;
//   event_mgr.info_handler = info_callback;

  /* set decoding parameters to default values */
  opj_set_default_decoder_parameters(&parameters);

  /* decode the code-stream */
  /* ---------------------- */
  if(file_format == J2K_CFMT)        /* JPEG-2000 codestream */
    codec = CODEC_J2K;
  else if(file_format == JP2_CFMT)   /* JPEG 2000 compressed image data */
    codec = CODEC_JP2;
  else if(file_format == JPT_CFMT)   /* JPEG 2000, JPIP */
    codec = CODEC_JPT;
  else
  {
    free(src);
    return DT_IMAGEIO_FILE_CORRUPTED; // can't happen
  }

  /* get a decoder handle */
  dinfo = opj_create_decompress(codec);

  /* catch events using our callbacks and give a local context */
  opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);

  /* setup the decoder decoding parameters using user parameters */
  opj_setup_decoder(dinfo, &parameters);

  /* open a byte stream */
  cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);

  /* decode the stream and fill the image structure */
  image = opj_decode(dinfo, cio);

  /* close the byte stream */
  opj_cio_close(cio);

  /* free the memory containing the code-stream */
  free(src);

  if(!image)
  {
    fprintf(stderr, "[j2k_open] Error: failed to decode image `%s'\n", filename);
    ret = DT_IMAGEIO_FILE_CORRUPTED;
    goto end_of_the_world;
  }

  if(image->color_space == CLRSPC_SYCC)
  {
    color_sycc_to_rgb(image);
  }

  //FIXME: openjpeg didn't have support for icc profiles before version 1.5
  // this needs some #ifdef magic and proper implementation
#ifdef HAVE_OPENJPEG_ICC
  if(image->icc_profile_buf)
  {
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
    color_apply_icc_profile(image);
#endif

    free(image->icc_profile_buf);
    image->icc_profile_buf = NULL;
    image->icc_profile_len = 0;
  }
#endif

  /* create output image */
  /* ------------------- */
  long signed_offsets[4] = {0, 0, 0, 0};
  int float_divs[4] = {1, 1, 1, 1};

  // some sanity checks
  if(image->numcomps == 0 || image->x1 == 0  || image->y1 == 0)
  {
    fprintf(stderr, "[j2k_open] Error: invalid raw image parameters in `%s'\n", filename);
    ret = DT_IMAGEIO_FILE_CORRUPTED;
    goto end_of_the_world;
  }

  for(int i = 0; i < image->numcomps; i++)
  {
    if(image->comps[i].w != image->x1 || image->comps[i].h != image->y1)
    {
      fprintf(stderr, "[j2k_open] Error: some component has different size in `%s'\n", filename);
      ret = DT_IMAGEIO_FILE_CORRUPTED;
      goto end_of_the_world;
    }
    if(image->comps[i].prec > 16)
    {
      fprintf(stderr,"[j2k_open] Error: precision %d is larger than 16 in `%s'\n", image->comps[1].prec, filename);
      ret = DT_IMAGEIO_FILE_CORRUPTED;
      goto end_of_the_world;
    }
  }

  img->width = image->x1;
  img->height = image->y1;
  img->bpp = 4*sizeof(float);

  float *buf = (float *)dt_mipmap_cache_alloc(img, DT_MIPMAP_FULL, a);
  if(!buf)
  {
    ret = DT_IMAGEIO_CACHE_FULL;
    goto end_of_the_world;
  }

  int i = image->numcomps;
  if(i > 4) i = 4;

  while(i)
  {
    i--;

    if(image->comps[i].sgnd)
      signed_offsets[i] =  1 << (image->comps[i].prec - 1);

    float_divs[i] = (1 << image->comps[i].prec) - 1;
  }

  // numcomps == 1 : grey  -> r = grey, g = grey, b = grey
  // numcomps == 2 : grey, alpha -> r = grey, g = grey, b = grey. put alpha into the mix?
  // numcomps == 3 : rgb -> rgb
  // numcomps == 4 : rgb, alpha -> rgb. put alpha into the mix?

  // first try: ignore alpha.
  if(image->numcomps < 3) // 1, 2 => grayscale
  {
    for(int i = 0; i < img->width * img->height; i++)
      buf[i*4 + 0] = buf[i*4 + 1] = buf[i*4 + 2] = (float)(image->comps[0].data[i] + signed_offsets[0]) / float_divs[0];
  }
  else // 3, 4 => rgb
  {
    for(int i = 0; i < img->width * img->height; i++)
      for(int k = 0; k < 3; k++) buf[i*4 + k] = (float)(image->comps[k].data[i] + signed_offsets[k]) / float_divs[k];
  }

  ret = DT_IMAGEIO_OK;

end_of_the_world:
  /* free remaining structures */
  if(dinfo)
    opj_destroy_decompress(dinfo);

  /* free image data structure */
  opj_image_destroy(image);

  return ret;
}
Пример #9
0
dt_imageio_retval_t dt_imageio_open_tiff(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
{
  // doing this once would be enough, but our imageio reading code is
  // compiled into dt's core and doesn't have an init routine.
  TIFFSetWarningHandler(_warning_handler);
  TIFFSetErrorHandler(_error_handler);

  const char *ext = filename + strlen(filename);
  while(*ext != '.' && ext > filename) ext--;
  if(strncmp(ext, ".tif", 4) && strncmp(ext, ".TIF", 4) && strncmp(ext, ".tiff", 5)
     && strncmp(ext, ".TIFF", 5))
    return DT_IMAGEIO_FILE_CORRUPTED;
  if(!img->exif_inited) (void)dt_exif_read(img, filename);

  tiff_t t;
  uint16_t config;

  t.image = img;

  if((t.tiff = TIFFOpen(filename, "rb")) == NULL) return DT_IMAGEIO_FILE_CORRUPTED;

  TIFFGetField(t.tiff, TIFFTAG_IMAGEWIDTH, &t.width);
  TIFFGetField(t.tiff, TIFFTAG_IMAGELENGTH, &t.height);
  TIFFGetField(t.tiff, TIFFTAG_BITSPERSAMPLE, &t.bpp);
  TIFFGetField(t.tiff, TIFFTAG_SAMPLESPERPIXEL, &t.spp);
  TIFFGetFieldDefaulted(t.tiff, TIFFTAG_SAMPLEFORMAT, &t.sampleformat);
  TIFFGetField(t.tiff, TIFFTAG_PLANARCONFIG, &config);

  if(TIFFRasterScanlineSize(t.tiff) != TIFFScanlineSize(t.tiff)) return DT_IMAGEIO_FILE_CORRUPTED;

  t.scanlinesize = TIFFScanlineSize(t.tiff);

  dt_print(DT_DEBUG_CAMERA_SUPPORT, "[tiff_open] %dx%d %dbpp, %d samples per pixel.\n", t.width, t.height, t.bpp, t.spp);

  // we only support 8/16 and 32 bits per pixel formats.
  if(t.bpp != 8 && t.bpp != 16 && t.bpp != 32)
  {
    TIFFClose(t.tiff);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  /* we only support 1,3 or 4 samples per pixel */
  if(t.spp != 1 && t.spp != 3 && t.spp != 4)
  {
    TIFFClose(t.tiff);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  /* initialize cached image buffer */
  t.image->width = t.width;
  t.image->height = t.height;

  t.image->buf_dsc.channels = 4;
  t.image->buf_dsc.datatype = TYPE_FLOAT;

  t.mipbuf = (float *)dt_mipmap_cache_alloc(mbuf, t.image);
  if(!t.mipbuf)
  {
    fprintf(stderr, "[tiff_open] error: could not alloc full buffer for image `%s'\n", t.image->filename);
    TIFFClose(t.tiff);
    return DT_IMAGEIO_CACHE_FULL;
  }

  /* dont depend on planar config if spp == 1 */
  if(t.spp > 1 && config != PLANARCONFIG_CONTIG)
  {
    fprintf(stderr, "[tiff_open] error: planar config other than contig is not supported.\n");
    TIFFClose(t.tiff);
    return DT_IMAGEIO_FILE_CORRUPTED;
  }

  if((t.buf = _TIFFmalloc(t.scanlinesize)) == NULL)
  {
    TIFFClose(t.tiff);
    return DT_IMAGEIO_CACHE_FULL;
  }

  int ok = 1;

  if(t.bpp == 8 && t.sampleformat == SAMPLEFORMAT_UINT && config == PLANARCONFIG_CONTIG)
    ok = _read_planar_8(&t);
  else if(t.bpp == 16 && t.sampleformat == SAMPLEFORMAT_UINT && config == PLANARCONFIG_CONTIG)
    ok = _read_planar_16(&t);
  else if(t.bpp == 32 && t.sampleformat == SAMPLEFORMAT_IEEEFP && config == PLANARCONFIG_CONTIG)
    ok = _read_planar_f(&t);
  else
  {
    fprintf(stderr, "[tiff_open] error: Not a supported tiff image format.");
    ok = 0;
  }

  _TIFFfree(t.buf);
  TIFFClose(t.tiff);

  return (ok == 1 ? DT_IMAGEIO_OK : DT_IMAGEIO_FILE_CORRUPTED);
}