501 lines
11 KiB
C
501 lines
11 KiB
C
|
// 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 <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
|
||
|
|
||
|
/** 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<ysize && !badorder; y++) {
|
||
|
for (z=0; z<zsize && !badorder; z++) {
|
||
|
if (starttab[y+z*ysize] < cur) badorder = 1;
|
||
|
else cur = starttab[y+z*ysize];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ImageIO_seek( im, (long) (512 + 2*tablen*4), 0);
|
||
|
|
||
|
cur = 512 + 2*tablen*4;
|
||
|
|
||
|
base = (byte *) ImageIO_alloc((size_t) (xsize*ysize+TAGLEN) * 4);
|
||
|
if (!base)
|
||
|
exit(1);
|
||
|
|
||
|
addimgtag(base,xsize,ysize);
|
||
|
|
||
|
if (badorder) {
|
||
|
for (z=0; z<zsize; z++) {
|
||
|
lptr = base;
|
||
|
for (y=0; y<ysize; y++) {
|
||
|
if (cur != starttab[y+z*ysize]) {
|
||
|
ImageIO_seek( im, (long) starttab[y+z*ysize], 0);
|
||
|
cur = starttab[y+z*ysize];
|
||
|
}
|
||
|
|
||
|
if (lengthtab[y+z*ysize]>(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<ysize; y++) {
|
||
|
for (z=0; z<zsize; z++) {
|
||
|
if (cur != starttab[y+z*ysize]) {
|
||
|
ImageIO_seek( im, (long) starttab[y+z*ysize], 0);
|
||
|
cur = starttab[y+z*ysize];
|
||
|
}
|
||
|
|
||
|
ImageIO_read(im, rledat, (size_t) lengthtab[y+z*ysize]);
|
||
|
cur += lengthtab[y+z*ysize];
|
||
|
expandrow(lptr,rledat,3-z);
|
||
|
}
|
||
|
lptr += (xsize * 4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ImageIO_free(starttab);
|
||
|
ImageIO_free(lengthtab);
|
||
|
ImageIO_free(rledat);
|
||
|
return base;
|
||
|
} /* end of RLE case */
|
||
|
|
||
|
else { /* not RLE */
|
||
|
verdat = (byte *) ImageIO_alloc((size_t) xsize);
|
||
|
base = (byte *) ImageIO_alloc((size_t) (xsize*ysize+TAGLEN) * 4);
|
||
|
if (!base || !verdat)
|
||
|
exit(1);
|
||
|
|
||
|
addimgtag(base,xsize,ysize);
|
||
|
|
||
|
ImageIO_seek( im, 512L,0);
|
||
|
|
||
|
for (z=0; z<zsize; z++) {
|
||
|
lptr = base;
|
||
|
for (y=0; y<ysize; y++) {
|
||
|
ImageIO_read(im, verdat, (size_t) xsize);
|
||
|
interleaverow(lptr,verdat,3-z,xsize);
|
||
|
lptr += (xsize * 4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ImageIO_free(verdat);
|
||
|
return base;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|