Rasterize one page of a PDF at resolution (xres, yres) in canvas units.

    The image is sized to match the integer pixels dimensions implied by
    (xres, yres) even if those numbers are noninteger. The image's DPI will
     be overridden with the values in page_dpi.

    :param input_file: pathlike
    :param output_file: pathlike
    :param xres: resolution at which to rasterize page
    :param yres:
    :param raster_device:
    :param log:
    :param pageno: page number to rasterize (beginning at page 1)
    :param page_dpi: resolution tuple (x, y) overriding output image DPI
    :param rotation: 0, 90, 180, 270: clockwise angle to rotate page
    :param filter_vector: if True, remove vector graphics objects
    :return:

def rasterize_pdf(
    input_file,
    output_file,
    xres,
    yres,
    raster_device,
    log,
    pageno=1,
    page_dpi=None,
    rotation=None,
    filter_vector=False,
):
    """Rasterize one page of a PDF at resolution (xres, yres) in canvas units.

    The image is sized to match the integer pixels dimensions implied by
    (xres, yres) even if those numbers are noninteger. The image's DPI will
     be overridden with the values in page_dpi.

    :param input_file: pathlike
    :param output_file: pathlike
    :param xres: resolution at which to rasterize page
    :param yres:
    :param raster_device:
    :param log:
    :param pageno: page number to rasterize (beginning at page 1)
    :param page_dpi: resolution tuple (x, y) overriding output image DPI
    :param rotation: 0, 90, 180, 270: clockwise angle to rotate page
    :param filter_vector: if True, remove vector graphics objects
    :return:
    """
    res = xres, yres
    int_res = round(xres), round(yres)
    if not page_dpi:
        page_dpi = res

    with NamedTemporaryFile(delete=True) as tmp:
        args_gs = (
            [
                'gs',
                '-dQUIET',
                '-dSAFER',
                '-dBATCH',
                '-dNOPAUSE',
                f'-sDEVICE={raster_device}',
                f'-dFirstPage={pageno}',
                f'-dLastPage={pageno}',
                f'-r{str(int_res[0])}x{str(int_res[1])}',
            ]
            + (['-dFILTERVECTOR'] if filter_vector else [])
            + [
                '-o',
                tmp.name,
                '-dAutoRotatePages=/None',  # Probably has no effect on raster
                '-f',
                fspath(input_file),
            ]
        )

        log.debug(args_gs)
        p = run(args_gs, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
        if _gs_error_reported(p.stdout):
            log.error(p.stdout)
        else:
            log.debug(p.stdout)

        if p.returncode != 0:
            log.error('Ghostscript rasterizing failed')
            raise SubprocessOutputError()

        # Ghostscript only accepts integers for output resolution
        # if the resolution happens to be fractional, then the discrepancy
        # would change the size of the output page, especially if the DPI
        # is quite low. Resize the image to the expected size

        tmp.seek(0)
        with Image.open(tmp) as im:
            expected_size = (
                round(im.size[0] / int_res[0] * res[0]),
                round(im.size[1] / int_res[1] * res[1]),
            )
            if expected_size != im.size or page_dpi != (xres, yres):
                log.debug(
                    f"Ghostscript: resize output image {im.size} -> {expected_size}"
                )
                im = im.resize(expected_size)

            if rotation is not None:
                log.debug("Rotating output by %i", rotation)
                # rotation is a clockwise angle and Image.ROTATE_* is
                # counterclockwise so this cancels out the rotation
                if rotation == 90:
                    im = im.transpose(Image.ROTATE_90)
                elif rotation == 180:
                    im = im.transpose(Image.ROTATE_180)
                elif rotation == 270:
                    im = im.transpose(Image.ROTATE_270)
                if rotation % 180 == 90:
                    page_dpi = page_dpi[1], page_dpi[0]
            im.save(fspath(output_file), dpi=page_dpi)