/* $Id: cpl_frameset_io.c,v 1.21 2007/11/29 11:39:25 llundin Exp $ * * This file is part of the ESO Common Pipeline Library * Copyright (C) 2001-2004 European Southern Observatory * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * $Author: llundin $ * $Date: 2007/11/29 11:39:25 $ * $Revision: 1.21 $ * $Name: $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "cpl_frameset_io.h" #include "cpl_frame.h" #include "cpl_frame_impl.h" #include "cpl_imagelist_defs.h" #include "cpl_tools.h" #include "cpl_errorstate.h" /** * @defgroup cpl_frameset_io Frame Sets IO functions * * @par Synopsis: * @code * #include * @endcode */ /**@{*/ /* * Private functions */ static int cpl_fits_has_image(const char *, int); static cpl_error_code cpl_imagelist_append_from_file(cpl_imagelist *, int *, const char *, cpl_type, int, int); /*----------------------------------------------------------------------------*/ /** @brief Load an imagelist from a frameset @param fset The frames set @param itype The required image type @param pnum The plane number, 1 for first, 0 for all planes @param extnum The extension number, 0 for primary, n for nth, -1 for all @return the loaded list of images or NULL on error. @note The returned cpl_imagelist must be deallocated using cpl_imagelist_delete() Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if fset is NULL - CPL_ERROR_ILLEGAL_INPUT if pnum is negative, extnum is lower than -1 or one image cannot be loaded as specified */ /*----------------------------------------------------------------------------*/ cpl_imagelist * cpl_imagelist_load_frameset(const cpl_frameset * fset, cpl_type itype, int pnum, int extnum) { cpl_imagelist * self; const cpl_frame * cur_frame; int selfsize; /* Test entries */ cpl_ensure(fset != NULL, CPL_ERROR_NULL_INPUT, NULL); cpl_ensure(pnum >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL); cpl_ensure(extnum >= -1, CPL_ERROR_ILLEGAL_INPUT, NULL); /* Create empty output image list */ self = cpl_imagelist_new(); selfsize = 0; for (cur_frame = cpl_frameset_get_first_const(fset); cur_frame != NULL; cur_frame = cpl_frameset_get_next_const(fset)) { const char * filename = cpl_frame_get_filename(cur_frame); if (extnum < 0) { /* Image(s) from all extensions requested. */ /* Get the nb of extensions - may fail, e.g. on invalid FITS ... */ const int nb_extensions = cpl_frame_get_nextensions(cur_frame); int iextnum; if (nb_extensions < 0) break; for (iextnum = 0; iextnum <= nb_extensions; iextnum++) { const int has_image = cpl_fits_has_image(filename, iextnum); if (has_image < 0) break; /* Allow only 1st HDU to not have image data */ if ((iextnum > 0 || has_image) && cpl_imagelist_append_from_file(self, &selfsize, filename, itype, pnum, iextnum)) break; } if (iextnum <= nb_extensions) break; } else { if (cpl_imagelist_append_from_file(self, &selfsize, filename, itype, pnum, extnum)) break; } } if (cur_frame != NULL) { const char * filename = cpl_frame_get_filename(cur_frame); cpl_imagelist_delete(self); (void)cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__, __LINE__, "file=%s, " "itype=%d, pnum=%d, extnum=%d", filename ? filename : "", itype, pnum, extnum); return NULL; } cx_assert(cpl_imagelist_get_size(self) == selfsize); /* Require created imagelist to be non-empty */ if (selfsize == 0) { const char * filename = cpl_frame_get_filename(cur_frame); cpl_imagelist_delete(self); (void)cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__, __LINE__, "file=%s, " "itype=%d, pnum=%d, extnum=%d", filename ? filename : "", itype, pnum, extnum); return NULL; } return self; } /**@}*/ /*----------------------------------------------------------------------------*/ /** @internal @brief Append the specified images to an imagelist from a file @param self The imagelist to append to @param pselfsize Increase with number of images appended @param filename The file to read from @param itype The required image type @param pnum The plane number, 1 for first, 0 for all planes @param extnum The extension number, 0 for primary, n for nth, -1 for all @return CPL_ERROR_NONE, or the relevant error code on error Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if fset is NULL - CPL_ERROR_ILLEGAL_INPUT if pnum is negative, extnum is lower than -1 or one image cannot be loaded as specified */ /*----------------------------------------------------------------------------*/ static cpl_error_code cpl_imagelist_append_from_file(cpl_imagelist * self, int * pselfsize, const char * filename, cpl_type itype, int pnum, int extnum) { int selfsize = cpl_imagelist_get_size(self); cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT); cpl_ensure_code(pselfsize != NULL, CPL_ERROR_NULL_INPUT); cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT); if (pnum == 0) { /* All planes required */ cpl_imagelist * onelist = cpl_imagelist_load(filename, itype, extnum); const int onesize = cpl_imagelist_get_size(onelist); int j; cpl_ensure_code(onelist != NULL, CPL_ERROR_ILLEGAL_INPUT); /* Move the images from onelist to self */ for (j = 0; j < onesize; j++) { cpl_image * img = cpl_imagelist_unset(onelist, 0); if (cpl_imagelist_set(self, img, selfsize)) { /* Type or size could differ */ cpl_imagelist_delete(onelist); cpl_image_delete(img); cpl_ensure_code(0, CPL_ERROR_ILLEGAL_INPUT); } selfsize++; } cx_assert(cpl_imagelist_get_size(onelist) == 0); cpl_imagelist_delete(onelist); } else { /* Only one plane required */ cpl_image * img = cpl_image_load(filename, itype, pnum-1, extnum); cpl_ensure_code(img != NULL, CPL_ERROR_ILLEGAL_INPUT); if (cpl_imagelist_set(self, img, selfsize)) { /* Type or size could differ */ cpl_image_delete(img); cpl_ensure_code(0, CPL_ERROR_ILLEGAL_INPUT); } selfsize++; } cx_assert(cpl_imagelist_get_size(self) == selfsize); *pselfsize = selfsize; return CPL_ERROR_NONE; } /*----------------------------------------------------------------------------*/ /** @internal @brief See if an extension has image data or not @param filename The file to test @param extnum The extension number, 0 for primary, n for nth @return 1 if the extension has image data, 0 if not, negative on error */ /*----------------------------------------------------------------------------*/ static int cpl_fits_has_image(const char * filename, int extnum) { fitsfile * file; int error = 0; int naxis; cpl_ensure(filename != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE); cpl_ensure(extnum >= 0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE); if (fits_open_diskfile(&file, filename, READONLY, &error)) { (void)cpl_error_set_message_macro(cpl_func, CPL_ERROR_FILE_IO, __FILE__, __LINE__, "fits_open_diskfile('%s') " "returned %d: %s", filename, error, cpl_tools_get_cfitsio_msg(error)); return -1; } if (extnum > 0) { if (fits_movabs_hdu(file, 1 + extnum, NULL, &error)) { int error2; fits_close_file(file, &error2); (void)cpl_error_set_message_macro(cpl_func, CPL_ERROR_BAD_FILE_FORMAT, __FILE__, __LINE__, "fits_movabs_hdu('%s') " "returned %d: %s", filename, error, cpl_tools_get_cfitsio_msg(error)); return -2; } } if (fits_get_img_dim(file, &naxis, &error)) { int error2; fits_close_file(file, &error2); (void)cpl_error_set_message_macro(cpl_func, CPL_ERROR_BAD_FILE_FORMAT, __FILE__, __LINE__, "fits_get_img_dim('%s') " "returned %d: %s", filename, error, cpl_tools_get_cfitsio_msg(error)); return -3; } if (fits_close_file(file, &error)) { (void)cpl_error_set_message_macro(cpl_func, CPL_ERROR_BAD_FILE_FORMAT, __FILE__, __LINE__, "fits_close_file('%s') " "returned %d: %s", filename, error, cpl_tools_get_cfitsio_msg(error)); return -4; } return naxis == 2 || naxis == 3 ? 1 : 0; }