Пример #1
0
// TODO simplify and enhance compression using 1 pixel orders BLACK or WHITE.
void Bitmap::compress(BitsPerPixel session_color_depth, OutStream & outbuffer) const
{
    if (this->data_bitmap->compressed_size()) {
        outbuffer.out_copy_bytes(this->data_bitmap->compressed_data(), this->data_bitmap->compressed_size());
        return;
    }

    uint8_t * tmp_data_compressed = outbuffer.get_current();

    ConstImageDataView const image_view{
        this->data(),
        this->cx(),
        this->cy(),
        this->line_size(),
        this->bpp(),
        ConstImageDataView::Storage::BottomToTop
    };

    if ((session_color_depth == BitsPerPixel{32}) && ((this->bpp() == BitsPerPixel{24}) || (this->bpp() == BitsPerPixel{32}))) {
        rle_compress60(image_view, outbuffer);
    }
    else {
        rle_compress(image_view, outbuffer);
    }

    // Memoize result of compression
    this->data_bitmap->copy_compressed_buffer(
        tmp_data_compressed, outbuffer.get_current() - tmp_data_compressed);
}
    void emit(OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon,
              const RDPPolygonCB & oldcmd) const {
        RDPPrimaryOrderHeader header(RDP::STANDARD, 0);

        // TODO check that
        int16_t pointx = this->xStart;
        int16_t pointy = this->yStart;
        if (!common.clip.contains_pt(pointx, pointy)) {
            header.control |= RDP::BOUNDS;
        }
        else {
            for (uint8_t i = 0; i < this->NumDeltaEntries; i++) {
                pointx += this->deltaPoints[i].xDelta;
                pointy += this->deltaPoints[i].yDelta;

                if (!common.clip.contains_pt(pointx, pointy)) {
                    header.control |= RDP::BOUNDS;
                    break;
                }
            }
        }

        header.control |= (is_1_byte(this->xStart - oldcmd.xStart) && is_1_byte(this->yStart - oldcmd.yStart)) * RDP::DELTA;

        header.fields =
              (this->xStart          != oldcmd.xStart         ) * 0x0001
            | (this->yStart          != oldcmd.yStart         ) * 0x0002
            | (this->bRop2           != oldcmd.bRop2          ) * 0x0004
            | (this->fillMode        != oldcmd.fillMode       ) * 0x0008
            | (this->backColor       != oldcmd.backColor      ) * 0x0010
            | (this->foreColor       != oldcmd.foreColor      ) * 0x0020
            | (this->brush.org_x     != oldcmd.brush.org_x    ) * 0x0040
            | (this->brush.org_y     != oldcmd.brush.org_y    ) * 0x0080
            | (this->brush.style     != oldcmd.brush.style    ) * 0x0100
            | (this->brush.hatch     != oldcmd.brush.hatch    ) * 0x0200
            | (memcmp(this->brush.extra, oldcmd.brush.extra, 7) != 0) * 0x0400
            | (this->NumDeltaEntries != oldcmd.NumDeltaEntries) * 0x0800
            | ((this->NumDeltaEntries != oldcmd.NumDeltaEntries) ||
               memcmp(this->deltaPoints, oldcmd.deltaPoints,
                      this->NumDeltaEntries * sizeof(DeltaPoint))
               ) * 0x1000
              ;

        common.emit(stream, header, oldcommon);

        header.emit_coord(stream, 0x0001, this->xStart, oldcmd.xStart);
        header.emit_coord(stream, 0x0002, this->yStart, oldcmd.yStart);

        if (header.fields & 0x0004) { stream.out_uint8(this->bRop2); }

        if (header.fields & 0x0008) { stream.out_uint8(this->fillMode); }

        if (header.fields & 0x0010) {
            emit_rdp_color(stream, this->backColor);
        }
        if (header.fields & 0x0020) {
            emit_rdp_color(stream, this->foreColor);
        }

        header.emit_brush(stream, 0x0040, this->brush, oldcmd.brush);

        if (header.fields & 0x0800) { stream.out_uint8(this->NumDeltaEntries); }

        if (header.fields & 0x1000) {
            uint32_t offset_cbData = stream.get_offset();
            stream.out_clear_bytes(1);

            uint8_t * zeroBit = stream.get_current();
            stream.out_clear_bytes((this->NumDeltaEntries + 3) / 4);
            *zeroBit = 0;

            for (uint8_t i = 0, m4 = 0; i < this->NumDeltaEntries; i++, m4++) {
                if (m4 == 4) {
                    m4 = 0;
                }

                if (i && !m4) {
                    *(++zeroBit) = 0;
                }

                if (!this->deltaPoints[i].xDelta) {
                    *zeroBit |= (1 << (7 - m4 * 2));
                }
                else {
                    stream.out_DEP(this->deltaPoints[i].xDelta);
                }

                if (!this->deltaPoints[i].yDelta) {
                    *zeroBit |= (1 << (6 - m4 * 2));
                }
                else {
                    stream.out_DEP(this->deltaPoints[i].yDelta);
                }
            }

            stream.set_out_uint8(stream.get_offset() - offset_cbData - 1, offset_cbData);
        }
    }
Пример #3
0
    void emit( OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon
             , const RDPMultiDstBlt & oldcmd) const {
        RDPPrimaryOrderHeader header(RDP::STANDARD, 0);

        int16_t nLeftRect = 0;
        int16_t nTopRect  = 0;
        int16_t nWidth    = 0;
        int16_t nHeight   = 0;
        if (!common.clip.contains(Rect(nLeftRect, nTopRect, nWidth, nHeight))) {
            header.control |= RDP::BOUNDS;
        }
        else {
            for (uint8_t i = 0; i < this->nDeltaEntries; i++) {
                nLeftRect += this->deltaEncodedRectangles[i].leftDelta;
                nTopRect  += this->deltaEncodedRectangles[i].topDelta;
                nWidth    =  this->deltaEncodedRectangles[i].width;
                nHeight   =  this->deltaEncodedRectangles[i].height;

                if (!common.clip.contains(Rect(nLeftRect, nTopRect, nWidth, nHeight))) {
                    header.control |= RDP::BOUNDS;
                    break;
                }
            }
        }

        header.control |= (is_1_byte(this->nLeftRect - oldcmd.nLeftRect) && is_1_byte(this->nTopRect - oldcmd.nTopRect) &&
            is_1_byte(this->nWidth - oldcmd.nWidth) && is_1_byte(this->nHeight - oldcmd.nHeight)) * RDP::DELTA;

        header.fields =
                (this->nLeftRect     != oldcmd.nLeftRect    ) * 0x0001
              | (this->nTopRect      != oldcmd.nTopRect     ) * 0x0002
              | (this->nWidth        != oldcmd.nWidth       ) * 0x0004
              | (this->nHeight       != oldcmd.nHeight      ) * 0x0008
              | (this->bRop          != oldcmd.bRop         ) * 0x0010
              | (this->nDeltaEntries != oldcmd.nDeltaEntries) * 0x0020
              | (
                 (this->nDeltaEntries != oldcmd.nDeltaEntries) ||
                 memcmp(this->deltaEncodedRectangles, oldcmd.deltaEncodedRectangles,
                        this->nDeltaEntries * sizeof(RDP::DeltaEncodedRectangle))
                                                            ) * 0x0040
              ;

        common.emit(stream, header, oldcommon);

        header.emit_coord(stream, 0x0001, this->nLeftRect, oldcmd.nLeftRect);
        header.emit_coord(stream, 0x0002, this->nTopRect,  oldcmd.nTopRect);
        header.emit_coord(stream, 0x0004, this->nWidth,    oldcmd.nWidth);
        header.emit_coord(stream, 0x0008, this->nHeight,   oldcmd.nHeight);

        if (header.fields & 0x0010) { stream.out_uint8(this->bRop); }

        if (header.fields & 0x0020) { stream.out_uint8(this->nDeltaEntries); }

        if (header.fields & 0x0040) {
            uint32_t offset_cbData = stream.get_offset();
            stream.out_clear_bytes(2);


            uint8_t * zeroBit = stream.get_current();
            stream.out_clear_bytes((this->nDeltaEntries + 1) / 2);

            *zeroBit = 0;
            for (uint8_t i = 0, m2 = 0; i < this->nDeltaEntries; i++, m2++) {
                if (m2 == 2) {
                    m2 = 0;
                }

                if (i && !m2) {
                    *(++zeroBit) = 0;
                }

                if (!this->deltaEncodedRectangles[i].leftDelta) {
                    *zeroBit |= (1 << (7 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].leftDelta);
                }

                if (!this->deltaEncodedRectangles[i].topDelta) {
                    *zeroBit |= (1 << (6 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].topDelta);
                }

                if (!this->deltaEncodedRectangles[i].width) {
                    *zeroBit |= (1 << (5 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].width);
                }

                if (!this->deltaEncodedRectangles[i].height) {
                    *zeroBit |= (1 << (4 - m2 * 4));
                }
                else {
                    stream.out_DEP(this->deltaEncodedRectangles[i].height);
                }
            }

            stream.set_out_uint16_le(stream.get_offset() - offset_cbData - 2, offset_cbData);
        }
    }   // void emit(OutStream & stream, RDPOrderCommon & common, const RDPOrderCommon & oldcommon, const RDPMultiDstBlt & oldcmd) const