| |
| """Image processor class for EvaByte.""" |
|
|
| from typing import Dict, List, Optional, Union, Tuple |
|
|
| import io |
| from transformers.image_processing_utils import BaseImageProcessor |
| from transformers.image_utils import ( |
| ImageInput, |
| PILImageResampling, |
| valid_images, |
| validate_preprocess_arguments, |
| ) |
| from PIL import Image |
|
|
| def _get_qtable_bytes(): |
| return { |
| 5: b'\xff\xd8\xff\xdb\x00C\x00\xa0nx\x8cxd\xa0\x8c\x82\x8c\xb4\xaa\xa0\xbe\xf0\xff\xff\xf0\xdc\xdc\xf0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdb\x00C\x01\xa0\xb4\xb4\xf0\xd2\xf0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd9', |
| 10: b'\xff\xd8\xff\xdb\x00C\x00P7<F<2PFAFZUP_x\xc8\x82xnnx\xf5\xaf\xb9\x91\xc8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdb\x00C\x01PZZxix\xeb\x82\x82\xeb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd9', |
| 15: b'\xff\xd8\xff\xdb\x00C\x005%(/(!5/+/<95?P\x85WPIIP\xa3u{a\x85\xc1\xaa\xcb\xc8\xbe\xaa\xba\xb7\xd5\xf0\xff\xff\xd5\xe2\xff\xe6\xb7\xba\xff\xff\xff\xff\xff\xff\xff\xff\xff\xce\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdb\x00C\x015<<PFP\x9dWW\x9d\xff\xdc\xba\xdc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd9', |
| 20: b'\xff\xd8\xff\xdb\x00C\x00(\x1c\x1e#\x1e\x19(#!#-+(0<dA<77<{X]Id\x91\x80\x99\x96\x8f\x80\x8c\x8a\xa0\xb4\xe6\xc3\xa0\xaa\xda\xad\x8a\x8c\xc8\xff\xcb\xda\xee\xf5\xff\xff\xff\x9b\xc1\xff\xff\xff\xfa\xff\xe6\xfd\xff\xf8\xff\xdb\x00C\x01(--<5<vAAv\xf8\xa5\x8c\xa5\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xff\xd9', |
| 25: b'\xff\xd8\xff\xdb\x00C\x00 \x16\x18\x1c\x18\x14 \x1c\x1a\x1c$" &0P40,,0bFJ:Ptfzxrfpn\x80\x90\xb8\x9c\x80\x88\xae\x8anp\xa0\xda\xa2\xae\xbe\xc4\xce\xd0\xce|\x9a\xe2\xf2\xe0\xc8\xf0\xb8\xca\xce\xc6\xff\xdb\x00C\x01 $$0*0^44^\xc6\x84p\x84\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xff\xd9', |
| 30: b'\xff\xd8\xff\xdb\x00C\x00\x1b\x12\x14\x17\x14\x11\x1b\x17\x16\x17\x1e\x1c\x1b (B+(%%(Q:=0B`Ued_U][jx\x99\x81jq\x90s[]\x85\xb5\x86\x90\x9e\xa3\xab\xad\xabg\x80\xbc\xc9\xba\xa6\xc7\x99\xa8\xab\xa4\xff\xdb\x00C\x01\x1b\x1e\x1e(#(N++N\xa4n]n\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xff\xd9', |
| 50: b'\xff\xd8\xff\xdb\x00C\x00\x10\x0b\x0c\x0e\x0c\n\x10\x0e\r\x0e\x12\x11\x10\x13\x18(\x1a\x18\x16\x16\x181#%\x1d(:3=<9387@H\\N@DWE78PmQW_bghg>Mqypdx\\egc\xff\xdb\x00C\x01\x10\x12\x12\x18\x15\x18/\x1a\x1a/cB8Bcccccccccccccccccccccccccccccccccccccccccccccccccc\xff\xd9', |
| 75: b'\xff\xd8\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c $.\' ",#\x1c\x1c(7),01444\x1f\'9=82<.342\xff\xdb\x00C\x01\x08\t\t\x0c\x0b\x0c\x18\r\r\x182!\x1c!22222222222222222222222222222222222222222222222222\xff\xd9', |
| 95: b'\xff\xd8\xff\xdb\x00C\x00\x02\x01\x01\x01\x01\x01\x02\x01\x01\x01\x02\x02\x02\x02\x02\x04\x03\x02\x02\x02\x02\x05\x04\x04\x03\x04\x06\x05\x06\x06\x06\x05\x06\x06\x06\x07\t\x08\x06\x07\t\x07\x06\x06\x08\x0b\x08\t\n\n\n\n\n\x06\x08\x0b\x0c\x0b\n\x0c\t\n\n\n\xff\xdb\x00C\x01\x02\x02\x02\x02\x02\x02\x05\x03\x03\x05\n\x07\x06\x07\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\xff\xd9', |
| 100: b'\xff\xd8\xff\xdb\x00C\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\xff\xdb\x00C\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\xff\xd9', |
| } |
|
|
|
|
| def _resize_if_exceeding_max_len( |
| width: int, height: int, min_len: Optional[int] = 16, max_len: Optional[int] = None |
| ) -> Tuple[int, int]: |
| """ |
| Get the output size of the image after resizing given a dictionary specifying the max and min sizes. |
| |
| Args: |
| height (`int`): |
| Height of the input image. |
| width (`int`): |
| Width of the input image. |
| max_len (`Dict[str, int]`, *optional*, defaults to the maximum size of the image): |
| Defines the maximum dimensions of the image. |
| |
| Returns: |
| The output size of the image after resizing. |
| """ |
| max_len = max(height, width) if max_len is None else max_len |
| aspect_ratio = width / height |
|
|
| if width >= height and width > max_len: |
| width = max_len |
| height = int(width / aspect_ratio) |
| if height % 2 != 0: |
| height += 1 |
| elif height > width and height > max_len: |
| height = max_len |
| width = int(height * aspect_ratio) |
| if width % 2 != 0: |
| width += 1 |
|
|
| |
| height = max(height, min_len) |
| width = max(width, min_len) |
| return width, height |
|
|
| class EvaByteImageProcessor(BaseImageProcessor): |
|
|
| model_input_names = [] |
| |
| def __init__( |
| self, |
| do_resize: bool = True, |
| resample: PILImageResampling = PILImageResampling.LANCZOS, |
| size: Dict[str, int] = None, |
| do_convert_rgb: bool = True, |
| jpeg_quality: int = 25, |
| jpeg_subsampling: str = "4:2:0", |
| jpeg_streamtype: str = 2, |
| jpeg_restart_marker_blocks: int = 1, |
| **kwargs, |
| ) -> None: |
| super().__init__(**kwargs) |
| self.do_resize = do_resize |
| self.resample = resample |
| self.size = size if size is not None else {"longest_edge": 384} |
| self.do_convert_rgb = do_convert_rgb |
| self.jpeg_quality = jpeg_quality |
| self.jpeg_subsampling = jpeg_subsampling |
| self.jpeg_streamtype = jpeg_streamtype |
| self.jpeg_restart_marker_blocks = jpeg_restart_marker_blocks |
|
|
| def jpeg_encode( |
| self, |
| image, |
| jpeg_quality, |
| jpeg_subsampling, |
| jpeg_streamtype, |
| jpeg_restart_marker_blocks, |
| ): |
| with io.BytesIO() as output: |
| image.save( |
| output, |
| format="JPEG", |
| quality=jpeg_quality, |
| subsampling=jpeg_subsampling, |
| streamtype=jpeg_streamtype, |
| restart_marker_blocks=jpeg_restart_marker_blocks |
| ) |
| jpeg_bytes = output.getvalue() |
| return jpeg_bytes |
|
|
| def jpeg_merge_qtables( |
| self, |
| image_bytes, |
| jpeg_quality=None, |
| ): |
| if jpeg_quality is None: |
| jpeg_quality = self.jpeg_quality |
| qtable_bytes = _get_qtable_bytes()[jpeg_quality] |
| return image_bytes[:2] + qtable_bytes[2:-2] + image_bytes[2:] |
| |
| def resize( |
| self, |
| image: Image, |
| size: Dict[str, int], |
| resample: PILImageResampling = PILImageResampling.LANCZOS, |
| ) -> Image: |
| if "longest_edge" in size: |
| width, height = image.size |
| |
| width, height = _resize_if_exceeding_max_len(width, height, max_len=size["longest_edge"]) |
| size = (width, height) |
| elif "width" in size and "height" in size: |
| size = (size["width"], size["height"]) |
| else: |
| raise ValueError("size must be a dictionary with key 'longest_edge' or 'height' and 'width'.") |
| resized_image = image.resize(size, resample=resample) |
| return resized_image |
|
|
| def preprocess( |
| self, |
| images: ImageInput, |
| do_resize: bool = None, |
| resample = None, |
| size: Dict[str, int] = None, |
| do_convert_rgb: bool = None, |
| jpeg_quality: int = None, |
| jpeg_subsampling: str = None, |
| jpeg_streamtype: str = None, |
| jpeg_restart_marker_blocks: int = None, |
| ): |
| do_resize = do_resize if do_resize is not None else self.do_resize |
| size = size if size is not None else self.size |
| resample = resample if resample is not None else self.resample |
| do_convert_rgb = do_convert_rgb if do_convert_rgb is not None else self.do_convert_rgb |
|
|
| jpeg_quality = jpeg_quality if jpeg_quality is not None else self.jpeg_quality |
| jpeg_subsampling = jpeg_subsampling if jpeg_subsampling is not None else self.jpeg_subsampling |
| jpeg_streamtype = jpeg_streamtype if jpeg_streamtype is not None else self.jpeg_streamtype |
| jpeg_restart_marker_blocks = jpeg_restart_marker_blocks if jpeg_restart_marker_blocks is not None else self.jpeg_restart_marker_blocks |
|
|
| if images is not None and not valid_images(images): |
| raise ValueError( |
| "Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, " |
| "torch.Tensor, tf.Tensor or jax.ndarray." |
| ) |
|
|
| validate_preprocess_arguments( |
| do_resize=do_resize, |
| size=size, |
| resample=resample, |
| ) |
| images_list = images |
| if do_convert_rgb: |
| images_list = [ |
| [ |
| image.convert("RGB") for image in images |
| ] |
| for images in images_list |
| ] |
|
|
| if do_resize: |
| images_list = [ |
| [ |
| self.resize(image=image, size=size, resample=resample) |
| for image in images |
| ] |
| for images in images_list |
| ] |
|
|
| jpeg_bytes = [ |
| [ |
| self.jpeg_encode( |
| image, |
| jpeg_quality, |
| jpeg_subsampling, |
| jpeg_streamtype, |
| jpeg_restart_marker_blocks |
| ) for image in images |
| ] |
| for images in images_list |
| ] |
| return jpeg_bytes |
|
|