2013-11-26 03:58:01 +04:00
|
|
|
/**
|
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
|
|
* RDP6 Planar Codec
|
|
|
|
*
|
|
|
|
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2013-11-26 07:26:08 +04:00
|
|
|
#include <winpr/crt.h>
|
|
|
|
#include <winpr/print.h>
|
|
|
|
|
|
|
|
#include <freerdp/codec/bitmap.h>
|
|
|
|
|
2013-11-26 03:58:01 +04:00
|
|
|
#include "planar.h"
|
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5])
|
2013-11-26 03:58:01 +04:00
|
|
|
{
|
2013-11-26 07:26:08 +04:00
|
|
|
int bpp;
|
2013-11-26 03:58:01 +04:00
|
|
|
int i, j, k;
|
|
|
|
|
|
|
|
k = 0;
|
2013-11-26 07:26:08 +04:00
|
|
|
bpp = FREERDP_PIXEL_FORMAT_BPP(format);
|
|
|
|
|
|
|
|
if (bpp == 32)
|
2013-11-26 03:58:01 +04:00
|
|
|
{
|
2013-11-26 08:29:20 +04:00
|
|
|
UINT32* pixel;
|
2013-11-26 07:26:08 +04:00
|
|
|
|
2013-11-26 08:29:20 +04:00
|
|
|
for (i = height - 1; i >= 0; i--)
|
2013-11-26 03:58:01 +04:00
|
|
|
{
|
2013-11-26 08:29:20 +04:00
|
|
|
pixel = (UINT32*) &data[scanline * i];
|
|
|
|
|
2013-11-26 07:26:08 +04:00
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2013-11-26 08:29:20 +04:00
|
|
|
GetARGB32(planes[0][k], planes[0][k], planes[2][k], planes[3][k], *pixel);
|
|
|
|
pixel++;
|
2013-11-26 07:26:08 +04:00
|
|
|
k++;
|
|
|
|
}
|
2013-11-26 03:58:01 +04:00
|
|
|
}
|
2013-11-26 07:26:08 +04:00
|
|
|
}
|
|
|
|
else if (bpp == 24)
|
|
|
|
{
|
2013-11-26 08:29:20 +04:00
|
|
|
UINT32* pixel;
|
2013-11-26 07:26:08 +04:00
|
|
|
|
2013-11-26 08:29:20 +04:00
|
|
|
for (i = height - 1; i >= 0; i--)
|
2013-11-26 07:26:08 +04:00
|
|
|
{
|
2013-11-26 08:29:20 +04:00
|
|
|
pixel = (UINT32*) &data[scanline * i];
|
|
|
|
|
2013-11-26 07:26:08 +04:00
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
2013-11-26 08:29:20 +04:00
|
|
|
GetRGB32(planes[1][k], planes[2][k], planes[3][k], *pixel);
|
|
|
|
planes[0][k] = 0xFF; /* A */
|
|
|
|
pixel++;
|
2013-11-26 07:26:08 +04:00
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
2013-11-26 03:58:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2013-11-26 07:26:08 +04:00
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int* dstSize)
|
2013-11-27 00:16:40 +04:00
|
|
|
{
|
2013-11-27 07:16:31 +04:00
|
|
|
int i, j;
|
2013-11-27 03:04:29 +04:00
|
|
|
BYTE* dstp;
|
2013-11-27 00:16:40 +04:00
|
|
|
BYTE symbol;
|
2013-11-27 03:04:29 +04:00
|
|
|
int cSegments;
|
2013-11-27 00:16:40 +04:00
|
|
|
int nRunLength;
|
|
|
|
int cRawBytes;
|
|
|
|
BYTE* rawValues;
|
2013-11-27 03:04:29 +04:00
|
|
|
int outPlaneSize;
|
2013-11-27 07:16:31 +04:00
|
|
|
int outSegmentSize;
|
|
|
|
int nControlBytes;
|
2013-11-27 00:16:40 +04:00
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
cSegments = 0;
|
2013-11-27 00:16:40 +04:00
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
if (!outPlane)
|
2013-11-28 01:23:20 +04:00
|
|
|
{
|
|
|
|
outPlaneSize = width * height * 2;
|
2013-11-27 03:04:29 +04:00
|
|
|
outPlane = malloc(outPlaneSize);
|
2013-11-28 01:23:20 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outPlaneSize = *dstSize;
|
|
|
|
}
|
2013-11-27 00:16:40 +04:00
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
dstp = outPlane;
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
2013-11-27 00:16:40 +04:00
|
|
|
{
|
2013-11-27 03:04:29 +04:00
|
|
|
cRawBytes = 0;
|
2013-11-27 23:46:38 +04:00
|
|
|
nRunLength = -1;
|
2013-11-27 03:04:29 +04:00
|
|
|
rawValues = &inPlane[i * width];
|
|
|
|
|
|
|
|
for (j = 0; j <= width; j++)
|
2013-11-27 00:16:40 +04:00
|
|
|
{
|
2013-11-27 23:46:38 +04:00
|
|
|
if ((nRunLength < 0) && (j != width))
|
2013-11-27 00:16:40 +04:00
|
|
|
{
|
2013-11-27 03:04:29 +04:00
|
|
|
symbol = inPlane[(i * width) + j];
|
2013-11-27 23:46:38 +04:00
|
|
|
nRunLength = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((j != width) && (inPlane[(i * width) + j] == symbol))
|
|
|
|
{
|
|
|
|
nRunLength++;
|
2013-11-28 01:23:20 +04:00
|
|
|
continue;
|
2013-11-27 00:16:40 +04:00
|
|
|
}
|
2013-11-28 01:23:20 +04:00
|
|
|
|
|
|
|
if (nRunLength >= 3)
|
2013-11-27 00:16:40 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
cRawBytes += 1;
|
2013-11-27 00:16:40 +04:00
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
#if 0
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("RAW[");
|
2013-11-27 00:16:40 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
for (k = 0; k < cRawBytes; k++)
|
|
|
|
{
|
|
|
|
printf("0x%02X%s", rawValues[k],
|
|
|
|
((k + 1) == cRawBytes) ? "" : ", ");
|
|
|
|
}
|
2013-11-27 00:16:40 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("] RUN[%d]\n", nRunLength);
|
2013-11-27 07:16:31 +04:00
|
|
|
#endif
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
while (cRawBytes > 15)
|
|
|
|
{
|
|
|
|
printf("handling cRawBytes > 15\n");
|
|
|
|
|
|
|
|
nControlBytes = 1;
|
|
|
|
outSegmentSize = 15 + nControlBytes;
|
|
|
|
|
|
|
|
if (((dstp - outPlane) + outSegmentSize) > outPlaneSize)
|
2013-11-27 23:46:38 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("overflow: %d > %d\n", ((dstp - outPlane) + outSegmentSize), outPlaneSize);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(0, 15);
|
|
|
|
dstp++;
|
2013-11-27 23:46:38 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
CopyMemory(dstp, rawValues, 15);
|
|
|
|
cRawBytes -= 15;
|
|
|
|
rawValues += 15;
|
|
|
|
dstp += 15;
|
|
|
|
}
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (nRunLength > 47)
|
|
|
|
{
|
|
|
|
nControlBytes = (((nRunLength - 15) + 46) / 47) + 1;
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
outSegmentSize = cRawBytes + nControlBytes;
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (((dstp - outPlane) + outSegmentSize) > outPlaneSize)
|
|
|
|
{
|
|
|
|
printf("overflow: %d > %d\n", ((dstp - outPlane) + outSegmentSize), outPlaneSize);
|
2013-11-27 23:46:38 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(15, cRawBytes);
|
|
|
|
nRunLength -= 15;
|
|
|
|
nControlBytes--;
|
|
|
|
dstp++;
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
CopyMemory(dstp, rawValues, cRawBytes);
|
|
|
|
dstp += cRawBytes;
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
while (nControlBytes--)
|
|
|
|
{
|
|
|
|
if (nRunLength > 47)
|
2013-11-27 23:46:38 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(2, (47 - 32));
|
|
|
|
nRunLength -= 47;
|
|
|
|
dstp++;
|
2013-11-27 23:46:38 +04:00
|
|
|
}
|
2013-11-28 01:23:20 +04:00
|
|
|
else if (nRunLength > 31)
|
2013-11-27 07:16:31 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(2, (nRunLength - 32));
|
|
|
|
nRunLength = 0;
|
|
|
|
dstp++;
|
2013-11-27 23:46:38 +04:00
|
|
|
}
|
2013-11-28 01:23:20 +04:00
|
|
|
else if (nRunLength > 15)
|
2013-11-27 07:16:31 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(1, (nRunLength - 16));
|
|
|
|
nRunLength = 0;
|
|
|
|
dstp++;
|
2013-11-27 23:46:38 +04:00
|
|
|
}
|
2013-11-28 01:23:20 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*dstp = PLANAR_CONTROL_BYTE(0, nRunLength);
|
|
|
|
nRunLength = 0;
|
|
|
|
dstp++;
|
|
|
|
}
|
|
|
|
}
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (nRunLength > 31)
|
|
|
|
{
|
|
|
|
nControlBytes = 2;
|
|
|
|
outSegmentSize = cRawBytes + nControlBytes;
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (((dstp - outPlane) + outSegmentSize) > outPlaneSize)
|
2013-11-27 23:46:38 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("overflow: %d > %d\n", ((dstp - outPlane) + outSegmentSize), outPlaneSize);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(15, cRawBytes);
|
|
|
|
dstp++;
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
CopyMemory(dstp, rawValues, cRawBytes);
|
|
|
|
rawValues += cRawBytes;
|
|
|
|
dstp += cRawBytes;
|
|
|
|
cRawBytes = 0;
|
2013-11-27 23:46:38 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
nRunLength -= 32;
|
|
|
|
*dstp = PLANAR_CONTROL_BYTE(2, nRunLength);
|
|
|
|
dstp++;
|
|
|
|
}
|
|
|
|
else if (nRunLength > 15)
|
|
|
|
{
|
|
|
|
nControlBytes = 2;
|
|
|
|
outSegmentSize = cRawBytes + nControlBytes;
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (((dstp - outPlane) + outSegmentSize) > outPlaneSize)
|
2013-11-27 23:46:38 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("overflow: %d > %d\n", ((dstp - outPlane) + outSegmentSize), outPlaneSize);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(15, cRawBytes);
|
|
|
|
dstp++;
|
2013-11-27 07:16:31 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
CopyMemory(dstp, rawValues, cRawBytes);
|
|
|
|
rawValues += cRawBytes;
|
|
|
|
dstp += cRawBytes;
|
|
|
|
cRawBytes = 0;
|
|
|
|
|
|
|
|
nRunLength -= 16;
|
|
|
|
*dstp = PLANAR_CONTROL_BYTE(1, nRunLength);
|
|
|
|
dstp++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nControlBytes = 1;
|
|
|
|
outSegmentSize = cRawBytes + nControlBytes;
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (((dstp - outPlane) + outSegmentSize) > outPlaneSize)
|
|
|
|
{
|
|
|
|
printf("overflow: %d > %d\n", ((dstp - outPlane) + outSegmentSize), outPlaneSize);
|
|
|
|
return NULL;
|
2013-11-27 03:04:29 +04:00
|
|
|
}
|
2013-11-27 23:46:38 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(nRunLength, cRawBytes);
|
|
|
|
dstp++;
|
|
|
|
|
|
|
|
CopyMemory(dstp, rawValues, cRawBytes);
|
|
|
|
rawValues += cRawBytes;
|
|
|
|
dstp += cRawBytes;
|
2013-11-27 23:46:38 +04:00
|
|
|
cRawBytes = 0;
|
|
|
|
}
|
2013-11-28 01:23:20 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cRawBytes += (nRunLength + 1);
|
|
|
|
|
|
|
|
if (j == width)
|
2013-11-27 23:46:38 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("end of scanline: cRawBytes: %d nRunLength: %d\n", cRawBytes, nRunLength);
|
2013-11-27 23:46:38 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
nRunLength = 0;
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (cRawBytes > 15)
|
|
|
|
{
|
|
|
|
printf("cRawBytes > 15 unhandled\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-27 07:16:31 +04:00
|
|
|
|
|
|
|
#if 0
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("RAW[");
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
for (k = 0; k < cRawBytes; k++)
|
|
|
|
{
|
|
|
|
printf("0x%02X%s", rawValues[k],
|
|
|
|
((k + 1) == cRawBytes) ? "" : ", ");
|
|
|
|
}
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
printf("] RUN[%d]\n", nRunLength);
|
2013-11-27 07:16:31 +04:00
|
|
|
#endif
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
outSegmentSize = cRawBytes + 1;
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (((dstp - outPlane) + outSegmentSize) > outPlaneSize)
|
|
|
|
{
|
|
|
|
printf("overflow: %d > %d\n", ((dstp - outPlane) + outSegmentSize), outPlaneSize);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
*dstp = PLANAR_CONTROL_BYTE(nRunLength, cRawBytes);
|
|
|
|
dstp++;
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
CopyMemory(dstp, rawValues, cRawBytes);
|
|
|
|
dstp += cRawBytes;
|
2013-11-27 23:46:38 +04:00
|
|
|
}
|
2013-11-28 01:23:20 +04:00
|
|
|
}
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (j != width)
|
|
|
|
{
|
|
|
|
symbol = inPlane[(i * width) + j];
|
|
|
|
nRunLength = 0;
|
2013-11-27 01:07:55 +04:00
|
|
|
}
|
|
|
|
}
|
2013-11-27 07:16:31 +04:00
|
|
|
//printf("---\n");
|
2013-11-27 01:07:55 +04:00
|
|
|
}
|
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
//printf("\n");
|
|
|
|
|
|
|
|
*dstSize = (dstp - outPlane);
|
2013-11-27 01:07:55 +04:00
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
return outPlane;
|
|
|
|
}
|
2013-11-27 01:30:43 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
int freerdp_bitmap_planar_compress_planes_rle(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes, int* dstSizes)
|
2013-11-27 03:04:29 +04:00
|
|
|
{
|
2013-11-28 01:23:20 +04:00
|
|
|
int outPlanesSize = width * height;
|
|
|
|
|
|
|
|
dstSizes[0] = outPlanesSize;
|
|
|
|
|
|
|
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[0], width, height, outPlanes, &dstSizes[0]))
|
2013-11-27 07:16:31 +04:00
|
|
|
return 0;
|
2013-11-27 01:30:43 +04:00
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
outPlanes += dstSizes[0];
|
|
|
|
outPlanesSize -= dstSizes[0];
|
|
|
|
dstSizes[1] = outPlanesSize;
|
|
|
|
|
|
|
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[1], width, height, outPlanes, &dstSizes[1]))
|
2013-11-27 07:16:31 +04:00
|
|
|
return 0;
|
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
outPlanes += dstSizes[1];
|
|
|
|
outPlanesSize -= dstSizes[1];
|
|
|
|
dstSizes[2] = outPlanesSize;
|
|
|
|
|
|
|
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[2], width, height, outPlanes, &dstSizes[2]))
|
2013-11-27 07:16:31 +04:00
|
|
|
return 0;
|
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
outPlanes += dstSizes[2];
|
|
|
|
outPlanesSize -= dstSizes[2];
|
|
|
|
dstSizes[3] = outPlanesSize;
|
|
|
|
|
|
|
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[3], width, height, outPlanes, &dstSizes[3]))
|
2013-11-27 07:16:31 +04:00
|
|
|
return 0;
|
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
outPlanes += dstSizes[3];
|
|
|
|
outPlanesSize -= dstSizes[3];
|
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
return 1;
|
2013-11-27 03:04:29 +04:00
|
|
|
}
|
2013-11-27 01:30:43 +04:00
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane)
|
2013-11-27 03:04:29 +04:00
|
|
|
{
|
|
|
|
char s2c;
|
|
|
|
BYTE u2c;
|
|
|
|
int delta;
|
|
|
|
int i, j, k;
|
2013-11-27 01:30:43 +04:00
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
if (!outPlane)
|
|
|
|
{
|
|
|
|
outPlane = (BYTE*) malloc(width * height);
|
2013-11-27 01:30:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
k = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < width; j++)
|
|
|
|
{
|
|
|
|
if (i < 1)
|
|
|
|
{
|
2013-11-27 03:04:29 +04:00
|
|
|
delta = inPlane[j];
|
2013-11-27 01:30:43 +04:00
|
|
|
|
|
|
|
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (delta * -1)) + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-27 03:04:29 +04:00
|
|
|
delta = inPlane[(i * width) + j] - inPlane[((i - 1) * width) + j];
|
2013-11-27 01:30:43 +04:00
|
|
|
|
|
|
|
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (delta * -1)) + 1);
|
|
|
|
|
|
|
|
s2c = (s2c >= 0) ? (s2c << 1) : (char) (((~((BYTE) s2c) + 1) << 1) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
u2c = (BYTE) s2c;
|
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
outPlane[(i * width) + j] = u2c;
|
2013-11-27 01:30:43 +04:00
|
|
|
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
return outPlane;
|
|
|
|
}
|
|
|
|
|
|
|
|
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5])
|
|
|
|
{
|
2013-11-27 07:16:31 +04:00
|
|
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[0], width, height, outPlanes[0]);
|
|
|
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[1], width, height, outPlanes[1]);
|
|
|
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[2], width, height, outPlanes[2]);
|
|
|
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[3], width, height, outPlanes[3]);
|
2013-11-27 01:30:43 +04:00
|
|
|
|
2013-11-27 01:07:55 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-26 07:26:08 +04:00
|
|
|
BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* dstData, int* dstSize)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
BYTE* dstp;
|
|
|
|
int planeSize;
|
2013-11-28 01:23:20 +04:00
|
|
|
int dstSizes[4];
|
2013-11-27 03:04:29 +04:00
|
|
|
BYTE* planes[5];
|
2013-11-26 07:26:08 +04:00
|
|
|
BYTE* planesBuffer;
|
2013-11-27 03:04:29 +04:00
|
|
|
BYTE* deltaPlanes[5];
|
|
|
|
BYTE* deltaPlanesBuffer;
|
2013-11-28 01:23:20 +04:00
|
|
|
BYTE* rlePlanes[4];
|
2013-11-27 03:04:29 +04:00
|
|
|
BYTE* rlePlanesBuffer;
|
|
|
|
BYTE FormatHeader = 0;
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
FormatHeader |= PLANAR_FORMAT_HEADER_NA;
|
|
|
|
|
2013-11-26 08:29:20 +04:00
|
|
|
planeSize = width * height;
|
2013-11-27 03:04:29 +04:00
|
|
|
|
|
|
|
planesBuffer = malloc(planeSize * 5);
|
2013-11-26 07:26:08 +04:00
|
|
|
planes[0] = &planesBuffer[planeSize * 0];
|
|
|
|
planes[1] = &planesBuffer[planeSize * 1];
|
|
|
|
planes[2] = &planesBuffer[planeSize * 2];
|
|
|
|
planes[3] = &planesBuffer[planeSize * 3];
|
2013-11-27 03:04:29 +04:00
|
|
|
planes[4] = &planesBuffer[planeSize * 4];
|
|
|
|
|
|
|
|
deltaPlanesBuffer = malloc(planeSize * 5);
|
|
|
|
deltaPlanes[0] = &deltaPlanesBuffer[planeSize * 0];
|
|
|
|
deltaPlanes[1] = &deltaPlanesBuffer[planeSize * 1];
|
|
|
|
deltaPlanes[2] = &deltaPlanesBuffer[planeSize * 2];
|
|
|
|
deltaPlanes[3] = &deltaPlanesBuffer[planeSize * 3];
|
|
|
|
deltaPlanes[4] = &deltaPlanesBuffer[planeSize * 4];
|
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
rlePlanesBuffer = malloc(planeSize * 4);
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
freerdp_split_color_planes(data, format, width, height, scanline, planes);
|
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
freerdp_bitmap_planar_delta_encode_planes(planes, width, height, deltaPlanes);
|
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
if (freerdp_bitmap_planar_compress_planes_rle(deltaPlanes, width, height, rlePlanesBuffer, (int*) &dstSizes) > 0)
|
2013-11-27 07:16:31 +04:00
|
|
|
{
|
|
|
|
FormatHeader |= PLANAR_FORMAT_HEADER_RLE;
|
|
|
|
|
2013-11-28 01:23:20 +04:00
|
|
|
rlePlanes[0] = &rlePlanesBuffer[0];
|
|
|
|
rlePlanes[1] = &rlePlanesBuffer[dstSizes[0]];
|
|
|
|
rlePlanes[2] = &rlePlanesBuffer[dstSizes[0] + dstSizes[1]];
|
|
|
|
rlePlanes[3] = &rlePlanesBuffer[dstSizes[0] + dstSizes[1] + dstSizes[2]];
|
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
printf("R: [%d/%d] G: [%d/%d] B: [%d/%d]\n",
|
|
|
|
dstSizes[1], planeSize, dstSizes[2], planeSize, dstSizes[3], planeSize);
|
|
|
|
}
|
2013-11-27 03:04:29 +04:00
|
|
|
|
2013-11-26 07:26:08 +04:00
|
|
|
if (!dstData)
|
|
|
|
{
|
2013-11-27 07:16:31 +04:00
|
|
|
size = 1;
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
2013-11-27 07:16:31 +04:00
|
|
|
{
|
|
|
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
|
|
|
size += dstSizes[0];
|
|
|
|
else
|
|
|
|
size += planeSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
|
|
|
size += (dstSizes[1] + dstSizes[2] + dstSizes[3]);
|
|
|
|
else
|
|
|
|
size += (planeSize * 3);
|
2013-11-26 07:26:08 +04:00
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
|
|
|
|
size++;
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
dstData = malloc(size);
|
|
|
|
*dstSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
dstp = dstData;
|
|
|
|
|
|
|
|
*dstp = FormatHeader; /* FormatHeader */
|
|
|
|
dstp++;
|
|
|
|
|
|
|
|
/* AlphaPlane */
|
|
|
|
|
|
|
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
|
|
|
{
|
2013-11-27 07:16:31 +04:00
|
|
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, rlePlanes[0], dstSizes[0]); /* Alpha */
|
|
|
|
dstp += dstSizes[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, planes[0], planeSize); /* Alpha */
|
|
|
|
dstp += planeSize;
|
|
|
|
}
|
2013-11-26 07:26:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* LumaOrRedPlane */
|
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, rlePlanes[1], dstSizes[1]); /* Red */
|
|
|
|
dstp += dstSizes[1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, planes[1], planeSize); /* Red */
|
|
|
|
dstp += planeSize;
|
|
|
|
}
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
/* OrangeChromaOrGreenPlane */
|
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, rlePlanes[2], dstSizes[2]); /* Green */
|
|
|
|
dstp += dstSizes[2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, planes[2], planeSize); /* Green */
|
|
|
|
dstp += planeSize;
|
|
|
|
}
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
/* GreenChromeOrBluePlane */
|
|
|
|
|
2013-11-27 07:16:31 +04:00
|
|
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, rlePlanes[3], dstSizes[3]); /* Blue */
|
|
|
|
dstp += dstSizes[3];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CopyMemory(dstp, planes[3], planeSize); /* Blue */
|
|
|
|
dstp += planeSize;
|
|
|
|
}
|
2013-11-26 07:26:08 +04:00
|
|
|
|
|
|
|
/* Pad1 (1 byte) */
|
|
|
|
|
|
|
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
|
|
|
|
{
|
|
|
|
*dstp = 0;
|
|
|
|
dstp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = (dstp - dstData);
|
|
|
|
*dstSize = size;
|
|
|
|
|
2013-11-27 03:04:29 +04:00
|
|
|
free(rlePlanesBuffer);
|
|
|
|
free(deltaPlanesBuffer);
|
2013-11-26 07:26:08 +04:00
|
|
|
free(planesBuffer);
|
|
|
|
|
|
|
|
return dstData;
|
|
|
|
}
|