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