#include "image.h"
-#include "io.h"
#include "log.h"
+#include "iolayer.h"
#include <stdlib.h>
#include <errno.h>
Some of these functions are internal.
-=over 4
+=over
=cut
*/
/*
-=item gnext(mbuf *mb)
+=item gpeek(mbuf *mb)
Fetches a character but does NOT advance. Returns a pointer to
the byte or NULL on failure (internal).
/*
-=item skip_spaces(mb)
+=item skip_comment(mb)
Advances in stream over whitespace and a comment if one is found. (internal)
int type;
int x, y, ch;
int width, height, maxval, channels, pcount;
+ int rounder;
char *cp;
unsigned char *uc;
mbuf buf;
i_color val;
- int mult;
i_clear_error();
- /* char *pp; */
-
mm_log((1,"i_readpnm(ig %p, length %d)\n", ig, length));
- /*
- pp = mymalloc(20);
-
- pp[-1]= 'c';
- pp[-2]= 'c';
-
- bndcheck_all();
-
- myfree(pp);
-
- mm_log((1, "Hack is exiting\n"));
-
-*/
-
io_glue_commit_types(ig);
init_buf(&buf, ig);
mm_log((1, "i_readpnm: error reading maxval\n"));
return NULL;
}
+
+ if (maxval == 0) {
+ i_push_error(0, "maxval is zero - invalid pnm file");
+ mm_log((1, "i_readpnm: maxval is zero, invalid pnm file\n"));
+ return NULL;
+ }
+ else if (maxval > 65535) {
+ i_push_errorf(0, "maxval of %d is over 65535 - invalid pnm file",
+ maxval);
+ mm_log((1, "i_readpnm: maxval of %d is over 65535 - invalid pnm file\n"));
+ return NULL;
+ }
+ else if (type >= 4 && maxval > 255) {
+ i_push_errorf(0, "maxval of %d is over 255 - not currently supported by Imager for binary pnm", maxval);
+ mm_log((1, "i_readpnm: maxval of %d is over 255 - not currently supported by Imager for binary pnm\n", maxval));
+ return NULL;
+ }
} else maxval=1;
+ rounder = maxval / 2;
if (!(cp = gnext(&buf)) || !misspace(*cp)) {
i_push_error(0, "garbage in header, invalid PNM file");
im = i_img_empty_ch(NULL, width, height, channels);
+ i_tags_add(&im->tags, "i_format", 0, "pnm", -1, 0);
+
switch (type) {
case 1: /* Ascii types */
case 2:
case 3:
- mult = type == 1 ? 255 : 1;
for(y=0;y<height;y++) for(x=0; x<width; x++) {
for(ch=0; ch<channels; ch++) {
int t;
- if (gnum(&buf, &t)) val.channel[ch] = t;
+ if (gnum(&buf, &t)) val.channel[ch] = (t * 255 + rounder) / maxval;
else {
mm_log((1,"i_readpnm: gnum() returned false in data\n"));
return im;
case 4: /* binary pbm */
for(y=0;y<height;y++) for(x=0; x<width; x+=8) {
- if ( (uc = gnext(&buf)) ) {
+ if ( (uc = (unsigned char*)gnext(&buf)) ) {
int xt;
int pc = width-x < 8 ? width-x : 8;
/* mm_log((1,"i_readpnm: y=%d x=%d pc=%d\n", y, x, pc)); */
case 6: /* binary ppm */
for(y=0;y<height;y++) for(x=0; x<width; x++) {
for(ch=0; ch<channels; ch++) {
- if ( (uc = gnext(&buf)) ) val.channel[ch] = *uc;
+ if ( (uc = (unsigned char*)gnext(&buf)) )
+ val.channel[ch] = (*uc * 255 + rounder) / maxval;
else {
mm_log((1,"i_readpnm: gnext() returned false in data\n"));
return im;
return im;
}
+
undef_int
-i_writeppm(i_img *im,int fd) {
+i_writeppm_wiol(i_img *im, io_glue *ig) {
char header[255];
int rc;
- mm_log((1,"i_writeppm(im* 0x%x,fd %d)\n",im,fd));
- if (im->channels!=3) {
- mm_log((1,"i_writeppm: ppm is 3 channel only (current image is %d)\n",im->channels));
- return(0);
+ mm_log((1,"i_writeppm(im %p, ig %p)\n", im, ig));
+ i_clear_error();
+
+ /* Add code to get the filename info from the iolayer */
+ /* Also add code to check for mmapped code */
+
+ io_glue_commit_types(ig);
+
+ if (im->channels == 3) {
+ sprintf(header,"P6\n#CREATOR: Imager\n%d %d\n255\n",im->xsize,im->ysize);
+ if (ig->writecb(ig,header,strlen(header))<0) {
+ i_push_error(errno, "could not write ppm header");
+ mm_log((1,"i_writeppm: unable to write ppm header.\n"));
+ return(0);
+ }
+
+ if (!im->virtual && im->bits == i_8_bits && im->type == i_direct_type) {
+ rc = ig->writecb(ig,im->idata,im->bytes);
+ }
+ else {
+ unsigned char *data = mymalloc(3 * im->xsize);
+ if (data != NULL) {
+ int y = 0;
+ static int rgb_chan[3] = { 0, 1, 2 };
+
+ rc = 0;
+ while (y < im->ysize && rc >= 0) {
+ i_gsamp(im, 0, im->xsize, y, data, rgb_chan, 3);
+ rc = ig->writecb(ig, data, im->xsize * 3);
+ ++y;
+ }
+ myfree(data);
+ }
+ else {
+ i_push_error(0, "Out of memory");
+ return 0;
+ }
+ }
+ if (rc<0) {
+ i_push_error(errno, "could not write ppm data");
+ mm_log((1,"i_writeppm: unable to write ppm data.\n"));
+ return(0);
+ }
}
-
- sprintf(header,"P6\n#CREATOR: Imager\n%d %d\n255\n",im->xsize,im->ysize);
-
- if (mywrite(fd,header,strlen(header))<0) {
- mm_log((1,"i_writeppm: unable to write ppm header.\n"));
- return(0);
+ else if (im->channels == 1) {
+ sprintf(header, "P5\n#CREATOR: Imager\n%d %d\n255\n",
+ im->xsize, im->ysize);
+ if (ig->writecb(ig,header, strlen(header)) < 0) {
+ i_push_error(errno, "could not write pgm header");
+ mm_log((1,"i_writeppm: unable to write pgm header.\n"));
+ return(0);
+ }
+
+ if (!im->virtual && im->bits == i_8_bits && im->type == i_direct_type) {
+ rc=ig->writecb(ig,im->idata,im->bytes);
+ }
+ else {
+ unsigned char *data = mymalloc(im->xsize);
+ if (data != NULL) {
+ int y = 0;
+ int chan = 0;
+
+ rc = 0;
+ while (y < im->ysize && rc >= 0) {
+ i_gsamp(im, 0, im->xsize, y, data, &chan, 1);
+ rc = ig->writecb(ig, data, im->xsize);
+ ++y;
+ }
+ myfree(data);
+ }
+ else {
+ i_push_error(0, "Out of memory");
+ return 0;
+ }
+ }
+ if (rc<0) {
+ i_push_error(errno, "could not write pgm data");
+ mm_log((1,"i_writeppm: unable to write pgm data.\n"));
+ return(0);
+ }
}
-
- rc=mywrite(fd,im->data,im->bytes);
- if (rc<0) {
- mm_log((1,"i_writeppm: unable to write ppm data.\n"));
+ else {
+ i_push_error(0, "can only save 1 or 3 channel images to pnm");
+ mm_log((1,"i_writeppm: ppm/pgm is 1 or 3 channel only (current image is %d)\n",im->channels));
return(0);
}
+ ig->closecb(ig);
+
return(1);
}
+/*
+=back
+=head1 AUTHOR
+Arnar M. Hrafnkelsson <addi@umich.edu>
+=head1 SEE ALSO
+Imager(3)
-
+=cut
+*/