/* Image Data in Memory */ static VALUE initialize_loader(int argc, VALUE *argv, VALUE self) { GdkPixbufLoader* loader; GError* error = NULL; VALUE arg1, is_mime_type; rb_scan_args(argc, argv, "02", &arg1, &is_mime_type); if (NIL_P(arg1)) { loader = gdk_pixbuf_loader_new(); } else { if (is_mime_type == Qtrue) { #if RBGDK_PIXBUF_CHECK_VERSION(2,4,0) loader = gdk_pixbuf_loader_new_with_mime_type(RVAL2CSTR(arg1), &error); #else rb_warning("Not supported GTK+-2.0/2.2."); loader = gdk_pixbuf_loader_new(); #endif } else { /* Default behavior */ loader = gdk_pixbuf_loader_new_with_type(RVAL2CSTR(arg1), &error); } if(error) RAISE_GERROR(error); } G_INITIALIZE(self, loader); return Qnil; }
static Image* LoadImage (ArchiveFile& file, const char *extension) { RGBAImage* image = (RGBAImage *) 0; /* load the buffer from pk3 or filesystem */ ScopedArchiveBuffer buffer(file); GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_type(extension, (GError**) 0); if (loader == (GdkPixbufLoader*)0) { g_warning("could not get a loader for: '%s'\n", extension); return image; } GError *error = (GError *) 0; if (gdk_pixbuf_loader_write(loader, (const guchar *) buffer.buffer, static_cast<gsize> (buffer.length), &error)) { int pos = 0; GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); const int width = gdk_pixbuf_get_width(pixbuf); const int height = gdk_pixbuf_get_height(pixbuf); const gboolean hasAlpha = gdk_pixbuf_get_has_alpha(pixbuf); const int stepWidth = gdk_pixbuf_get_n_channels(pixbuf); const guchar *pixels = gdk_pixbuf_get_pixels(pixbuf); image = new RGBAImage(width, height, false); byte *rgba = image->getRGBAPixels(); const int rowextra = gdk_pixbuf_get_rowstride(pixbuf) - width * stepWidth; for (int y = 0; y < height; ++y, pixels += rowextra) { for (int x = 0; x < width; ++x) { rgba[pos++] = *(pixels++); rgba[pos++] = *(pixels++); rgba[pos++] = *(pixels++); if (hasAlpha && *pixels != 255) image->setHasAlpha(true); rgba[pos++] = hasAlpha ? *(pixels++) : 255; } } g_object_unref(pixbuf); } else { g_warning("image could not get loaded: '%s' %s\n", file.getName().c_str(), (error != (GError *) 0) ? error->message : ""); if (error) g_error_free(error); } gdk_pixbuf_loader_close(loader, (GError**) 0); return image; }
static GdkPixbuf* compose_splash(const gchar *version) { gint xpos = 224; gint ypos = 36; GdkPixbufLoader *loader; GdkPixbuf *base, *digit; GError *err = NULL; guint i; gchar *p, *filename; p = gwy_find_self_dir("pixmaps"); filename = g_build_filename(p, "splash.png", NULL); g_free(p); base = gdk_pixbuf_new_from_file(filename, &err); if (!base) { g_warning("Cannot load base splash image: %s", err->message); g_clear_error(&err); sanity_check(filename); g_free(filename); return NULL; } g_free(filename); while (*version) { loader = NULL; for (i = 0; i < G_N_ELEMENTS(digits); i++) { if (*version == digits[i].c) break; } if (i == G_N_ELEMENTS(digits)) { g_warning("Cannot find image for %c", *version); version++; continue; } loader = gdk_pixbuf_loader_new_with_type("png", &err); /* We have already successfully loaded base PNG */ g_assert(loader); if (!gdk_pixbuf_loader_write(loader, digits[i].data, digits[i].len, &err)) { g_critical("Cannot load in-line image for %c as PNG", *version); break; } if (!gdk_pixbuf_loader_close(loader, &err)) { g_critical("Cannot load in-line image for %c as PNG", *version); break; } digit = gdk_pixbuf_loader_get_pixbuf(loader); g_assert(digit); gdk_pixbuf_composite(digit, base, xpos, ypos, gdk_pixbuf_get_width(digit), gdk_pixbuf_get_height(digit), xpos, ypos, 1.0, 1.0, GDK_INTERP_NEAREST, 255); xpos += gdk_pixbuf_get_width(digit); g_object_unref(loader); version++; } return base; }
static void sanity_check(const gchar *filename) { GdkPixbufLoader *loader; GSList *formats, *l; GError *err = NULL; GdkPixbuf *pixbuf; gchar *buf = NULL; gsize size; FILE *fh; gboolean ok, fileok = TRUE; g_printerr("Performing sanity check for %s.\n", filename); fileok &= ok = g_file_test(filename, G_FILE_TEST_EXISTS); g_printerr("Does it exist: %s\n", ok ? "YES" : "NO"); fileok &= ok = g_file_test(filename, G_FILE_TEST_IS_REGULAR); g_printerr("Is it a regular file: %s\n", ok ? "YES" : "NO"); fh = fopen(filename, "rb"); fileok &= ok = !!fh; g_printerr("Can we open it for reading: %s\n", ok ? "YES" : "NO"); if (fh) fclose(fh); else g_printerr("fopen() fails with: %s\n", g_strerror(errno)); fileok &= ok = g_file_get_contents(filename, &buf, &size, &err); g_printerr("Can we use g_file_get_contents(): %s\n", ok ? "YES" : "NO"); if (!ok) { g_printerr("g_file_get_contents() fails with: %s\n", err->message); g_clear_error(&err); } if (!fileok) { if (buf) g_free(buf); g_printerr("The file does not seem OK. No point continuing.\n"); return; } g_printerr("The file seems OK, continuing checks.\n"); pixbuf = gdk_pixbuf_new_from_file(filename, &err); if (pixbuf) { g_printerr("Apparently we can load the pixbuf (%dx%d) now?!\n", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); g_printerr("What has changed?\n"); g_printerr("This is completely f****d up.\n"); g_object_unref(pixbuf); } else { g_printerr("gdk_pixbuf_new_from_file() fails with: %s\n", err->message); g_clear_error(&err); } g_printerr("Checking the pixbuf loaders.\n"); formats = gdk_pixbuf_get_formats(); for (l = formats; l; l = g_slist_next(l)) { GdkPixbufFormat *pixbuf_format = (GdkPixbufFormat*)l->data; gchar **ext; gchar *fmtname, *desc, *exts; fmtname = gdk_pixbuf_format_get_name(pixbuf_format); desc = gdk_pixbuf_format_get_description(pixbuf_format); ext = gdk_pixbuf_format_get_extensions(pixbuf_format); exts = g_strjoinv(" ", ext); g_printerr("Found format %s: %s (%s)\n", fmtname, desc, exts); g_free(exts); g_strfreev(ext); g_free(desc); format_check(pixbuf_format, buf, size); loader = gdk_pixbuf_loader_new_with_type(fmtname, &err); if (!loader) { g_printerr(" Cannot create loader for %s: %s\n", fmtname, err->message); g_clear_error(&err); g_free(fmtname); continue; } ok = gdk_pixbuf_loader_write(loader, buf, size, &err); if (ok) { g_printerr(" Loader %s accepts the file content.\n", fmtname); ok = gdk_pixbuf_loader_close(loader, &err); if (ok) { g_printerr(" Loader %s accepts the entire file.\n", fmtname); pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); if (pixbuf) { g_printerr(" Obtained pixbuf %dx%d from the loader.\n", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); } else { g_printerr(" Cannot obtain pixbuf from the loader.\n"); } } else { g_printerr(" Loader %s fails at close(): %s.\n", fmtname, err->message); g_clear_error(&err); } } else { g_printerr(" Loader %s does not accept the file content: %s\n", fmtname, err->message); g_clear_error(&err); } g_object_unref(loader); g_free(fmtname); } g_slist_free(formats); }
/** * be sure to unref the result if it is non-NULL * * TODO : this is really overkill for now. * only wmf/emf will require regenerating the pixbuf for different scale * factors. And even then we should cache them. */ static GdkPixbuf * soi_get_pixbuf (SheetObjectImage *soi, double scale) { GError *err = NULL; guint8 *data; guint32 data_len; GdkPixbufLoader *loader = NULL; GdkPixbuf *pixbuf = NULL; gboolean ret; g_return_val_if_fail (IS_SHEET_OBJECT_IMAGE (soi), NULL); data = soi->bytes.data; data_len = soi->bytes.len; if (data == NULL || data_len == 0) return pixbuf; if (soi->type != NULL && !strcmp (soi->type, "wmf")) loader = gdk_pixbuf_loader_new_with_type (soi->type, &err); else loader = gdk_pixbuf_loader_new (); if (soi->type == NULL || strlen (soi->type) == 0) g_signal_connect (loader, "size-prepared", G_CALLBACK (soi_info_cb), soi); if (loader) { ret = gdk_pixbuf_loader_write (loader, soi->bytes.data, soi->bytes.len, &err); /* Close in any case. But don't let error during closing * shadow error from loader_write. */ gdk_pixbuf_loader_close (loader, ret ? &err : NULL); if (ret) pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf) { g_object_ref (G_OBJECT (pixbuf)); d (printf ("pixbuf width=%d, height=%d\n", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf))); if (soi->crop_top != 0.0 || soi->crop_bottom != 0.0 || soi->crop_left != 0.0 || soi->crop_right != 0.0) { d (printf ("crop rect top=%g, bottom=%g, " "left=%g, right=%g\n", soi->crop_top, soi->crop_bottom, soi->crop_left, soi->crop_right)); pixbuf = soi_get_cropped_pixbuf (soi, pixbuf); } } g_object_unref (G_OBJECT (loader)); } if (!pixbuf) { if (!soi->dumped) { static int count = 0; char *filename = g_strdup_printf ("unknown%d.%s", count++, soi->type); #if 0 GsfOutput *file = gsf_output_stdio_new (filename, NULL); if (file) { gsf_output_write (GSF_OUTPUT (file), soi->bytes.len, soi->bytes.data); gsf_output_close (GSF_OUTPUT (file)); g_object_unref (file); } #endif g_free (filename); soi->dumped = TRUE; } if (err != NULL) { g_warning ("%s", err->message); g_error_free (err); err = NULL; } else { g_warning ("Unable to display image"); } } return pixbuf; }
bool _openslide_gdkpixbuf_read(const char *format, const char *filename, int64_t offset, int64_t length, uint32_t *dest, int32_t w, int32_t h, GError **err) { GdkPixbufLoader *loader = NULL; uint8_t *buf = g_slice_alloc(BUFSIZE); bool success = false; struct load_state state = { .w = w, .h = h, }; // open and seek FILE *f = _openslide_fopen(filename, "rb", err); if (!f) { goto DONE; } if (fseeko(f, offset, SEEK_SET)) { _openslide_io_error(err, "Couldn't fseek %s", filename); goto DONE; } // create loader loader = gdk_pixbuf_loader_new_with_type(format, err); if (!loader) { goto DONE; } g_signal_connect(loader, "area-prepared", G_CALLBACK(area_prepared), &state); // read data while (length) { size_t count = fread(buf, 1, MIN(length, BUFSIZE), f); if (!count) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FAILED, "Short read loading pixbuf from %s", filename); goto DONE; } if (!gdk_pixbuf_loader_write(loader, buf, count, err)) { g_prefix_error(err, "gdk-pixbuf error: "); goto DONE; } if (state.err) { goto DONE; } length -= count; } // finish load if (!gdk_pixbuf_loader_close(loader, err)) { g_prefix_error(err, "gdk-pixbuf error: "); goto DONE; } if (state.err) { goto DONE; } g_assert(state.pixbuf); // copy pixels uint8_t *pixels = gdk_pixbuf_get_pixels(state.pixbuf); int rowstride = gdk_pixbuf_get_rowstride(state.pixbuf); for (int32_t y = 0; y < h; y++) { for (int32_t x = 0; x < w; x++) { dest[y * w + x] = 0xFF000000 | // A pixels[y * rowstride + x * 3 + 0] << 16 | // R pixels[y * rowstride + x * 3 + 1] << 8 | // G pixels[y * rowstride + x * 3 + 2]; // B } } success = true; DONE: // clean up if (loader) { gdk_pixbuf_loader_close(loader, NULL); g_object_unref(loader); } if (f) { fclose(f); } g_slice_free1(BUFSIZE, buf); // now that the loader is closed, we know state.err won't be set // behind our back if (state.err) { // signal handler validation errors override GdkPixbuf errors g_clear_error(err); g_propagate_error(err, state.err); // signal handler errors should have been noticed before falling through g_assert(!success); } return success; }
bool wxAnimation::Load(wxInputStream &stream, wxAnimationType type) { UnRef(); char anim_type[12]; switch (type) { case wxANIMATION_TYPE_GIF: strcpy(anim_type, "gif"); break; case wxANIMATION_TYPE_ANI: strcpy(anim_type, "ani"); break; default: anim_type[0] = '\0'; break; } // create a GdkPixbufLoader GError *error = NULL; GdkPixbufLoader *loader; if (type != wxANIMATION_TYPE_INVALID && type != wxANIMATION_TYPE_ANY) loader = gdk_pixbuf_loader_new_with_type(anim_type, &error); else loader = gdk_pixbuf_loader_new(); if (!loader) { wxLogDebug(wxT("Could not create the loader for '%s' animation type"), anim_type); return false; } // connect to loader signals g_signal_connect(loader, "area-updated", G_CALLBACK(gdk_pixbuf_area_updated), this); guchar buf[2048]; while (stream.IsOk()) { // read a chunk of data stream.Read(buf, sizeof(buf)); // fetch all data into the loader if (!gdk_pixbuf_loader_write(loader, buf, stream.LastRead(), &error)) { gdk_pixbuf_loader_close(loader, &error); wxLogDebug(wxT("Could not write to the loader")); return false; } } // load complete if (!gdk_pixbuf_loader_close(loader, &error)) { wxLogDebug(wxT("Could not close the loader")); return false; } // wait until we get the last area_updated signal return true; }
static gboolean ani_load_chunk (AniLoaderContext *context, GError **error) { int i; if (context->chunk_id == 0x0) { if (BYTES_LEFT (context) < 8) return FALSE; context->chunk_id = read_int32 (context); context->chunk_size = read_int32 (context); /* Pad it up to word length */ if (context->chunk_size % 2) context->chunk_size += (2 - (context->chunk_size % 2)); } while (context->chunk_id == TAG_LIST) { if (BYTES_LEFT (context) < 12) return FALSE; read_int32 (context); context->chunk_id = read_int32 (context); context->chunk_size = read_int32 (context); /* Pad it up to word length */ if (context->chunk_size % 2) context->chunk_size += (2 - (context->chunk_size % 2)); } if (context->chunk_id == TAG_icon) { GError *loader_error = NULL; guchar *data; guint32 towrite; if (context->loader == NULL) { if (context->pos >= context->NumFrames) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Unexpected icon chunk in animation")); return FALSE; } #ifdef DEBUG_ANI g_print ("opening loader\n"); #endif context->loader = gdk_pixbuf_loader_new_with_type ("ico", &loader_error); if (loader_error) { g_propagate_error (error, loader_error); return FALSE; } g_signal_connect (context->loader, "area_prepared", G_CALLBACK (prepared_callback), context); g_signal_connect (context->loader, "area_updated", G_CALLBACK (updated_callback), context); } towrite = MIN (context->chunk_size, BYTES_LEFT (context)); data = context->byte; context->byte += towrite; context->cp += towrite; #ifdef DEBUG_ANI g_print ("miss %d, get %d, leftover %d\n", context->chunk_size, towrite, BYTES_LEFT (context)); #endif context->chunk_size -= towrite; if (!gdk_pixbuf_loader_write (context->loader, data, towrite, &loader_error)) { g_propagate_error (error, loader_error); gdk_pixbuf_loader_close (context->loader, NULL); g_object_unref (context->loader); context->loader = NULL; return FALSE; } if (context->chunk_size == 0) { #ifdef DEBUG_ANI g_print ("closing loader\n"); #endif if (!gdk_pixbuf_loader_close (context->loader, &loader_error)) { g_propagate_error (error, loader_error); g_object_unref (context->loader); context->loader = NULL; return FALSE; } g_object_unref (context->loader); context->loader = NULL; context->chunk_id = 0x0; } return BYTES_LEFT (context) > 0; } if (BYTES_LEFT (context) < context->chunk_size) return FALSE; if (context->chunk_id == TAG_anih) { context->HeaderSize = read_int32 (context); context->NumFrames = read_int32 (context); context->NumSteps = read_int32 (context); context->Width = read_int32 (context); context->Height = read_int32 (context); context->BitCount = read_int32 (context); context->NumPlanes = read_int32 (context); context->DisplayRate = read_int32 (context); context->Flags = read_int32 (context); #ifdef DEBUG_ANI g_print ("HeaderSize \t%" G_GUINT32_FORMAT "\nNumFrames \t%" G_GUINT32_FORMAT "\nNumSteps \t%" G_GUINT32_FORMAT "\nWidth \t%" G_GUINT32_FORMAT "\nHeight \t%" G_GUINT32_FORMAT "\nBitCount \t%" G_GUINT32_FORMAT "\nNumPlanes \t%" G_GUINT32_FORMAT "\nDisplayRate \t%" G_GUINT32_FORMAT "\nSequenceFlag \t%d" "\nIconFlag \t%d" "\n", context->HeaderSize, context->NumFrames, context->NumSteps, context->Width, context->Height, context->BitCount, context->NumPlanes, context->DisplayRate, (context->Flags & 0x2) != 0, (context->Flags & 0x1) != 0); #endif if (!(context->Flags & 0x2)) context->NumSteps = context->NumFrames; if (context->NumFrames == 0 || context->NumFrames >= 1024 || context->NumSteps == 0 || context->NumSteps >= 1024) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Invalid header in animation")); return FALSE; } context->animation = g_object_new (GDK_TYPE_PIXBUF_ANI_ANIM, NULL); if (!context->animation) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Not enough memory to load animation")); return FALSE; } context->animation->n_pixbufs = context->NumFrames; context->animation->n_frames = context->NumSteps; context->animation->total_time = context->NumSteps * (context->DisplayRate * 1000 / 60); context->animation->width = 0; context->animation->height = 0; context->animation->pixbufs = g_try_new0 (GdkPixbuf*, context->NumFrames); context->animation->delay = g_try_new (gint, context->NumSteps); context->animation->sequence = g_try_new (gint, context->NumSteps); if (!context->animation->pixbufs || !context->animation->delay || !context->animation->sequence) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Not enough memory to load animation")); return FALSE; } for (i = 0; i < context->NumSteps; i++) { /* default values if the corresponding chunks are absent */ context->animation->delay[i] = context->DisplayRate * 1000 / 60; context->animation->sequence[i] = MIN (i, context->NumFrames - 1); } }
bool wxAnimation::Load(wxInputStream &stream, wxAnimationType type) { UnRef(); char anim_type[12]; switch (type) { case wxANIMATION_TYPE_GIF: strcpy(anim_type, "gif"); break; case wxANIMATION_TYPE_ANI: strcpy(anim_type, "ani"); break; default: anim_type[0] = '\0'; break; } // create a GdkPixbufLoader GError *error = NULL; GdkPixbufLoader *loader; if (type != wxANIMATION_TYPE_INVALID && type != wxANIMATION_TYPE_ANY) loader = gdk_pixbuf_loader_new_with_type(anim_type, &error); else loader = gdk_pixbuf_loader_new(); if (!loader || error != NULL) // even if the loader was allocated, an error could have happened { wxLogDebug(wxT("Could not create the loader for '%s' animation type: %s"), anim_type, error->message); return false; } // connect to loader signals g_signal_connect(loader, "area-updated", G_CALLBACK(gdk_pixbuf_area_updated), this); guchar buf[2048]; bool data_written = false; while (stream.IsOk()) { // read a chunk of data if (!stream.Read(buf, sizeof(buf)) && stream.GetLastError() != wxSTREAM_EOF) // EOF is OK for now { // gdk_pixbuf_loader_close wants the GError == NULL gdk_pixbuf_loader_close(loader, NULL); return false; } // fetch all data into the loader if (!gdk_pixbuf_loader_write(loader, buf, stream.LastRead(), &error)) { wxLogDebug(wxT("Could not write to the loader: %s"), error->message); // gdk_pixbuf_loader_close wants the GError == NULL gdk_pixbuf_loader_close(loader, NULL); return false; } data_written = true; } if (!data_written) { wxLogDebug("Could not read data from the stream..."); return false; } // load complete: gdk_pixbuf_loader_close will now check if the data we // wrote inside the pixbuf loader does make sense and will give an error // if it doesn't (because of a truncated file, corrupted data or whatelse) if (!gdk_pixbuf_loader_close(loader, &error)) { wxLogDebug(wxT("Could not close the loader: %s"), error->message); return false; } // wait until we get the last area_updated signal return data_written; }