def insert_tile(self, zoom, row, col, data): with self.db_connection as db_connection: cursor = db_connection.cursor() compression = self.compression data_type = self.data_type if compression and (data_type == "xray"): db_connection.text_factory = str data_compressed = blosc.pack_array(data, cname=compression) data = data_compressed if data_type == "image/TIFF": try: assert data.dtype == "uint8" except: raise TypeError("dtype %s not supported" % data.dtype) image = Image.fromarray(np.uint8(data)) buf = ioBuffer() if compression == "tiff_lzw": TiffImagePlugin.WRITE_LIBTIFF = True image.save(buf, "TIFF", compression=compression) TiffImagePlugin.WRITE_LIBTIFF = False else: image.save(buf, "TIFF", compression=compression) buf.seek(0) data = Binary(buf.read()) if data_type == "image/JPEG2000": try: assert data.dtype == "uint8" except: raise TypeError("dtype %s not supported" % data.dtype) image = Image.fromarray(np.uint8(data)) buf = ioBuffer() image.save(buf, "j2k") buf.seek(0) data = Binary(buf.read()) try: cursor.execute(""" INSERT INTO tiles (zoom_level, tile_row, tile_column, tile_data) VALUES (?,?,?,?) """, (zoom, row, col, data)) except: raise
def worker_map(temp_db, tile_dict, extra_args, invert_y): """ Function responsible for sending the correct oriented tile data to a temporary sqlite3 database. Inputs: temp_db -- a temporary sqlite3 database that will hold this worker's tiles tile_dict -- a dictionary with TMS coordinates and file path for a tile tile_info -- a list of ZoomMetadata objects pre-generated for this tile set imagery -- the type of image format to send to the sqlite3 database invert_y -- a function that will flip the Y axis of the tile if present """ tile_info = extra_args['tile_info'] imagery = extra_args['imagery'] jpeg_quality = extra_args['jpeg_quality'] zoom = tile_dict['z'] if extra_args['renumber']: zoom -= 1 level = next((item for item in tile_info if item.zoom == zoom), None) # fiddle with offsets based on absolute (NSG profile) vs relative row/column numbering x_row = tile_dict['x'] if extra_args[ 'nsg_profile'] else tile_dict['x'] - level.min_tile_row if invert_y is not None: y_column = invert_y(zoom, tile_dict['y']) if not extra_args['nsg_profile']: y_offset = invert_y(zoom, level.max_tile_col) y_column -= y_offset else: y_column = tile_dict['y'] if extra_args[ 'nsg_profile'] else tile_dict['y'] - level.min_tile_col if IOPEN is not None: img = IOPEN(tile_dict['path'], 'r') data = ioBuffer() # TODO add options for "mvt" and "GeoJson" if imagery == 'mixed': if img_has_transparency(img): data = img_to_buf(img, 'png', jpeg_quality).read() else: data = img_to_buf(img, 'jpeg', jpeg_quality).read() else: data = img_to_buf(img, imagery, jpeg_quality).read() temp_db.insert_image_blob(zoom, x_row, y_column, sbinary(data)) else: file_handle = open(tile_dict['path'], 'rb') data = buffer(file_handle.read()) temp_db.insert_image_blob(zoom, x_row, y_column, data) file_handle.close()
def img_to_buf(img, img_type, jpeg_quality=75): """ Returns a buffer array with image binary data for the input image. This code is based on logic implemented in MapProxy to convert PNG images to JPEG then return the buffer. Inputs: img -- an image on the filesystem to be converted to binary img_type -- the MIME type of the image (JPG, PNG) """ defaults = {} buf = ioBuffer() if img_type == 'jpeg': img.convert('RGB') # Hardcoding a default compression of 75% for JPEGs defaults['quality'] = jpeg_quality elif img_type == 'source': img_type = img.format img.save(buf, img_type, **defaults) buf.seek(0) return buf
def worker_map(temp_db, tile_dict, extra_args, invert_y): """ Function responsible for sending the correct oriented tile data to a temporary sqlite3 database. Inputs: temp_db -- a temporary sqlite3 database that will hold this worker's tiles tile_dict -- a dictionary with TMS coordinates and file path for a tile tile_info -- a list of ZoomMetadata objects pre-generated for this tile set imagery -- the type of image format to send to the sqlite3 database invert_y -- a function that will flip the Y axis of the tile if present """ tile_info = extra_args['tile_info'] imagery = extra_args['imagery'] jpeg_quality = extra_args['jpeg_quality'] zoom = tile_dict['z'] level = next((item for item in tile_info if item.zoom == zoom), None) x_row = tile_dict['x'] - level.min_tile_row if invert_y is not None: y_offset = invert_y(tile_dict['z'], level.max_tile_col) y_column = invert_y(tile_dict['z'], tile_dict['y']) y_column -= y_offset else: y_column = tile_dict['y'] - level.min_tile_col if IOPEN is not None: img = IOPEN(tile_dict['path'], 'r') data = ioBuffer() if imagery == 'mixed': if img_has_transparency(img): data = img_to_buf(img, 'png', jpeg_quality).read() else: data = img_to_buf(img, 'jpeg', jpeg_quality).read() else: data = img_to_buf(img, imagery, jpeg_quality).read() temp_db.insert_image_blob(zoom, x_row, y_column, sbinary(data)) else: file_handle = open(tile_dict['path'], 'rb') data = buffer(file_handle.read()) temp_db.insert_image_blob(zoom, x_row, y_column, data) file_handle.close()
def get_tiledata(self, zoom, row, col): with self.db_connection as db_connection: cursor = db_connection.cursor() data_type = self.data_type if self.compression and (data_type == "xray"): db_connection.text_factory = str try: cursor.execute(""" SELECT tile_data from tiles WHERE zoom_level=? AND tile_row=? AND tile_column=?; """, (str(zoom), str(row), str(col))) except: raise if data_type == "xray": if self.compression: data = blosc.unpack_array(cursor.fetchone()[0]) else: data = cursor.fetchone()[0] if data_type == "image/TIFF": data = cursor.fetchone()[0] # img = Image.frombuffer("L", (255, 255), data) img = Image.open(ioBuffer(data)) data = np.array(img) return data