X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=demo_prior;a=blobdiff_plain;f=libs%2Fimago2%2Fsrc%2Ffile_ppm.c;fp=libs%2Fimago2%2Fsrc%2Ffile_ppm.c;h=55aa5e3d9ea0ab011f7f9f9fdd0a3e34b8e24945;hp=0000000000000000000000000000000000000000;hb=3a9f6854df479d81442273c9d0b133c49c5c8f66;hpb=0b24071f728b7c8550daa1b7aa7c4012cb70ef4c diff --git a/libs/imago2/src/file_ppm.c b/libs/imago2/src/file_ppm.c new file mode 100644 index 0000000..55aa5e3 --- /dev/null +++ b/libs/imago2/src/file_ppm.c @@ -0,0 +1,258 @@ +/* +libimago - a multi-format image file input/output library. +Copyright (C) 2010-2017 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +*/ + +/* -- Portable Pixmap (PPM) module (also supports PGM) -- */ + +#include +#include +#include +#include "imago2.h" +#include "ftype_module.h" +#include "byteord.h" + +static int check(struct img_io *io); +static int read(struct img_pixmap *img, struct img_io *io); +static int write(struct img_pixmap *img, struct img_io *io); + +int img_register_ppm(void) +{ + static struct ftype_module mod = {".ppm:.pgm:.pnm", check, read, write}; + return img_register_module(&mod); +} + + +static int check(struct img_io *io) +{ + char id[2]; + int res = -1; + long pos = io->seek(0, SEEK_CUR, io->uptr); + + if(io->read(id, 2, io->uptr) < 2) { + io->seek(pos, SEEK_SET, io->uptr); + return -1; + } + + if(id[0] == 'P' && (id[1] == '6' || id[1] == '3' || id[1] == '5')) { + res = 0; + } + io->seek(pos, SEEK_SET, io->uptr); + return res; +} + +static int iofgetc(struct img_io *io) +{ + char c; + return io->read(&c, 1, io->uptr) < 1 ? -1 : c; +} + +static char *iofgets(char *buf, int size, struct img_io *io) +{ + int c; + char *ptr = buf; + + while(--size > 0 && (c = iofgetc(io)) != -1) { + *ptr++ = c; + if(c == '\n') break; + } + *ptr = 0; + + return ptr == buf ? 0 : buf; +} + +static int read(struct img_pixmap *img, struct img_io *io) +{ + char buf[256]; + int xsz, ysz, maxval, got_hdrlines = 1; + int i, greyscale, numval, valsize, fbsize, text; + enum img_fmt fmt; + + if(!iofgets(buf, sizeof buf, io)) { + return -1; + } + if(!(buf[0] == 'P' && (buf[1] == '6' || buf[1] == '3' || buf[1] == '5'))) { + return -1; + } + greyscale = buf[1] == '5' ? 1 : 0; + text = buf[1] == '3' ? 1 : 0; + + while(got_hdrlines < 3 && iofgets(buf, sizeof buf, io)) { + if(buf[0] == '#') continue; + + switch(got_hdrlines) { + case 1: + if(sscanf(buf, "%d %d\n", &xsz, &ysz) < 2) { + return -1; + } + break; + + case 2: + if(sscanf(buf, "%d\n", &maxval) < 1) { + return -1; + } + default: + break; + } + got_hdrlines++; + } + + if(xsz < 1 || ysz < 1 || maxval <= 0 || maxval > 65535) { + return -1; + } + + valsize = maxval < 256 ? 1 : 2; + numval = xsz * ysz * (greyscale ? 1 : 3); + fbsize = numval * valsize; + + if(valsize > 1) { + fmt = greyscale ? IMG_FMT_GREYF : IMG_FMT_RGBF; + } else { + fmt = greyscale ? IMG_FMT_GREY8 : IMG_FMT_RGB24; + } + + if(img_set_pixels(img, xsz, ysz, fmt, 0) == -1) { + return -1; + } + + if(!text) { + if(io->read(img->pixels, fbsize, io->uptr) < (unsigned int)fbsize) { + return -1; + } + if(maxval == 255) { + return 0; /* we're done, no conversion necessary */ + } + + if(maxval < 256) { + unsigned char *ptr = img->pixels; + for(i=0; ipixels + numval; + float *dest = (float*)img->pixels + numval; + + for(i=0; i> 8) | (val << 8); +#endif + *--dest = (float)val / (float)maxval; + } + } + } else { + char *pptr = img->pixels; + int c = iofgetc(io); + + for(i=0; ifmt) { + case IMG_FMT_RGBA32: + if(img_copy(&tmpimg, img) == -1) { + goto done; + } + if(img_convert(&tmpimg, IMG_FMT_RGB24) == -1) { + goto done; + } + img = &tmpimg; + + case IMG_FMT_RGB24: + case IMG_FMT_GREY8: + sprintf(buf, fmt, greyscale ? 5 : 6, img->width, img->height, 255); + if(io->write(buf, strlen(buf), io->uptr) < strlen(buf)) { + goto done; + } + sz = img->width * img->height * nval; + if(io->write(img->pixels, sz, io->uptr) < (unsigned int)sz) { + goto done; + } + res = 0; + break; + + case IMG_FMT_RGBAF: + if(img_copy(&tmpimg, img) == -1) { + goto done; + } + if(img_convert(&tmpimg, IMG_FMT_RGBF) == -1) { + goto done; + } + img = &tmpimg; + + case IMG_FMT_RGBF: + case IMG_FMT_GREYF: + sprintf(buf, fmt, greyscale ? 5 : 6, img->width, img->height, 65535); + if(io->write(buf, strlen(buf), io->uptr) < strlen(buf)) { + goto done; + } + fptr = img->pixels; + maxfval = 0; + for(i=0; iwidth * img->height * nval; i++) { + float val = *fptr++; + if(val > maxfval) maxfval = val; + } + fptr = img->pixels; + for(i=0; iwidth * img->height * nval; i++) { + uint16_t val = (uint16_t)(*fptr++ / maxfval * 65535.0); + img_write_uint16_be(io, val); + } + res = 0; + break; + + default: + break; + } + +done: + img_destroy(&tmpimg); + return res; +}