This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via 3568538bbc1602c05313b9224c1884a42a411ad6 (commit) via 983c8bab63c33eef9e7de3278cd5a8329486ab93 (commit) from 7044b9ef7967a50a1f0b437ad5a0554325484296 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/3568538bbc1602c05313b9224c1884a42a411...
commit 3568538bbc1602c05313b9224c1884a42a411ad6 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 15 19:05:29 2014 +0200
loaders: Implement Write() instead of Save()
This change implements Write() functions instead of the Save() functions for all loaders and removes Write() callback from GP_Loader structure.
It also adds a generic GP_LoaderSaveImage() function and bunch of GP_WriteFOO() functions.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/build/syms/Loaders_symbols.txt b/build/syms/Loaders_symbols.txt index bf8cb76c..2654ae54 100644 --- a/build/syms/Loaders_symbols.txt +++ b/build/syms/Loaders_symbols.txt @@ -3,6 +3,7 @@ GP_FWrite GP_MatchJPG GP_ReadJPG GP_LoadJPG +GP_WriteJPG GP_SaveJPG GP_ReadJPGMetaData GP_LoadJPGMetaData @@ -13,6 +14,7 @@ GP_ReadPNG GP_LoadPNG GP_ReadPNGMetaData GP_LoadPNGMetaData +GP_WritePNG GP_SavePNG GP_PNG
@@ -36,29 +38,34 @@ GP_GIF GP_MatchTIFF GP_ReadTIFF GP_LoadTIFF +GP_WriteTIFF GP_SaveTIFF GP_TIFF
GP_ReadPBM GP_LoadPBM +GP_WritePBM GP_SavePBM GP_MatchPBM GP_PBM
GP_ReadPGM GP_LoadPGM +GP_WritePGM GP_SavePGM GP_MatchPGM GP_PGM
GP_ReadPPM GP_LoadPPM +GP_WritePPM GP_SavePPM GP_MatchPPM GP_PPM
GP_ReadPNM GP_LoadPNM +GP_WritePNM GP_SavePNM GP_MatchPNM GP_PNM @@ -84,6 +91,7 @@ GP_LoadTmpFile GP_LoaderBySignature GP_LoaderByFilename GP_LoaderLoadImage +GP_LoaderSaveImage GP_ReadImage GP_LoadImage GP_SaveImage diff --git a/demos/c_simple/loaders_register.c b/demos/c_simple/loaders_register.c index 4c596c40..5152d6b5 100644 --- a/demos/c_simple/loaders_register.c +++ b/demos/c_simple/loaders_register.c @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2014 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
@@ -24,7 +24,7 @@
Shows how to register custom image loader/saver.
- Feed it with small image (cca 60x60 pixels) to produce ascii art version. + Feed it with small image (cca 60x60 pixels) to produce ASCII art version.
*/
@@ -37,17 +37,21 @@ /* * Saves 2 bpp grayscale image as ASCII Art */ -static int save(const GP_Context *img, const char *dst_path, - GP_ProgressCallback *callback) +static int write_data(const GP_Context *img, GP_IO *io, + GP_ProgressCallback *callback) { + GP_IO *bio; + int err; + if (img->pixel_type != GP_PIXEL_G2) { errno = ENOSYS; return 1; }
- FILE *f = fopen(dst_path, "w"); + /* Create buffered I/O */ + bio = GP_IOWBuffer(io, 0);
- if (f == NULL) + if (!bio) return 1;
unsigned int i, j; @@ -58,35 +62,33 @@ static int save(const GP_Context *img, const char *dst_path,
switch (p) { case 0: - fprintf(f, " "); + err = GP_IOFlush(bio, " ", 2); break; case 1: - fprintf(f, ".."); + err = GP_IOFlush(bio, "..", 2); break; case 2: - fprintf(f, "()"); + err = GP_IOFlush(bio, "()", 2); break; case 3: - fprintf(f, "OO"); + err = GP_IOFlush(bio, "OO", 2); break; } + + if (err) + return 1; }
- fprintf(f, "n"); + if (GP_IOFlush(bio, "n", 1)) + return 1;
if (GP_ProgressCallbackReport(callback, img->h, j, img->w)) { - fclose(f); - unlink(dst_path); errno = ECANCELED; return 1; } }
- if (fclose(f)) - return 1; - GP_ProgressCallbackDone(callback); - return 0; }
@@ -96,7 +98,7 @@ static GP_PixelType save_ptypes[] = { };
GP_Loader loader = { - .Save = save, + .Write = write_data, .save_ptypes = save_ptypes, .fmt_name = "ASCII Art", .extensions = {"txt", NULL}, diff --git a/include/loaders/GP_JPG.h b/include/loaders/GP_JPG.h index 381c084c..ff57d2c3 100644 --- a/include/loaders/GP_JPG.h +++ b/include/loaders/GP_JPG.h @@ -32,7 +32,7 @@ #include "loaders/GP_Loader.h"
/* - * Reads a JPEG from an IO stream. + * Reads a JPEG from an I/O stream. * * Returns newly allocated context cotaining the loaded image or in case of * failure NULL and errno is set. @@ -51,6 +51,12 @@ int GP_ReadJPGMetaData(GP_IO *io, GP_MetaData *data); int GP_LoadJPGMetaData(const char *src_path, GP_MetaData *data);
/* + * Writes JPEG into an I/O stream. + */ +int GP_WriteJPG(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback); + +/* * Saves JPEG to a file. */ int GP_SaveJPG(const GP_Context *src, const char *dst_path, diff --git a/include/loaders/GP_Loader.h b/include/loaders/GP_Loader.h index 90aeebb7..e0afc5aa 100644 --- a/include/loaders/GP_Loader.h +++ b/include/loaders/GP_Loader.h @@ -34,7 +34,6 @@ #include "loaders/GP_IO.h" #include "loaders/GP_MetaData.h"
- /* * Reads an image from a IO stream. * @@ -77,7 +76,7 @@ int GP_SaveImage(const GP_Context *src, const char *dst_path, */ typedef struct GP_Loader { /* - * Reads an image from an IO stream. + * Reads an image from an I/O stream. * * Returns newly allocated context cotaining the loaded image or in * case of failure NULL and errno is set. @@ -85,11 +84,12 @@ typedef struct GP_Loader { GP_Context *(*Read)(GP_IO *io, GP_ProgressCallback *callback);
/* - * Save an image. + * Writes an image into an I/O stream. * - * Returns zero on succes, non-zero on failure and errno must be set. + * Returns zero on success, non-zero on failure and errno must be set. */ - int (*Save)(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback); + int (*Write)(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback);
/* * GP_PIXEL_UNKNOWN terminated array of formats loader supports for save. @@ -154,6 +154,15 @@ GP_Context *GP_LoaderLoadImage(const GP_Loader *self, const char *src_path, GP_ProgressCallback *callback);
/* + * Generic SaveImage for a given loader. + * + * The function/ prepares the IO from file, calls the loader Write() method, + * closes the IO and returns the context. + */ +int GP_LoaderSaveImage(const GP_Loader *self, const GP_Context *src, + const char *dst_path, GP_ProgressCallback *callback); + +/* * List loaders into the stdout */ void GP_ListLoaders(void); diff --git a/include/loaders/GP_PNG.h b/include/loaders/GP_PNG.h index eb607010..0ef1e7c6 100644 --- a/include/loaders/GP_PNG.h +++ b/include/loaders/GP_PNG.h @@ -51,8 +51,13 @@ int GP_ReadPNGMetaData(GP_IO *io, GP_MetaData *data); int GP_LoadPNGMetaData(const char *src_path, GP_MetaData *data);
/* - * Saves PNG to a file. Zero is returned on succes. Upon failure non-zero is - * returned and errno is filled accordingly. + * Writes PNG into an I/O stream. + */ +int GP_SavePNG(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback); + +/* + * Saves PNG to a file. */ int GP_SavePNG(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback); diff --git a/include/loaders/GP_PNM.h b/include/loaders/GP_PNM.h index 13d5f4b4..4397c636 100644 --- a/include/loaders/GP_PNM.h +++ b/include/loaders/GP_PNM.h @@ -32,6 +32,9 @@ GP_Context *GP_ReadPBM(GP_IO *io, GP_ProgressCallback *callback);
GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback);
+int GP_WritePBM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback); + int GP_SavePBM(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback);
@@ -43,6 +46,9 @@ GP_Context *GP_ReadPGM(GP_IO *io, GP_ProgressCallback *callback); GP_Context *GP_LoadPGM(const char *src_path, GP_ProgressCallback *callback);
+int GP_WritePGM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback); + int GP_SavePGM(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback);
@@ -53,6 +59,9 @@ GP_Context *GP_ReadPPM(GP_IO *io, GP_ProgressCallback *callback);
GP_Context *GP_LoadPPM(const char *src_path, GP_ProgressCallback *callback);
+int GP_WritePPM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback); + int GP_SavePPM(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback);
@@ -63,6 +72,9 @@ GP_Context *GP_ReadPNM(GP_IO *io, GP_ProgressCallback *callback);
GP_Context *GP_LoadPNM(const char *src_path, GP_ProgressCallback *callback);
+int GP_WritePNM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback); + int GP_SavePNM(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback);
diff --git a/include/loaders/GP_TIFF.h b/include/loaders/GP_TIFF.h index ef5e4f33..e7fc9bc9 100644 --- a/include/loaders/GP_TIFF.h +++ b/include/loaders/GP_TIFF.h @@ -39,10 +39,16 @@ GP_Context *GP_ReadTIFF(GP_IO *io, GP_ProgressCallback *callback); GP_Context *GP_LoadTIFF(const char *src_path, GP_ProgressCallback *callback);
/* + * Writes TIFF into an I/O stream. + */ +int GP_WriteTIFF(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback); + +/* * Saves TIFF. */ int GP_SaveTIFF(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback); + GP_ProgressCallback *callback);
/* * Looks for TIFF file signature. Returns non-zero if found. diff --git a/libs/loaders/GP_BMP.c b/libs/loaders/GP_BMP.c index 2d042bf2..24aa2b04 100644 --- a/libs/loaders/GP_BMP.c +++ b/libs/loaders/GP_BMP.c @@ -850,6 +850,8 @@ int GP_WriteBMP(const GP_Context *src, GP_IO *io, struct bitmap_info_header header; int err;
+ GP_DEBUG(1, "Writing BMP to I/O (%p)", io); + if ((err = bmp_fill_header(src, &header))) goto err;
@@ -865,36 +867,15 @@ err: return 1; }
- int GP_SaveBMP(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback) { - GP_IO *io; - - GP_DEBUG(1, "Saving BMP Image '%s'", dst_path); - - io = GP_IOFile(dst_path, GP_IO_WRONLY); - - if (!io) - return 1; - - if (GP_WriteBMP(src, io, callback)) { - GP_IOClose(io); - unlink(dst_path); - return 1; - } - - if (GP_IOClose(io)) { - unlink(dst_path); - return 1; - } - - return 0; + return GP_LoaderSaveImage(&GP_BMP, src, dst_path, callback); }
struct GP_Loader GP_BMP = { .Read = GP_ReadBMP, - .Save = GP_SaveBMP, + .Write = GP_WriteBMP, .save_ptypes = out_pixel_types, .Match = GP_MatchBMP,
diff --git a/libs/loaders/GP_JPG.c b/libs/loaders/GP_JPG.c index dfca66fa..fa2713a9 100644 --- a/libs/loaders/GP_JPG.c +++ b/libs/loaders/GP_JPG.c @@ -40,10 +40,6 @@ #include "loaders/GP_LineConvert.h" #include "loaders/GP_JPG.h"
-#ifdef HAVE_JPEG - -#include <jpeglib.h> - /* * 0xff 0xd8 - start of image * 0xff 0x.. - start of frame @@ -56,6 +52,10 @@ int GP_MatchJPG(const void *buf) return !memcmp(buf, JPEG_SIGNATURE, JPEG_SIGNATURE_LEN); }
+#ifdef HAVE_JPEG + +#include <jpeglib.h> + struct my_jpg_err { struct jpeg_error_mgr error_mgr; jmp_buf setjmp_buf; @@ -144,7 +144,7 @@ struct my_source_mgr { GP_IO *io; };
-static void dummy(j_decompress_ptr GP_UNUSED(cinfo)) +static void dummy_src(j_decompress_ptr GP_UNUSED(cinfo)) { }
@@ -157,12 +157,12 @@ static boolean fill_input_buffer(struct jpeg_decompress_struct *cinfo)
if (ret < 0) { GP_WARN("Failed to fill buffer"); - return 0; + return FALSE; }
src->mgr.next_input_byte = src->buffer; src->mgr.bytes_in_buffer = ret; - return 1; + return TRUE; }
static void skip_input_data(struct jpeg_decompress_struct *cinfo, long num_bytes) @@ -187,9 +187,9 @@ static void skip_input_data(struct jpeg_decompress_struct *cinfo, long num_bytes static inline void init_source_mgr(struct my_source_mgr *src, GP_IO *io, void *buf, size_t buf_size) { - src->mgr.init_source = dummy; + src->mgr.init_source = dummy_src; src->mgr.resync_to_restart = jpeg_resync_to_restart; - src->mgr.term_source = dummy; + src->mgr.term_source = dummy_src; src->mgr.fill_input_buffer = fill_input_buffer; src->mgr.skip_input_data = skip_input_data; src->mgr.bytes_in_buffer = 0; @@ -431,22 +431,77 @@ static int save(struct jpeg_compress_struct *cinfo, return 0; }
+struct my_dest_mgr { + struct jpeg_destination_mgr mgr; + void *buffer; + ssize_t size; + GP_IO *io; +}; + +static void dummy_dst(j_compress_ptr GP_UNUSED(cinfo)) +{ +} + +static boolean empty_output_buffer(j_compress_ptr cinfo) +{ + struct my_dest_mgr *dest = (void*)cinfo->dest; + + if (GP_IOWrite(dest->io, dest->buffer, dest->size) != dest->size) { + GP_DEBUG(1, "Failed to write JPEG buffer"); + return FALSE; + } + + dest->mgr.next_output_byte = dest->buffer; + dest->mgr.free_in_buffer = dest->size; + + return TRUE; +} + +static void term_destination(j_compress_ptr cinfo) +{ + struct my_dest_mgr *dest = (void*)cinfo->dest; + ssize_t to_write = dest->size - dest->mgr.free_in_buffer; + + if (to_write > 0) { + if (GP_IOWrite(dest->io, dest->buffer, to_write) != to_write) { + GP_DEBUG(1, "Failed to write JPEG buffer"); + //TODO: Error handling + return; + } + } +} + +static inline void init_dest_mgr(struct my_dest_mgr *dst, GP_IO *io, + void *buf, size_t buf_size) +{ + dst->mgr.init_destination = dummy_dst; + dst->mgr.empty_output_buffer = empty_output_buffer; + dst->mgr.term_destination = term_destination; + dst->mgr.next_output_byte = buf; + dst->mgr.free_in_buffer = buf_size; + + dst->io = io; + dst->buffer = buf; + dst->size = buf_size; +} + static GP_PixelType out_pixel_types[] = { GP_PIXEL_BGR888, GP_PIXEL_G8, GP_PIXEL_UNKNOWN };
-int GP_SaveJPG(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +int GP_WriteJPG(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { - FILE *f; struct jpeg_compress_struct cinfo; GP_PixelType out_pix; struct my_jpg_err my_err; + struct my_dest_mgr dst; + uint8_t buf[1024]; int err;
- GP_DEBUG(1, "Saving JPG Image '%s'", dst_path); + GP_DEBUG(1, "Writing JPG Image to I/O (%p)", io);
out_pix = GP_LineConvertible(src->pixel_type, out_pixel_types);
@@ -457,19 +512,10 @@ int GP_SaveJPG(const GP_Context *src, const char *dst_path, return 1; }
- f = fopen(dst_path, "wb"); - - if (f == NULL) { - err = errno; - GP_DEBUG(1, "Failed to open '%s' for writing: %s", - dst_path, strerror(errno)); - goto err0; - } - if (setjmp(my_err.setjmp_buf)) { - err = EIO; - //TODO: is cinfo allocated? - goto err2; + errno = EIO; + return 1; + }
cinfo.err = jpeg_std_error(&my_err.error_mgr); @@ -477,7 +523,8 @@ int GP_SaveJPG(const GP_Context *src, const char *dst_path,
jpeg_create_compress(&cinfo);
- jpeg_stdio_dest(&cinfo, f); + init_dest_mgr(&dst, io, buf, sizeof(buf)); + cinfo.dest = (void*)&dst;
cinfo.image_width = src->w; cinfo.image_height = src->h; @@ -504,40 +551,22 @@ int GP_SaveJPG(const GP_Context *src, const char *dst_path, else err = save(&cinfo, src, callback);
- if (err) - goto err3; + if (err) { + jpeg_destroy_compress(&cinfo); + errno = err; + return 1; + }
jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo);
- if (fclose(f)) { - err = errno; - GP_DEBUG(1, "Failed to close file '%s': %s", - dst_path, strerror(errno)); - goto err1; - }
GP_ProgressCallbackDone(callback); return 0; -err3: - jpeg_destroy_compress(&cinfo); -err2: - fclose(f); -err1: - unlink(dst_path); -err0: - errno = err; - return 1; }
#else
-int GP_MatchJPG(const void GP_UNUSED(*buf)) -{ - errno = ENOSYS; - return -1; -} - GP_Context *GP_ReadJPG(GP_IO GP_UNUSED(*io), GP_ProgressCallback GP_UNUSED(*callback)) { @@ -545,22 +574,21 @@ GP_Context *GP_ReadJPG(GP_IO GP_UNUSED(*io), return NULL; }
-int GP_ReadJPGMetaData(GP_IO GP_UNUSED(*io), GP_MetaData GP_UNUSED(*data)) +int GP_WriteJPG(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { errno = ENOSYS; return 1; }
-int GP_LoadJPGMetaData(const char GP_UNUSED(*src_path), - GP_MetaData GP_UNUSED(*data)) +int GP_ReadJPGMetaData(GP_IO GP_UNUSED(*io), GP_MetaData GP_UNUSED(*data)) { errno = ENOSYS; return 1; }
-int GP_SaveJPG(const GP_Context GP_UNUSED(*src), - const char GP_UNUSED(*dst_path), - GP_ProgressCallback GP_UNUSED(*callback)) +int GP_LoadJPGMetaData(const char GP_UNUSED(*src_path), + GP_MetaData GP_UNUSED(*data)) { errno = ENOSYS; return 1; @@ -573,10 +601,16 @@ GP_Context *GP_LoadJPG(const char *src_path, GP_ProgressCallback *callback) return GP_LoaderLoadImage(&GP_JPG, src_path, callback); }
+int GP_SaveJPG(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_JPG, src, dst_path, callback); +} + struct GP_Loader GP_JPG = { #ifdef HAVE_JPEG .Read = GP_ReadJPG, - .Save = GP_SaveJPG, + .Write = GP_WriteJPG, .save_ptypes = out_pixel_types, #endif .Match = GP_MatchJPG, diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c index 12ca2fc8..f1d51f24 100644 --- a/libs/loaders/GP_Loader.c +++ b/libs/loaders/GP_Loader.c @@ -126,9 +126,9 @@ void GP_ListLoaders(void) for (i = 0; loaders[i]; i++) { printf("Format: %sn", loaders[i]->fmt_name); printf("Read:t%sn", loaders[i]->Read ? "Yes" : "No"); - printf("Save:t%sn", loaders[i]->Save ? "Yes" : "No"); + printf("Write:t%sn", loaders[i]->Write ? "Yes" : "No"); if (loaders[i]->save_ptypes) { - printf("Saves Pixel Types: "); + printf("Write Pixel Types: "); for (j = 0; loaders[i]->save_ptypes[j]; j++) { GP_PixelType ptype = loaders[i]->save_ptypes[j]; printf("%s ", GP_PixelTypeName(ptype)); @@ -282,6 +282,8 @@ GP_Context *GP_LoaderLoadImage(const GP_Loader *self, const char *src_path, GP_Context *res; int err;
+ GP_DEBUG(1, "Loading Image '%s'", src_path); + if (!self->Read) { errno = ENOSYS; return NULL; @@ -384,6 +386,37 @@ out: return 1; }
+int GP_LoaderSaveImage(const GP_Loader *self, const GP_Context *src, + const char *dst_path, GP_ProgressCallback *callback) +{ + GP_IO *io; + + GP_DEBUG(1, "Saving image '%s' format %s", dst_path, self->fmt_name); + + if (!self->Write) { + errno = ENOSYS; + return 1; + } + + io = GP_IOFile(dst_path, GP_IO_WRONLY); + + if (!io) + return 1; + + if (self->Write(src, io, callback)) { + GP_IOClose(io); + unlink(dst_path); + return 1; + } + + if (GP_IOClose(io)) { + unlink(dst_path); + return 1; + } + + return 0; +} + int GP_SaveImage(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback) { @@ -394,11 +427,7 @@ int GP_SaveImage(const GP_Context *src, const char *dst_path, return 1; }
- if (l->Save) - return l->Save(src, dst_path, callback); - - errno = ENOSYS; - return 1; + return GP_LoaderSaveImage(l, src, dst_path, callback); }
const GP_Loader *GP_LoaderBySignature(const void *buf) diff --git a/libs/loaders/GP_PNG.c b/libs/loaders/GP_PNG.c index deabf9ab..924eae37 100644 --- a/libs/loaders/GP_PNG.c +++ b/libs/loaders/GP_PNG.c @@ -522,38 +522,41 @@ static int write_png_data(const GP_Context *src, png_structp png, return 0; }
-int GP_SavePNG(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +static void write_data(png_structp png_ptr, png_bytep data, png_size_t len) +{ + GP_IO *io = png_get_io_ptr(png_ptr); + + if (GP_IOWrite(io, data, len) != (ssize_t)len) + png_error(png_ptr, "Write Error"); +} + +static void flush_data(png_structp png_ptr) +{ + (void)png_ptr; +} + +int GP_WritePNG(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { - FILE *f; png_structp png; png_infop png_info = NULL; int err;
- GP_DEBUG(1, "Saving PNG Image '%s'", dst_path); + GP_DEBUG(1, "Writing PNG Image to I/O (%p)", io);
if (prepare_png_header(src, NULL, NULL, NULL)) { GP_DEBUG(1, "Can't save png with %s pixel type", GP_PixelTypeName(src->pixel_type)); - err = ENOSYS; - goto err0; - } - - f = fopen(dst_path, "wb"); - - if (f == NULL) { - err = errno; - GP_DEBUG(1, "Failed to open '%s' for writing: %s", - dst_path, strerror(errno)); - goto err0; + errno = ENOSYS; + return 1; }
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png == NULL) { GP_DEBUG(1, "Failed to allocate PNG write buffer"); - err = ENOMEM; - goto err2; + errno = ENOMEM; + return 1; }
png_info = png_create_info_struct(png); @@ -561,17 +564,17 @@ int GP_SavePNG(const GP_Context *src, const char *dst_path, if (png_info == NULL) { GP_DEBUG(1, "Failed to allocate PNG info buffer"); err = ENOMEM; - goto err3; + goto err; }
if (setjmp(png_jmpbuf(png))) { GP_DEBUG(1, "Failed to write PNG file :("); //TODO: should we get better error description from libpng? err = EIO; - goto err3; + goto err; }
- png_init_io(png, f); + png_set_write_fn(png, io, write_data, flush_data);
int bit_endian_flag = 0; /* Fill png header and prepare for data */ @@ -579,28 +582,15 @@ int GP_SavePNG(const GP_Context *src, const char *dst_path,
/* Write bitmap buffer */ if ((err = write_png_data(src, png, callback, bit_endian_flag))) - goto err3; + goto err;
png_write_end(png, png_info); png_destroy_write_struct(&png, &png_info);
- if (fclose(f)) { - err = errno; - GP_DEBUG(1, "Failed to close file '%s': %s", - dst_path, strerror(errno)); - goto err1; - } - GP_ProgressCallbackDone(callback); - return 0; -err3: +err: png_destroy_write_struct(&png, png_info == NULL ? NULL : &png_info); -err2: - fclose(f); -err1: - unlink(dst_path); -err0: errno = err; return 1; } @@ -632,9 +622,8 @@ int GP_LoadPNGMetaData(const char GP_UNUSED(*src_path), GP_MetaData GP_UNUSED(*d return 1; }
-int GP_SavePNG(const GP_Context GP_UNUSED(*src), - const char GP_UNUSED(*dst_path), - GP_ProgressCallback GP_UNUSED(*callback)) +int GP_WritePNG(const GP_Context *src, GP_IO GP_UNUSED(*io), + GP_ProgressCallback *callback) { errno = ENOSYS; return 1; @@ -647,10 +636,16 @@ GP_Context *GP_LoadPNG(const char *src_path, GP_ProgressCallback *callback) return GP_LoaderLoadImage(&GP_PNG, src_path, callback); }
+int GP_SavePNG(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_PNG, src, dst_path, callback); +} + GP_Loader GP_PNG = { #ifdef HAVE_LIBPNG .Read = GP_ReadPNG, - .Save = GP_SavePNG, + .Write = GP_WritePNG, .save_ptypes = save_ptypes, #endif .Match = GP_MatchPNG, diff --git a/libs/loaders/GP_PNM.c b/libs/loaders/GP_PNM.c index ba459183..4f3f646d 100644 --- a/libs/loaders/GP_PNM.c +++ b/libs/loaders/GP_PNM.c @@ -348,17 +348,17 @@ static int get_ascii_int(struct buf *buf, int *val) /* * Five times faster than printf("%u", byte) */ -static inline int write_ascii_byte(FILE *f, uint8_t byte) +static inline int write_ascii_byte(GP_IO *io, uint8_t byte) { if (byte >= 100) - fputc_unlocked('0' + byte/100, f); + GP_IOPutC(io, '0' + byte/100);
if (byte >= 10) - fputc_unlocked('0' + (byte%100)/10, f); + GP_IOPutC(io, '0' + (byte%100)/10);
- fputc_unlocked('0' + (byte%10), f); + GP_IOPutC(io, '0' + (byte%10));
- return fputc_unlocked(' ', f) == EOF; + return GP_IOPutC(io, ' '); }
/* @@ -631,7 +631,7 @@ static int load_bin_rgb888(struct buf *buf, GP_Context *ctx, return 0; }
-static int save_ascii(FILE *f, const GP_Context *ctx, +static int save_ascii(GP_IO *io, const GP_Context *ctx, GP_ProgressCallback *cb, int inv) { uint32_t x, y; @@ -644,7 +644,7 @@ static int save_ascii(FILE *f, const GP_Context *ctx, if (inv) val = !val;
- if (write_ascii_byte(f, val)) { + if (write_ascii_byte(io, val)) { err = errno; GP_DEBUG(1, "Failed to write data"); return err; @@ -655,7 +655,9 @@ static int save_ascii(FILE *f, const GP_Context *ctx, GP_DEBUG(1, "Operation aborted"); return ECANCELED; } - fprintf(f, "n"); + + if (GP_IOPutC(io, 'n')) + return errno; }
GP_ProgressCallbackDone(cb); @@ -717,14 +719,13 @@ static GP_PixelType pbm_save_pixels[] = { GP_PIXEL_UNKNOWN, };
-int GP_SavePBM(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +int GP_WritePBM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { - FILE *f; + GP_IO *bio; int err;
- GP_DEBUG(1, "Saving context %ux%u %s to '%s'", - src->w, src->h, GP_PixelTypeName(src->pixel_type), dst_path); + GP_DEBUG(1, "Writing PBM into I/O (%p)", io);
if (src->pixel_type != GP_PIXEL_G1) { GP_DEBUG(1, "Invalid pixel type '%s'", @@ -733,27 +734,22 @@ int GP_SavePBM(const GP_Context *src, const char *dst_path, return 1; }
- f = fopen(dst_path, "w"); - - if (f == NULL) + bio = GP_IOWBuffer(io, 0); + if (!bio) return 1;
- if (fprintf(f, "P1n%u %un", - (unsigned int) src->w, (unsigned int) src->h) < 0) { - err = EIO; - goto err0; + if (GP_IOPrintF(io, "P1n%u %un", + (unsigned int) src->w, (unsigned int) src->h)) { + err = errno; + goto err; }
- if ((err = save_ascii(f, src, callback, 1))) - goto err0; + if ((err = save_ascii(bio, src, callback, 1))) + goto err;
- if (fclose(f)) - goto err0; - - return 0; -err0: - fclose(f); - unlink(dst_path); + return GP_IOClose(bio); +err: + GP_IOClose(bio); errno = err; return 1; } @@ -892,15 +888,13 @@ static GP_PixelType pgm_save_pixels[] = { GP_PIXEL_UNKNOWN, };
-int GP_SavePGM(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +int GP_WritePGM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { - FILE *f; - int depth; - int err = EIO; + int err, depth; + GP_IO *bio;
- GP_DEBUG(1, "Saving context %ux%u %s to '%s'", - src->w, src->h, GP_PixelTypeName(src->pixel_type), dst_path); + GP_DEBUG(1, "Writing PGM to I/O (%p)", io);
if ((depth = pixel_to_depth(src->pixel_type)) == -1) { GP_DEBUG(1, "Invalid pixel type '%s'", @@ -909,34 +903,22 @@ int GP_SavePGM(const GP_Context *src, const char *dst_path, return 1; }
- f = fopen(dst_path, "w"); + bio = GP_IOWBuffer(io, 0); + if (!bio) + return 1;
- if (f == NULL) { + if (GP_IOPrintF(io, "P2n%u %un%un", + (unsigned int) src->w, (unsigned int) src->h, depth)) { err = errno; - GP_DEBUG(1, "Failed to open file '%s': %s", - dst_path, strerror(errno)); - goto err0; + goto err; }
- if (fprintf(f, "P2n%u %un%un", - (unsigned int) src->w, (unsigned int) src->h, depth) < 0) - goto err1; - - if ((err = save_ascii(f, src, callback, 0))) - goto err1; - - if (fclose(f)) { - err = errno; - GP_DEBUG(1, "Failed to close file '%s': %s", - dst_path, strerror(errno)); - goto err0; - } + if ((err = save_ascii(bio, src, callback, 0))) + goto err;
- return 0; -err1: - fclose(f); -err0: - unlink(dst_path); + return GP_IOClose(bio); +err: + GP_IOClose(bio); errno = err; return 1; } @@ -1020,7 +1002,7 @@ static int write_binary_ppm(FILE *f, GP_Context *src) return 0; }
-static int save_ascii_rgb888(FILE *f, const GP_Context *ctx, +static int save_ascii_rgb888(GP_IO *io, const GP_Context *ctx, GP_LineConvert Convert, GP_ProgressCallback *cb) { uint32_t x, y; @@ -1037,9 +1019,9 @@ static int save_ascii_rgb888(FILE *f, const GP_Context *ctx, }
for (x = 0; x < ctx->w; x++) { - ret |= write_ascii_byte(f, addr[2]); - ret |= write_ascii_byte(f, addr[1]); - ret |= write_ascii_byte(f, addr[0]); + ret |= write_ascii_byte(io, addr[2]); + ret |= write_ascii_byte(io, addr[1]); + ret |= write_ascii_byte(io, addr[0]);
if (ret) return errno; @@ -1052,7 +1034,7 @@ static int save_ascii_rgb888(FILE *f, const GP_Context *ctx, return ECANCELED; }
- if (fprintf(f, "n") < 0) + if (GP_IOPutC(io, 'n')) return errno; }
@@ -1065,16 +1047,15 @@ static GP_PixelType ppm_save_pixels[] = { GP_PIXEL_UNKNOWN, };
-int GP_SavePPM(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +int GP_WritePPM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { GP_Pixel out_pix; GP_LineConvert Convert; - FILE *f; - int err = EIO; + GP_IO *bio; + int err = 0;
- GP_DEBUG(1, "Saving context %ux%u %s to '%s'", - src->w, src->h, GP_PixelTypeName(src->pixel_type), dst_path); + GP_DEBUG(1, "Writing PPM into I/O (%p)", io);
out_pix = GP_LineConvertible(src->pixel_type, ppm_save_pixels);
@@ -1085,37 +1066,25 @@ int GP_SavePPM(const GP_Context *src, const char *dst_path, return 1; }
- f = fopen(dst_path, "w"); + bio = GP_IOWBuffer(io, 0); + if (!bio) + return 1;
- if (f == NULL) { + if (GP_IOPrintF(io, "P3n%u %un255n", + (unsigned int) src->w, (unsigned int) src->h)) { err = errno; - GP_DEBUG(1, "Failed to open file '%s': %s", - dst_path, strerror(errno)); - goto err0; + goto err; }
- if (fprintf(f, "P3n%u %un255n", - (unsigned int) src->w, (unsigned int) src->h) < 0) - goto err1; - Convert = GP_LineConvertGet(src->pixel_type, out_pix);
- if ((err = save_ascii_rgb888(f, src, Convert, callback))) - goto err1; + if ((err = save_ascii_rgb888(bio, src, Convert, callback))) + goto err;
- if (fclose(f)) { - err = errno; - GP_DEBUG(1, "Failed to close file '%s': %s", - dst_path, strerror(errno)); - goto err0; - } - - return 0; -err1: - fclose(f); -err0: + return GP_IOClose(bio); +err: + GP_IOClose(bio); errno = err; - unlink(dst_path); return 1; }
@@ -1153,20 +1122,20 @@ static GP_PixelType pnm_save_pixels[] = { GP_PIXEL_UNKNOWN, };
-int GP_SavePNM(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +int GP_WritePNM(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { switch (src->pixel_type) { case GP_PIXEL_G1: case GP_PIXEL_G2: case GP_PIXEL_G4: case GP_PIXEL_G8: - return GP_SavePGM(src, dst_path, callback); + return GP_WritePGM(src, io, callback); case GP_PIXEL_RGB888: - return GP_SavePPM(src, dst_path, callback); + return GP_WritePPM(src, io, callback); default: if (GP_LineConvertible(src->pixel_type, ppm_save_pixels)) - return GP_SavePPM(src, dst_path, callback); + return GP_WritePPM(src, io, callback);
errno = EINVAL; return 1; @@ -1178,24 +1147,48 @@ GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback) return GP_LoaderLoadImage(&GP_PBM, src_path, callback); }
+int GP_SavePBM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_PBM, src, dst_path, callback); +} + GP_Context *GP_LoadPGM(const char *src_path, GP_ProgressCallback *callback) { return GP_LoaderLoadImage(&GP_PGM, src_path, callback); }
+int GP_SavePGM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_PGM, src, dst_path, callback); +} + GP_Context *GP_LoadPPM(const char *src_path, GP_ProgressCallback *callback) { return GP_LoaderLoadImage(&GP_PPM, src_path, callback); }
+int GP_SavePPM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_PPM, src, dst_path, callback); +} + GP_Context *GP_LoadPNM(const char *src_path, GP_ProgressCallback *callback) { return GP_LoaderLoadImage(&GP_PNM, src_path, callback); }
+int GP_SavePNM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_PNM, src, dst_path, callback); +} + struct GP_Loader GP_PBM = { .Read = GP_ReadPBM, - .Save = GP_SavePBM, + .Write = GP_WritePBM, .save_ptypes = pbm_save_pixels, .Match = GP_MatchPBM,
@@ -1205,7 +1198,7 @@ struct GP_Loader GP_PBM = {
struct GP_Loader GP_PGM = { .Read = GP_ReadPGM, - .Save = GP_SavePGM, + .Write = GP_WritePGM, .save_ptypes = pgm_save_pixels, .Match = GP_MatchPGM,
@@ -1215,7 +1208,7 @@ struct GP_Loader GP_PGM = {
struct GP_Loader GP_PPM = { .Read = GP_ReadPPM, - .Save = GP_SavePPM, + .Write = GP_WritePPM, .save_ptypes = ppm_save_pixels, .Match = GP_MatchPPM,
@@ -1225,7 +1218,7 @@ struct GP_Loader GP_PPM = {
struct GP_Loader GP_PNM = { .Read = GP_ReadPNM, - .Save = GP_SavePNM, + .Write = GP_WritePNM, .save_ptypes = pnm_save_pixels, /* * Avoid double Match diff --git a/libs/loaders/GP_TIFF.c b/libs/loaders/GP_TIFF.c index 400d6734..29f4812e 100644 --- a/libs/loaders/GP_TIFF.c +++ b/libs/loaders/GP_TIFF.c @@ -40,10 +40,6 @@
#include "GP_TIFF.h"
-#ifdef HAVE_TIFF - -#include <tiffio.h> - #define TIFF_HEADER_LITTLE "IIx2a0" #define TIFF_HEADER_BIG "MM0x2a"
@@ -58,6 +54,10 @@ int GP_MatchTIFF(const void *buf) return 0; }
+#ifdef HAVE_TIFF + +#include <tiffio.h> + static const char *compression_name(uint16_t compression) { switch (compression) { @@ -442,10 +442,7 @@ static tsize_t tiff_io_read(thandle_t io, void *buf, tsize_t size)
static tsize_t tiff_io_write(thandle_t io, void *buf, tsize_t size) { - (void) io; - (void) buf; - GP_WARN("stub called"); - return size; + return GP_IOWrite(io, buf, size); }
static toff_t tiff_io_seek(thandle_t io, toff_t offset, int whence) @@ -643,12 +640,14 @@ static GP_PixelType save_ptypes[] = { GP_PIXEL_UNKNOWN, };
-int GP_SaveTIFF(const GP_Context *src, const char *dst_path, - GP_ProgressCallback *callback) +int GP_WriteTIFF(const GP_Context *src, GP_IO *io, + GP_ProgressCallback *callback) { TIFF *tiff; int err = 0;
+ GP_DEBUG(1, "Writing TIFF to I/O (%p)", io); + if (GP_PixelHasFlags(src->pixel_type, GP_PIXEL_HAS_ALPHA)) { GP_DEBUG(1, "Alpha channel not supported yet"); errno = ENOSYS; @@ -673,11 +672,13 @@ int GP_SaveTIFF(const GP_Context *src, const char *dst_path, }
/* Open TIFF image */ - tiff = TIFFOpen(dst_path, "w"); + tiff = TIFFClientOpen("GFXprim IO", "w", io, tiff_io_read, + tiff_io_write, tiff_io_seek, tiff_io_close, + tiff_io_size, NULL, NULL);
- if (tiff == NULL) { - GP_DEBUG(1, "Failed to open tiff '%s'", dst_path); - //ERRNO? + if (!tiff) { + GP_DEBUG(1, "TIFFClientOpen failed"); + errno = EIO; return 1; }
@@ -706,7 +707,6 @@ int GP_SaveTIFF(const GP_Context *src, const char *dst_path,
if (err) { TIFFClose(tiff); - unlink(dst_path); errno = err; return 1; } @@ -718,19 +718,6 @@ int GP_SaveTIFF(const GP_Context *src, const char *dst_path,
#else
-int GP_MatchTIFF(const void GP_UNUSED(*buf)) -{ - errno = ENOSYS; - return -1; -} - -int GP_OpenTIFF(const char GP_UNUSED(*src_path), - void GP_UNUSED(**t)) -{ - errno = ENOSYS; - return 1; -} - GP_Context *GP_ReadTIFF(GP_IO GP_UNUSED(*io), GP_ProgressCallback GP_UNUSED(*callback)) { @@ -738,9 +725,8 @@ GP_Context *GP_ReadTIFF(GP_IO GP_UNUSED(*io), return NULL; }
-int GP_SaveTIFF(const GP_Context GP_UNUSED(*src), - const char GP_UNUSED(*dst_path), - GP_ProgressCallback GP_UNUSED(*callback)) +int GP_WriteTIFF(const GP_Context GP_UNUSED(*src), GP_IO GP_UNUSED(*io), + GP_ProgressCallback GP_UNUSED(*callback)) { errno = ENOSYS; return 1; @@ -753,10 +739,16 @@ GP_Context *GP_LoadTIFF(const char *src_path, GP_ProgressCallback *callback) return GP_LoaderLoadImage(&GP_TIFF, src_path, callback); }
+int GP_SaveTIFF(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + return GP_LoaderSaveImage(&GP_TIFF, src, dst_path, callback); +} + struct GP_Loader GP_TIFF = { #ifdef HAVE_TIFF .Read = GP_ReadTIFF, - .Save = GP_SaveTIFF, + .Write = GP_WriteTIFF, .save_ptypes = save_ptypes, #endif .Match = GP_MatchTIFF,
http://repo.or.cz/w/gfxprim.git/commit/983c8bab63c33eef9e7de3278cd5a8329486a...
commit 983c8bab63c33eef9e7de3278cd5a8329486ab93 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 15 21:16:50 2014 +0200
loaders: IO: Add new functions
* Add GP_IOFlush() that works like Write() but either writes whole or returns an error.
* Add GP_IOWBuffer a write buffered I/O that can be created on the top of an I/O.
* Add GP_IOPutC() unlike the libc putc() it returns zero on success.
* Add GP_IOPrintF()
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/build/syms/Loaders_symbols.txt b/build/syms/Loaders_symbols.txt index bb834f97..bf8cb76c 100644 --- a/build/syms/Loaders_symbols.txt +++ b/build/syms/Loaders_symbols.txt @@ -118,13 +118,16 @@ GP_LineConvertGet GP_IOFile GP_IOMem GP_IOSubIO +GP_IOWBuffer GP_IOMark GP_IOSize GP_IOFill +GP_IOFlush GP_IOReadF GP_IOReadB2 GP_IOReadB4 GP_IOWriteF +GP_IOPrintF
GP_IOZlib GP_IOZlibReset diff --git a/include/loaders/GP_IO.h b/include/loaders/GP_IO.h index 19a1c78e..041321a3 100644 --- a/include/loaders/GP_IO.h +++ b/include/loaders/GP_IO.h @@ -79,6 +79,14 @@ static inline off_t GP_IOSeek(GP_IO *io, off_t off, enum GP_IOWhence whence) return io->Seek(io, off, whence); }
+/* + * PutC returns zero on success, non-zero on failure. + */ +static inline int GP_IOPutC(GP_IO *io, char c) +{ + return io->Write(io, &c, 1) != 1; +} + //static inline void *GP_IOMap(GP_IO *io, size_t len, off_t off) //{ // return io->Map(io, len, off); @@ -120,6 +128,13 @@ off_t GP_IOSize(GP_IO *io); int GP_IOFill(GP_IO *io, void *buf, size_t size);
/* + * Like Write but either writes whole buffer or retuns error. + * + * Returns zero on succes non-zero on failure. + */ +int GP_IOFlush(GP_IO *io, void *buf, size_t size); + +/* * Marks a current position, returns to mark in I/O stream. */ enum GP_IOMarkTypes { @@ -134,7 +149,7 @@ int GP_IOMark(GP_IO *self, enum GP_IOMarkTypes type); * * */ -enum GP_IOReadFTypes { +enum GP_IOFTypes { /* Constant byte in lower half */ GP_IO_CONST = 0x0000, /* Pointer to one byte */ @@ -176,6 +191,14 @@ int GP_IOReadF(GP_IO *self, uint16_t *types, ...); int GP_IOWriteF(GP_IO *self, uint16_t *types, ...);
/* + * Printf like function. + * + * Returns zero on success, non-zero on failure. + */ +int GP_IOPrintF(GP_IO *self, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +/* * GP_IOReadF wrappers for convinient reading of single value */ int GP_IOReadB4(GP_IO *io, uint32_t *val); @@ -213,4 +236,11 @@ GP_IO *GP_IOMem(void *buf, size_t size, void (*free)(void *)); */ GP_IO *GP_IOSubIO(GP_IO *pio, size_t size);
+/* + * Creates a writeable buffered I/O on the top of the existing I/O. + * + * Passing zero as bsize select default buffer size. + */ +GP_IO *GP_IOWBuffer(GP_IO *pio, size_t bsize); + #endif /* LOADERS_GP_IO_H */ diff --git a/libs/loaders/GP_IO.c b/libs/loaders/GP_IO.c index 145058b8..329fdd43 100644 --- a/libs/loaders/GP_IO.c +++ b/libs/loaders/GP_IO.c @@ -374,6 +374,82 @@ GP_IO *GP_IOSubIO(GP_IO *pio, size_t size) return io; }
+struct buf_io { + GP_IO *io; + size_t bsize; + size_t bpos; + uint8_t buf[]; +}; + +static int wbuf_close(GP_IO *io) +{ + struct buf_io *buf_io = GP_IO_PRIV(io); + int ret = 0; + + GP_DEBUG(1, "Closing BufferIO (from %p)", buf_io->io); + + if (buf_io->bpos) { + if (GP_IOFlush(buf_io->io, buf_io->buf, buf_io->bsize)) + ret = 1; + } + + free(io); + return ret; +} + +static ssize_t buf_write(GP_IO *io, void *buf, size_t size) +{ + struct buf_io *buf_io = GP_IO_PRIV(io); + size_t bfree = buf_io->bsize - buf_io->bpos; + + if (bfree < size) { + GP_DEBUG(1, "Flusing BufferIO (%p)", io); + if (GP_IOFlush(buf_io->io, buf_io->buf, buf_io->bpos)) + return -1; + buf_io->bpos = 0; + } + + if (size > buf_io->bsize) { + GP_DEBUG(1, "Buffer too large, doing direct write (%p)", io); + if (GP_IOFlush(buf_io->io, buf, size)) + return -1; + return size; + } + + memcpy(buf_io->buf + buf_io->bpos, buf, size); + buf_io->bpos += size; + return size; +} + +GP_IO *GP_IOWBuffer(GP_IO *pio, size_t bsize) +{ + GP_IO *io; + struct buf_io *buf_io; + + if (!bsize) + bsize = 512; + + GP_DEBUG(1, "Creating IOWBuffer (from %p) size=%zu", pio, bsize); + + //TODO: Do not create buffer IO for MemIO, just copy the callbacks to new IO + io = malloc(sizeof(GP_IO) + sizeof(*buf_io) + bsize); + + if (!io) + return NULL; + + io->Write = buf_write; + io->Close = wbuf_close; + io->Read = NULL; + io->Seek = NULL; + + buf_io = GP_IO_PRIV(io); + buf_io->io = pio; + buf_io->bsize = bsize; + buf_io->bpos = 0; + + return io; +} + int GP_IOMark(GP_IO *self, enum GP_IOMarkTypes type) { off_t ret; @@ -441,6 +517,58 @@ int GP_IOFill(GP_IO *io, void *buf, size_t size) return 0; }
+int GP_IOFlush(GP_IO *io, void *buf, size_t size) +{ + size_t wrote = 0; + int ret; + + do { + ret = GP_IOWrite(io, (char*)buf + wrote, size - wrote); + + if (ret <= 0) { + GP_DEBUG(1, "Failed to flush buffer: %s", + strerror(errno)); + return 1; + } + + wrote += ret; + + } while (wrote < size); + + return 0; +} + +int GP_IOPrintF(GP_IO *io, const char *fmt, ...) +{ + va_list va, vac; + size_t size; + int ret; + char buf[1024]; + char *bufp = buf; + + va_start(va, fmt); + va_copy(vac, va); + size = vsnprintf(buf, sizeof(buf), fmt, vac); + va_end(vac); + + if (size >= sizeof(buf)) { + bufp = malloc(size+1); + if (!bufp) + return 1; + + vsnprintf(bufp, size, fmt, va); + } + + ret = GP_IOFlush(io, bufp, size); + + if (size >= sizeof(buf)) + free(bufp); + + va_end(va); + + return ret; +} + #define TYPE(x) ((x) & GP_IO_TYPE_MASK) #define VAL(x) ((x) & ~GP_IO_TYPE_MASK)
-----------------------------------------------------------------------
Summary of changes: build/syms/Loaders_symbols.txt | 11 ++ demos/c_simple/loaders_register.c | 38 ++++---- include/loaders/GP_IO.h | 32 ++++++- include/loaders/GP_JPG.h | 8 ++- include/loaders/GP_Loader.h | 19 +++- include/loaders/GP_PNG.h | 9 ++- include/loaders/GP_PNM.h | 12 +++ include/loaders/GP_TIFF.h | 8 ++- libs/loaders/GP_BMP.c | 27 +----- libs/loaders/GP_IO.c | 128 ++++++++++++++++++++++++ libs/loaders/GP_JPG.c | 146 +++++++++++++++++----------- libs/loaders/GP_Loader.c | 43 +++++++-- libs/loaders/GP_PNG.c | 73 +++++++------- libs/loaders/GP_PNM.c | 197 ++++++++++++++++++------------------- libs/loaders/GP_TIFF.c | 56 +++++------ 15 files changed, 520 insertions(+), 287 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.