Re: gdk-pixbuf, loading jpeg from network and displaying



On Wed, 20 Sep 2000 23:39:02 -0400, Michael Rothwell <rothwell holly-springs nc us> wrote:
Hi,

I've been trying to find a way to load image data from memory and
display it. I will be fetching the data from the network, and ideally
would like to display it incrementally, but that's not necessary. THe
main thing is to be able to load a JPEG from a network data source and
display it in a GTK app. Anyone have some advice? Sample code?

Thanks!

-M

_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list


Hopefully I haven't screwed this up too badly...


/*FIXME look into g_io stuff, instead of reading data in the idle function */
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixbuf-loader.h>

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT (80)
#define BUFFER_SIZE (1024 * 8)

typedef struct {
        GdkPixbufLoader *loader;
        GdkPixbuf *pixbuf;
        int width;
        int height;

        GtkWidget *win;
        GtkWidget *scrolled_window;
        GtkWidget *drawing_area;

        int socket_fd;
} WebImage;

static void error_quit (const gchar *error_msg)
{
        g_print ("\nError: %s\n", error_msg);
        exit (1);
}
/* cutting and pasting (from some BSD socket tutorial) a bunch of stuff
 * I don't understand
 */
static int http_socket_new_with_file_request (const gchar *host_name, 
                                              const gchar *image_file)
{
        int socket_fd, ret;
        struct hostent *he;
        struct sockaddr_in host_addr;
        gchar *request_string;

        he = gethostbyname (host_name);
        if (he == NULL)
                error_quit ("couldn't resolve host name");

        socket_fd = socket (AF_INET, SOCK_STREAM, 0);
        if (socket_fd == -1)
                error_quit ("couldn't create socket file descriptor");

        host_addr.sin_family = AF_INET;
        host_addr.sin_port = htons (PORT);
        host_addr.sin_addr = *((struct in_addr *)he->h_addr);

        ret = connect (socket_fd, (struct sockaddr *)&host_addr,
                       sizeof (struct sockaddr));
        if (ret == -1)
                error_quit ("couldn't connect");

        request_string = g_strdup_printf ("GET %s\r\n", image_file);

        ret = send (socket_fd, request_string, strlen (request_string), 0);
        if (ret != strlen (request_string)) {
                g_free (request_string);
                error_quit ("couldn't send all of the request");
        }

        g_free (request_string);

        return socket_fd;
}

/*FIXME make sure you don't read past the pixbuf image data
 * (ex: drawing_area is bigger than the pixbuf being drawn).
 * Doesn't matter here since drawing_area size was set to pixbuf size
 */
static gint drawing_area_expose_cb (GtkWidget *drawing_area, 
                                    GdkEventExpose *event,
                                    gpointer data)
{
        WebImage *web_image = (WebImage *) data;

        if (gdk_pixbuf_get_has_alpha (web_image->pixbuf)) {
                gdk_pixbuf_render_to_drawable_alpha (
                                web_image->pixbuf,      
                                web_image->drawing_area->window,
                                event->area.x, event->area.y,
                                event->area.x, event->area.y,
                                event->area.width, event->area.height,
                                GDK_PIXBUF_ALPHA_FULL,
                                0, // alpha_threshold ?
                                GDK_RGB_DITHER_MAX,
                                0, 0);
        }
        else {
                gdk_pixbuf_render_to_drawable (
                                web_image->pixbuf, 
                                web_image->drawing_area->window,
                                web_image->drawing_area->style->black_gc,
                                event->area.x, event->area.y,   
                                event->area.x, event->area.y,   
                                event->area.width, event->area.height, 
                                GDK_RGB_DITHER_MAX,
                                0, 0);  
        }

        return FALSE;
}
                
static gint area_prepared_cb (GdkPixbuf *loader, gpointer data)
{
        WebImage *web_image = (WebImage *) data;
        
        web_image->pixbuf = gdk_pixbuf_loader_get_pixbuf (
                                                GDK_PIXBUF_LOADER (loader));
        web_image->width = gdk_pixbuf_get_width (web_image->pixbuf);
        web_image->height = gdk_pixbuf_get_height (web_image->pixbuf);
        
        web_image->win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        gtk_signal_connect (GTK_OBJECT (web_image->win), "destroy",
                            GTK_SIGNAL_FUNC (gtk_main_quit), NULL);

        web_image->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
        gtk_widget_set_usize (web_image->scrolled_window, 500, 500);
        gtk_container_add (GTK_CONTAINER (web_image->win), 
                           web_image->scrolled_window);

        web_image->drawing_area = gtk_drawing_area_new ();
        gtk_signal_connect (GTK_OBJECT (web_image->drawing_area), 
                            "expose_event",
                            GTK_SIGNAL_FUNC (drawing_area_expose_cb), 
                            (gpointer) web_image);
        gtk_scrolled_window_add_with_viewport (
                        GTK_SCROLLED_WINDOW (web_image->scrolled_window), 
                        web_image->drawing_area);
        gtk_drawing_area_size (GTK_DRAWING_AREA (web_image->drawing_area), 
                               web_image->width, 
                               web_image->height);

        gtk_widget_show_all (web_image->win);
        
        return FALSE;
}

/*FIXME need to check drawing_area and pixbuf sizes? 
 * see drawing_area_expose_cb()
 */
static gint area_updated_cb (GdkPixbuf *loader, 
                             guint x, guint y, 
                             guint width, guint height, 
                             gpointer data)
{
        WebImage *web_image = (WebImage *) data;

        if (gdk_pixbuf_get_has_alpha (web_image->pixbuf)) {
                gdk_pixbuf_render_to_drawable_alpha (
                                web_image->pixbuf,      
                                web_image->drawing_area->window,
                                x, y,
                                x, y,
                                width, height,
                                GDK_PIXBUF_ALPHA_FULL,
                                0, // alpha_threshold ?
                                GDK_RGB_DITHER_MAX,
                                0, 0);
        }
        else {
                gdk_pixbuf_render_to_drawable (
                                web_image->pixbuf, 
                                web_image->drawing_area->window,
                                web_image->drawing_area->style->black_gc,
                                x, y,   
                                x, y,   
                                width, height, 
                                GDK_RGB_DITHER_MAX,
                                0, 0);  
        }

        return FALSE;
}

static gint recv_image_data (gpointer data)
{
        WebImage *web_image = (WebImage *) data;


        int num_bytes_received;
        gchar buffer[BUFFER_SIZE];

        num_bytes_received = recv (web_image->socket_fd, 
                                   buffer, BUFFER_SIZE, 
                                   0);
        if (num_bytes_received <= 0) {
                g_print ("all done?\n");
                close (web_image->socket_fd);
                gdk_pixbuf_loader_close (
                                GDK_PIXBUF_LOADER (web_image->loader));
                return FALSE;
        }

        g_print ("writing %d bytes\n", num_bytes_received);
        gdk_pixbuf_loader_write (GDK_PIXBUF_LOADER (web_image->loader), 
                                 buffer, num_bytes_received);

        return TRUE;
}

int main (int argc, char *argv[])
{
        WebImage web_image;
        gchar *host_name, *image_file;

        gtk_init (&argc, &argv);
        gdk_rgb_init ();

        if (argc < 3) {
                g_print (
                   "usage:   %s <hostname>   <image>\n"
                   "example: %s www.gimp.org /icons/gimp_in_action1.jpeg\n", 
                    argv[0], argv[0]);
                host_name = "www.gimp.org";
                image_file = "/icons/gimp_in_action1.jpeg";
        }
        else {
                host_name = argv[1];
                image_file = argv[2];
        }

        g_print ("\nhost_name: %s\nimage_file: %s\n", host_name, image_file);
        web_image.socket_fd = http_socket_new_with_file_request (
                                                host_name, image_file);

        web_image.loader = gdk_pixbuf_loader_new ();
        gtk_signal_connect (GTK_OBJECT (web_image.loader), 
                            "area_prepared",
                            GTK_SIGNAL_FUNC (area_prepared_cb), 
                            (gpointer) &web_image);
        gtk_signal_connect (GTK_OBJECT (web_image.loader), 
                            "area_updated", 
                            GTK_SIGNAL_FUNC (area_updated_cb), 
                            (gpointer) &web_image);

        gtk_idle_add (recv_image_data, (gpointer) &web_image);
        gtk_main ();    
        return 0;
}





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]