Beispiel #1
0
/**
 * gdk_pixbuf_new:
 * @colorspace: Color space for image
 * @has_alpha: Whether the image should have transparency information
 * @bits_per_sample: Number of bits per color sample
 * @width: Width of image in pixels, must be > 0
 * @height: Height of image in pixels, must be > 0
 *
 * Creates a new #GdkPixbuf structure and allocates a buffer for it.  The 
 * buffer has an optimal rowstride.  Note that the buffer is not cleared;
 * you will have to fill it completely yourself.
 *
 * Return value: (nullable): A newly-created #GdkPixbuf with a reference count of 1, or
 * %NULL if not enough memory could be allocated for the image buffer.
 **/
GdkPixbuf *
gdk_pixbuf_new (GdkColorspace colorspace, 
                gboolean      has_alpha,
                int           bits_per_sample,
                int           width,
                int           height)
{
	guchar *buf;
	int rowstride;

	rowstride = gdk_pixbuf_calculate_rowstride (colorspace,
						    has_alpha,
						    bits_per_sample,
						    width,
						    height);
	if (rowstride <= 0)
		return NULL;

	buf = g_try_malloc_n (height, rowstride);
	if (!buf)
		return NULL;

	return gdk_pixbuf_new_from_data (buf, colorspace, has_alpha, bits_per_sample,
					 width, height, rowstride,
					 free_buffer, NULL);
}
Beispiel #2
0
/**
 * gdk_pixbuf_new:
 * @colorspace: Color space for image
 * @has_alpha: Whether the image should have transparency information
 * @bits_per_sample: Number of bits per color sample
 * @width: Width of image in pixels, must be > 0
 * @height: Height of image in pixels, must be > 0
 *
 * Creates a new #GdkPixbuf structure and allocates a buffer for it.  The 
 * buffer has an optimal rowstride.  Note that the buffer is not cleared;
 * you will have to fill it completely yourself.
 *
 * Return value: A newly-created #GdkPixbuf with a reference count of 1, or 
 * %NULL if not enough memory could be allocated for the image buffer.
 **/
GdkPixbuf *
gdk_pixbuf_new (GdkColorspace colorspace, 
                gboolean      has_alpha,
                int           bits_per_sample,
                int           width,
                int           height)
{
	guchar *buf;
	int channels;
	int rowstride;

	g_return_val_if_fail (colorspace == GDK_COLORSPACE_RGB, NULL);
	g_return_val_if_fail (bits_per_sample == 8, NULL);
	g_return_val_if_fail (width > 0, NULL);
	g_return_val_if_fail (height > 0, NULL);

	channels = has_alpha ? 4 : 3;
        rowstride = width * channels;
        if (rowstride / channels != width || rowstride + 3 < 0) /* overflow */
                return NULL;
        
	/* Always align rows to 32-bit boundaries */
	rowstride = (rowstride + 3) & ~3;

	buf = g_try_malloc_n (height, rowstride);
	if (!buf)
		return NULL;

	return gdk_pixbuf_new_from_data (buf, colorspace, has_alpha, bits_per_sample,
					 width, height, rowstride,
					 free_buffer, NULL);
}
Beispiel #3
0
static gpointer
try_malloc_n (gsize n_blocks, gsize n_block_bytes, GError **error)
{
    gpointer ptr = g_try_malloc_n (n_blocks, n_block_bytes);
    if (ptr == NULL)
      g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_MEMORY,
                           _("Failed to allocate memory"));
    return ptr;
}
Beispiel #4
0
void *g_try_malloc(size_t size)
{
    return g_try_malloc_n(1, size);
}
Beispiel #5
0
/**
 * gdk_pixbuf_from_pixdata:
 * @pixdata: a #GdkPixdata to convert into a #GdkPixbuf.
 * @copy_pixels: whether to copy raw pixel data; run-length encoded
 *     pixel data is always copied.
 * @error: location to store possible errors.
 * 
 * Converts a #GdkPixdata to a #GdkPixbuf. If @copy_pixels is %TRUE or
 * if the pixel data is run-length-encoded, the pixel data is copied into
 * newly-allocated memory; otherwise it is reused.
 *
 * Returns: (transfer full): a new #GdkPixbuf.
 * Deprecated: 2.32: Use #GResource instead.
 **/
GdkPixbuf*
gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
			 gboolean          copy_pixels,
			 GError          **error)
{
  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;

  g_debug ("gdk_pixbuf_from_pixdata() called on:");
  g_debug ("\tEncoding %s", encoding == GDK_PIXDATA_ENCODING_RAW ? "raw" : "rle");
  g_debug ("\tDimensions: %d x %d", pixdata->width, pixdata->height);
  g_debug ("\tRowstride: %d, Length: %d", pixdata->rowstride, pixdata->length);
  g_debug ("\tCopy pixels == %s", copy_pixels ? "true" : "false");

  if (encoding == GDK_PIXDATA_ENCODING_RLE)
    copy_pixels = TRUE;

  /* Sanity check the length and dimensions */
  if (SIZE_OVERFLOWS (pixdata->height, pixdata->rowstride))
    {
      g_set_error_literal (error, GDK_PIXBUF_ERROR,
                           GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                           _("Image pixel data corrupt"));
      return NULL;
    }

  if (encoding == GDK_PIXDATA_ENCODING_RAW &&
      pixdata->length >= 1 &&
      pixdata->length < pixdata->height * pixdata->rowstride - GDK_PIXDATA_HEADER_LENGTH)
    {
      g_set_error_literal (error, GDK_PIXBUF_ERROR,
                           GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                           _("Image pixel data corrupt"));
      return NULL;
    }

  if (copy_pixels)
    {
      data = g_try_malloc_n (pixdata->height, pixdata->rowstride);
      if (!data)
	{
	  g_set_error (error, GDK_PIXBUF_ERROR,
		       GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
		       g_dngettext(GETTEXT_PACKAGE,
				   "failed to allocate image buffer of %u byte",
				   "failed to allocate image buffer of %u bytes",
				   pixdata->rowstride * pixdata->height),
		       pixdata->rowstride * pixdata->height);
	  return NULL;
	}
    }
  if (encoding == GDK_PIXDATA_ENCODING_RLE)
    {
      const guint8 *rle_buffer = pixdata->pixel_data;
      guint8 *rle_buffer_limit = NULL;
      guint8 *image_buffer = data;
      guint8 *image_limit = data + pixdata->rowstride * pixdata->height;
      gboolean check_overrun = FALSE;

      if (pixdata->length >= 1)
        rle_buffer_limit = pixdata->pixel_data + pixdata->length - GDK_PIXDATA_HEADER_LENGTH;

      while (image_buffer < image_limit &&
             (rle_buffer_limit != NULL || rle_buffer > rle_buffer_limit))
	{
	  guint length;

	  if (RLE_OVERRUN(1))
	    {
	      check_overrun = TRUE;
	      break;
	    }

	  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 (RLE_OVERRUN(bpp < 4 ? 3 : 4))
	        {
	          check_overrun = TRUE;
	          break;
	        }
	      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);
	      if (RLE_OVERRUN(bpp))
	        {
	          check_overrun = TRUE;
	          break;
		}
	      rle_buffer += bpp;
	    }
	  else
	    {
	      length *= bpp;
	      check_overrun = image_buffer + length > image_limit;
	      if (check_overrun)
		length = image_limit - image_buffer;
	      if (RLE_OVERRUN(length))
	        {
	          check_overrun = TRUE;
	          break;
		}
	      memcpy (image_buffer, rle_buffer, length);
	      image_buffer += length;
	      rle_buffer += length;
	    }
	}
      if (check_overrun)
	{
	  g_free (data);
	  g_set_error_literal (error, GDK_PIXBUF_ERROR,
                               GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                               _("Image pixel data corrupt"));
	  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);
}
Beispiel #6
0
static void
mem_overflow (void)
{
  gsize a = G_MAXSIZE / 10 + 10;
  gsize b = 10;
  gpointer p, q;
  typedef char X[10];

#define CHECK_PASS(P)	p = (P); g_assert (p == NULL);
#define CHECK_FAIL(P)	p = (P); g_assert (p != NULL);

  CHECK_PASS (g_try_malloc_n (a, a));
  CHECK_PASS (g_try_malloc_n (a, b));
  CHECK_PASS (g_try_malloc_n (b, a));
  CHECK_FAIL (g_try_malloc_n (b, b));

  CHECK_PASS (g_try_malloc0_n (a, a));
  CHECK_PASS (g_try_malloc0_n (a, b));
  CHECK_PASS (g_try_malloc0_n (b, a));
  CHECK_FAIL (g_try_malloc0_n (b, b));

  q = g_malloc (1);
  CHECK_PASS (g_try_realloc_n (q, a, a));
  CHECK_PASS (g_try_realloc_n (q, a, b));
  CHECK_PASS (g_try_realloc_n (q, b, a));
  CHECK_FAIL (g_try_realloc_n (q, b, b));
  free (p);

  CHECK_PASS (g_try_new (X, a));
  CHECK_FAIL (g_try_new (X, b));

  CHECK_PASS (g_try_new0 (X, a));
  CHECK_FAIL (g_try_new0 (X, b));

  q = g_try_malloc (1);
  CHECK_PASS (g_try_renew (X, q, a));
  CHECK_FAIL (g_try_renew (X, q, b));
  free (p);

#undef CHECK_FAIL
#undef CHECK_PASS

#define CHECK_FAIL(P)	if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) { p = (P); exit (0); } g_test_trap_assert_failed();
#define CHECK_PASS(P)	if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) { p = (P); exit (0); } g_test_trap_assert_passed();

  CHECK_FAIL (g_malloc_n (a, a));
  CHECK_FAIL (g_malloc_n (a, b));
  CHECK_FAIL (g_malloc_n (b, a));
  CHECK_PASS (g_malloc_n (b, b));

  CHECK_FAIL (g_malloc0_n (a, a));
  CHECK_FAIL (g_malloc0_n (a, b));
  CHECK_FAIL (g_malloc0_n (b, a));
  CHECK_PASS (g_malloc0_n (b, b));

  q = g_malloc (1);
  CHECK_FAIL (g_realloc_n (q, a, a));
  CHECK_FAIL (g_realloc_n (q, a, b));
  CHECK_FAIL (g_realloc_n (q, b, a));
  CHECK_PASS (g_realloc_n (q, b, b));
  free (q);

  CHECK_FAIL (g_new (X, a));
  CHECK_PASS (g_new (X, b));

  CHECK_FAIL (g_new0 (X, a));
  CHECK_PASS (g_new0 (X, b));

  q = g_malloc (1);
  CHECK_FAIL (g_renew (X, q, a));
  CHECK_PASS (g_renew (X, q, b));
  free (q);
}