File indexing completed on 2024-12-22 04:17:13

0001 /***************************************************************************
0002  *                                                                         *
0003  *   copyright : (C) 2015 C. Barth Netterfield                             *
0004  *                   netterfield@astro.utoronto.ca                         *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  ***************************************************************************/
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 #include <sys/types.h>
0016 #include <sys/stat.h>
0017 #include <fcntl.h>
0018 #include <unistd.h>
0019 
0020 #include "bis.h"
0021 
0022 char *BIS_ERRORSTR[] = {"OK", "Could not open file", "Unknown file format"};
0023 
0024 
0025 BISfile *BISopen(char *filename) {
0026   BISfile *bis;
0027   int nr;
0028   unsigned short us_in;
0029   
0030   bis = (BISfile*) malloc(sizeof(BISfile));
0031   
0032   bis->status = BIS_OK;
0033   
0034   bis->fileName = malloc (strlen(filename)+1);
0035   
0036   strcpy(bis->fileName,filename);
0037   
0038   bis->fp = open(filename, O_RDONLY);
0039   
0040   if (bis->fp<0) {
0041     bis->status = BIS_NOOPEN;
0042     return (bis);
0043   }
0044   
0045   nr = read(bis->fp, &us_in,2);
0046   bis->formatType = us_in;
0047   nr += read(bis->fp, &us_in,2);
0048   bis->frameSize = us_in;
0049   
0050   switch (bis->formatType) {
0051     case 0xe6b0:
0052       bis->imagesPerFrame = 5;
0053       break;
0054     default:
0055       bis->status = BIS_UNKNOWN;
0056       break;
0057   }
0058   
0059   return (bis);
0060 }
0061 
0062 
0063 void BISclose(BISfile *bis) {
0064   if ((bis->fp>0) && (bis->status!=BIS_NOOPEN)) {
0065     close(bis->fp);
0066   }
0067   free(bis->fileName);
0068   free(bis);
0069 }
0070 
0071 
0072 /* initialize the image into a empty image, ready for use */
0073 /* this is essentially a constructor, and should be called on */
0074 /* any new bis image before use! */
0075 void BISInitImage(BISimage *image) {
0076   image->w = image->h = image->x = image->y = 0;
0077   image->allocated = 0;
0078   image->img = NULL;
0079 }
0080 
0081 
0082 /* free any memory allocated to the bis image */
0083 /* note: the image is still valid and can be used again */
0084 /* without calling BISInitImage */
0085 void BISFreeImage(BISimage *image) {
0086   if (image->img) {
0087     free(image->img);
0088   }
0089   BISInitImage(image);
0090 }
0091 
0092 
0093 int isBISfile(char *filename) {
0094   BISfile *bis;
0095   int is_bis;
0096   
0097   bis = BISopen(filename);
0098   is_bis = (bis->status == BIS_OK);
0099   BISclose(bis);
0100   
0101   return (is_bis);
0102 }
0103 
0104 int BISnframes(BISfile *bis) {
0105   off_t bytes;
0106   
0107   bytes = lseek(bis->fp,0,SEEK_END);
0108   
0109   if (bytes<0) bytes = 0L;
0110   
0111   if (bis->frameSize >0L) {
0112     //return (bytes);
0113     return ((bytes-4L)/bis->frameSize);
0114   } else {
0115     return 0;
0116   }
0117 }
0118 
0119 int BISreadimage(BISfile *bis, int frame, int i_img, BISimage *I) {
0120   int nframes;
0121   //unsigned short us_in[5];
0122   unsigned short image_offsets[5];
0123   unsigned short image_dim[4];
0124   int nr;
0125   int img_size;
0126   
0127   nframes = BISnframes(bis);
0128   if (frame < 0) { // last frame
0129     frame = nframes - 1;
0130   }
0131   
0132   if ((frame >= nframes) || (nframes<1)) { // can't read past end;
0133     I->w = I->h = I->x = I->y = 0;
0134     return 0;
0135   }
0136   
0137   if (i_img >= bis->imagesPerFrame) {
0138     I->w = I->h = I->x = I->y = 0;
0139     return 0;
0140   }
0141   
0142   // read the image offsets
0143   off_t offset = (off_t)frame * (off_t)bis->frameSize + 4L;
0144   //lseek(bis->fp, frame*bis->frameSize+4, SEEK_SET);
0145   lseek(bis->fp, offset, SEEK_SET);
0146   nr = read(bis->fp, &image_offsets, 10); // read offsets
0147   if ((nr!=10) || (image_offsets[i_img] <1)) {
0148     I->w = I->h = I->x = I->y = 0;
0149     return 0;
0150   }
0151   
0152   // Sanity check: offset points to the beginning of the frame
0153   // image_offsets[i_img] + offset points to the start of the image.
0154   // so image_offsets[i_img] had better be smaller than frameSize - 8 for
0155   // a 0 size image.  FIXME: tighter constraint?
0156   if (image_offsets[i_img] > bis->frameSize- 8) {
0157     I->w = I->h = I->x = I->y = 0;
0158     return 0;
0159   }
0160 
0161   // Read the image size and position data
0162   //lseek(bis->fp, frame*bis->frameSize+4+us_in[i_img], SEEK_SET);
0163   lseek(bis->fp, offset+(off_t)image_offsets[i_img], SEEK_SET);
0164   nr = read(bis->fp, &image_dim, 8); // read image dimensions
0165   if (nr!=8) {
0166     I->w = I->h = I->x = I->y = 0;
0167     return 0;
0168   }
0169   I->w = image_dim[0];
0170   I->h = image_dim[1];
0171   I->x = image_dim[2];
0172   I->y = image_dim[3];
0173 
0174   if ((I->w < 1) || (I->h < 1)) {
0175     I->w = I->h = I->x = I->y = 0;
0176     return 0;
0177   }
0178 
0179   // read the image
0180   img_size = I->w * I->h;
0181 
0182   // Sanity Check:
0183   // image_size + image_offsets[i_image] + 8 had better be smaller than
0184   // frameSize in order to fit in the frame.
0185   if (image_offsets[i_img] + img_size > bis->frameSize- 8) {
0186     I->w = I->h = I->x = I->y = 0;
0187     return 0;
0188   }
0189 
0190   if (img_size > I->allocated) {
0191     I->img = realloc(I->img, img_size+1);
0192     I->allocated = img_size;
0193   }
0194   
0195   nr = read(bis->fp, I->img, img_size); // read image
0196   if (nr != img_size) {
0197     I->w = I->h = I->x = I->y = 0;
0198     return 0;
0199   }
0200     
0201   return 1;
0202 }
0203