int TGA_Write(char *filename, Image_t *Image, int rle) { FILE *stream; unsigned char IDLength=0; unsigned char ColorMapType=0, ColorMapStart=0, ColorMapLength=0, ColorMapDepth=0; unsigned short XOffset=0, YOffset=0, Width=Image->Width, Height=Image->Height; unsigned char Depth=(unsigned char)Image->Depth, ImageDescriptor=0, ImageType; switch(Image->Depth) { case 32: case 24: case 16: ImageType=rle?10:2; break; case 8: ImageType=rle?11:3; break; default: return 0; } if((stream=fopen(filename, "wb"))==NULL) return 0; fwrite(&IDLength, sizeof(unsigned char), 1, stream); fwrite(&ColorMapType, sizeof(unsigned char), 1, stream); fwrite(&ImageType, sizeof(unsigned char), 1, stream); fwrite(&ColorMapStart, sizeof(unsigned short), 1, stream); fwrite(&ColorMapLength, sizeof(unsigned short), 1, stream); fwrite(&ColorMapDepth, sizeof(unsigned char), 1, stream); fwrite(&XOffset, sizeof(unsigned short), 1, stream); fwrite(&XOffset, sizeof(unsigned short), 1, stream); fwrite(&Width, sizeof(unsigned short), 1, stream); fwrite(&Height, sizeof(unsigned short), 1, stream); fwrite(&Depth, sizeof(unsigned char), 1, stream); fwrite(&ImageDescriptor, sizeof(unsigned char), 1, stream); if(rle) { unsigned char *ptr; int i, bpp=Depth>>3; for(i=0, ptr=Image->Data;i<Height;i++, ptr+=Width*bpp) rle_write(ptr, Width, bpp, stream); } else
static gboolean _cairo_surface_write_as_tga (cairo_surface_t *image, char **buffer, gsize *buffer_size, char **keys, char **values, GError **error) { GthBufferData *buffer_data; int out_bpp = 0; int row; guchar header[18]; guchar footer[26]; gboolean rle_compression; gboolean alpha; guchar *pixels, *ptr, *buf; int width, height; int rowstride; rle_compression = TRUE; if (keys && *keys) { char **kiter = keys; char **viter = values; while (*kiter) { if (strcmp (*kiter, "compression") == 0) { if (*viter == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "Must specify a compression type"); return FALSE; } if (strcmp (*viter, "none") == 0) rle_compression = FALSE; else if (strcmp (*viter, "rle") == 0) rle_compression = TRUE; else { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "Unsupported compression type passed to the TGA saver"); return FALSE; } } else { g_warning ("Bad option name '%s' passed to the TGA saver", *kiter); return FALSE; } ++kiter; ++viter; } } width = cairo_image_surface_get_width (image); height = cairo_image_surface_get_height (image); alpha = _cairo_image_surface_get_has_alpha (image); pixels = _cairo_image_surface_flush_and_get_data (image); rowstride = cairo_image_surface_get_stride (image); buffer_data = gth_buffer_data_new (); /* write the header */ header[0] = 0; /* No image identifier / description */ header[1] = 0; header[2] = rle_compression ? 10 : 2; header[3] = header[4] = header[5] = header[6] = header[7] = 0; header[8] = header[9] = 0; /* xorigin */ header[10] = header[11] = 0; /* yorigin */ header[12] = width % 256; header[13] = width / 256; header[14] = height % 256; header[15] = height / 256; if (alpha) { out_bpp = 4; header[16] = 32; /* bpp */ header[17] = 0x28; /* alpha + orientation */ } else { out_bpp = 3; header[16] = 24; /* bpp */ header[17] = 0x20; /* alpha + orientation */ } gth_buffer_data_write (buffer_data, header, sizeof (header), error); /* allocate a small buffer to convert image data */ buf = g_try_malloc (width * out_bpp * sizeof (guchar)); if (! buf) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Insufficient memory")); return FALSE; } ptr = pixels; for (row = 0; row < height; ++row) { _cairo_copy_line_as_rgba_little_endian (buf, ptr, width, alpha); if (rle_compression) rle_write (buffer_data, buf, width, out_bpp, error); else gth_buffer_data_write (buffer_data, buf, width * out_bpp, error); ptr += rowstride; } g_free (buf); /* write the footer */ memset (footer, 0, 8); /* No extensions, no developer directory */ memcpy (footer + 8, magic, sizeof (magic)); /* magic signature */ gth_buffer_data_write (buffer_data, footer, sizeof (footer), error); gth_buffer_data_get (buffer_data, buffer, buffer_size); gth_buffer_data_free (buffer_data, FALSE); return TRUE; }
static gboolean _gdk_pixbuf_save_as_tga (GdkPixbuf *pixbuf, const char *filename, char **keys, char **values, GError **error) { FILE *fp; int out_bpp = 0; int row; guchar header[18]; guchar footer[26]; gboolean rle_compression; gboolean alpha; guchar *pixels, *ptr, *buf; int width, height; int rowstride; rle_compression = TRUE; if (keys && *keys) { char **kiter = keys; char **viter = values; while (*kiter) { if (strcmp (*kiter, "compression") == 0) { if (*viter == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "Must specify a compression type"); return FALSE; } if (strcmp (*viter, "none") == 0) rle_compression = FALSE; else if (strcmp (*viter, "rle") == 0) rle_compression = TRUE; else { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "Unsupported compression type passed to the TGA saver"); return FALSE; } } else { g_warning ("Bad option name '%s' passed to the TGA saver", *kiter); return FALSE; } ++kiter; ++viter; } } width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); alpha = gdk_pixbuf_get_has_alpha (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); if ((fp = fopen (filename, "wb")) == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Can't write image to file '%s'", filename); return FALSE; } header[0] = 0; /* No image identifier / description */ header[1]= 0; header[2]= rle_compression ? 10 : 2; header[3] = header[4] = header[5] = header[6] = header[7] = 0; header[8] = header[9] = 0; /* xorigin */ header[10] = header[11] = 0; /* yorigin */ header[12] = width % 256; header[13] = width / 256; header[14] = height % 256; header[15] = height / 256; if (alpha) { out_bpp = 4; header[16] = 32; /* bpp */ header[17] = 0x28; /* alpha + orientation */ } else { out_bpp = 3; header[16] = 24; /* bpp */ header[17] = 0x20; /* alpha + orientation */ } /* write header to front of file */ fwrite (header, sizeof (header), 1, fp); /* allocate a small buffer to convert image data */ buf = g_try_malloc (width * out_bpp * sizeof (guchar)); if (! buf) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, "Couldn't allocate memory for writing TGA file '%s'", filename); return FALSE; } ptr = pixels; for (row = 0; row < height; ++row) { bgr2rgb (buf, ptr, width, out_bpp, alpha); if (rle_compression) rle_write (fp, buf, width, out_bpp); else fwrite (buf, width * out_bpp, 1, fp); ptr += rowstride; } g_free (buf); /* footer must be the last thing written to file */ memset (footer, 0, 8); /* No extensions, no developer directory */ memcpy (footer + 8, magic, sizeof (magic)); /* magic signature */ fwrite (footer, sizeof (footer), 1, fp); fclose (fp); return TRUE; }