cvs: gd /playground/gdbmp gd_bmp.c

[email protected] ("Scott MacVicar") Fri, 09 May 2008 11:13:20 -0000
Newsgroups php.gd.cvs
Message-ID <cvsscottmac1210331600@cvsserver>
scottmac		Fri May  9 11:13:20 2008 UTC

  Modified files:              
    /gd/playground/gdbmp	gd_bmp.c 
  Log:
  Use tmpfile for IO that doesn't support seek, also fix a memory leak.
  
http://cvs.php.net/viewvc.cgi/gd/playground/gdbmp/gd_bmp.c?r1=1.12&r2=1.13&diff_format=u
Index: gd/playground/gdbmp/gd_bmp.c
diff -u gd/playground/gdbmp/gd_bmp.c:1.12 gd/playground/gdbmp/gd_bmp.c:1.13
--- gd/playground/gdbmp/gd_bmp.c:1.12	Thu Mar 27 14:36:27 2008
+++ gd/playground/gdbmp/gd_bmp.c	Fri May  9 11:13:20 2008
@@ -12,7 +12,7 @@
 
 	----------------------------------------------------------------------------
  */
-/* $Id: gd_bmp.c,v 1.12 2008/03/27 14:36:27 scottmac Exp $ */
+/* $Id: gd_bmp.c,v 1.13 2008/05/09 11:13:20 scottmac Exp $ */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -89,12 +89,28 @@
 	int i, row, xpos, pixel;
 	int error = 0;
 	unsigned char *uncompressed_row = NULL, *uncompressed_row_start = NULL;
+	FILE *tmpfile_for_compression = NULL;
+	gdIOCtxPtr out_original = NULL;
 
 	/* No compression if its true colour or we don't support seek */
-	if (im->trueColor || !out->seek) {
+	if (im->trueColor) {
 		compression = 0;
 	}
 
+	if (compression == 1 && !out->seek) {
+		/* Try to create a temp file where we can seek */
+		if ((tmpfile_for_compression = tmpfile()) == NULL) {
+			compression = 0;
+		} else {
+			out_original = out;
+			if ((out = (gdIOCtxPtr)gdNewFileCtx(tmpfile_for_compression)) == NULL) {
+				out = out_original;
+				out_original = NULL;
+				compression = 0;
+			}
+		}
+	}
+
 	bitmap_size = ((im->sx * (im->trueColor ? 24 : 8)) / 8) * im->sy;
 
 	/* 40 byte Windows v3 header */
@@ -151,7 +167,7 @@
 			uncompressed_row = uncompressed_row_start = (unsigned char *) gdCalloc(gdImageSX(im) * 2, sizeof(char));
 			if (!uncompressed_row) {
 				/* malloc failed */
-				return;
+				goto cleanup;
 			}
 		}
 
@@ -193,7 +209,7 @@
 		if (compression && uncompressed_row) {
 			gdFree(uncompressed_row);
 			if (error != 0) {
-				return;
+				goto cleanup;
 			}
 			/* Update filesize based on new values and set compression flag */
 			Putchar(BMP_RLE_COMMAND, out);
@@ -225,6 +241,47 @@
 			}
 		}
 	}
+
+
+	/* If we needed a tmpfile for compression copy it over to out_original */
+	if (tmpfile_for_compression) {
+		unsigned char* copy_buffer = NULL;
+		int buffer_size = 0;
+
+		gdSeek(out, 0);
+		copy_buffer = (unsigned char *) gdMalloc(1024 * sizeof(unsigned char));
+		if (copy_buffer == NULL) {
+			goto cleanup;
+		}
+
+		while ((buffer_size = gdGetBuf(copy_buffer, 1024, out)) != EOF) {
+			if (buffer_size == 0) {
+				break;
+			}
+			gdPutBuf(copy_buffer , buffer_size, out_original);
+		}
+		gdFree(copy_buffer);
+
+		/* Replace the temp with the original which now has data */
+		out->gd_free(out);
+		out = out_original;
+		out_original = NULL;
+	}
+
+cleanup:
+	if (tmpfile_for_compression) {
+#ifdef WIN32
+		_rmtmp();
+#else
+		fclose(tmpfile_for_compression);
+#endif
+		tmpfile_for_compression = NULL;
+	}
+
+	if (out_original) {
+		out_original->gd_free(out_original);
+	}
+	return;
 }
 
 static int compress_row(unsigned char *row, int length)
@@ -232,15 +289,15 @@
 	int rle_type = 0;
 	int compressed_length = 0;
 	int pixel = 0, compressed_run = 0, rle_compression = 0;
-	unsigned char *uncompressed_row = NULL, *uncompressed_rowp = NULL;
+	unsigned char *uncompressed_row = NULL, *uncompressed_rowp = NULL, *uncompressed_start = NULL;
 
 	uncompressed_row = (unsigned char *) gdMalloc(length);
 	if (!uncompressed_row) {
 		return -1;
 	}
-	
+
 	memcpy(uncompressed_row, row, length);
-	uncompressed_rowp = uncompressed_row;
+	uncompressed_start = uncompressed_rowp = uncompressed_row;
 
 	for (pixel = 0; pixel < length; pixel++)
 	{
@@ -296,6 +353,8 @@
 		}
 	}
 
+	gdFree(uncompressed_start);
+
 	return compressed_length;
 }