dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/ImageIO/inr_impl.h

516 lines
14 KiB
C++
Executable File
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

// 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
#ifdef CGAL_HEADER_ONLY
#define CGAL_INLINE_FUNCTION inline
#else
#define CGAL_INLINE_FUNCTION
#endif
#include <CGAL/ImageIO/fgetns.h>
#include <string>
#include <sstream>
#include <string.h>
/* Magic header for inrimages v4 */
#define INR4_MAGIC "#INRIMAGE-4#{"
/** Magic header for inrimages */
#define INR_MAGIC "#INR"
typedef struct stringListElementStruct {
char *string;
struct stringListElementStruct *next;
} stringListElement;
/* list element with a pointer on a string */
typedef struct {
stringListElement *begin, *end;
} stringListHead;
/* string list descriptor */
#include <clocale>
class Set_numeric_locale {
const char * old_locale;
public:
Set_numeric_locale(const char* locale)
: old_locale(std::setlocale(LC_NUMERIC, locale))
{
}
~Set_numeric_locale() {
std::setlocale(LC_NUMERIC, old_locale);
}
};
static void addStringElement(stringListHead *strhead,
const char *str);
/* add a string element at the tail of given list */
static void concatStringElement(const stringListHead *strhead,
const char *str);
/* concat given string at the last element of given list */
/* Writes the given inrimage header in an already opened file.*/
CGAL_INLINE_FUNCTION
int _writeInrimageHeader(const _image *im, ENDIANNESS end) {
std::size_t pos, i;
char type[30], endianness[5], buf[257], scale[20];
std::ostringstream oss;
Set_numeric_locale num_locale("C");
if(im->openMode != OM_CLOSE) {
/* fix word kind */
switch(im->wordKind) {
case WK_FLOAT:
sprintf(type, "float");
scale[0] = '\0';
break;
case WK_FIXED:
switch(im->sign) {
case SGN_SIGNED:
sprintf(type, "signed fixed");
break;
case SGN_UNSIGNED:
sprintf(type, "unsigned fixed");
break;
default:
return -1;
}
sprintf(scale, "SCALE=2**0\n");
break;
default:
return -1;
}
switch(end) {
case END_LITTLE:
sprintf(endianness, "decm");
break;
case END_BIG:
sprintf(endianness, "sun");
break;
default:
/* fix architecture endianness */
if( _getEndianness() == END_LITTLE)
sprintf(endianness, "decm");
else
sprintf(endianness, "sun");
break;
}
/* write header information */
oss << INR4_MAGIC << "\n";
oss << "XDIM=" << im->xdim << "\n";
oss << "YDIM=" << im->ydim << "\n";
oss << "ZDIM=" << im->zdim << "\n";
oss << "VDIM=" << im->vdim << "\n";
oss << "TYPE=" << type << "\n";
oss << "PIXSIZE=" << im->wdim*8 <<" bits\n";
oss << scale << "CPU=" << endianness << "\n";
oss << "VX=" << im->vx << "\n";
oss << "VY=" << im->vy << "\n";
oss << "VZ=" << im->vz << "\n";
if ( im->cx != 0 )
oss << "XO="<< im->cx << "\n";
if ( im->cy != 0 )
oss << "YO="<< im->cy << "\n";
if ( im->cz != 0 )
oss << "ZO="<< im->cz << "\n";
if ( im->tx != 0.0 )
oss << "TX="<< im->tx << "\n";
if ( im->ty != 0.0 )
oss << "TY="<< im->ty << "\n";
if ( im->tz != 0.0 )
oss << "TZ="<< im->tz << "\n";
if ( im->rx != 0.0 )
oss << "RX="<< im->rx <<"\n";
if ( im->ry != 0.0 )
oss << "RY="<< im->ry << "\n";
if ( im->rz != 0.0 )
oss << "RZ=" << im->rz <<"\n";
pos = oss.str().length();
if(ImageIO_write(im, oss.str().data(), oss.str().length()) == 0)
return -1;
/* write user strings */
if ( im->user != NULL ) {
for(i = 0; i < im->nuser; i++) {
if ( im->user[i] == NULL ) continue;
pos += strlen(im->user[i]) + 2;
if(ImageIO_write(im, "#", 1) == 0) return -1;
if(ImageIO_write(im, im->user[i], strlen(im->user[i])) == 0) return -1;
if(ImageIO_write(im, "\n", 1) == 0) return -1;
}
}
/* write end of header */
pos = pos % 256;
if(pos > 252) {
for(i = pos; i < 256; i++)
if(ImageIO_write(im, "\n", 1) != 1) return -1;
pos = 0;
}
buf[0] = '\0';
for(i = pos; i < 252; i++) strcat(buf, "\n");
strcat(buf, "##}\n");
if(ImageIO_write(im, buf, strlen(buf)) == 0) return -1;
else return 1;
}
else return -1;
}
/* Writes the given image body in an already opened file.*/
CGAL_INLINE_FUNCTION
bool _writeInrimageData(const _image *im) {
std::size_t size, nbv, nwrt, i, v;
unsigned char **vp;
if(im->openMode != OM_CLOSE) {
/* scalar or interlaced vectors */
if(im->vectMode != VM_NON_INTERLACED) {
size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim;
nwrt = ImageIO_write(im, im->data, size);
return nwrt == size;
}
/* non interlaced vectors: interlace for saving */
else {
nbv = im->xdim * im->ydim * im->zdim;
size = im->xdim * im->ydim * im->zdim * im->wdim;
vp = (unsigned char **) ImageIO_alloc(im->vdim * sizeof(unsigned char *));
for(v = 0; v < im->vdim; v++)
vp[v] = (unsigned char *) im->data + v * size;
for(i = 0; i < nbv; i++)
for(v = 0; v < im->vdim; v++) {
if(ImageIO_write(im, (const void *) vp[v], im->wdim) != im->wdim)
return false;
vp[v] += im->wdim;
}
ImageIO_free(vp);
return true;
}
}
else return false;
}
/* read header of an opened inrimage */
CGAL_INLINE_FUNCTION
int readInrimageHeader(const char *,_image *im) {
char str[257];
int n, nusr;
stringListHead strl = { NULL, NULL };
stringListElement *oel, *el;
Set_numeric_locale num_locale("C");
if(im->openMode != OM_CLOSE) {
/* read image magic number */
if(!fgetns(str, 257, im )) return -1;
if(strcmp(str, INR4_MAGIC)) return -1;
/* while read line does not begin with '#' or '\n', read line
and decode field */
if(!fgetns(str, 257, im)) return -1;
while(str[0] != '#' && str[0] != '\0') {
if(!strncmp(str, "XDIM=", 5)) {
std::istringstream iss(str+5);
if(!(iss >> im->xdim)) return -1;
}
else if(!strncmp(str, "YDIM=", 5)) {
std::istringstream iss(str+5);
if(!(iss >> im->ydim)) return -1;
}
else if(!strncmp(str, "ZDIM=", 5)) {
std::istringstream iss(str+5);
if(!(iss >> im->zdim)) return -1;
}
else if(!strncmp(str, "VDIM=", 5)) {
std::istringstream iss(str+5);
if(!(iss >> im->vdim)) return -1;
if(im->vdim == 1) im->vectMode = VM_SCALAR;
else im->vectMode = VM_INTERLACED;
}
else if(!strncmp(str, "VX=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->vx)) return -1;
}
else if(!strncmp(str, "VY=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->vy)) return -1;
}
else if(!strncmp(str, "VZ=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->vz)) return -1;
}
else if(!strncmp(str, "TYPE=", 5)) {
if(!strncmp(str+5, "float", 5)) im->wordKind = WK_FLOAT;
else {
if(!strncmp(str+5, "signed fixed", 12)) {
im->wordKind = WK_FIXED;
im->sign = SGN_SIGNED;
}
else if(!strncmp(str+5, "unsigned fixed", 14)) {
im->wordKind = WK_FIXED;
im->sign = SGN_UNSIGNED;
}
else return -1;
}
}
/* before "sscanf(str+8, "%i %n", &im->wdim, &n) != 1"
was used.
However the man said
...
n Nothing is expected; instead, the number of charac­
ters consumed thus far from the input is stored
through the next pointer, which must be a pointer
to int. This is not a conversion, although it can
be suppressed with the * flag. The C standard
says: `Execution of a %n directive does not incre­
ment the assignment count returned at the comple­
tion of execution' but the Corrigendum seems to
contradict this. Probably it is wise not to make
any assumptions on the effect of %n conversions on
the return value.
...
Thus I change it. It was yielding a RETURN_FAILURE with
insight (GM).
*/
else if(!strncmp(str, "PIXSIZE=", 8)) {
std::istringstream iss(str+8);
if(!(iss >> im->wdim)) return -1;
if(im->wdim != 8 && im->wdim != 16 && im->wdim != 32 &&
im->wdim != 64) return -1;
if ( im->wdim <= 9 ) {
if(strncmp(str+8+1, " bits", 5)) return -1;
}
else if ( im->wdim <= 99 ) {
if(strncmp(str+8+2, " bits", 5)) return -1;
}
else {
return -1;
}
im->wdim >>= 3;
}
else if(!strncmp(str, "SCALE=", 6)) ;
else if(!strncmp(str, "CPU=", 4)) {
if(!strncmp(str+4, "decm", 4)) im->endianness = END_LITTLE;
else if(!strncmp(str+4, "alpha", 5)) im->endianness = END_LITTLE;
else if(!strncmp(str+4, "pc", 2)) im->endianness = END_LITTLE;
else if(!strncmp(str+4, "sun", 3)) im->endianness = END_BIG;
else if(!strncmp(str+4, "sgi", 3)) im->endianness = END_BIG;
else return -1;
}
else if(!strncmp(str, "XO=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->cx)) return -1;
}
else if(!strncmp(str, "YO=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->cy)) return -1;
}
else if(!strncmp(str, "ZO=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->cz)) return -1;
}
else if(!strncmp(str, "TX=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->tx)) return -1;
}
else if(!strncmp(str, "TY=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->ty)) return -1;
}
else if(!strncmp(str, "TZ=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->tz)) return -1;
}
else if(!strncmp(str, "RX=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->rx)) return -1;
}
else if(!strncmp(str, "RY=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->ry)) return -1;
}
else if(!strncmp(str, "RZ=", 3)) {
std::istringstream iss(str+3);
if(!(iss >> im->rz)) return -1;
}
if(!fgetns(str, 257, im)) return -1;
}
/* parse user strings */
im->nuser = nusr = 0;
while(str[0] == '#' && strncmp(str, "##}", 3)) {
addStringElement(&strl, str + 1);
while(strlen(str) == 256) {
if(!fgetns(str, 257, im)) return -1;
concatStringElement(&strl, str);
}
nusr++;
if(!fgetns(str, 257, im)) return -1;
}
/* go to end of header */
while(strncmp(str, "##}", 3)) {
if(!fgetns(str, 257, im)) return -1;
}
/* check header validity */
if(im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 &&
im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 &&
(im->wordKind == WK_FLOAT || (im->wordKind == WK_FIXED &&
im->sign != SGN_UNKNOWN)) &&
im->endianness != END_UNKNOWN) {
if(nusr > 0) {
im->nuser = nusr;
im->user = (char **) ImageIO_alloc(im->nuser * sizeof(char *));
oel = NULL;
for(el = strl.begin, n = 0; el != NULL; el = oel, n++) {
im->user[n] = el->string;
oel = el->next;
ImageIO_free(el);
}
}
return 0;
}
else return -1;
}
else return -1;
}
/* add a string element at the tail of given list */
static void addStringElement(stringListHead *strhead, const char *str) {
stringListElement *el;
el = (stringListElement *) ImageIO_alloc(sizeof(stringListElement));
/* was strdup(str); */
el->string = (char*)ImageIO_alloc( strlen(str)+1);
memcpy(el->string, str, strlen(str)+1);
el->next = NULL;
if(strhead->begin == NULL)
strhead->begin = strhead->end = el;
else {
strhead->end->next = el;
strhead->end = el;
}
}
/* concat given string at the last element of given list */
static void concatStringElement(const stringListHead *strhead,
const char *str) {
stringListElement *el;
el = strhead->end;
el->string = (char *) realloc(el->string,
strlen(el->string) + strlen(str) + 1);
strcat(el->string, str);
}
CGAL_INLINE_FUNCTION
int testInrimageHeader(char *magic,const char *) {
if (!strcmp(magic, INR_MAGIC))
return 0;
else
return -1;
}
CGAL_INLINE_FUNCTION
int writeInrimage(char *name,_image *im) {
int res;
_openWriteImage( im, name );
if(!im->fd) {
fprintf(stderr, "writeInrimage: error: unable to open file \'%s\'\n", name );
return ImageIO_OPENING;
}
res = _writeInrimageHeader(im, END_UNKNOWN);
if (res < 0) {
fprintf(stderr, "writeInrimage: error: unable to write header of \'%s\'\n",
name);
ImageIO_close( im );
im->fd = NULL;
im->openMode = OM_CLOSE;
return( res );
}
if (!_writeInrimageData(im)) {
fprintf(stderr, "writeInrimage: error: unable to write data of \'%s\'\n",
name);
ImageIO_close( im );
im->fd = NULL;
im->openMode = OM_CLOSE;
return -1;
}
ImageIO_close( im );
im->fd = NULL;
im->openMode = OM_CLOSE;
return ( res );
}
CGAL_INLINE_FUNCTION
PTRIMAGE_FORMAT createInrimageFormat() {
PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT));
f->testImageFormat=&testInrimageHeader;
f->readImageHeader=&readInrimageHeader;
f->writeImage=&writeInrimage;
strcpy(f->fileExtension,".inr,.inr.gz,.gradient,.gradient.gz,.gradient_direction,.gradient_direction.gz");
strcpy(f->realName,"Inrimage");
return f;
}