def _get_time(self, i): """Call _read_timestamp() for a given frame.""" self._verify_frame_no(i) with FileLocker(self._file_lock): self._file.seek(self._image_offset + self._image_block_size * i + self._image_bytes) return self._read_timestamp()
def get_frame(self, i): self._verify_frame_no(i) with FileLocker(self._file_lock): self._file.seek(self._image_offset + self._image_block_size * i) imdata = np.fromfile(self._file, self.pixel_type, self._pixel_count ).reshape(self._shape) # Timestamp immediately follows tfloat, ts = self._read_timestamp() md = {'time': ts, 'time_float': tfloat, 'gamut': self.metadata['gamut']} return Frame(imdata, frame_no=i, metadata=md)
def _read_tag_block(self, off_set, accum_dict): ''' Internal helper-function for reading the tagged blocks. ''' with FileLocker(self.file_lock): self.f.seek(self.off_setup + self.setup_length + off_set) block_size = self.unpack(DWORD) b_type = self.unpack(WORD) more_tags = self.unpack(WORD) if b_type == 1004: # docs say to ignore range data it seems to be a poison flag, # if see this, give up tag parsing return block_size, 0 try: d_name, d_type = TAGGED_FIELDS[b_type] except KeyError: return block_size, more_tags if d_type == '': # print "can't deal with <" + d_name + "> tagged data" return block_size, more_tags s_tmp = _build_struct(d_type) if (block_size - 8) % s_tmp.size != 0: # print 'something is wrong with your data types' return block_size, more_tags d_count = (block_size - 8) // (s_tmp.size) data = self.unpack('%d' % d_count + d_type) if not isinstance(data, tuple): # fix up data due to design choice in self.unpack data = (data, ) # parse time if b_type == 1002 or b_type == 1001: data = [(datetime.datetime.fromtimestamp(d >> 32), (FRACTION_MASK & d) / MAX_INT) for d in data] # convert exposure to seconds if b_type == 1003: data = [d / (MAX_INT) for d in data] accum_dict[d_name] = data return block_size, more_tags
def _hash_fun(self): """Generates the md5 hash of the header of the file. Here the header is defined as everything before the first image starts. This includes all of the meta-data (including the plethora of time stamps) so this will be unique. """ # get the file lock (so we don't screw up any other reads) with FileLocker(self.file_lock): self.f.seek(0) max_loc = self.image_locations[0] md5 = hashlib.md5() chunk_size = 128 * md5.block_size chunk_count = (max_loc // chunk_size) + 1 for j in range(chunk_count): md5.update(self.f.read(128 * md5.block_size)) self._hash = md5.hexdigest()
def _get_frame(self, number): with FileLocker(self.file_lock): # get basic information about the frame we want image_start = self.image_locations[number] annotation_size = self.unpack(DWORD, image_start) # this is not used, but is needed to advance the point in the file annotation = self.unpack('%db' % (annotation_size - 8)) image_size = self.unpack(DWORD) cfa = self.cfa compression = self.compression # sort out data type looking at the cached version data_type = self._data_type # actual bit per pixel actual_bits = image_size * 8 // (self._pixel_count) # so this seem wrong as 10 or 12 bits won't fit in 'u1' # but I (TAC) may not understand and don't have a packed file # (which the docs seem to imply don't exist) to test on so # I am leaving it. good luck. if actual_bits in (10, 12): data_type = 'u1' # move the file to the right point in the file self.f.seek(image_start + annotation_size) # suck the data out of the file and shove into linear # numpy array frame = frombuffer(self.f.read(image_size), data_type) # if mono-camera if cfa == CFA_NONE: if compression != 0: raise ValueError("Can not deal with compressed files\n" + "compression level: " + "{}".format(compression)) # we are working with a monochrome camera # un-pack packed data if (actual_bits == 10): frame = _ten2sixteen(frame) elif (actual_bits == 12): frame = _twelve2sixteen(frame) elif (actual_bits % 8): raise ValueError('Data should be byte aligned, ' + 'or 10 or 12 bit packed (appears to be' + ' %dbits/pixel?!)' % actual_bits) # re-shape to an array # flip the rows # and the cast to proper type frame = frame.reshape(self._height, self._width)[::-1].astype(self._dtype) if actual_bits in (10, 12): frame = frame[::-1, :] # Don't know why it works this way, but it does... # else, some sort of color layout else: if compression == 0: # and re-order so color is RGB (naively saves as BGR) frame = frame.reshape(self._height, self._width, 3)[::-1, :, ::-1].astype(self._dtype) elif compression == 2: raise ValueError("Can not process un-interpolated movies") else: raise ValueError("Should never hit this, " + "you have an un-documented file\n" + "compression level: " + "{}".format(compression)) return frame