#include #include #include /* #define DEBUG 1 */ /* * RROWL * subroutine reads a row of either bit, byte, short, long, * float, or double pixels into a long array BUF * from the file descriptor FD using the parameters * found in the CVL header AREA. * Returns 1 on success, 0 on end-of-file, -1 on error. * Partial reads after retries are treated as errors. * Alters a zero value in the optional bits/band field of AREA. * Calls READP to avoid pipe shortchanging on reads. * The optional CVL header exponent bit fields are only used * to distinguish floating and integral values of the same size; * otherwise, if the bits per pixel fields match an allowable * input pixel type then that type is used with further checks. * cc -c -O rrowl.c * Written by Robert L. Kirby, U. of Md. CVL, August 4, 1983 * with modifications by Diane Donaldson and Chris Welsh. * * Modified 04/22/87 for switching on cv_bp rather than cv_bb, better error * handling/messages and diagnostics, Joe Sanjour */ int rrowl (fd, buf, area) int fd; /* Input file descriptor */ long *buf; /* Buffer to receive converted values */ struct cvl_p *area; { int bcnt; /* Bytes read */ int nbytes; /* Bytes per input row */ register int icnt; /* Data items in row */ register long *obp = buf; /* Output buffer pointer */ icnt = area->cv_cols; /* use thead() to check header for inconsistencies */ switch(thead(area,1)) { case 1: { fprintf(stderr,"rrowl: inconsistencies found in header, fixed\n"); break; } case -1: { fprintf(stderr,"rrowl: inconsistencies found in header, unfixable\n"); return(-1); } #ifdef DEBUG case 0: { fprintf(stderr,"rrowl: header okay\n"); break; } default: { fprintf(stderr,"rrowl: thead is being wierd\n"); break; } #endif DEBUG } /* end switch */ if (area->cv_bb <= LONGBITS) { if((nbytes = (area->cv_cols * area->cv_bp + BYTEBITS - 1) / BYTEBITS) == 0) /* Bytes per row */ { fprintf(stderr,"rrowl: error, bits per pixel = 0 ???\n"); return(-1); } #ifdef DEBUG fprintf(stderr,"rrowl: %d bytes per row\n",nbytes); #endif DEBUG if((bcnt = readp(fd, (char *) buf, nbytes)) == nbytes) { /* start after last pixel then go backward */ obp += icnt; switch(area->cv_bp) { case 1: { /* Character buffer of packed pixels */ register char *bp = ((char *) buf) + icnt / BYTEBITS; /* bit mask for packed binary values */ register mask = 1 << (icnt % BYTEBITS); do { if ((mask >>= 1) == 0) { mask = 1 << (BYTEBITS -1); bp--; } *--obp = ( *bp & mask) != 0; } while (--icnt); return(1); } #if BYTEBITS != SHORTBITS case BYTEBITS: { /* Character buffer */ register char *bp = ((char *) buf) + icnt; if(!area->cv_sbp || area->cv_sbp == area->cv_bp) do { /* Unsigned pixel values */ *--obp = *--bp & ((1 << BYTEBITS) -1); } while (--icnt > 0); else do { /* Signed pixel values */ *--obp = *--bp; } while (--icnt > 0); return(1); } #endif #if SHORTBITS != LONGBITS case SHORTBITS: { /* After last value and going backward */ register short *bp = ((short *) buf) + icnt; if(!area->cv_sbp || area->cv_sbp == area->cv_bp) do { /* Unsigned pixel values */ --bp; /* This is because of a nasty compiler bug */ *--obp = *bp & ((1L << SHORTBITS) -1); } while (--icnt > 0); else do { /* Signed pixel values */ *--obp = *--bp; } while (--icnt > 0); return(1); } #endif #if LONGBITS >= DOUBLEBITS #if LONGBITS == DOUBLEBITS case DOUBLEBITS: if(area->cv_ebp != 0 || area->cv_ebb != 0) { /* After last value to go backward */ register double *bp = ((double *) buf) + icnt; do { *--obp = *--bp; } while (--icnt > 0); return(1); } #else case DOUBLEBITS: { /* After last value to go backward */ register double *bp = ((double *) buf) + icnt; do { *--obp = *--bp; } while (--icnt > 0); return(1); } #endif #if FLOATBITS != DOUBLEBITS case FLOATBITS: { /* After last value and going backward */ register float *bp = ((float *) buf + icnt; do { *--obp = *--bp; } while (--icnt > 0); return(1); } #endif /* Otherwise use longs as is */ return(1); #else #if LONGBITS >= FLOATBITS #if LONGBITS > FLOATBITS case FLOATBITS: { /* After last value to go backward */ register float *bp = ((float *) buf) + icnt; do { *--obp = *--bp; } while (--icnt > 0); return(1); } case LONGBITS: return(1); #else case FLOATBITS: if(area->cv_ebp != 0 || area->cv_ebb != 0) { /* After last value to go backward */ register float *bp = ((float *) buf) + icnt; do { *--obp = *--bp; } while (--icnt > 0); return(1); } return(1); #endif #endif #endif default: { fprintf(stderr,"rrowl: error, bits per pixel = %d\n",area->cv_bp); return(-1); } } } } else switch(area->cv_bp) { #if FLOATBITS > LONGBITS case FLOATBITS: { /* Buffer for values bigger than requested */ float ibuf[IBUFSIZE / sizeof (float)]; /* Fetch pixel values cycling forward thru buffer */ register float *bp = ibuf; for(;;) { nbytes = icnt >= IBUFSIZE / sizeof *ibuf ? sizeof ibuf : icnt * sizeof *ibuf; if((bcnt = readp(fd, (char *) ibuf, nbytes)) != nbytes) { if(bp != ibuf) { /* Only a partial read */ fprintf(stderr,"rrowl: partial read\n"); return(-1); } break; } bp = ibuf; do { *obp++ = *bp++; if(--icnt == 0) return(1); } while (bp < ibuf + IBUFSIZE / sizeof *ibuf); } } #if FLOATBITS != DOUBLEBITS case DOUBLEBITS: { /* Buffer for values bigger than requested */ double ibuf[IBUFSIZE / sizeof (double)]; /* Fetch pixel values cycling forward thru buffer */ register double *bp = ibuf; for(;;) { nbytes = icnt >= IBUFSIZE / sizeof *ibuf ? sizeof ibuf : icnt * sizeof *ibuf; if((bcnt = readp(fd, (char *) ibuf, nbytes)) != nbytes) { if(bp != ibuf) { /* Only a partial read */ fprintf(stderr,"rrowl: partial read\n"); return(-1); } break; } bp = ibuf; do { *obp++ = *bp++; if(--icnt == 0) return(1); } while (bp < ibuf + IBUFSIZE / sizeof *ibuf); } } #endif #else #if DOUBLEBITS > LONGBITS case DOUBLEBITS: { /* Buffer for values bigger than requested */ double ibuf[IBUFSIZE / sizeof (double)]; /* Fetch pixel values cycling forward thru buffer */ register double *bp = ibuf; for(;;) { nbytes = icnt >= IBUFSIZE / sizeof *ibuf ? sizeof ibuf : icnt * sizeof *ibuf; if((bcnt = readp(fd, (char *) ibuf, nbytes)) != nbytes) { if(bp != ibuf) { /* Only a partial read */ fprintf(stderr,"rrowl: partial read\n"); return(-1); } break; } bp = ibuf; do { *obp++ = *bp++; if(--icnt == 0) return(1); } while (bp < ibuf + IBUFSIZE / sizeof *ibuf); } } #endif #endif } if (bcnt == 0) return(0); /* end of input file */ else { fprintf(stderr,"rrowl: read errors\n"); return(-1); /* read errors */ } }