// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) // All rights reserved. // // This file is part of the ImageIO Library, and as been adapted for // CGAL (www.cgal.org). // 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. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau /* * xviris.c - load routine for IRIS 'rgb' format pictures * * LoadIRIS() * WriteIRIS() */ #ifdef CGAL_HEADER_ONLY #define CGAL_INLINE_FUNCTION inline #else #define CGAL_INLINE_FUNCTION #endif #include #include #include /** Magic header for RGB files */ #define IRIS_MAGIC 0732 typedef unsigned char byte; #define BPPMASK 0x00ff #define ITYPE_VERBATIM 0x0000 #define ITYPE_RLE 0x0100 #define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE) #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM) #define BPP(type) ((type) & BPPMASK) #define RLE(bpp) (ITYPE_RLE | (bpp)) #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) #define TAGLEN (5) #define RINTLUM (79) #define GINTLUM (156) #define BINTLUM (21) #define OFFSET_R 3 /* this is byte order dependent */ #define OFFSET_G 2 #define OFFSET_B 1 #define OFFSET_A 0 #define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8) #define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */ static byte *getimagedata (const _image *im, unsigned short, int, int, int); static void interleaverow (byte *, byte *, int, int); static void expandrow (byte *, byte *, int); static void readtab (const _image *im, unsigned long *, int); static void addimgtag (byte *, int, int); static unsigned short getshort (const _image *im); static unsigned long getlong (const _image *im); CGAL_INLINE_FUNCTION int testIrisHeader(char *magic,const char *) { if((((unsigned char *)magic)[0]<<8) + ((unsigned char *)magic)[1] == IRIS_MAGIC) return 0; else return -1; } CGAL_INLINE_FUNCTION PTRIMAGE_FORMAT createIrisFormat() { PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); f->testImageFormat=&testIrisHeader; f->readImageHeader=&readIrisImage; f->writeImage=0; strcpy(f->fileExtension,".rgb"); strcpy(f->realName,"IRIS"); return f; } /******************************************/ static void interleaverow(byte *lptr, byte *cptr, int z, int n) { lptr += z; while(n--) { *lptr = *cptr++; lptr += 4; } } /******************************************/ static void expandrow(byte *optr, byte *iptr, int z) { byte pixel, count; optr += z; while (1) { pixel = *iptr++; if ( !(count = (pixel & 0x7f)) ) return; if (pixel & 0x80) { while (count>=8) { optr[0*4] = iptr[0]; optr[1*4] = iptr[1]; optr[2*4] = iptr[2]; optr[3*4] = iptr[3]; optr[4*4] = iptr[4]; optr[5*4] = iptr[5]; optr[6*4] = iptr[6]; optr[7*4] = iptr[7]; optr += 8*4; iptr += 8; count = byte(count - 8); } while(count--) { *optr = *iptr++; optr+=4; } } else { pixel = *iptr++; while(count>=8) { optr[0*4] = pixel; optr[1*4] = pixel; optr[2*4] = pixel; optr[3*4] = pixel; optr[4*4] = pixel; optr[5*4] = pixel; optr[6*4] = pixel; optr[7*4] = pixel; optr += 8*4; count = byte(count - 8); } while(count--) { *optr = pixel; optr+=4; } } } } /****************************************************/ static void readtab(const _image *im, unsigned long *tab, int n) { while (n) { *tab++ = getlong(im); n--; } } /*****************************************************/ static void addimgtag(byte *dptr, int xsize, int ysize) { /* this is used to extract image data from core dumps. I doubt this is necessary... --jhb */ dptr = dptr + (xsize * ysize * 4); dptr[0] = 0x12; dptr[1] = 0x34; dptr[2] = 0x56; dptr[3] = 0x78; dptr += 4; dptr[0] = 0x59; dptr[1] = 0x49; dptr[2] = 0x33; dptr[3] = 0x33; dptr += 4; dptr[0] = 0x69; dptr[1] = 0x43; dptr[2] = 0x42; dptr[3] = 0x22; dptr += 4; dptr[0] = byte((xsize>>24)&0xff); dptr[1] = byte((xsize>>16)&0xff); dptr[2] = byte((xsize>> 8)&0xff); dptr[3] = byte((xsize )&0xff); dptr += 4; dptr[0] = byte((ysize>>24)&0xff); dptr[1] = byte((ysize>>16)&0xff); dptr[2] = byte((ysize>> 8)&0xff); dptr[3] = byte((ysize )&0xff); } /* byte order independent read/write of shorts and longs. */ /*****************************************************/ static unsigned short getshort( const _image *im) { byte buf[2]; ImageIO_read( im, buf, (size_t) 2); return (unsigned short)((buf[0]<<8)+(buf[1]<<0)); } /*****************************************************/ static unsigned long getlong( const _image *im ) { byte buf[4]; ImageIO_read( im, buf, (size_t) 4); return (((unsigned long) buf[0])<<24) + (((unsigned long) buf[1])<<16) + (((unsigned long) buf[2])<<8) + buf[3]; } /*****************************************************/ CGAL_INLINE_FUNCTION int readIrisImage( const char *, _image *im ) { byte *rawdata, *rptr; byte *pic824, *bptr, *iptr; std::size_t i, j, size; unsigned short imagic, type; unsigned int xsize, ysize, zsize; /* read header information from file */ imagic = getshort( im ); type = getshort( im ); getshort( im ); xsize = getshort( im ); ysize = getshort( im ); zsize = getshort( im ); if ( ImageIO_error(im) ) return( 0 ); if (imagic != IRIS_MAGIC) return( 0 ); rawdata = getimagedata(im, type, xsize, ysize, zsize); if (!rawdata) return( 0 ); if ( ImageIO_error(im) ) return( 0 ); /* probably truncated file */ /* t1=texture_alloc(); (void) strcpy(t1->name,fname); t1->type=IRIS; t1->nrows = ysize; t1->ncols = xsize; t1->image = create_int_array(t1->nrows,t1->ncols);*/ /* got the raw image data. Convert to an XV image (1,3 bytes / pix) */ if (zsize < 3) { /* grayscale */ im->xdim = xsize; im->ydim = ysize; im->zdim = 1; im->vdim = 1; im->wdim = 1; im->wordKind = WK_FIXED; im->sign = SGN_UNSIGNED; im->data = ImageIO_alloc(xsize * ysize); pic824 = (byte *) ImageIO_alloc((size_t) xsize * ysize); if (!pic824) exit(-1); /* copy plane 3 from rawdata into pic824, inverting pic vertically */ for (i = 0, bptr = pic824; i < ysize; i++) { rptr = rawdata + 3 + ((ysize - 1) - i) * (xsize * 4); for (j = 0; j < xsize; j++, bptr++, rptr += 4) *bptr = *rptr; } size = im->xdim * im->ydim; for (bptr = pic824, iptr = (unsigned char *) im->data, i = 0; i < size; ++i, ++iptr, ++bptr) { *iptr = *bptr; } ImageIO_free(pic824); } else { /* truecolor */ im->xdim = xsize; im->ydim = ysize; im->zdim = zsize / 3; im->vdim = 4; im->wdim = 1; im->wordKind = WK_FIXED; im->sign = SGN_UNSIGNED; im->data = ImageIO_alloc(xsize * ysize * im->zdim * 4); pic824 = (byte *) ImageIO_alloc((size_t) xsize * ysize * 3); if (!pic824) exit(1); /* copy plane 3 from rawdata into pic824, inverting pic vertically */ for (i = 0, bptr = pic824; i< ysize; i++) { rptr = rawdata + ((ysize - 1) - i) * (xsize * 4); for (j=0; j< xsize; j++, rptr += 4) { *bptr++ = rptr[3]; *bptr++ = rptr[2]; *bptr++ = rptr[1]; } } size = im->xdim * im->ydim; for (bptr = pic824, iptr = (unsigned char *) im->data, i = 0; i < size; ++i, iptr += 4, bptr += 3) { if ( _getEndianness() == END_LITTLE ) { iptr[0] = 0xFF; iptr[1] = bptr[2]; iptr[2] = bptr[1]; iptr[3] = bptr[0]; } else { iptr[0] = bptr[0]; iptr[1] = bptr[1]; iptr[2] = bptr[2]; iptr[3] = 0xFF; } } ImageIO_free(pic824); } ImageIO_free(rawdata); return 1; } /****************************************************/ static byte *getimagedata(const _image *im, unsigned short type, int xsize, int ysize, int zsize) { /* read in a B/W RGB or RGBA iris image file and return a pointer to an array of 4-byte pixels, arranged ABGR, NULL on error */ byte *base, *lptr; byte *verdat; int y, z, tablen; int bpp, rle, badorder; int rlebuflen; byte *rledat; unsigned long *starttab, *lengthtab, cur; rle = ISRLE(type); bpp = BPP(type); if (bpp != 1) { return (byte *) NULL; } if (rle) { rlebuflen = 2 * xsize + 10; tablen = ysize * zsize; starttab = (unsigned long *) ImageIO_alloc((size_t) tablen * sizeof(long)); lengthtab = (unsigned long *) ImageIO_alloc((size_t) tablen * sizeof(long)); rledat = (byte *) ImageIO_alloc((size_t) rlebuflen); if (!starttab || !lengthtab || !rledat) exit(1); ImageIO_seek( im, 512L, SEEK_SET ); readtab(im, starttab, tablen); readtab(im, lengthtab, tablen); if ( ImageIO_error(im) ) { ImageIO_free(starttab); ImageIO_free(lengthtab); ImageIO_free(rledat); return (byte *) NULL; } /* check data order */ cur = 0; badorder = 0; for (y=0; y(unsigned long)rlebuflen) { ImageIO_free(starttab); ImageIO_free(lengthtab); ImageIO_free(rledat); ImageIO_free(base); return (byte *) NULL; } ImageIO_read(im, rledat, (size_t) lengthtab[y+z*ysize]); cur += lengthtab[y+z*ysize]; expandrow(lptr,rledat,3-z); lptr += (xsize * 4); } } } else { lptr = base; for (y=0; y