Commits

Anonymous committed f353fd1

Use tmpfile for IO that doesn't support seek, also fix a memory leak.

  • Participants
  • Parent commits 8cd6354

Comments (0)

Files changed (1)

 	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 */
 			uncompressed_row = uncompressed_row_start = (unsigned char *) gdCalloc(gdImageSX(im) * 2, sizeof(char));
 			if (!uncompressed_row) {
 				/* malloc failed */
-				return;
+				goto cleanup;
 			}
 		}
 
 		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);
 			}
 		}
 	}
+
+
+	/* 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)
 	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++)
 	{
 		}
 	}
 
+	gdFree(uncompressed_start);
+
 	return compressed_length;
 }