1 /***************************************************************************
2  *                                                                         *
3  *   copyright : (C) 2015 C. Barth Netterfield                             *
4  *                   netterfield@astro.utoronto.ca                         *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  ***************************************************************************/
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <stdint.h>
20 
21 #include "its.h"
22 
23 char *ITS_ERRORSTR[] = {"OK", "Could not open file", "Unknown file format"};
24 
25 
ITSopen(char * filename)26 ITSfile *ITSopen(char *filename) {
27   ITSfile *its;
28   char *index_filename;
29 
30   its = (ITSfile*) malloc(sizeof(ITSfile));
31 
32   its->status = ITS_OK;
33 
34   its->fileName = malloc (strlen(filename)+1);
35   index_filename = malloc (strlen(filename)+5);
36 
37   sprintf(index_filename, "%s.its", filename);
38   strcpy(its->fileName,filename);
39 
40   its->fp_data = open(filename, O_RDONLY);
41   if (its->fp_data<0) {
42     its->status = ITS_NOOPEN;
43   free(index_filename);
44   return (its);
45   }
46 
47   its->fp_index = open(index_filename, O_RDONLY);
48   free(index_filename);
49   if (its->fp_index<0) {
50     its->status = ITS_NOOPEN;
51     return (its);
52   }
53 
54   return (its);
55 }
56 
57 
ITSclose(ITSfile * its)58 void ITSclose(ITSfile *its) {
59   if (its->status != ITS_NOOPEN) {
60     if (its->fp_index > 0) {
61       close(its->fp_index);
62     }
63     if (its->fp_data > 0) {
64       close(its->fp_data);
65     }
66   }
67 
68   free(its->fileName);
69   free(its);
70 }
71 
72 
73 /* initialize the image into a empty image, ready for use */
74 /* this is essentially a constructor, and should be called on */
75 /* any new its image before use! */
ITSInitImage(ITSimage * image)76 void ITSInitImage(ITSimage *image) {
77   image->w = image->h = image->x = image->y = 0;
78   image->allocated = 0;
79   image->img = NULL;
80 }
81 
82 
83 /* free any memory allocated to the its image */
84 /* note: the image is still valid and can be used again */
85 /* without calling ITSInitImage */
ITSFreeImage(ITSimage * image)86 void ITSFreeImage(ITSimage *image) {
87   if (image->img) {
88     free(image->img);
89   }
90   ITSInitImage(image);
91 }
92 
93 
isITSfile(char * filename)94 int isITSfile(char *filename) {
95   ITSfile *its;
96   int is_its;
97 
98   its = ITSopen(filename);
99   is_its = (its->status == ITS_OK);
100   ITSclose(its);
101 
102   return (is_its);
103 }
104 
checkHeader(unsigned char * h)105 int checkHeader(unsigned char *h) {
106   unsigned char sw[] = {0xeb, 0x90, 0x14, 0x6f, 0x00};
107   unsigned char crc = 0;
108   int i;
109 
110   for (i=0; i<5; i++) {
111     if (h[i] != sw[i]) {
112       fprintf(stderr, "bad byte %d in checkHeader\n", i);
113       return (0);
114     }
115   }
116   for (i=0; i<14; i++) {
117     crc ^= h[i];
118   }
119   if (crc != h[14]) {
120     fprintf(stderr, "bad checksum in header\n");
121     return 0;
122   }
123 
124   return(1);
125 }
126 
127 // how many frames in the file?  Check the length of the index.
ITSnframes(ITSfile * its)128 int ITSnframes(ITSfile *its) {
129   off_t bytes;
130 
131   bytes = lseek(its->fp_index,0,SEEK_END);
132 
133   if (bytes<0) bytes = 0L;
134 
135   return (bytes/INDEX_WORD_SIZE);
136 }
137 
ITSreadimage(ITSfile * its,int frame,int i_img,ITSimage * I)138 int ITSreadimage(ITSfile *its, int frame, int i_img, ITSimage *I) {
139   int nframes;
140   off_t offset;
141   int nr;
142   uint64_t index;
143   unsigned char buf_in[1024];
144   unsigned short w, h;
145   unsigned char ni;
146   int img_size;
147 
148   nframes = ITSnframes(its);
149   if (frame < 0) { // last frame
150     frame = nframes - 1;
151   }
152 
153   if ((frame >= nframes) || (nframes<1)) { // can't read past end;
154     I->w = I->h = I->x = I->y = 0;
155     return 0;
156   }
157 
158   // First read the index file to find the index.
159   offset = lseek(its->fp_index,frame*INDEX_WORD_SIZE, SEEK_SET);
160   if (offset != frame*INDEX_WORD_SIZE) {
161     I->w = I->h = I->x = I->y = 0;
162     return 0;
163   }
164 
165   nr = read(its->fp_index, &index, INDEX_WORD_SIZE);
166   if (nr != INDEX_WORD_SIZE) {
167     I->w = I->h = I->x = I->y = 0;
168     return 0;
169   }
170 
171   // Second: read the header in the data file
172   offset = lseek(its->fp_data, index, SEEK_SET);
173   if (offset != index) {
174     I->w = I->h = I->x = I->y = 0;
175     return 0;
176   }
177 
178   nr = read(its->fp_data, buf_in, 15);
179   if (nr != 15) {
180     I->w = I->h = I->x = I->y = 0;
181     return 0;
182   }
183 
184   if (!checkHeader(buf_in)) {
185     I->w = I->h = I->x = I->y = 0;
186     return 0;
187   }
188 
189   w = *((unsigned short *)(buf_in+9));
190   h = *((unsigned short *)(buf_in+11));
191   ni = *((unsigned char *)(buf_in+13));
192 
193   if (i_img >= ni) {
194     I->w = I->h = I->x = I->y = 0;
195     return 0;
196   }
197 
198   img_size = w * h;
199   if (I->allocated < img_size) {
200     I->img = realloc(I->img, img_size+1);
201     I->allocated = img_size;
202   }
203 
204   // Now read in the actual image
205   offset = lseek(its->fp_data, i_img*(img_size + 4), SEEK_CUR);
206   if (offset>=0) {
207     nr  = read(its->fp_data, &(I->x), 2);
208     nr += read(its->fp_data, &(I->y), 2);
209     nr += read(its->fp_data, I->img, img_size);
210   }
211   if ((offset<0) || (nr != img_size + 4)) {
212     I->w = I->h = I->x = I->y = 0;
213     return 0;
214   }
215 
216   I->w = w;
217   I->h = h;
218 
219   return 1;
220 }
221 
222