codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#include <gtk/gtk.h> #include <glib.h> #include <gdk-pixbuf/gdk-pixbuf.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <dirent.h> #include <queue> /** * gnome_thumbnail_scale_down_pixbuf: * @pixbuf: a #GdkPixbuf * @dest_width: the desired new width * @dest_height: the desired new height * * Scales the pixbuf to the desired size. This function * is a lot faster than gdk-pixbuf when scaling down by * large amounts. * * Return value: a scaled pixbuf * * Since: 2.2 **/ GdkPixbuf * gnome_desktop_thumbnail_scale_down_pixbuf (GdkPixbuf *pixbuf, int dest_width, int dest_height) { int source_width, source_height; int s_x1, s_y1, s_x2, s_y2; int s_xfrac, s_yfrac; int dx, dx_frac, dy, dy_frac; div_t ddx, ddy; int x, y; int r, g, b, a; int n_pixels; gboolean has_alpha; guchar *dest, *src, *xsrc, *src_pixels; GdkPixbuf *dest_pixbuf; int pixel_stride; int source_rowstride, dest_rowstride; if (dest_width == 0 || dest_height == 0) { return NULL; } source_width = gdk_pixbuf_get_width (pixbuf); source_height = gdk_pixbuf_get_height (pixbuf); g_assert (source_width >= dest_width); g_assert (source_height >= dest_height); ddx = div (source_width, dest_width); dx = ddx.quot; dx_frac = ddx.rem; ddy = div (source_height, dest_height); dy = ddy.quot; dy_frac = ddy.rem; has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); source_rowstride = gdk_pixbuf_get_rowstride (pixbuf); src_pixels = gdk_pixbuf_get_pixels (pixbuf); dest_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 8, dest_width, dest_height); dest = gdk_pixbuf_get_pixels (dest_pixbuf); dest_rowstride = gdk_pixbuf_get_rowstride (dest_pixbuf); pixel_stride = (has_alpha)?4:3; s_y1 = 0; s_yfrac = -dest_height/2; while (s_y1 < source_height) { s_y2 = s_y1 + dy; s_yfrac += dy_frac; if (s_yfrac > 0) { s_y2++; s_yfrac -= dest_height; } s_x1 = 0; s_xfrac = -dest_width/2; while (s_x1 < source_width) { s_x2 = s_x1 + dx; s_xfrac += dx_frac; if (s_xfrac > 0) { s_x2++; s_xfrac -= dest_width; } /* Average block of [x1,x2[ x [y1,y2[ and store in dest */ r = g = b = a = 0; n_pixels = 0; src = src_pixels + s_y1 * source_rowstride + s_x1 * pixel_stride; for (y = s_y1; y < s_y2; y++) { xsrc = src; if (has_alpha) { for (x = 0; x < s_x2-s_x1; x++) { n_pixels++; r += xsrc[3] * xsrc[0]; g += xsrc[3] * xsrc[1]; b += xsrc[3] * xsrc[2]; a += xsrc[3]; xsrc += 4; } } else { for (x = 0; x < s_x2-s_x1; x++) { n_pixels++; r += *xsrc++; g += *xsrc++; b += *xsrc++; } } src += source_rowstride; } if (has_alpha) { if (a != 0) { *dest++ = r / a; *dest++ = g / a; *dest++ = b / a; *dest++ = a / n_pixels; } else { *dest++ = 0; *dest++ = 0; *dest++ = 0; *dest++ = 0; } } else { *dest++ = r / n_pixels; *dest++ = g / n_pixels; *dest++ = b / n_pixels; } s_x1 = s_x2; } s_y1 = s_y2; dest += dest_rowstride - dest_width * pixel_stride; } return dest_pixbuf; } static GdkPixbuf * scale_pixbuf_preserve_aspect_ratio (GdkPixbuf *pixbuf, gint size, GdkInterpType interp) { GdkPixbuf *new_icon; gdouble w, h, new_width, new_height, max_edge; w = gdk_pixbuf_get_width (pixbuf); h = gdk_pixbuf_get_height (pixbuf); max_edge = MAX (w, h); new_width = size * (w / max_edge); new_height = size * (h / max_edge); /* Scale the image down, preserving the aspect ratio */ new_icon = gdk_pixbuf_scale_simple (pixbuf, (gint)new_width, (gint)new_height, interp); //new_icon = gnome_desktop_thumbnail_scale_down_pixbuf(pixbuf, (gint)new_width, (gint)new_height); return new_icon; } static int global_sequence[20] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; static GMutex *global_sequence_mutex = NULL; std::queue<std::string> imageQueue; void init_give_me_next_number () { g_assert (global_sequence_mutex == NULL); global_sequence_mutex = g_mutex_new (); } int give_me_next_number () { static int current_number = 0; int ret_val; g_mutex_lock (global_sequence_mutex); ret_val = global_sequence[current_number]; current_number++; g_mutex_unlock (global_sequence_mutex); return ret_val; } static void* say_hello(gpointer data) { g_print ("Hello World! It's me, thread #%d using sequence number %d!\n", GPOINTER_TO_INT (data), give_me_next_number ()); int thread_nr = GPOINTER_TO_INT (data); int errors = 0; std::queue<std::string> fiveBatch; //while (!imageQueue.empty()) while (!fiveBatch.empty() || !imageQueue.empty()) { //std::string imageName = imageQueue.front(); if(fiveBatch.empty()) { for(int i = 0; i < 5; i++) { g_mutex_lock (global_sequence_mutex); if(!imageQueue.empty()) { fiveBatch.push(imageQueue.front()); imageQueue.pop(); } g_mutex_unlock (global_sequence_mutex); } } std::string imageName = fiveBatch.front(); fiveBatch.pop(); // Lock for popping of queue //g_mutex_lock (global_sequence_mutex); //imageQueue.pop(); //g_mutex_unlock (global_sequence_mutex); // unlock GError *gerror = NULL; GdkPixbuf *originalpb; std::string imagePath = "/home/mark/ThumbnailingBenchmarks/2000_Wallpapers-Reanimation/" + imageName; std::string thumbnailPath = "/home/mark/ThumbnailingBenchmarks/thumbnails/GDK_INTERP_BILINEAR/" + imageName + ".png"; originalpb = gdk_pixbuf_new_from_file_at_scale(imagePath.c_str(), 200, 200, true, &gerror); if (!originalpb) { printf("error message: %s\n", gerror->message); errors++; gdk_pixbuf_unref(originalpb); continue; //exit(1); } gdk_pixbuf_save (originalpb, thumbnailPath.c_str(), "png", &gerror, NULL); gdk_pixbuf_unref(originalpb); printf("Thread # %d <> %s\n", thread_nr, imageName.c_str()); } printf("\n\nThere where %i errors! in thread: %d \n", errors, thread_nr); g_thread_exit (NULL); } void listdir(const char *path) { // first off, we need to create a pointer to a directory DIR *pdir = NULL; // remember, it's good practice to initialise a pointer to NULL! pdir = opendir (path); // "." will refer to the current directory struct dirent *pent = NULL; if (pdir == NULL) // if pdir wasn't initialised correctly { // print an error message and exit the program printf ("\nERROR! pdir could not be initialised correctly"); return; // exit the function } // end if while ((pent = readdir (pdir))) // while there is still something in the directory to list { if (pent == NULL) // if pent has not been initialised correctly { // print an error message, and exit the program printf ("\nERROR! pent could not be initialised correctly"); return; // exit the function } if (strcmp(".", pent->d_name) == 0 || strcmp("..", pent->d_name) == 0) continue; // otherwise, it was initialised correctly. let's print it on the console: imageQueue.push(pent->d_name); } // finally, let's close the directory closedir (pdir); } void GLibThumbnailingBenchmark() { int errors = 0; while (!imageQueue.empty()) { GError *gerror = NULL; GdkPixbuf *originalpb, *thumbpixbuff; std::string imageName = imageQueue.front(); imageQueue.pop(); std::string imagePath = "/home/mark/ThumbnailingBenchmarks/2000_Wallpapers-Reanimation/" + imageName; std::string thumbnailPath = "/home/mark/ThumbnailingBenchmarks/thumbnails/GDK_INTERP_BILINEAR/" + imageName + ".png"; originalpb = gdk_pixbuf_new_from_file(imagePath.c_str(), &gerror); if (!originalpb) { printf("error message: %s\n", gerror->message); errors++; gdk_pixbuf_unref(originalpb); gdk_pixbuf_unref(thumbpixbuff); continue; //exit(1); } thumbpixbuff = scale_pixbuf_preserve_aspect_ratio(originalpb, 200, GDK_INTERP_BILINEAR); gdk_pixbuf_save (originalpb, thumbnailPath.c_str(), "png", &gerror, NULL); gdk_pixbuf_unref(thumbpixbuff); gdk_pixbuf_unref(originalpb); printf("<> %s\n", imageName.c_str()); } printf("\n\nThere where %i errors!\n", errors); } void GLibThumbnailingBenchmarkRapid() { int errors = 0; while (!imageQueue.empty()) { GError *gerror = NULL; GdkPixbuf *originalpb; std::string imageName = imageQueue.front(); imageQueue.pop(); std::string imagePath = "/home/mark/ThumbnailingBenchmarks/2000_Wallpapers-Reanimation/" + imageName; std::string thumbnailPath = "/home/mark/ThumbnailingBenchmarks/thumbnails/GDK_INTERP_BILINEAR/" + imageName + ".png"; originalpb = gdk_pixbuf_new_from_file_at_scale(imagePath.c_str(), 200, 200, true, &gerror); if (!originalpb) { printf("error message: %s\n", gerror->message); errors++; gdk_pixbuf_unref(originalpb); continue; //exit(1); } gdk_pixbuf_save (originalpb, thumbnailPath.c_str(), "png", &gerror, NULL); gdk_pixbuf_unref(originalpb); printf("<> %s\n", imageName.c_str()); } printf("\n\nThere where %i errors!\n", errors); } void GlibThreadedThumbnailingBenchmark() { // Setup threads static int numOfThreads = 4; GThread *threads[numOfThreads]; GError *error = NULL; if (!g_thread_supported ()) g_thread_init (NULL); init_give_me_next_number (); int i; for (i = 0; i < numOfThreads; i++) { g_print ("creating thread %d\n", i); threads[i] = g_thread_create (say_hello, GINT_TO_POINTER (i), TRUE, &error); if (error) { g_print ("Error creating thread %d, exiting\n"); g_error_free (error); exit (1); } } g_thread_exit (NULL); exit(1); } int main (int argc, char *argv[]) { gtk_set_locale (); gtk_init (NULL, NULL); // This fills the imageQueue queue listdir("/home/mark/ThumbnailingBenchmarks/2000_Wallpapers-Reanimation"); // GLib Thumbnailing Benchmark //GLibThumbnailingBenchmark(); // Glib more rapid thumbnailing benchmark //GLibThumbnailingBenchmarkRapid(); //Glib threaded thumbnailing (this is the GLibThumbnailingBenchmarkRapid benchmark only in multiple threads) GlibThreadedThumbnailingBenchmark(); return 0; }
Private
[
?
]
Run code
Submit