Re: Quick question...



from what I've heard there is no
standard for that (i think there
is a gdk_?_get_pixel();/set_pixel();
but I think its time-consuming).


to create (see gdk-pixbuf/gdk-pixbuf*.[ch])

GdkPixbuf *
gdk_pixbuf_new_from_data (const guchar *data, GdkColorspace colorspace,
gboolean has_alpha,
                          int bits_per_sample, int width, int height, int rowstride,
                          GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data)

I also have some odds and ends here I could ship you
(I think I picked this up and modified it
for the purpose of saving raw images
at optimized speed without jpeg compression etc...)

damn; I know I picked this up somewhere in
"contrib/" but I cant find the originals
right now.


Anyhow; this might help... hope so,
                        -Tristan


=========================================================

gboolean
gdk_pixdata_from_pixbuf (GdkPixdata      *pixdata,
                         const GdkPixbuf *pixbuf)

GdkPixbuf*
gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
                         gboolean          copy_pixels)


/***************** extract from ".h" ************************/


typedef enum
{
  /* colorspace + alpha */
  GDK_PIXDATA_COLOR_TYPE_RGB    = 0x01,
  GDK_PIXDATA_COLOR_TYPE_RGBA   = 0x02,
  GDK_PIXDATA_COLOR_TYPE_MASK   = 0xff,
  /* width, support 8bits only currently */
  GDK_PIXDATA_SAMPLE_WIDTH_8    = 0x01 << 16,
  GDK_PIXDATA_SAMPLE_WIDTH_MASK = 0x0f << 16,
  /* encoding */
  GDK_PIXDATA_ENCODING_RAW      = 0x01 << 24,
  GDK_PIXDATA_ENCODING_RLE      = 0x02 << 24,
  GDK_PIXDATA_ENCODING_MASK     = 0x0f << 24
} GdkPixdataType;

typedef struct _GdkPixdata GdkPixdata;
struct _GdkPixdata
{
  guint32 magic;        /* GDK_PIXBUF_MAGIC_NUMBER */
  gint32  length;       /* <1 to disable length checks, otherwise:
                         * GDK_PIXDATA_HEADER_LENGTH + pixel_data length
                         */
  guint32 pixdata_type; /* GdkPixdataType */
  guint32 rowstride;    /* maybe 0 to indicate non-padded data */
  guint32 width;
  guint32 height;
  guint8 *pixel_data;
};
#define GDK_PIXDATA_HEADER_LENGTH       (4 + 4 + 4 + 4 + 4 + 4)

typedef enum
{
  /* type of source to save */
  GDK_PIXDATA_DUMP_PIXDATA_STREAM       = 0,
  GDK_PIXDATA_DUMP_PIXDATA_STRUCT       = 1,
  GDK_PIXDATA_DUMP_MACROS               = 2,
  /* type of variables to use */
  GDK_PIXDATA_DUMP_GTYPES               = 0,
  GDK_PIXDATA_DUMP_CTYPES               = 1 << 8,
  GDK_PIXDATA_DUMP_STATIC               = 1 << 9,
  GDK_PIXDATA_DUMP_CONST                = 1 << 10,
  /* save RLE decoder macro? */
  GDK_PIXDATA_DUMP_RLE_DECODER          = 1 << 16,
} GdkPixdataDumpType;



/********************** extract from ".c" **********************/



gboolean
gdk_pixdata_from_pixbuf (GdkPixdata      *pixdata,
                         const GdkPixbuf *pixbuf)
{
  guint height, rowstride, bpp, length;
  guint8 *img_buffer;

  g_return_val_if_fail (pixdata != NULL, FALSE);
  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
  g_return_val_if_fail (pixbuf->bits_per_sample == 8, FALSE);
  g_return_val_if_fail ((pixbuf->n_channels == 3 && !pixbuf->has_alpha)
||
                        (pixbuf->n_channels == 4 && pixbuf->has_alpha), FALSE);
  g_return_val_if_fail (pixbuf->rowstride >= pixbuf->width, FALSE);

  height = pixbuf->height;
  rowstride = pixbuf->rowstride;
  bpp = pixbuf->has_alpha ? 4 : 3;

  img_buffer = pixbuf->pixels;
  length = rowstride * height;

  pixdata->magic = 0; // <-- now thats hard core !!
  pixdata->length = GDK_PIXDATA_HEADER_LENGTH + length;
  pixdata->pixdata_type = pixbuf->has_alpha ?
GDK_PIXDATA_COLOR_TYPE_RGBA : GDK_PIXDATA_COLOR_TYPE_RGB;
  pixdata->pixdata_type |= GDK_PIXDATA_SAMPLE_WIDTH_8;
  pixdata->pixdata_type |= GDK_PIXDATA_ENCODING_RAW;
  pixdata->rowstride = rowstride;
  pixdata->width = pixbuf->width;
  pixdata->height = height;
  pixdata->pixel_data = img_buffer;

  return TRUE;
}




GdkPixbuf*
gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
                         gboolean          copy_pixels)
{
  guint encoding, bpp;
  guint8 *data = NULL;

  g_return_val_if_fail (pixdata != NULL, NULL);
  g_return_val_if_fail (pixdata->width > 0, NULL);
  g_return_val_if_fail (pixdata->height > 0, NULL);
  g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
  g_return_val_if_fail ((pixdata->pixdata_type &
GDK_PIXDATA_COLOR_TYPE_MASK) == 
                        GDK_PIXDATA_COLOR_TYPE_RGB ||
                        (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == 
                        GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
  g_return_val_if_fail ((pixdata->pixdata_type &
GDK_PIXDATA_SAMPLE_WIDTH_MASK) == 
                        GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
  g_return_val_if_fail ((pixdata->pixdata_type &
GDK_PIXDATA_ENCODING_MASK) == 
                        GDK_PIXDATA_ENCODING_RAW ||
                        (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == 
                        GDK_PIXDATA_ENCODING_RLE, NULL);
  g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);

  bpp = (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == 
      GDK_PIXDATA_COLOR_TYPE_RGB ? 3 : 4;
  encoding = pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK;

  if (encoding == GDK_PIXDATA_ENCODING_RLE)
      copy_pixels = TRUE;

  if (copy_pixels)
    {
      data = g_try_malloc (pixdata->rowstride * pixdata->height);
      if (!data)
        {
          return NULL;
        }
    }
  if (encoding == GDK_PIXDATA_ENCODING_RLE)
    {
      const guint8 *rle_buffer = pixdata->pixel_data;
      guint8 *image_buffer = data;
      guint8 *image_limit = data + pixdata->rowstride * pixdata->height;
      gboolean check_overrun = FALSE;

      while (image_buffer < image_limit)
        {
          guint length = *(rle_buffer++);

          if (length & 128)
            {
              length = length - 128;
              check_overrun = image_buffer + length * bpp > image_limit;
              if (check_overrun)
                length = (image_limit - image_buffer) / bpp;
              if (bpp < 4)      /* RGB */
                do
                  {
                    memcpy (image_buffer, rle_buffer, 3);
                    image_buffer += 3;
                  }
                while (--length);
              else              /* RGBA */
                do
                  {
                    memcpy (image_buffer, rle_buffer, 4);
                    image_buffer += 4;
                  }
                while (--length);
              rle_buffer += bpp;
            }
          else
            {
              length *= bpp;
              check_overrun = image_buffer + length > image_limit;
              if (check_overrun)
                length = image_limit - image_buffer;
              memcpy (image_buffer, rle_buffer, length);
              image_buffer += length;
              rle_buffer += length;
            }
        }
      if (check_overrun)
        {
          return NULL;
        }
    }
  else if (copy_pixels)
    memcpy (data, pixdata->pixel_data, pixdata->rowstride *
pixdata->height);
  else
    data = pixdata->pixel_data;

  return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB,
                                   (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) ==
GDK_PIXDATA_COLOR_TYPE_RGBA,
                                   8, pixdata->width, pixdata->height, pixdata->rowstride,
                                   copy_pixels ? (GdkPixbufDestroyNotify) g_free : NULL, data);
}



Ian Molton wrote:

How do I create a pixmap (or similar) of a specified colourdepth, AND
get an efficient way of /directly/ manipulating the pixels in it?
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list



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