// load a full-res thumbnail: int dt_imageio_large_thumbnail(const char *filename, uint8_t **buffer, int32_t *width, int32_t *height, int32_t *orientation) { int ret = 0; int res = 1; // raw image thumbnail libraw_data_t *raw = libraw_init(0); libraw_processed_image_t *image = NULL; ret = libraw_open_file(raw, filename); if(ret) goto libraw_fail; ret = libraw_unpack_thumb(raw); if(ret) goto libraw_fail; ret = libraw_adjust_sizes_info_only(raw); if(ret) goto libraw_fail; image = libraw_dcraw_make_mem_thumb(raw, &ret); if(!image || ret) goto libraw_fail; *orientation = raw->sizes.flip; if(image->type == LIBRAW_IMAGE_JPEG) { dt_imageio_jpeg_t jpg; if(dt_imageio_jpeg_decompress_header(image->data, image->data_size, &jpg)) goto libraw_fail; *buffer = (uint8_t *)malloc((size_t)sizeof(uint8_t)*jpg.width*jpg.height*4); if(!*buffer) goto libraw_fail; *width = jpg.width; *height = jpg.height; if(dt_imageio_jpeg_decompress(&jpg, *buffer)) { free(*buffer); *buffer = 0; goto libraw_fail; } res = 0; } // clean up raw stuff. libraw_recycle(raw); libraw_close(raw); free(image); if(0) { libraw_fail: // fprintf(stderr,"[imageio] %s: %s\n", filename, libraw_strerror(ret)); libraw_close(raw); res = 1; } return res; }
// thread routine int process_files(void *q) { int ret; int count = 0; char outfn[1024], *fn; libraw_data_t *iprc = libraw_init(0); if (!iprc) { fprintf(stderr, "Cannot create libraw handle\n"); return -1; } while ((fn = get_next_file())) { iprc->params.half_size = 1; /* dcraw -h */ iprc->params.use_camera_wb = use_camera_wb; iprc->params.use_auto_wb = use_auto_wb; iprc->params.output_tiff = tiff_mode; ret = libraw_open_file(iprc, fn); if (verbose) fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model); HANDLE_ERRORS(ret); ret = libraw_unpack(iprc); HANDLE_ERRORS(ret); ret = libraw_dcraw_process(iprc); HANDLE_ERRORS(ret); snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tif" : "ppm"); if (verbose) fprintf(stderr, "Writing file %s\n", outfn); ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn); HANDLE_ERRORS(ret); count++; } libraw_close(iprc); printf("Processed %d files\n", count); return 0; }
int main(int ac, char *av[]) { if (ac != 3) { fprintf(stderr, "Usage: %s <input_file> <output_file>\n %d", av[0],ac); exit(1); } libraw_data_t *iprc = libraw_init(0); if (!iprc) { fprintf(stderr, "Cannot create libraw handle\n"); exit(1); } iprc->params.half_size = 1; /* dcraw -h */ iprc->params.use_camera_wb = 1; /* dcraw -w */ char outfn[1024]; int ret = libraw_open_file(iprc, av[1]); HANDLE_ERROR(ret); printf("Processing %s (%s %s)\n", av[1], iprc->idata.make, iprc->idata.model); ret = libraw_unpack(iprc); HANDLE_ERROR(ret); ret = libraw_dcraw_process(iprc); HANDLE_ERROR(ret); strcpy(outfn, av[2]); printf("Writing to %s\n", outfn); ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn); HANDLE_ERROR(ret); libraw_close(iprc); return 0; }
int main(int ac, char *av[]) { int i; libraw_data_t *iprc = libraw_init(0); if(!iprc) { fprintf(stderr,"Cannot create libraw handle\n"); exit(1); } iprc->params.half_size = 1; /* dcraw -h */ for (i=1;i<ac;i++) { char outfn[1024]; int ret = libraw_open_file(iprc,av[i]); HANDLE_ALL_ERRORS(ret); printf("Processing %s (%s %s)\n",av[i],iprc->idata.make,iprc->idata.model); ret = libraw_unpack(iprc); HANDLE_ALL_ERRORS(ret); ret = libraw_dcraw_process(iprc); HANDLE_ALL_ERRORS(ret); strcpy(outfn,av[i]); strcat(outfn,".ppm"); printf("Writing to %s\n",outfn); ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn); HANDLE_FATAL_ERROR(ret); } libraw_close(iprc); return 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; }
void reload_defaults(dt_iop_module_t *module) { // raw images need wb (to convert from uint16_t to float): if(dt_image_is_raw(&module->dev->image_storage)) { module->default_enabled = 1; module->hide_enable_button = 1; } else module->default_enabled = 0; dt_iop_temperature_params_t tmp = (dt_iop_temperature_params_t) { 5000.0, {1.0, 1.0, 1.0} }; // get white balance coefficients, as shot char filename[DT_MAX_PATH_LEN]; int ret=0; /* check if file is raw / hdr */ if(dt_image_is_raw(&module->dev->image_storage)) { gboolean from_cache = TRUE; dt_image_full_path(module->dev->image_storage.id, filename, DT_MAX_PATH_LEN, &from_cache); libraw_data_t *raw = libraw_init(0); ret = libraw_open_file(raw, filename); if(!ret) { module->default_enabled = 1; for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.cam_mul[k]; if(tmp.coeffs[0] <= 0.0) { for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.pre_mul[k]; } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // could not get useful info, try presets: char makermodel[1024]; char *model = makermodel; dt_colorspaces_get_makermodel_split(makermodel, 1024, &model, module->dev->image_storage.exif_maker, module->dev->image_storage.exif_model); for(int i=0; i<wb_preset_count; i++) { if(!strcmp(wb_preset[i].make, makermodel) && !strcmp(wb_preset[i].model, model)) { // just take the first preset we find for this camera for(int k=0; k<3; k++) tmp.coeffs[k] = wb_preset[i].channel[k]; break; } } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // final security net: hardcoded default that fits most cams. tmp.coeffs[0] = 2.0f; tmp.coeffs[1] = 1.0f; tmp.coeffs[2] = 1.5f; } } else { tmp.coeffs[0] /= tmp.coeffs[1]; tmp.coeffs[2] /= tmp.coeffs[1]; tmp.coeffs[1] = 1.0f; } // remember daylight wb used for temperature/tint conversion, // assuming it corresponds to CIE daylight (D65) if(module->gui_data) { dt_iop_temperature_gui_data_t *g = (dt_iop_temperature_gui_data_t *)module->gui_data; for(int c = 0; c < 3; c++) g->daylight_wb[c] = raw->color.pre_mul[c]; if(g->daylight_wb[0] == 1.0f && g->daylight_wb[1] == 1.0f && g->daylight_wb[2] == 1.0f) { // if we didn't find anything for daylight wb, look for a wb preset with appropriate name. // we're normalising that to be D65 char makermodel[1024]; char *model = makermodel; dt_colorspaces_get_makermodel_split(makermodel, 1024, &model, module->dev->image_storage.exif_maker, module->dev->image_storage.exif_model); for(int i=0; i<wb_preset_count; i++) { if(!strcmp(wb_preset[i].make, makermodel) && !strcmp(wb_preset[i].model, model) && !strncasecmp(wb_preset[i].name, "daylight", 8)) { for(int k=0; k<3; k++) g->daylight_wb[k] = wb_preset[i].channel[k]; break; } } } float temp, tint, mul[3]; for(int k=0; k<3; k++) mul[k] = g->daylight_wb[k]/tmp.coeffs[k]; convert_rgb_to_k(mul, &temp, &tint); dt_bauhaus_slider_set_default(g->scale_k, temp); dt_bauhaus_slider_set_default(g->scale_tint, tint); } } libraw_close(raw); } memcpy(module->params, &tmp, sizeof(dt_iop_temperature_params_t)); memcpy(module->default_params, &tmp, sizeof(dt_iop_temperature_params_t)); }
void reload_defaults(dt_iop_module_t *module) { // raw images need wb (to convert from uint16_t to float): if(dt_image_is_raw(&module->dev->image_storage)) { module->default_enabled = 1; module->hide_enable_button = 1; } else module->default_enabled = 0; dt_iop_temperature_params_t tmp = (dt_iop_temperature_params_t) { 5000.0, {1.0, 1.0, 1.0} }; // get white balance coefficients, as shot char filename[DT_MAX_PATH_LEN]; int ret=0; /* check if file is raw / hdr */ if(dt_image_is_raw(&module->dev->image_storage)) { dt_image_full_path(module->dev->image_storage.id, filename, DT_MAX_PATH_LEN); libraw_data_t *raw = libraw_init(0); ret = libraw_open_file(raw, filename); if(!ret) { module->default_enabled = 1; for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.cam_mul[k]; if(tmp.coeffs[0] <= 0.0) { for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.pre_mul[k]; } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // could not get useful info, try presets: char makermodel[1024]; char *model = makermodel; dt_colorspaces_get_makermodel_split(makermodel, 1024, &model, module->dev->image_storage.exif_maker, module->dev->image_storage.exif_model); for(int i=0; i<wb_preset_count; i++) { if(!strcmp(wb_preset[i].make, makermodel) && !strcmp(wb_preset[i].model, model)) { // just take the first preset we find for this camera for(int k=0; k<3; k++) tmp.coeffs[k] = wb_preset[i].channel[k]; break; } } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // final security net: hardcoded default that fits most cams. tmp.coeffs[0] = 2.0f; tmp.coeffs[1] = 1.0f; tmp.coeffs[2] = 1.5f; } } else { tmp.coeffs[0] /= tmp.coeffs[1]; tmp.coeffs[2] /= tmp.coeffs[1]; tmp.coeffs[1] = 1.0f; } } libraw_close(raw); } memcpy(module->params, &tmp, sizeof(dt_iop_temperature_params_t)); memcpy(module->default_params, &tmp, sizeof(dt_iop_temperature_params_t)); }
// TODO: use orientation to correctly rotate the image. // 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; preview = GTK_WIDGET(data); filename = gtk_file_chooser_get_preview_filename(file_chooser); if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) goto no_preview_fallback; // 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")) goto no_preview_fallback; pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL); have_preview = (pixbuf != NULL); if(!have_preview) { // raw image thumbnail int ret; libraw_data_t *raw = libraw_init(0); libraw_processed_image_t *image = NULL; ret = libraw_open_file(raw, filename); if(ret) goto libraw_fail; ret = libraw_unpack_thumb(raw); if(ret) goto libraw_fail; ret = libraw_adjust_sizes_info_only(raw); if(ret) goto libraw_fail; image = libraw_dcraw_make_mem_thumb(raw, &ret); if(!image || ret) goto libraw_fail; // const int orientation = raw->sizes.flip; GdkPixbuf *tmp; GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); have_preview = gdk_pixbuf_loader_write(loader, image->data, image->data_size, NULL); tmp = gdk_pixbuf_loader_get_pixbuf(loader); gdk_pixbuf_loader_close(loader, NULL); float ratio; if(image->type == LIBRAW_IMAGE_JPEG) { // jpeg dt_imageio_jpeg_t jpg; if(dt_imageio_jpeg_decompress_header(image->data, image->data_size, &jpg)) goto libraw_fail; ratio = 1.0*jpg.height/jpg.width; } else { // bmp -- totally untested ratio = 1.0*image->height/image->width; } int width = 128, height = 128*ratio; pixbuf = gdk_pixbuf_scale_simple(tmp, width, height, GDK_INTERP_BILINEAR); if(loader) g_object_unref(loader); // clean up raw stuff. libraw_recycle(raw); libraw_close(raw); free(image); if(0) { libraw_fail: // fprintf(stderr,"[imageio] %s: %s\n", filename, libraw_strerror(ret)); libraw_close(raw); have_preview = FALSE; } } if(!have_preview) { no_preview_fallback: pixbuf = gdk_pixbuf_new_from_inline(-1, dt_logo_128x128, FALSE, NULL); 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); }
static void _init_8( uint8_t *buf, uint32_t *width, uint32_t *height, const uint32_t imgid, const dt_mipmap_size_t size) { const uint32_t wd = *width, ht = *height; char filename[DT_MAX_PATH_LEN] = {0}; /* do not even try to process file if it isnt available */ dt_image_full_path(imgid, filename, DT_MAX_PATH_LEN); if (strlen(filename) == 0 || !g_file_test(filename, G_FILE_TEST_EXISTS)) { *width = *height = 0; return; } const int altered = dt_image_altered(imgid); int res = 1; const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); const int orientation = dt_image_orientation(cimg); // the orientation for this camera is not read correctly from exiv2, so we need // to go the full libraw path (as the thumbnail will be flipped the wrong way round) const int incompatible = !strncmp(cimg->exif_maker, "Phase One", 9); dt_image_cache_read_release(darktable.image_cache, cimg); // first try exif thumbnail, that's smaller and thus faster to load: if(!altered && !dt_conf_get_bool("never_use_embedded_thumb") && !dt_exif_thumbnail(filename, buf, wd, ht, orientation, width, height)) { res = 0; } else if(!altered && !dt_conf_get_bool("never_use_embedded_thumb") && !incompatible) { // try to load the embedded thumbnail in raw int ret; memset(filename, 0, DT_MAX_PATH_LEN); dt_image_full_path(imgid, filename, DT_MAX_PATH_LEN); const char *c = filename + strlen(filename); while(*c != '.' && c > filename) c--; if(!strcasecmp(c, ".jpg")) { // try to load jpg dt_imageio_jpeg_t jpg; if(!dt_imageio_jpeg_read_header(filename, &jpg)) { uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*jpg.width*jpg.height*4); if(!dt_imageio_jpeg_read(&jpg, tmp)) { // scale to fit dt_iop_flip_and_zoom_8(tmp, jpg.width, jpg.height, buf, wd, ht, orientation, width, height); res = 0; } free(tmp); } } else { // raw image thumbnail libraw_data_t *raw = libraw_init(0); libraw_processed_image_t *image = NULL; ret = libraw_open_file(raw, filename); if(ret) goto libraw_fail; ret = libraw_unpack_thumb(raw); if(ret) goto libraw_fail; ret = libraw_adjust_sizes_info_only(raw); if(ret) goto libraw_fail; image = libraw_dcraw_make_mem_thumb(raw, &ret); if(!image || ret) goto libraw_fail; const int orientation = raw->sizes.flip; if(image->type == LIBRAW_IMAGE_JPEG) { // JPEG: decode (directly rescaled to mip4) dt_imageio_jpeg_t jpg; if(dt_imageio_jpeg_decompress_header(image->data, image->data_size, &jpg)) goto libraw_fail; uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*jpg.width*jpg.height*4); if(dt_imageio_jpeg_decompress(&jpg, tmp)) { free(tmp); goto libraw_fail; } // scale to fit dt_iop_flip_and_zoom_8(tmp, jpg.width, jpg.height, buf, wd, ht, orientation, width, height); free(tmp); res = 0; } // clean up raw stuff. libraw_recycle(raw); libraw_close(raw); free(image); if(0) { libraw_fail: // fprintf(stderr,"[imageio] %s: %s\n", filename, libraw_strerror(ret)); libraw_close(raw); res = 1; } } } if(res) { // try the real thing: rawspeed + pixelpipe dt_imageio_module_format_t format; _dummy_data_t dat; format.bpp = _bpp; format.write_image = _write_image; format.levels = _levels; dat.head.max_width = wd; dat.head.max_height = ht; dat.buf = buf; // export with flags: ignore exif (don't load from disk), don't swap byte order, don't do hq processing, and signal we want thumbnail export res = dt_imageio_export_with_flags(imgid, "unused", &format, (dt_imageio_module_data_t *)&dat, 1, 1, 0, 1, NULL); if(!res) { // might be smaller, or have a different aspect than what we got as input. *width = dat.head.width; *height = dat.head.height; } } // fprintf(stderr, "[mipmap init 8] export image %u finished (sizes %d %d => %d %d)!\n", imgid, wd, ht, dat.head.width, dat.head.height); // any errors? if(res) { // fprintf(stderr, "[mipmap_cache] could not process thumbnail!\n"); *width = *height = 0; return; } // TODO: various speed optimizations: // TODO: also init all smaller mips! // TODO: use mipf, but: // TODO: if output is cropped, don't use mipf! }
static GthImage * _cairo_image_surface_create_from_raw (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gpointer user_data, GCancellable *cancellable, GError **error) { libraw_data_t *raw_data; int result; void *buffer = NULL; size_t size; GthImage *image = NULL; raw_data = libraw_init (LIBRAW_OPIONS_NO_MEMERR_CALLBACK | LIBRAW_OPIONS_NO_DATAERR_CALLBACK); if (raw_data == NULL) { _libraw_set_gerror (error, errno); goto fatal_error; } libraw_set_progress_handler (raw_data, _libraw_progress_cb, cancellable); if (! _g_input_stream_read_all (istream, &buffer, &size, cancellable, error)) goto fatal_error; raw_data->params.output_tiff = FALSE; raw_data->params.use_camera_wb = TRUE; raw_data->params.use_rawspeed = TRUE; raw_data->params.highlight = FALSE; raw_data->params.use_camera_matrix = TRUE; raw_data->params.output_color = RAW_OUTPUT_COLOR_SRGB; raw_data->params.output_bps = 8; raw_data->params.half_size = (requested_size > 0); result = libraw_open_buffer (raw_data, buffer, size); if (LIBRAW_FATAL_ERROR (result)) { _libraw_set_gerror (error, result); goto fatal_error; } /* */ #if RAW_USE_EMBEDDED_THUMBNAIL if (requested_size > 0) { /* read the thumbnail */ result = libraw_unpack_thumb (raw_data); if (result != LIBRAW_SUCCESS) { _libraw_set_gerror (error, result); goto fatal_error; } switch (raw_data->thumbnail.tformat) { case LIBRAW_THUMBNAIL_JPEG: image = _libraw_read_jpeg_data (raw_data->thumbnail.thumb, raw_data->thumbnail.tlength, requested_size, cancellable, error); break; case LIBRAW_THUMBNAIL_BITMAP: image = _libraw_read_bitmap_data (raw_data->thumbnail.twidth, raw_data->thumbnail.theight, raw_data->thumbnail.tcolors, 8, (guchar *) raw_data->thumbnail.thumb, raw_data->thumbnail.tlength); break; default: g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unsupported data format"); break; } if ((image != NULL) && (_libraw_get_tranform (raw_data) != GTH_TRANSFORM_NONE)) { cairo_surface_t *surface; cairo_surface_t *rotated; surface = gth_image_get_cairo_surface (image); rotated = _cairo_image_surface_transform (surface, _libraw_get_tranform (raw_data)); gth_image_set_cairo_surface (image, rotated); cairo_surface_destroy (rotated); cairo_surface_destroy (surface); } } else #endif { /* read the image */ libraw_processed_image_t *processed_image; result = libraw_unpack (raw_data); if (result != LIBRAW_SUCCESS) { _libraw_set_gerror (error, result); goto fatal_error; } result = libraw_dcraw_process (raw_data); if (result != LIBRAW_SUCCESS) { _libraw_set_gerror (error, result); goto fatal_error; } processed_image = libraw_dcraw_make_mem_image (raw_data, &result); if (result != LIBRAW_SUCCESS) { _libraw_set_gerror (error, result); goto fatal_error; } switch (processed_image->type) { case LIBRAW_IMAGE_JPEG: image = _libraw_read_jpeg_data (processed_image->data, processed_image->data_size, -1, cancellable, error); break; case LIBRAW_IMAGE_BITMAP: image = _libraw_read_bitmap_data (processed_image->width, processed_image->height, processed_image->colors, processed_image->bits, processed_image->data, processed_image->data_size); break; default: g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unsupported data format"); break; } libraw_dcraw_clear_mem (processed_image); } /* get the original size */ if ((original_width != NULL) && (original_height != NULL)) { result = libraw_adjust_sizes_info_only (raw_data); if (result != LIBRAW_SUCCESS) { _libraw_set_gerror (error, result); goto fatal_error; } *original_width = raw_data->sizes.iwidth; *original_height = raw_data->sizes.iheight; } fatal_error: if (raw_data != NULL) libraw_close (raw_data); g_free (buffer); return image; }