Пример #1
0
 def paint_webp(self, img_data, x, y, width, height, options, callbacks):
     if not self.webp_decoder or WEBP_PILLOW:
         #if webp is enabled, then Pillow should be able to take care of it:
         return self.paint_image("webp", img_data, x, y, width, height, options, callbacks)
     rgb_format = options.strget("rgb_format")
     has_alpha = options.boolget("has_alpha", False)
     buffer_wrapper, width, height, stride, has_alpha, rgb_format = self.webp_decoder.decompress(img_data, has_alpha, rgb_format, self.RGB_MODES)
     def free_buffer(*_args):
         buffer_wrapper.free()
     callbacks.append(free_buffer)
     data = buffer_wrapper.get_pixels()
     #if the backing can't handle this format,
     #ie: tray only supports RGBA
     if rgb_format not in self.RGB_MODES:
         from xpra.codecs.rgb_transform import rgb_reformat
         from xpra.codecs.image_wrapper import ImageWrapper
         img = ImageWrapper(x, y, width, height, data, rgb_format, len(rgb_format)*8, stride, len(rgb_format), ImageWrapper.PACKED, True, None)
         #log("rgb_reformat(%s, %s, %s) %i bytes", img, self.RGB_MODES, has_alpha and self._alpha_enabled, len(img_data))
         rgb_reformat(img, self.RGB_MODES, has_alpha and self._alpha_enabled)
         rgb_format = img.get_pixel_format()
         data = img.get_pixels()
         stride = img.get_rowstride()
     #replace with the actual rgb format we get from the decoder:
     options[b"rgb_format"] = rgb_format
     return self.paint_rgb(rgb_format, data, x, y, width, height, stride, options, callbacks)
Пример #2
0
def tight_encode(window, x, y, w, h, quality=0):
    img = window.get_image(x, y, w, h)
    window.acknowledge_changes()
    if not img:
        return []
    if quality==10:
        #Fill Compression
        header = make_header(RFBEncoding.TIGHT, x, y, w, h)
        header += struct.pack(b"!B", 0x80)
        pixel_format = bytestostr(img.get_pixel_format())
        log.warn("fill compression of %s", pixel_format)
        if not rgb_reformat(img, ("RGB",), False):
            log.error("Error: cannot convert %s to RGB", pixel_format)
        return [header, raw_pixels(img)]
    #try jpeg:
    data = pillow_encode("jpeg", img)
    header = tight_header(RFBEncoding.TIGHT, x, y, w, h, 0x90, len(data))
    return [header, data]
Пример #3
0
def mmap_send(mmap, mmap_size, image, rgb_formats, supports_transparency):
    if mmap_write is None:
        if first_time("mmap_write missing"):
            log.warn("Warning: cannot use mmap, no write method support")
        return None
    if image.get_pixel_format() not in rgb_formats:
        if not rgb_reformat(image, rgb_formats, supports_transparency):
            warning_key = "mmap_send(%s)" % image.get_pixel_format()
            if first_time(warning_key):
                log.warn("Waening: cannot use mmap to send %s" % image.get_pixel_format())
            return None
    start = monotonic_time()
    data = image.get_pixels()
    assert data, "failed to get pixels from %s" % image
    mmap_data, mmap_free_size = mmap_write(mmap, mmap_size, data)
    elapsed = monotonic_time()-start+0.000000001 #make sure never zero!
    log("%s MBytes/s - %s bytes written to mmap in %.1f ms", int(len(data)/elapsed/1024/1024), len(data), 1000*elapsed)
    if mmap_data is None:
        return None
    #replace pixels with mmap info:
    return mmap_data, mmap_free_size, len(data)
Пример #4
0
def rgb_encode(coding,
               image,
               rgb_formats,
               supports_transparency,
               speed,
               rgb_zlib=True,
               rgb_lz4=True,
               rgb_lzo=False):
    pixel_format = bytestostr(image.get_pixel_format())
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s",
    #    (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        log(
            "rgb_encode reformatting because %s not in %s, supports_transparency=%s",
            pixel_format, rgb_formats, supports_transparency)
        if not rgb_reformat(image, rgb_formats, supports_transparency):
            raise Exception(
                "cannot find compatible rgb format to use for %s! (supported: %s)"
                % (pixel_format, rgb_formats))
        #get the new format:
        pixel_format = bytestostr(image.get_pixel_format())
        #switch encoding if necessary:
        if len(pixel_format) == 4:
            coding = "rgb32"
        elif len(pixel_format) == 3:
            coding = "rgb24"
        else:
            raise Exception("invalid pixel format %s" % pixel_format)
    #we may still want to re-stride:
    image.may_restride()
    #always tell client which pixel format we are sending:
    options = {"rgb_format": pixel_format}

    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    width = image.get_width()
    height = image.get_height()
    stride = image.get_rowstride()

    #compression stage:
    level = 0
    algo = "not"
    l = len(pixels)
    if l >= 512 and speed < 100:
        if l >= 4096:
            #speed=99 -> level=1, speed=0 -> level=9
            level = 1 + max(0, min(8, int(100 - speed) // 12))
        else:
            #fewer pixels, make it more likely we won't bother compressing
            #and use a lower level (max=5)
            level = max(0, min(5, int(115 - speed) // 20))
    if level > 0:
        cwrapper = compression.compressed_wrapper(coding,
                                                  pixels,
                                                  level=level,
                                                  zlib=rgb_zlib,
                                                  lz4=rgb_lz4,
                                                  lzo=rgb_lzo,
                                                  brotli=False,
                                                  none=True)
        algo = cwrapper.algorithm
        if algo == "none" or len(cwrapper) >= (len(pixels) - 32):
            #no compression is enabled, or compressed is actually bigger!
            #(fall through to uncompressed)
            level = 0
        else:
            #add compressed marker:
            options[algo] = level
            #remove network layer compression marker
            #so that this data will be decompressed by the decode thread client side:
            cwrapper.level = 0
    if level == 0:
        #can't pass a raw buffer to bencode / rencode,
        #and even if we could, the image containing those pixels may be freed by the time we get to the encoder
        algo = "not"
        cwrapper = compression.Compressed(coding, pixels_to_bytes(pixels),
                                          True)
    if pixel_format.find("A") >= 0 or pixel_format.find("X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s for %5i bytes at %3i speed, %s compressed %4sx%-4s in %s/%s: %5s bytes down to %5s",
        level, l, speed, algo, image.get_width(), image.get_height(), coding,
        pixel_format, len(pixels), len(cwrapper.data))
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, cwrapper, options, width, height, stride, bpp
Пример #5
0
def encode(coding: str, image, options: dict):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s",
    #    (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4), pixel_format, rgb_formats)
    if pixel_format in ("BGRX", "BGRA", "RGBA"):
        rgb_formats = options.get("rgb_formats", ("BGRX", "BGRA", "RGBA"))
    elif pixel_format in ("RGB", "BGR"):
        rgb_formats = options.get("rgb_formats", ("RGB", "BGR"))
    else:
        raise Exception("unsupported pixel format %s" % pixel_format)
    supports_transparency = options.get("alpha", True)
    if pixel_format not in rgb_formats:
        log(
            "rgb_encode reformatting because %s not in %s, supports_transparency=%s",
            pixel_format, rgb_formats, supports_transparency)
        if not rgb_reformat(image, rgb_formats, supports_transparency):
            raise Exception(
                "cannot find compatible rgb format to use for %s! (supported: %s)"
                % (pixel_format, rgb_formats))
        #get the new format:
        pixel_format = image.get_pixel_format()
        #switch encoding if necessary:
        if len(pixel_format) == 4:
            coding = "rgb32"
        elif len(pixel_format) == 3:
            coding = "rgb24"
        else:
            raise Exception("invalid pixel format %s" % pixel_format)
    #we may still want to re-stride:
    image.may_restride()
    #always tell client which pixel format we are sending:
    client_options = {"rgb_format": pixel_format}

    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    width = image.get_width()
    height = image.get_height()
    stride = image.get_rowstride()
    speed = options.get("speed", 50)

    #compression stage:
    level = 0
    algo = "not"
    l = len(pixels)
    lz4 = options.get("lz4", False)
    if l >= 512 and (lz4 or speed < 100):
        if l >= 4096:
            level = 1 + max(0, min(7, int(100 - speed) // 14))
        else:
            #fewer pixels, make it more likely we won't bother compressing
            #and use a lower level (max=3)
            level = max(0, min(3, int(125 - speed) // 35))
    if level > 0:
        zlib = options.get("zlib", False)
        can_inline = l <= 32768
        cwrapper = compressed_wrapper(coding,
                                      pixels,
                                      level=level,
                                      zlib=zlib,
                                      lz4=lz4,
                                      brotli=False,
                                      none=False,
                                      can_inline=can_inline)
        if isinstance(cwrapper, LevelCompressed):
            #add compressed marker:
            client_options[cwrapper.algorithm] = cwrapper.level & 0xF
            #remove network layer compression marker
            #so that this data will be decompressed by the decode thread client side:
            cwrapper.level = 0
        elif can_inline and isinstance(pixels, memoryview):
            assert isinstance(cwrapper, Compressed)
            assert cwrapper.data == pixels
            #compression either did not work or was not enabled
            #and memoryview pixel data cannot be handled by the packet encoders
            #so we convert it to bytes so it can still be inlined with the packet data:
            cwrapper.data = rgb_transform.pixels_to_bytes(pixels)
    else:
        #can't pass a raw buffer to bencode / rencode,
        #and even if we could, the image containing those pixels may be freed by the time we get to the encoder
        algo = "not"
        cwrapper = Compressed(coding, rgb_transform.pixels_to_bytes(pixels),
                              True)
    if pixel_format.find("A") >= 0 or pixel_format.find("X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s for %5i bytes at %3i speed, %s compressed %4sx%-4s in %s/%s: %5s bytes down to %5s",
        level, l, speed, algo, width, height, coding, pixel_format,
        len(pixels), len(cwrapper.data))
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, cwrapper, client_options, width, height, stride, bpp