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 972b83d7f74f4c22839536d0604183c717f545dc (commit) via 71dc80d8bbbdc5af75aed1896288e2d7a34cdead (commit) from 42571d6c7b8ffe8318c1ecfa32dbba3fc3c9c28b (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/972b83d7f74f4c22839536d0604183c717f54...
commit 972b83d7f74f4c22839536d0604183c717f545dc Author: Cyril Hrubis metan@ucw.cz Date: Sun Mar 2 21:29:00 2014 +0100
PCX: Implement PCX RLE I/O stream.
The loaders now internally uses RLE I/O stream.
TODO: Check errors from GP_IORead() in inner loops More tests
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/include/loaders/GP_PCX.h b/include/loaders/GP_PCX.h index 0d7d6e22..f5ce05c1 100644 --- a/include/loaders/GP_PCX.h +++ b/include/loaders/GP_PCX.h @@ -33,7 +33,6 @@ #include "core/GP_ProgressCallback.h" #include "loaders/GP_IO.h"
- /* * Reads a PCX from an IO stream. * diff --git a/libs/loaders/GP_PCX.c b/libs/loaders/GP_PCX.c index 698f82eb..61806583 100644 --- a/libs/loaders/GP_PCX.c +++ b/libs/loaders/GP_PCX.c @@ -37,6 +37,132 @@
#include "GP_PCX.h"
+/* + * PCX RLE I/O Stream + */ +struct rle { + /* RLE internal state */ + int cnt; + int val; + + /* Read counter */ + off_t pos; + + /* Source I/O stream */ + GP_IO *io; + + /* Read buffer */ + ssize_t buf_fill; + ssize_t buf_pos; + uint8_t buf[128]; +}; + +static int rle_getc(struct rle *rle) +{ + if (rle->buf_pos < rle->buf_fill) + return rle->buf[rle->buf_pos++]; + + rle->buf_fill = GP_IORead(rle->io, rle->buf, sizeof(rle->buf)); + + if (rle->buf_fill <= 0) + return -1; + + rle->buf_pos = 1; + return rle->buf[0]; +} + +/* + * RLE I/O stream + * + * - reads exactly size bytes unless read from underlying I/O has failed + * + * - the size is expected to be multiple of bytes_per_line, the specification + * forbids for RLE to span across pixel lines, but there are images that does + * so. This code only prints a warning in this case. + */ +static ssize_t rle_read(GP_IO *self, void *buf, size_t size) +{ + struct rle *priv = GP_IO_PRIV(self); + unsigned int read = 0; + uint8_t *bbuf = buf; + int b; + + for (;;) { + while (priv->cnt > 0 && read < size) { + bbuf[read++] = priv->val; + priv->cnt--; + } + + if (read >= size) { + priv->pos += read; + if (priv->cnt) + GP_WARN("Nonzero repeat count (%u) %02x at %zi", + priv->cnt, priv->val, priv->pos); + //priv->cnt = 0; + return read; + } + + b = rle_getc(priv); + + if (b < 0) + return priv->buf_fill; + + if ((b & 0xc0) == 0xc0) { + priv->cnt = b & 0x3f; + priv->val = rle_getc(priv); + if (priv->val < 0) + return priv->buf_fill; + } else { + priv->cnt = 1; + priv->val = b; + } + } +} + +/* + * Only seeks forward to skip padding also works for GP_IOTell(). + */ +static off_t rle_seek(GP_IO *self, off_t off, enum GP_IOWhence whence) +{ + uint8_t b; + struct rle *priv = GP_IO_PRIV(self); + + if (whence != GP_IO_SEEK_CUR || off < 0) + return EINVAL; + + while (off--) + rle_read(self, &b, 1); + + return priv->pos; +} + +static int rle_close(GP_IO *self) +{ + free(self); + return 0; +} + +GP_IO *rle(GP_IO *io) +{ + GP_IO *rle = malloc(sizeof(GP_IO) + sizeof(struct rle)); + + if (!rle) + return NULL; + + struct rle *priv = GP_IO_PRIV(rle); + + priv->cnt = 0; + priv->buf_fill = 0; + priv->io = io; + + rle->Read = rle_read; + rle->Write = NULL; + rle->Seek = rle_seek; + rle->Close = rle_close; + + return rle; +} + /* Creator ZSoft: 0x0a * Version: 0x00, 0x02, 0x03, 0x04, 0x05 * RLE: 0x01 @@ -88,69 +214,6 @@ struct pcx_header { uint8_t palette[48]; };
-static int get_byte(GP_IO *io) -{ - uint8_t buf; - - if (GP_IORead(io, &buf, 1) != 1) - return -1; - - return buf; -} - -static int readline(GP_IO *io, uint8_t *buf, unsigned int size, unsigned int padd) -{ - int b, val = 0, cnt = 0; - unsigned int read = 0; - - for (;;) { - while (cnt > 0 && read < size) { - buf[read++] = val; - cnt--; - } - - if (read >= size) { - goto end; - } - - b = get_byte(io); - - if (b == -1) { - GP_WARN("End of file reached unexpectedly"); - return 0; - } - - if ((b & 0xc0) == 0xc0) { - cnt = b & 0x3f; - val = get_byte(io); - } else { - cnt = 1; - val = b; - } - } - -end: - /* - * Data may be padded, read the excess bytes - */ - while (padd--) { - if (cnt) { - cnt--; - } else { - b = get_byte(io); - if ((b & 0xc0) == 0xc0) { - cnt = b & 0x3f; - get_byte(io); - } - } - } - - if (cnt) - GP_WARN("Nonzero repeat count at the line end (%u)", cnt); - - return 0; -} - #include "core/GP_BitSwap.h"
static int read_g1(GP_IO *io, struct pcx_header *header, @@ -164,20 +227,26 @@ static int read_g1(GP_IO *io, struct pcx_header *header, return EINVAL; }
+ GP_IO *rle_io = rle(io); + if (!rle_io) + return errno; + for (y = 0; y < res->h; y++) { uint8_t *addr = GP_PIXEL_ADDR(res, 0, y); - - readline(io, addr, res->bytes_per_row, padd); + GP_IORead(rle_io, addr, res->bytes_per_row); + GP_IOSeek(rle_io, GP_IO_SEEK_CUR, padd);
//TODO: FIX Endians GP_BitSwapRow_B1(addr, res->bytes_per_row);
if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) { GP_DEBUG(1, "Operation aborted"); + GP_IOClose(rle_io); return ECANCELED; } }
+ GP_IOClose(rle_io); return 0; }
@@ -188,8 +257,14 @@ static int read_rgb888(GP_IO *io, struct pcx_header *header, unsigned int bpr = header->bytes_per_line; uint8_t b[3 * bpr];
+ GP_IO *rle_io = rle(io); + if (!rle_io) + return errno; + for (y = 0; y < res->h; y++) { - readline(io, b, sizeof(b), 0); + //readline(io, b, sizeof(b), 0); + + GP_IORead(rle_io, b, sizeof(b));
for (x = 0; x < res->w; x++) { GP_Pixel pix = GP_Pixel_CREATE_RGB888(b[x], @@ -200,10 +275,12 @@ static int read_rgb888(GP_IO *io, struct pcx_header *header,
if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) { GP_DEBUG(1, "Operation aborted"); + GP_IOClose(rle_io); return ECANCELED; } }
+ GP_IOClose(rle_io); return 0; }
@@ -236,8 +313,12 @@ static int read_16_palette(GP_IO *io, struct pcx_header *header, return EINVAL; }
+ GP_IO *rle_io = rle(io); + if (!rle_io) + return errno; + for (y = 0; y < res->h; y++) { - readline(io, b, sizeof(b), 0); + GP_IORead(rle_io, b, sizeof(b));
i = 0;
@@ -252,55 +333,67 @@ static int read_16_palette(GP_IO *io, struct pcx_header *header,
if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) { GP_DEBUG(1, "Operation aborted"); + GP_IOClose(rle_io); return ECANCELED; } }
+ GP_IOClose(rle_io); return 0; }
+#define PALETTE_SIZE (3 * 256 + 1) + static int read_256_palette(GP_IO *io, struct pcx_header *header, GP_Context *res, GP_ProgressCallback *callback) { uint32_t x, y; unsigned int i; + uint8_t buf[GP_MAX(PALETTE_SIZE, header->bytes_per_line)]; GP_Pixel palette[256]; - uint8_t b[header->bytes_per_line];
if (GP_IOSeek(io, -769, GP_IO_SEEK_END) == (off_t)-1) { GP_DEBUG(1, "Failed to seek to palette: %s", strerror(errno)); return EIO; }
- if (get_byte(io) != 0x0c) { - GP_DEBUG(1, "Wrong palette marker"); + if (GP_IOFill(io, buf, PALETTE_SIZE)) { + GP_DEBUG(1, "Failed to read palette: %s", strerror(errno)); return EIO; }
- for (i = 0; i < 256; i++) { - palette[i] = get_byte(io) << 16; - palette[i] |= get_byte(io) << 8; - palette[i] |= get_byte(io); + if (buf[0] != 0x0c) { + GP_DEBUG(1, "Wrong palette marker"); + return EIO; }
+ for (i = 0; i < 256; i++) + palette[i] = (buf[3*i+1]<<16) | (buf[3*i+2])<<8 | buf[3*i+3]; + if (GP_IOSeek(io, 128, GP_IO_SEEK_SET) == (off_t)-1) { GP_DEBUG(1, "Failed to seek to image data: %s", strerror(errno)); return EIO; }
+ GP_IO *rle_io = rle(io); + if (!rle_io) + return errno; + for (y = 0; y < res->h; y++) { - readline(io, b, sizeof(b), 0); + GP_IORead(rle_io, buf, header->bytes_per_line);
for (x = 0; x < res->w; x++) - GP_PutPixel_Raw_24BPP(res, x, y, palette[b[x]]); + GP_PutPixel_Raw_24BPP(res, x, y, palette[buf[x]]);
if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) { GP_DEBUG(1, "Operation aborted"); + GP_IOClose(rle_io); return ECANCELED; } }
+ GP_IOClose(rle_io); return 0; }
http://repo.or.cz/w/gfxprim.git/commit/71dc80d8bbbdc5af75aed1896288e2d7a34cd...
commit 71dc80d8bbbdc5af75aed1896288e2d7a34cdead Author: Cyril Hrubis metan@ucw.cz Date: Sun Mar 2 18:45:02 2014 +0100
doc: loaders: Add PSD + cleanup.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/demos/spiv/spiv.1 b/demos/spiv/spiv.1 index fb23f1f5..bca63dd6 100644 --- a/demos/spiv/spiv.1 +++ b/demos/spiv/spiv.1 @@ -11,9 +11,9 @@ is a fast, lightweight and minimalistic image viewer build on the top of the GFXprim library. .PP Spiv supports wide range of image formats, currently supported are -JPEG, PNG, GIF, BMP, TIFF, PSP, PNM, PCX, JPEG2000 and CBZ (as well -general ZIP archives with images), and more will come in the -near future. +JPEG, PNG, GIF, BMP, TIFF, PSP, PSD, PNM, PCX, JPEG2000 and CBZ +(as well general ZIP archives with images), and more will come in +the near future. .PP Spiv supports variety of video backends (via GFXprim backends) currently these are X11, Linux Framebuffer, SDL and AAlib. Spiv also diff --git a/demos/spiv/spiv_help.c b/demos/spiv/spiv_help.c index 186b1c53..cecd1ecb 100644 --- a/demos/spiv/spiv_help.c +++ b/demos/spiv/spiv_help.c @@ -164,9 +164,9 @@ const char *man_head = "top of the GFXprim library.n" ".PPn" "Spiv supports wide range of image formats, currently supported aren" - "JPEG, PNG, GIF, BMP, TIFF, PSP, PNM, PCX, JPEG2000 and CBZ (as welln" - "general ZIP archives with images), and more will come in then" - "near future.n" + "JPEG, PNG, GIF, BMP, TIFF, PSP, PSD, PNM, PCX, JPEG2000 and CBZn" + "(as well general ZIP archives with images), and more will come inn" + "the near future.n" ".PPn" "Spiv supports variety of video backends (via GFXprim backends)n" "currently these are X11, Linux Framebuffer, SDL and AAlib. Spiv alson" diff --git a/doc/about.txt b/doc/about.txt index 018d71f9..f632eaaf 100644 --- a/doc/about.txt +++ b/doc/about.txt @@ -99,6 +99,11 @@ images into various standard formats (PNG, JPEG, GIF, TIFF, BMP, PNM, etc...). [green]#Composite image only for newer formats than 3.0# | [black]*No*
+| PSD | + Adobe Photoshop Image | + [green]#Thumbnail or Merged image (16 bit RGB and CMYK not supported yet)#| + [black]*No* + | PBM PGM PPM PNM | Netpbm portable bitmap | [green]#All but < 8bit binary grayscale# | diff --git a/doc/loaders.txt b/doc/loaders.txt index 1734718a..af588cb9 100644 --- a/doc/loaders.txt +++ b/doc/loaders.txt @@ -507,6 +507,57 @@ int GP_MatchPSP(const void *buf);
Matches a 'PSP' file signature. Returns non-zero if found.
+PSD Loader +~~~~~~~~~~ + +The 'PSD' loader can load a merged image (if present) or a thumbnail from an +Adobe Photoshop Image. Currently 16bit RGB and 16bit CMYK is not supported and +the loader will fallback to the thumbnail in this case (which is always 8bit +RGB). + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PSD.h> +/* or */ +#include <GP.h> + +GP_Context *GP_ReadPSD(GP_IO *io, GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Reads a 'PSP' image from readable 'GP_IO'. The link:loaders_io.html[IO stream] +is expected to start exactly at the 'PSD' file signature. + +Returns newly allocated context (containing decompressed image) or in case of +failure 'NULL' and 'errno' is set. + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PSD.h> +/* or */ +#include <GP.h> + +GP_Context *GP_LoadPSD(const char *src_path, GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Loads a merged image (if present) from a 'PSD' file. + +Fallbacks to thumbnail if merged image is not present or has unsupported pixel +type. + +Returns 'NULL' (TODO ERRNO) if merged image is not present/supported and +thumbnail is not present either. + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PSD.h> +/* or */ +#include <GP.h> + +int GP_MatchPSD(const void *buf); +------------------------------------------------------------------------------- + +Matches a 'PSD' file signature. Returns non-zero if found. + PNM Loaders ~~~~~~~~~~~
diff --git a/doc/loaders_python.txt b/doc/loaders_python.txt index ae2207e7..6ffaaa6a 100644 --- a/doc/loaders_python.txt +++ b/doc/loaders_python.txt @@ -23,6 +23,7 @@ import gfxprim.loaders as loaders img = loaders.LoadPPM(path, callback=None) img = loaders.LoadPCX(path, callback=None) img = loaders.LoadPSP(path, callback=None) + img = loaders.LoadPSD(path, callback=None) img = loaders.LoadTIFF(path, callback=None) -------------------------------------------------------------------------------
@@ -32,17 +33,20 @@ First one is general purpose loader function that automatically detects the file format. The format is detected from file extension first and if this fails files signature is used.
-May raise 'OSError' with errno set to 'EPERM', 'EISDIR', 'ENOENT' or any other -'errno' set by 'open(2)', 'read(2)', 'seek(2)'. +|=============================================================================== +| May raise 'OSError' with errno set to 'EPERM', 'EISDIR', 'ENOENT' or any other + 'errno' set by 'open(2)', 'read(2)', 'seek(2)'.
-May raise 'OSError' with errno set to 'ENOSYS' on unsupported or not recognized -format. +| May raise 'OSError' with errno set to 'ENOSYS' on unsupported or not recognized + format or if specific loader was disabled upon compilation.
-May raise 'OSError' with errno set to 'EIO' when file is damaged. +| May raise 'OSError' with errno set to 'EIO' or 'EINVAL' when file is damaged.
-May raise 'OSError' with errno set to 'ECANCELED' when action was aborted from -callback. See progress callback -link:core_python.html#Progress_Callback[documentation] for more. +| May raise 'OSError' with errno set to 'ECANCELED' when action was aborted from + callback. See link:core_python.html#Progress_Callback[progress callback] for + more. + +|===============================================================================
[source,python] @@ -65,16 +69,16 @@ Save image to a file.
For the Save() method the file format is derived from the extension.
-May raise 'OSError' with errno set to 'EPERM', 'EISDIR', 'ENOENT' or any other -'errno' set by 'open(2)', 'write(2)', 'seek(2)'. - -May raise 'OSError' with errno set to 'ENOSYS' on unsupported pixel type for -a given format. - -May raise 'OSError' with errno set to 'EIO' when filesystem is full. - -May raise 'OSError' with errno set to 'ECANCELED' when action was interrupted -by callback. +|=============================================================================== +| May raise 'OSError' with errno set to 'EPERM', 'EISDIR', 'ENOENT', 'ENOSPC' + or any other 'errno' set by 'open(2)', 'write(2)', 'seek(2)'. +| May raise 'OSError' with errno set to 'ENOSYS' if pixel type is not supported + by the format or if the save method is not implemented (possibly disabled upon + compilation). +| May raise 'OSError' with errno set to 'ECANCELED' when action was interrupted + by callback. See link:core_python.html#Progress_Callback[progress callback] + for more. +|===============================================================================
[source,python] ------------------------------------------------------------------------------- diff --git a/doc/spiv.txt b/doc/spiv.txt index 0fd031b1..4f678b82 100644 --- a/doc/spiv.txt +++ b/doc/spiv.txt @@ -6,8 +6,8 @@ Spiv is a fast, lightweight and minimalistic image viewer build on the top of the GFXprim library.
Spiv supports wide range of image formats, currently supported are JPEG, PNG, -GIF, BMP, TIFF, PSP, PNM, PCX, JPEG2000 and CBZ (as well general ZIP archives -with images), and more will come in the near future. +GIF, BMP, TIFF, PSP, PSD, PNM, PCX, JPEG2000 and CBZ (as well general ZIP +archives with images), and more will come in the near future.
Spiv implements image caches with LRU (last recently used) algorithm which speeds up subsequent image operations (rotations, going back and forth). diff --git a/include/loaders/GP_PSD.h b/include/loaders/GP_PSD.h index 8ab5b619..d8cd2213 100644 --- a/include/loaders/GP_PSD.h +++ b/include/loaders/GP_PSD.h @@ -22,7 +22,7 @@
/*
- PSD thumbnail image loader. + PSD image loader.
*/
@@ -34,7 +34,11 @@ #include "loaders/GP_IO.h"
/* - * Reads a PSD thumbnail from an IO stream. + * Reads a PSD from an IO stream. + * + * The loaders tries to read merged image (if present) and fallback to + * thumbnail. It may return NULL with errno untouched if neither merged image + * nor thumbnail was present (which seem to be really uncommon). * * Returns newly allocated context cotaining the loaded image or in case of * failure NULL and errno is set.
-----------------------------------------------------------------------
Summary of changes: demos/spiv/spiv.1 | 6 +- demos/spiv/spiv_help.c | 6 +- doc/about.txt | 5 + doc/loaders.txt | 51 ++++++++++ doc/loaders_python.txt | 40 ++++---- doc/spiv.txt | 4 +- include/loaders/GP_PCX.h | 1 - include/loaders/GP_PSD.h | 8 +- libs/loaders/GP_PCX.c | 245 +++++++++++++++++++++++++++++++-------------- 9 files changed, 261 insertions(+), 105 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.