Re: [gtk-list] Re: Displaying JPEGs




>  > From gtk-list-request@redhat.com Tue Feb 16 05:24:15 1999
>  > From: john@giorgio.hart.bbk.ac.uk
>  >
> 
> Mike Lindahl <mlindahl@phoenix.Princeton.EDU>
> > I am relatively new to GTK and am trying to get jpegs to display.  I am
> > using the libjpeg library and that is not a problem.  I have successfully
> > loaded the image into an array of memory.
> >
> > My problem comes in trying to display it.  My first idea was to use
> > successive calls to gdk_draw_point.  This works, however, it takes _way_
> > too long.  Since I am running on an 8-bit display, I also have to allocate
> > color entries (I am not entirely sure if I am doing this correctly,
> > but...).
> 
> kyto@is.s.u-tokyo.ac.jp (SAITO Jun)
> > I am stuck on a similar problem. That's why I joined this list ;)
> > I want to display an 8-bit gray scale image stored in an array,
> > Damn that slow color allocation, huh? As a last resort, I tried what
> > you did, and it was slow as hell :)
> 
> grundman@cs.uni-duesseldorf.de (Sven Grundmann)
> > I also want to disaply a 8 bit greyscale image out of raw data ! If you get
> > any further information please let me know .
> 
> John Cupitt (john.cupitt@ng-london.org.uk)
> > If you want something that will dither an RGB image from memory into an X
> > window, you need the gdk_rgb_*() functions. Take a look at testrgb in the gtk
> > sources.
> 
> Thanks John, I appreciate that pointer and will follow up on it, 
> The rest of us seem to share a common problem!
>  
> I am also very new to graphics programming and was having similiar
> performance problems.  I am drawing a map from raw data and so do
> not have the data in a recognizable file format to be drawn.
> 
> I set my display into Hi Color mode (16 bits 5-6-5), thinking that
> I would not need a color map and therefore wouldn't incur the delays
> associated with one.
> 
> My initial code constructed an entire row of rgb byte values (800 pixels
> times 3 bytes) and used gdk_draw_rgb_image() to put the row on the screen.
> And this took about 113 seconds to draw the whole map (600 rows worth).
> I haven't tried sending over the entire image 800x600x3 yet, but I
> probably will soon.
> 
> In my reading I think I've found that a pixmap is maintained and
> manipulated in the server, while an image map is maintained in the
> client program.  And that everytime I call a function with a _draw_
> then I am sending a message through gdk and through xlib to the server.
> And I believe that it is all this extra communication that is causing the
> delays.
> 
> I changed the program such that before I started drawing the pixels I called
>     gdk_image_init() and gdk_image_get()
> and plotted the pixels with
>    gdk_image_put_pixel()
> and finally sent the entire image to the server with
>    gdk_draw_image()
> 
> The net result is I cut display time from 113.911s to 3.987s.
> 
> Unfortunately, due to the way gdk_image_put_pixel() is written,
> I now have to manipulate pixels as 5-6-5 bitmapped entities.
> Not a very portable solution.
> 
> So I'm looking for a client side function which will map RGB values
> into pixels on an image.  All the necessary information seems to be
> in gdktypes.h in struct _GdkVisual.
> 
> Also perhaps someone can tell me, can I display an rgb image onto
> an 8 bit display, will the necessary conversion take place automagicly
> and quickly?
> 
> Any comments, critiques, or pointers would really be appreciated.
> 
> Larry
> 
> -- 
> To unsubscribe: mail -s unsubscribe gtk-list-request@redhat.com < /dev/null
> 
> 

As far as I can tell, the fastest possible thing to do is to directly
manipulate the XImage structure underlying a GdkImage.  For those of
us who need to squeeze out every possible cycle from our machines, but
still want to work within the X protocol, this seems to be the only
option.

I haven't used Imlib, but according to the tutorial, it works
internally in 24 bpp, which means extra conversions when data and
display are not 24 bpp.

The gdk API pixel-wise manipulations require function calls, which
have considerable overhead.

The solution is to directly work with the underlying data.  Someone
correct me if I'm wrong, please!  The actual gdk data is stored in an
underlying XImage structure.  This is a "private" member of GdkImage,
but it can be accessed with the macro defined in "gdkx.h" (make sure
to include gdkx.h).  The macro is:

    (XImage *) GDK_IMAGE_XIMAGE(GdkImage *image)

Once you have the XImage pointer, you can directly manipulate it, but
you have to be careful about things like display depth and bit masks.
Following is an example of converting grayscale byte-data into an
XImage.  The color analog is a simple change in the code.  The code
assumes a TRUE_COLOR visual for speed (no colormap.)  Note that you can
ensure getting a TRUE_COLOR visual using a command like, 

  gdk_image_new(GDK_IMAGE_FASTEST,
                gdk_visual_get_best_with_type(GDK_VISUAL_TRUE_COLOR),
							  im->ocols, im->orows);

Eight bit-displays don't work well with TRUE_COLOR, but they do work.  

In the code example below, IMAGE is a struct containing fields for the
number of rows and cols and the image data as one, long array of byte
data, one scan-line after another.  Note that the inner-loops could be
optimized by using pointer arithmetic rather than row/col indices.  This
code is somewhat obscure, but the idea is simple:  Figure out what
pixel-format X is expecting, and convert your data into it.  X expects
a pixel to be "bits_per_pixel" bits long, and the bits defining each color
level are located via the masks.

void hv_byte_2_ximage(const IMAGE *himage, XImage *ximage)
{
  /* Assumptions:
				1. Visual is TrueColor
				2. Visual depth is <= 24 bits
  */
  byte *b_ptr, *image = ximage->data;
  int i, j, t;
  int bytes_per_pixel, red_shift, green_shift, blue_shift;
  unsigned long pixval, red_mask, green_mask, blue_mask;
  int red_bits, green_bits, blue_bits;
  
  /* Assert visual is TrueColor */
  g_return_if_fail(ximage->red_mask || ximage->green_mask ||
												    ximage->blue_mask);
  /* Assert visual depth is <= 24 bits */
  g_return_if_fail(ximage->depth <= 24);

  b_ptr = himage->firstpix;
  bytes_per_pixel = ximage->bits_per_pixel >> 3;
  red_mask = ximage->red_mask;
  green_mask = ximage->green_mask;
  blue_mask = ximage->blue_mask;

  /* Find the number of bits to shift a pixel for ea. color channel by
				shifting the mask right, then left, & comparing with
original. */

  for (i = 0; red_mask == ((red_mask >> i) << i); i++);
  red_shift = i - 1;
  for (i = 0; green_mask == ((green_mask >> i) << i); i++);
  green_shift = i - 1;
  for (i = 0; blue_mask == ((blue_mask >> i) << i); i++);
  blue_shift = i - 1;

  /* Find the number of bits less than 8 used by each color
channel. */

  blue_bits = 8 - green_shift;
  green_bits = 8 - (red_shift - green_shift);
  red_bits = 8 - (ximage->depth - red_shift);

  if (ximage->byte_order == LSBFirst) {
    /* optimize this loop later */
    for (i = 0; i < himage->orows; i++) {
      for (j = 0; j < himage->ocols; j++) {
	pixval = himage->image[himage->ocols * i + j];
/* FOR COLOR, YOU PROBABLY JUST NEED TO SUBSTITUE rbyte, gbyte, AND blue
 byte VALUES FOR pixval IN THE RHS INSTANCES OF THE FOLLOWING LINE */
	pixval = pixval >> red_bits << red_shift |
	pixval >> green_bits << green_shift |
	pixval >> blue_bits << blue_shift;
	   for (t = 0; t < bytes_per_pixel; t++) {
		image[ximage->bytes_per_line *
		  (himage->orows - 1 - i) + j *
		  bytes_per_pixel + t] = (pixval >> (8 * t)) & 0xFF;
	   }
      }
    }
  } else
    g_warning("hv_byte_2_ximage: Unsupported byte order: MSB");
}

----------------------------------------------------------------
                       Joshua Richardson
Dept. Cognitive and Neural Systems / Center for Adaptive Systems
                       Boston University
----------------------------------------------------------------







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