Пример #1
0
static int
_write_buffer(const uint32_t key, const void *data, void *user_data)
{
  if(!data) return 1;
  struct dt_mipmap_buffer_dsc* dsc = (struct dt_mipmap_buffer_dsc*)data;
  // too small to write. no error, but don't write.
  if(dsc->width <= 8 && dsc->height <= 8) return 0;

  _iterate_data_t *d = (_iterate_data_t *)user_data;
  int written = fwrite(&(d->mip), sizeof(dt_mipmap_size_t), 1, d->f);
  if(written != 1) return 1;
  written = fwrite(&key, sizeof(uint32_t), 1, d->f);
  if(written != 1) return 1;

  if(d->compression_type)
  {
    // write buffer size, wd, ht and the full blob, as it is in memory.
    const int32_t length = compressed_buffer_size(d->compression_type, dsc->width, dsc->height);
    written = fwrite(&length, sizeof(int32_t), 1, d->f);
    if(written != 1) return 1;
    written = fwrite(&dsc->width, sizeof(int32_t), 1, d->f);
    if(written != 1) return 1;
    written = fwrite(&dsc->height, sizeof(int32_t), 1, d->f);
    if(written != 1) return 1;
    written = fwrite(dsc+1, sizeof(uint8_t), length, d->f);
    if(written != length) return 1;
  }
  else
  {
    dt_mipmap_buffer_t buf;
    buf.width  = dsc->width;
    buf.height = dsc->height;
    buf.imgid  = get_imgid(key);
    buf.size   = get_size(key);
    // skip to next 8-byte alignment, for sse buffers.
    buf.buf    = (uint8_t *)(dsc+1);

    const int cache_quality = dt_conf_get_int("database_cache_quality");
    const int32_t length = dt_imageio_jpeg_compress(buf.buf, d->blob, buf.width, buf.height, MIN(100, MAX(10, cache_quality)));
    written = fwrite(&length, sizeof(int32_t), 1, d->f);
    if(written != 1) return 1;
    written = fwrite(d->blob, sizeof(uint8_t), length, d->f);
    if(written != length) return 1;
  }

  return 0;
}
Пример #2
0
static void generate_thumbnail_cache()
{
  const int max_mip = DT_MIPMAP_2;
  fprintf(stderr, _("creating cache directories\n"));
  char filename[PATH_MAX] = {0};
  for(int k=DT_MIPMAP_0;k<=max_mip;k++)
  {
    snprintf(filename, sizeof(filename), "%s.d/%d", darktable.mipmap_cache->cachedir, k);
    fprintf(stderr, _("creating cache directory '%s'\n"), filename);
    int mkd = g_mkdir_with_parents(filename, 0750);
    if(mkd)
    {
      fprintf(stderr, _("could not create directory '%s'!\n"), filename);
      return;
    }
  }
  // some progress counter
  sqlite3_stmt *stmt;
  uint64_t image_count = 0, counter = 0;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(id) from images", -1, &stmt, 0);
  if(sqlite3_step(stmt) == SQLITE_ROW)
    image_count = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);

  // go through all images:
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images", -1, &stmt, 0);
  // could only alloc max_mip-1, but would need to detect the special case that max==0.
  const size_t bufsize = (size_t)4 * darktable.mipmap_cache->max_width[max_mip]
                         * darktable.mipmap_cache->max_height[max_mip];
  uint8_t *tmp = (uint8_t *)dt_alloc_align(16, bufsize);
  if(!tmp)
  {
    fprintf(stderr, "couldn't allocate temporary memory!\n");
    sqlite3_finalize(stmt);
    return;
  }
  const int cache_quality = MIN(100, MAX(10, dt_conf_get_int("database_cache_quality")));
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    const int32_t imgid = sqlite3_column_int(stmt, 0);
    // check whether all of these files are already there
    int all_exist = 1;
    for(int k=max_mip;k>=DT_MIPMAP_0;k--)
    {
      snprintf(filename, sizeof(filename), "%s.d/%d/%d.jpg", darktable.mipmap_cache->cachedir, k, imgid);
      all_exist &= !access(filename, R_OK); 
    }
    if(all_exist) goto next;
    dt_mipmap_buffer_t buf;
    // get largest thumbnail for this image
    // this one will take care of itself, we'll just write out the lower thumbs manually:
    dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, max_mip, DT_MIPMAP_BLOCKING, 'r');
    if(buf.width > 8 && buf.height > 8) // don't create for skulls
    for(int k=max_mip-1;k>=DT_MIPMAP_0;k--)
    {
      uint32_t width, height;
      const int wd = darktable.mipmap_cache->max_width[k];
      const int ht = darktable.mipmap_cache->max_height[k];
      // use exactly the same mechanism as the cache internally to rescale the thumbnail:
      dt_iop_flip_and_zoom_8(buf.buf, buf.width, buf.height, tmp, wd, ht, 0, &width, &height);

      snprintf(filename, sizeof(filename), "%s.d/%d/%d.jpg", darktable.mipmap_cache->cachedir, k, imgid);
      FILE *f = fopen(filename, "wb");
      if(f)
      {
        // allocate temp memory:
        uint8_t *blob = (uint8_t *)malloc(bufsize);
        if(!blob) goto write_error;
        const int32_t length
          = dt_imageio_jpeg_compress(tmp, blob, width, height, cache_quality);
        assert(length <= bufsize);
        int written = fwrite(blob, sizeof(uint8_t), length, f);
        if(written != length)
        {
write_error:
          unlink(filename);
        }
        free(blob);
        fclose(f);
      }
    }
    dt_mipmap_cache_release(darktable.mipmap_cache, &buf);
next:
    counter ++;
    fprintf(stderr, "\rimage %lu/%lu (%.02f%%)            ", counter, image_count, 100.0*counter/(float)image_count);
  }
  dt_free_align(tmp);
  sqlite3_finalize(stmt);
  fprintf(stderr, "done                     \n");
}