예제 #1
0
파일: vips.py 프로젝트: weexp/gdal2mbtiles
    def from_gdal_dataset(cls, dataset, band):
        """
        Creates a new 1-band pyvips.Image from `dataset` at `band`

        dataset: GDAL Dataset
        band: Number of the band, starting from 1
        """
        with LibVips.disable_warnings():
            filename = dataset.GetFileList()[0]
            image1 = Image.new_from_file(filename)

            # Extract the band
            image2 = image1.extract_band((band - 1), n=1)

            # Cast to the right datatype, if necessary
            datatype = dataset.GetRasterBand(band).NumPyDataType
            if VImageAdapter(image2).NumPyType() == datatype:
                return image2
            types = dict((v, k) for k, v in cls.NUMPY_TYPES.items())
            image3 = Image.new_from_memory(image2.write_to_memory(),
                                           width=image2.width,
                                           height=image2.height,
                                           bands=1,
                                           format=types[datatype])
            return image3
def extract_imgs(img_path:str, label_path:str, output_path:str):
    '''读取图像并进行切分处理

    Args:
        img_path(str): 要处理的图像路径
        label_path(str): 对应的标签图像
        output_path(str): 输出目录
    '''
    print('Loading source image from {}.'.format(img_path))
    src_img = vipImage.new_from_file(img_path)
    
    label_img = None
    if label_path is not None:
        print('Loading label image from {}.'.format(label_path))
        label_img = vipImage.new_from_file(label_path)

    # 输出图片基本信息
    for img in [('Source Image', src_img), ('Label Image', label_img)]:
        print('{} info:'.format(img[0]))
        if img[1] is None: continue
        for key in ['width', 'height', 'bands']:
            print('\t{}: {}'.format(key, getattr(img[1], key)))

    # 将图像完全加载到内存,耗时可能会很长,内存小的机器慎用
    print('Loading image to memory, it may take a few minutes.')
    src_img = load_to_memory(src_img)
    label_img = load_to_memory(label_img) if label_img is not None else None
    crop_and_save(src_img, label_img, output_path, img_path)
예제 #3
0
    def from_gdal_dataset(cls, dataset, band):
        """
        Creates a new 1-band pyvips.Image from `dataset` at `band`

        dataset: GDAL Dataset
        band: Number of the band, starting from 1
        """
        with LibVips.disable_warnings():
            filename = dataset.GetFileList()[0]
            image1 = Image.new_from_file(filename)

            # Extract the band
            image2 = image1.extract_band((band - 1), n=1)

            # Cast to the right datatype, if necessary
            datatype = dataset.GetRasterBand(band).NumPyDataType
            if VImageAdapter(image2).NumPyType() == datatype:
                return image2
            types = dict((v, k) for k, v in cls.NUMPY_TYPES.items())
            image3 = Image.new_from_memory(image2.write_to_memory(),
                                           width=image2.width,
                                           height=image2.height,
                                           bands=1, format=types[datatype])
            image3._buf = image2
            return image3
예제 #4
0
def rescale(img: Image,
            scale: Union[float, Tuple[float, float]],
            kernel: str = Kernel.LINEAR) -> Image:
    if isinstance(scale, float):
        return img.resize(scale, kernel=kernel)
    else:
        scale, vscale = scale
        return img.resize(scale, vscale=vscale, kernel=kernel)
예제 #5
0
    def add(self, im: pyvips.Image) -> pyvips.Image:
        """Use method which finds complementary color.

        Returns image
        """
        text = pyvips.Image.text(
            self.text, width=im.width, dpi=300, font=f"{self.font}"
        )
        text = text.rotate(self.rotate)

        # the position of the overlay in the image
        margin = 25
        position = self.position

        if position == "top-left":
            x_pos = margin
            y_pos = margin
        elif position == "top-right":
            x_pos = im.width - text.width - margin
            y_pos = margin
        elif position == "bottom-right":
            x_pos = im.width - text.width - margin
            y_pos = im.height - text.height - margin
        elif position == "bottom-left":
            x_pos = margin
            y_pos = im.height - text.height - margin
        else:
            print(f"Incorrect watermark position: {position}")
            sys.exit(1)

        # find the non-alpha image bands
        if im.hasalpha():
            no_alpha = im.extract_band(0, n=im.bands - 1)
        else:
            no_alpha = im

        # the pixels we will render the overlay on top of
        bg = no_alpha.crop(x_pos, y_pos, text.width, text.height)

        # mask the background with the text, so all non-text areas become zero, and find
        # the zero-excluding average
        avg = avgze(text.ifthenelse(bg, 0))

        # for each band, find the opposing value
        mx = 255 if im.format == "uchar" else 65535
        text_colour = [oppose(avg[i], mx) for i in range(len(avg))]

        # make an overlay ... we put solid colour into the image and set a faded version
        # of the text mask as the alpha
        overlay = bg.new_from_image(text_colour)
        overlay = overlay.bandjoin((text * self.opacity).cast("uchar"))

        # and composite that on to the original image
        im = im.composite(overlay, "over", x=x_pos, y=y_pos)
        return im
예제 #6
0
def getFontSizeByLanguage(string, font, renderer_lib, remove_height_offset=False):
    # get fontsize according to language
    string = cgi.escape(string)                   # Here preparing string to render if any special symbol found then convert into html code for render like(& to &)
    if int(renderer_lib) == 1:
        size = font.getsize(string)
        if remove_height_offset:
            size[1] -= font.getoffset(string)[1]
    else:
        size = pyImage.text(string, dpi=font['normal_font_size'], fontfile=font['normal_font_file']).width, pyImage.text(string, dpi=font['normal_font_size'], fontfile=font['normal_font_file']).height
        x = pyImage.text(string, dpi=font['normal_font_size'], fontfile=font['normal_font_file'])
    return size
예제 #7
0
파일: vips.py 프로젝트: weexp/gdal2mbtiles
    def write_buffer(self, image, resolution):
        if VImageAdapter(
                image).BufferSize() >= self.IMAGE_BUFFER_DISK_THRESHOLD:
            logger.debug('Buffering resolution {0} to disk'.format(resolution))
            vipsfile = Image.new_temp_file("%s.v")
            tempfile_image = image.write(vipsfile)
            return tempfile_image

        logger.debug('Buffering resolution {0} to memory'.format(resolution))
        return Image.new_from_memory(image.write_to_memory(), image.width,
                                     image.height, image.bands, 'uchar')
예제 #8
0
def get_vips_field(
    vips_image: VIPSImage, field: str, default: Any = None
) -> Any:
    try:
        return vips_image.get_value(field)
    except VIPSError:
        return default
예제 #9
0
def _reprocess_image(queue: Queue) -> None:
    global stats
    while not queue.empty():
        img_data = queue.get()
        img_data["filePath"] = f"{os.path.splitext(img_data['filePath'])[0]}.tif"
        tif_filename = os.path.basename(img_data["filePath"])
        local_file = f"TEMP_{os.path.basename(img_data['id'])}"
        logger.info(f"Processing {img_data['id']}")
        if _download_source_file(img_data, local_file):
            image = _preprocess_image(img_data, local_file)
            if image:
                image.tiffsave(tif_filename, tile=True, pyramid=True, compression=config.COMPRESSION_TYPE,
                    tile_width=config.PYTIF_TILE_WIDTH, tile_height=config.PYTIF_TILE_HEIGHT, \
                    xres=config.DPI_VALUE, yres=config.DPI_VALUE) # noqa
                new_tiff = Image.tiffload(tif_filename)
                _upload_files(img_data, local_file, tif_filename)
                gql.update_item(img_data['id'], new_tiff.height, new_tiff.width)
                os.remove(tif_filename)
            os.remove(local_file)
            logger.info(f'Completed {local_file}')
        else:
            gql.remove_missing_item(img_data['id'])
            Statistic.download_err(img_data)
        Statistic.attempted()
        queue.task_done()
예제 #10
0
    def __init__(self, piece_theme: str, size: int = 70):

        piece_dir = os.path.join('data', 'piece', piece_theme)

        #: Maps pieces to their corresponding .svg filenames
        self.pieces_map = {
            'r': 'bR',
            'q': 'bQ',
            'n': 'bN',
            'k': 'bK',
            'p': 'bP',
            'b': 'bB',
            'R': 'wR',
            'Q': 'wQ',
            'N': 'wN',
            'K': 'wK',
            'P': 'wP',
            'B': 'wB'
        }

        # Reads the available piece theme's .svg images and save them as .png of appropraite size
        for piece in self.pieces_map:
            piece_path = os.path.join(piece_dir,
                                      self.pieces_map[piece] + '.svg')
            image = VipsImage.thumbnail(piece_path, size, height=size)
            image.write_to_file(f"Images/{ self.pieces_map[piece]}.png")

        #: Dictionary where pieces are the keys and corresponding PIL Images are the values
        self.piece_imgs = dict()
        for piece in self.pieces_map:
            self.piece_imgs[piece] = Image.open(
                f"Images/{ self.pieces_map[piece]}.png")
예제 #11
0
    def write_buffer(self, image, resolution):
        if VImageAdapter(image).BufferSize() >= self.IMAGE_BUFFER_DISK_THRESHOLD:
            logger.debug(
                'Buffering resolution {0} to disk'.format(resolution)
            )
            vipsfile = Image.new_temp_file("%s.v")
            tempfile_image = image.write(vipsfile)
            return tempfile_image

        logger.debug(
            'Buffering resolution {0} to memory'.format(resolution)
        )
        return Image.new_from_memory(
            image.write_to_memory(), image.width, image.height, image.bands,
            'uchar'
        )
예제 #12
0
파일: vips.py 프로젝트: weexp/gdal2mbtiles
 def new_rgba(cls, width, height, ink=None):
     """Creates a new transparent RGBA image sized width × height."""
     # Creating a placeholder image with new_from_memory (equivalent of the
     # old vipsCC frombuffer) creates an image
     # which is a few byes different when written back to memory, which means
     # we can't store and retrieve it from its hash.  So instead we use a
     # temporary transparent 256x256 file for the initial image
     image = Image.new_from_file(
         os.path.join(os.path.dirname(os.path.realpath(__file__)),
                      'default_rgba.png'))
     image = image.copy(
         width=width,
         height=height,
         coding='none',  # No coding and no compression
         interpretation='srgb',
         xres=2.835,
         yres=2.835,  # Arbitrary 600 dpi
         xoffset=0,
         yoffset=0  # Working buffer
     )
     if ink is not None:
         image.draw_rect([ink.r, ink.g, ink.b, ink.a],
                         0,
                         0,
                         width,
                         height,
                         fill=True)
     return image
예제 #13
0
    def cvtStandardImgFormat(self, savePath, fmt, compression=False):
        im_arr = self.getPixelArray()

        if fmt.endswith('jpg') and im_arr[0] > 65535 and im_arr[1] > 65535:
            print('Too Large size for JPEG-2000 format...')
            return

        elif fmt.endswith('png') and im_arr[0] > 10000 and im_arr[1] > 10000:
            print('Too Large size for PNG format...')
            return

        fname = os.path.basename(self.filename)
        sname = os.path.splitext(fname)[-1]

        im = Image.new_from_array(im_arr)

        if fmt.endswith('tiff'):
            if compression:
                im.write_to_file(savePath + '/' + sname + '.' + fmt,
                                 compression='lzw')
            else:
                im.write_to_file(savePath + '/' + sname + '.' + fmt,
                                 compression='lzw')
        else:
            im.write_to_file(savePath + '/' + sname + '.' + fmt)
예제 #14
0
def pyvips_loader(path: str,
                  access=pyvips.Access.RANDOM,
                  memory=True) -> Image:
    """
    Strange performance gain when using Access.RANDOM
    """
    return Image.new_from_file(path, access=access, memory=memory)
예제 #15
0
    def add_to_image(self, im: pyvips.Image) -> pyvips.Image:
        """Add watermark to supplied image."""
        LOG.info("Adding watermark '%s'", self.text)
        text = pyvips.Image.text(
            self.text, width=im.width, dpi=300, font=f"{self.font}"
        )
        text = text.rotate(self.rotate)
        text = (text * self.opacity).cast("uchar")
        text = text.embed(
            self.x_margin,
            (im.height - text.height) - self.y_margin,
            im.width,
            im.height,
        )

        if self.replicate:
            text = text.replicate(
                1 + im.width / text.width, 1 + im.height / text.height
            )
            text = text.crop(0, 0, im.width, im.height)

        # we want to blend into the visible part of the image and leave any alpha
        # channels untouched ... we need to split im into two parts
        # guess how many bands from the start of im contain visible colour information
        if im.hasalpha():
            alpha = im.extract_band(im.bands - 1)
            im = im.extract_band(0, n=im.bands - 1)
        else:
            alpha = None

        if im.bands == 4:
            # cmyk
            text_color: Any = list(rgb_to_cmyk(self.fg_color))
        elif im.bands == 3:
            # rgb
            text_color = list(self.fg_color)
        else:
            # mono
            text_color = rgb_to_grayscale(self.fg_color)
        LOG.info("Watermark fg_color: %s (original: %s)", text_color, self.fg_color)
        im = text.ifthenelse(text_color, im, blend=True)

        # reattach alpha
        if alpha:
            im = im.bandjoin(alpha)
        return im
def test_vips_to_numpy():
    img = VIPSImage.new_from_array([[1, 2, 3], [4, 5, 6]])
    arr = vips_to_numpy(img)
    h, w, d = arr.shape
    assert w == img.width
    assert h == img.height
    assert d == img.bands
    assert arr.dtype == vips_format_to_dtype[img.format]
예제 #17
0
 def read_func(path, region, page=None, subifd=None):  # noqa
     opts = dict(page=page)
     if subifd is not None:
         opts['subifd'] = subifd
     tiff_page = VIPSImage.tiffload(str(path), **opts)
     im = tiff_page.extract_area(region.left, region.top, region.width,
                                 region.height)
     return im
예제 #18
0
    def __init__(self,
                 original_image,
                 output_raster_width,
                 output_raster_height,
                 total_seconds,
                 fps,
                 image_lib='cv'):
        self.file_path = original_image
        self.image_lib = None

        self.output_raster_width = output_raster_width
        self.output_raster_height = output_raster_height
        self.total_frames = int(float(total_seconds) * float(fps))

        self.image_lib = image_lib

        self.fps = fps

        if self.image_lib == 'pillow':
            print('using Pillow')
            self.original_image = PImage.open(self.file_path)
            self.original_image_width, self.original_image_height = self.original_image.size

        if self.image_lib == 'vips':
            from pyvips import Image as VImage
            from gi.repository import Vips
            print('using vips')
            self.original_image = VImage.new_from_file(self.file_path)
            self.original_image_width = self.original_image.width
            self.original_image_height = self.original_image.height

        self.output_file_name = 'output'

        if self.image_lib == 'cv':
            print('using cv')
            self.original_image = cv2.imread(self.file_path,
                                             cv2.IMREAD_UNCHANGED)
            self.original_image_height, self.original_image_width, _ = self.original_image.shape

        self.processed_frames = 0
        self.render_start_time = 0
        self.render_status = 'queued'
        self.render_estimated_seconds_remaining = 0
        self.render_estimated_total_seconds = 0
        self.render_fps = 0

        self.prores_mez = False

        self.ffmpeg = shutil.which('ffmpeg')
        if not self.ffmpeg:
            self.ffmpeg = '/usr/local/bin/ffmpeg'

        self.convert = shutil.which('convert')

        if not self.convert:
            self.convert = '/usr/local/bin/convert'

        self.water_mark = False
예제 #19
0
def vips_image_to_numpy(img: Image) -> np.ndarray:
    """
    https://libvips.github.io/pyvips/intro.html#numpy-and-pil
    """

    np_3d = np.ndarray(buffer=img.write_to_memory(),
                       dtype=FORMAT_TO_DTYPE[img.format],
                       shape=[img.height, img.width, img.bands])
    return np_3d
예제 #20
0
def numpy_to_vips(np_array: np.ndarray,
                  width: Optional[int] = None,
                  height: Optional[int] = None,
                  n_channels: Optional[int] = None) -> VIPSImage:
    """
    Convert a Numpy array to a VIPS image.

    Parameters
    ----------
    np_array : array-like
        Numpy array to convert.
        If 1D, it is expected it contains flattened image data.
    width : int (optional)
        Width of the image, must be given if `np_array` is 1D,
        otherwise inferred from shape.
    height : int (optional)
        Height of the image, must be given if `np_array` is 1D,
        otherwise inferred from shape.
    n_channels : int (optional)
        n_channels of the image, must be given if `np_array` is 1D,
        otherwise inferred from shape.

    Returns
    -------
    image
        VIPS image representation of the array

    Raises
    ------
    ValueError
        If it is impossible to convert provided array.
    """
    if not np_array.flags['C_CONTIGUOUS']:
        np_array = np.ascontiguousarray(np_array)

    if np_array.ndim > 3:
        raise NotImplementedError
    elif np_array.ndim > 1:
        if np_array.ndim == 2:
            height_, width_ = np_array.shape
            n_channels_ = 1
        else:
            height_, width_, n_channels_ = np_array.shape

        width = width if width is not None else width_
        height = height if height is not None else height_
        n_channels = n_channels if n_channels is not None else n_channels_

    if width * height * n_channels != np_array.size:
        raise ValueError(f"Cannot convert {np_array} to VIPS image")

    flat = np_array.reshape(np_array.size)
    vips_format = dtype_to_vips_format[str(np_array.dtype)]
    return VIPSImage.new_from_memory(flat.data, width, height, n_channels,
                                     vips_format)
예제 #21
0
def pyvips_resize_by_size(img: Image,
                          size: Tuple[int, int],
                          kernel: str = Kernel.LINEAR) -> Image:
    """
    size -> height, width
    """
    # w, h = size
    h, w = size
    scale = w / img.width
    vscale = h / img.height
    return img.resize(scale, vscale=vscale, kernel=kernel)
예제 #22
0
 def _extract_channels(im: VIPSImage, c: Optional[Union[int, List[int]]]) -> VIPSImage:
     if c is None or im.bands == len(c):
         return im
     elif type(c) is int or len(c) == 1:
         if len(c) == 1:
             c = c[0]
         return im.extract_band(c)
     else:
         channels = list(itemgetter(*c)(im))
         im = channels[0].bandjoin(channels[1:])
         return im
예제 #23
0
    def vips_thumbnail(
        self, width: int, height: int, **loader_options
    ) -> VIPSImage:
        """Get VIPS thumbnail using vips shrink-on-load features."""

        filename = self.vips_filename_with_options(
            str(self.format.path),
            **loader_options
        )

        image = cached_vips_file(self.format)
        if image.interpretation in ("grey16", "rgb16"):
            # Related to https://github.com/libvips/libvips/issues/1941 ?
            return VIPSImage.thumbnail(
                filename, width, height=height,
                size=VIPSSize.FORCE, linear=True
            ).colourspace(image.interpretation)

        return VIPSImage.thumbnail(
            filename, width, height=height, size=VIPSSize.FORCE
        )
예제 #24
0
def generate_properties(filename):
    print(f'Generating {filename} ...')

    with open(filename, 'w') as f:
        f.write('        // Auto-generated properties\n')

        # all magic properties
        tmp_file = Image.new_temp_file('%s.v')
        all_properties = tmp_file.get_fields()
        for name in all_properties:
            cpp_name = cppize(name)
            f.write(f'        .property("{cpp_name}", &Image::{cpp_name})\n')
예제 #25
0
def bandreduction(bands: List[VIPSImage],
                  reduction: ChannelReduction) -> VIPSImage:
    if reduction == ChannelReduction.ADD:
        return VIPSImage.sum(bands).cast(bands[0].format)
    elif reduction == ChannelReduction.MAX:
        return Operation.call('bandrank', bands, index=len(bands) - 1)
    elif reduction == ChannelReduction.MIN:
        return Operation.call('bandrank', bands, index=0)
    elif reduction == ChannelReduction.MED:
        return Operation.call('bandrank', bands, index=-1)
    else:
        raise ValueError(f"{reduction} not implemented")
예제 #26
0
파일: vips.py 프로젝트: weexp/gdal2mbtiles
    def from_numpy_array(cls, array, width, height, bands, format):
        """
        Returns a new pyvips.Image created from a NumPy `array` of pixel data.

        array: The NumPy array
        width: Integer dimension
        height: Integer dimension
        bands: Number of bands in the buffer
        format: Band format (all bands must be the same format)
        """
        array = array.astype(cls.NUMPY_TYPES[format])
        buf = memoryview(array)
        image = Image.new_from_memory(buf, width, height, bands, format)
        return image
예제 #27
0
파일: Dataset.py 프로젝트: biigle/maia
    def load_image(self, image_id):
        """Load the specified image and return a [H,W,3] Numpy array.
        """
        # Load image with Vips because if ignores EXIF rotation (as it should).
        image = self.vips_image_to_numpy_array(VipsImage.new_from_file(self.image_info[image_id]['path']))
        # image = skimage.io.imread(self.image_info[image_id]['path'])
        # If grayscale. Convert to RGB for consistency.
        if image.ndim != 3 or image.shape[-1] == 1:
            image = skimage.color.gray2rgb(image.squeeze())
        # If has an alpha channel, remove it for consistency
        if image.shape[-1] == 4:
            image = image[..., :3]

        return image
예제 #28
0
    def process_image(self, imageId, proposals):
        try:
            image = VipsImage.new_from_file(self.images[imageId])

            if bool(self.scale_factors) != False:
                scale_factor = self.scale_factors[imageId]
                image = image.resize(scale_factor)
                proposals = np.round(
                    np.array(proposals, dtype=np.float32) *
                    scale_factor).astype(int)

            masks = []
            for proposal in proposals:
                mask = np.zeros((image.height, image.width), dtype=np.uint8)
                cv2.circle(mask, (proposal[0], proposal[1]), proposal[2], 1,
                           -1)
                masks.append(mask.astype(np.bool))

            image_paths = []
            mask_paths = []
            mean_pixels = []

            for i, proposal in enumerate(proposals):
                image_file = '{}_{}.jpg'.format(imageId, i)
                image_crop, mask_crops = self.generate_crop(
                    image, masks, proposal)
                mask_file = self.save_mask(mask_crops, image_file,
                                           self.training_masks_path)
                image_crop.write_to_file(os.path.join(
                    self.training_images_path, image_file),
                                         strip=True,
                                         Q=95)
                image_paths.append(image_file)
                mask_paths.append(mask_file)
                np_crop = np.ndarray(buffer=image_crop.write_to_memory(),
                                     shape=[
                                         image_crop.height, image_crop.width,
                                         image_crop.bands
                                     ],
                                     dtype=np.uint8)
                mean_pixels.append(
                    np_crop.reshape((-1, image.bands)).mean(axis=0))

        except VipsError as e:
            print('Image #{} is corrupt! Skipping...'.format(imageId))

            return False, False, False

        return image_paths, mask_paths, mean_pixels
예제 #29
0
    def read_window(self,
                    region,
                    out_width,
                    out_height,
                    c: Optional[Union[int, List[int]]] = None,
                    **other):
        tier = self.format.pyramid.most_appropriate_tier(
            region, (out_width, out_height))
        region = region.scale_to_tier(tier)

        page = tier.data.get('page_index')
        tiff_page = VIPSImage.jp2kload(str(self.format.path), page=page)
        im = tiff_page.extract_area(region.left, region.top, region.width,
                                    region.height)
        return self._extract_channels(im, c)
예제 #30
0
    def read_tile(self,
                  tile,
                  c: Optional[Union[int, List[int]]] = None,
                  **other):
        tier = tile.tier
        page = tier.data.get('page_index')
        tiff_page = VIPSImage.jp2kload(str(self.format.path), page=page)

        # There is no direct access to underlying tiles in vips
        # But the following computation match vips implementation so that only the tile
        # that has to be read is read.
        # https://github.com/jcupitt/tilesrv/blob/master/tilesrv.c#L461
        # TODO: is direct tile access significantly faster ?
        im = tiff_page.extract_area(tile.left, tile.top, tile.width,
                                    tile.height)
        return self._extract_channels(im, c)
예제 #31
0
    def from_numpy_array(cls, array, width, height, bands, format):
        """
        Returns a new pyvips.Image created from a NumPy `array` of pixel data.

        array: The NumPy array
        width: Integer dimension
        height: Integer dimension
        bands: Number of bands in the buffer
        format: Band format (all bands must be the same format)
        """
        array = array.astype(cls.NUMPY_TYPES[format])
        buf = memoryview(array)
        image = Image.new_from_memory(buf, width, height, bands, format)

        # Hold on to the numpy array to prevent garbage collection
        image._numpy_array = array
        return image
예제 #32
0
    def create_post_file_kwargs(self, post, force_file=False, no_file=False):
        if post.id in self._prepared_post_kwargs and not force_file and not no_file:
            return self._prepared_post_kwargs[post.id]

        post.file.seek(0)
        file = InputFile(post.file, filename=f'{post.id}.{post.file_extension}')
        kwargs = {}
        if force_file:
            self.logger.info(f'┏ {post.id}: Preparing document as {post.file_extension}')
            kwargs['document'] = file
            func = danbooru_bot.updater.bot.send_document
            return func, kwargs
        elif no_file:
            self.logger.info(f'┏ {post.id}: Forced no file')
            func = danbooru_bot.updater.bot.send_message
            return func, kwargs
        elif post.is_image:
            width, height = post.image_width, post.image_height
            self.logger.info(f'┏ {post.id}: Preparing photo')
            if post.file_size > 10 * 1024**2 or width + height > 10000:
                post.file.seek(0)
                image = Image.new_from_buffer(post.file.read(), '')

                while True:
                    while width + height > 10000:
                        width, height = int(width * .75), int(height * .75)

                    if (scale := width / image.width) != 1:  # type: ignore
                        image = image.resize(scale)  # type: ignore
                        self.logger.info(f'┃ Resizing to a scale of {scale:.2f} [{image.width}x{image.height}]')

                    with BytesIO() as out:
                        out.write(image.write_to_buffer('.jpg'))  # type: ignore
                        out.seek(0)
                        new_length = len(out.read())
                        if new_length > 10 * 1024**2:
                            image = image.resize(.9)  # type: ignore
                            continue
                        self.logger.info(f'┃ Reduced file size from {post.file_size / 1024**2:.2f}Mb to {new_length / 1024**2:.2f}Mb')
                        out.seek(0)
                        file = InputFile(out, filename=f'{post.id}.jpg')
                    break

            kwargs['photo'] = file
            func = danbooru_bot.updater.bot.send_photo
예제 #33
0
def vips_to_numpy(vips_image: VIPSImage) -> np.ndarray:
    """
    Convert a VIPS image to a Numpy array.

    Parameters
    ----------
    vips_image : VIPSImage
        VIPS image to convert

    Returns
    -------
    image
        Array representation of VIPS image.
        Shape is always (height, width, bands).
    """
    return np.ndarray(
        buffer=vips_image.write_to_memory(),
        dtype=vips_format_to_dtype[vips_image.format],
        shape=[vips_image.height, vips_image.width, vips_image.bands])
예제 #34
0
 def new_rgba(cls, width, height, ink=None):
     """Creates a new transparent RGBA image sized width × height."""
     # Creating a placeholder image with new_from_memory (equivalent of the
     # old vipsCC frombuffer) creates an image
     # which is a few byes different when written back to memory, which means
     # we can't store and retrieve it from its hash.  So instead we use a
     # temporary transparent 256x256 file for the initial image
     image = Image.new_from_file(
         os.path.join(
             os.path.dirname(os.path.realpath(__file__)), 'default_rgba.png'
         )
     )
     image = image.copy(
         width=width, height=height,
         coding='none',  # No coding and no compression
         interpretation='srgb',
         xres=2.835, yres=2.835,  # Arbitrary 600 dpi
         xoffset=0, yoffset=0  # Working buffer
     )
     if ink is not None:
         image.draw_rect(
             [ink.r, ink.g, ink.b, ink.a], 0, 0, width, height, fill=True
         )
     return image
예제 #35
0
 def image(self):
     if self._image is None:
         self._image = Image.new_from_file(self.inputfile)
     return self._image