25 printf(
"Error initialising Bitmap from file '%s'...\n", (
char*) filename);
49 init(imgData,
size, w, h,
"RGBA", linestep);
54Bitmap::Bitmap(
const char* imgData, uint32
size, uint32 w, uint32 h,
const char* encoding, uint32 linestep) {
55 init(imgData,
size, w, h, encoding, linestep);
59 if ((
stricmp(encoding,
"RGBA") == 0) && (linestep ==
width * 4)) {
261 if (update == NULL) {
341 if ( (x = updateBox.
getLeftX()) < 0) {
385 uint32 w = (uint32) box.
size.
w;
386 uint32 h = (uint32) box.
size.
h;
397 bitmap =
new Bitmap(w, h);
407 char* output =
new char[len];
408 uint32* src = (uint32*)
data;
411 for (uint32 n=0; n<len; n++) {
421 uint32* dst = (uint32*)
data;
423 for (uint32 n=0; n<len; n++) {
469 uint32* src = (uint32*) update->
data;
470 uint32* dst = (uint32*)
data;
475 int tsize = update->
size/4;
477 while (pos < tsize) {
479 len = (*src & 0xFFFFFF);
484 memcpy(dst, src, len*4);
491 for (n=0; n<len; n++)
499 printf(
"Wrong CTRL: %d ", ctrl);
512 uint32* src = (uint32*)update->
data;
513 uint32* dst = (uint32*)
data;
518 int tsize = update->
size/4;
521 while (pos < tsize) {
523 len = (*src & 0xFFFFFF);
528 for (n=0; n<len; n++) {
543 for (n=0; n<len; n++) {
551 printf(
"Wrong CTRL: %d ", ctrl);
564 uint32* src = (uint32*)update->
data;
565 uint32* dst = (uint32*)
data;
570 int tsize = update->
size/4;
571 while (pos < tsize) {
573 len = (*src & 0xFFFFFF);
578 memcpy(dst, src, len*4);
591 printf(
"Wrong CTRL: %d ", ctrl);
604 uint32* src = (uint32*)update->
data;
605 uint32* dst = (uint32*)
data;
610 int tsize = update->
size/4;
611 while (pos < tsize) {
613 len = (*src & 0xFFFFFF);
619 memcpy(dst, src, len*4);
626 for (n=0; n<len; n++)
640 printf(
"Wrong CTRL: %d ", ctrl);
658bool Bitmap::setPixel(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha) {
662 if ((y < 0) || (y >=
height) || (x < 0) || (x >=
width))
665 uint32* dst = ((uint32*)
data) + y*
width + x;
666 *dst = red + (((uint32)green) << 8) + (((uint32)blue) << 16) + (((uint32)alpha) << 24);
676 *(
data+pos+1) = green;
677 *(
data+pos+2) = blue;
678 *(
data+pos+3) = alpha;
687 if ((y < 0) || (y >=
height) || (x < 0) || (x >=
width))
690 unsigned int* dst = ((
unsigned int*)
data) + y*
width + x;
691 *dst |= red + (((uint32)green) << 8) + (((uint32)blue) << 16) + (((uint32)alpha) << 24);
701 *(
data+pos+1) |= green;
702 *(
data+pos+2) |= blue;
703 *(
data+pos+3) |= alpha;
720 if ( (pixel->
x < 0) || (pixel->
y < 0) || (pixel->
x >=
width) || (pixel->
y >=
height) )
728 if ( (x < 0) || (y < 0) || (x >=
width) || (y >=
height) )
730 return (y *
width*4) + (x * 4);
734 if ( (x < 0) || (y < 0) || (x >=
width) || (y >=
height) )
736 return (y *
width*4) + (x * 4);
742 d = ldiv(pos,
width);
768 uint32 byteWidth =
width*4;
769 char* eraseLine =
new char[byteWidth];
782 for (n=0; n<byteWidth; n+=4)
783 memcpy(eraseLine+n, c, 4);
786 for (n=0; n <
size; n+=(byteWidth))
787 memcpy(
data+n, eraseLine, byteWidth);
802 unsigned int oldcolval = oldColor.
r + (oldColor.
g << 8) + (oldColor.
b << 16);
803 unsigned int newcolval = newColor.
r + (newColor.
g << 8) + (newColor.
b << 16);
805 unsigned int* src = (
unsigned int*)
data;
807 for (
int n = 0; n < len; n++) {
808 unsigned int pixel = *src;
809 if ((pixel & 0xffffff) == oldcolval)
810 *src = (pixel & 0xff000000) + newcolval;
823 uint32 byteWidth =
width*4;
838 if ( (w <= 0) || (h <= 0) )
842 uint32 copybytes = w * 4;
843 char* src =
new char[copybytes];
845 for (n=0; n < copybytes; n+=4) {
852 char* dst =
data + (y*byteWidth + x*4);
853 for (n=0; n < h; n++) {
854 memcpy(dst, src, copybytes);
864 if ( (x < 0) || (y < 0) || (x >=
width) || (y >=
height) )
867 resColor.
r = *(
unsigned char*)(
data + pos);
868 resColor.
g = *(
unsigned char*)(
data + pos + 1);
869 resColor.
b = *(
unsigned char*)(
data + pos + 2);
877 if ( (x < 0) || (y < 0) || (x >=
width) || (y >=
height) )
879 unsigned char* ppix = (
unsigned char*)
data + (y*
width*4) + (x*4);
880 ppix[0]=(
unsigned char)((weight*color.
r)+(1-weight)*ppix[0]);
881 ppix[1]=(
unsigned char)((weight*color.
g)+(1-weight)*ppix[1]);
882 ppix[2]=(
unsigned char)((weight*color.
b)+(1-weight)*ppix[2]);
894 double const dw=x2-x1;
895 double const dh=y2-y1;
896 double const slx=dh/(dw ? dw : 0.000001);
897 double const sly=dw/(dh ? dh : 0.000001);
907 else if ((dh != 0) && (dw != 0)) {
908 alpha = atan((
double)dw/dh);
926 for(
int x=tx1;x<=tx2;x++)
928 int const ri=int(raster);
930 double const in_y0=1.0-(raster-ri);
931 double const in_y1=1.0-(ri+1-raster);
934 for (
int n=0; n<extras; n++)
945 else if ((dh != 0) && (dw != 0)) {
946 alpha = atan((
double)dw/dh);
964 for(
int y=ty1;y<=ty2;y++)
966 int const ri=int(raster);
968 double const in_x0=1.0-(raster-ri);
969 double const in_x1=1.0-(ri+1-raster);
972 for (
int n=0; n<extras; n++)
990 if (w < this->
width) {
994 else if (w > this->width) {
1006 else if (h > this->height) {
1013 int newWidth = (int)(this->
width * factor);
1014 int newHeight = (int)(this->
height * factor);
1016 if ((newWidth == 0) || (newHeight == 0) )
1018 else if ((newWidth == this->
width) || (newHeight == this->
height) )
1026 if ( (scale <= 0) || (this->
width == 0) || (this->
height == 0) )
1028 int newWidth, newHeight;
1029 double factor = 1.0;
1036 newWidth = (int)(this->
width * factor);
1037 if ((
double)newWidth != (this->
width * factor))
1039 newHeight = (int)(this->
height * factor);
1040 if ((
double)newHeight != (this->
height * factor))
1043 if ((newWidth == 0) || (newHeight == 0) )
1045 char* newData = this->
createResizedData(newWidth, newHeight, scaleUp, scaleDown, scale66);
1046 if (newData == NULL)
1049 Bitmap* bitmap =
new Bitmap(newData, newWidth, newHeight,
true);
1055 if ( (w == 0) || (h == 0) || (this->
width == 0) || (this->
height == 0) )
1085 int max = (int)fabs(factor) + 5;
1087 double best_penalty = 9999;
1088 double best_factor = 0;
1093 for (
int a=1; a<max; a++) {
1094 for (
int b=1; b<max; b++) {
1095 for (
int c=-1; c<=1; c++) {
1096 f = ((double)a/b) * pow(1.5, (
double)c);
1097 err = fabs(f - factor);
1099 penalty = err * max * max;
1106 if (penalty < best_penalty) {
1110 best_penalty = penalty;
1116 if (best_penalty < 9999) {
1139 uint32 w = this->
width;
1141 if ((scaleUp == 0) && (scaleDown == 0) && (scale66 == 0))
1144 char* newData = NULL;
1145 char* tempData = NULL;
1154 else if (scale66 == -1) {
1159 if (scaleDown > 1) {
1166 else if (scale66 == 1) {
1168 if (scaleDown > 1) {
1175 else if (scale66 == -1) {
1177 if (scaleDown > 1) {
1184 else if (scaleDown > 1) {
1197 if ( (bitmap->
width == this->width) && (bitmap->
height == this->height) && (bitmap->
size == this->size) ) {
1201 else if ( (bitmap->
width == this->width) && (bitmap->
height == this->height) ) {
1202 delete [] this->
data;
1208 else if (!shouldResize) {
1209 delete [] this->
data;
1217 if (bitmap2 == NULL)
1228 delete [] this->
data;
1233 bitmap->
data = NULL;
1373bool Bitmap::drawCircle(uint32 xCenter, uint32 yCenter, uint32 radius,
const Color& color,
double weight,
double lineWidth,
bool filled) {
1375 if ((((
int)lineWidth) > 1) && (!filled)) {
1376 for (
int n=0-(
round(lineWidth/2)); n<
round(lineWidth/2); n++) {
1377 drawCircle(xCenter, yCenter, radius+n, color, weight, 1);
1382 #define D(r,y) (ceil(sqrt((double)r*r - y*y)) - sqrt((double)r*r - y*y))
1390 for(ax=0; ax<x; ++ax)
1398 if (
D(radius,y) < T) --x;
1399 putQuadPixel(xCenter, yCenter, x, y, color, I*(1-
D(radius,y)));
1401 putQuadPixel(xCenter, yCenter, x-1, y, color, I*(1-
D(radius,y)));
1404 for(ax=0; ax<x; ++ax)
1451 if (!horizontal && !vertical)
1454 char* newData =
new char[
size];
1456 int32* dst = (int32*)newData;
1459 if (vertical && !horizontal) {
1460 for (y =
height-1; y >= 0; y--) {
1462 for (x = 0; x < (int32)
width; x++) {
1469 else if (vertical && horizontal) {
1470 for (y =
height; y > 0; y--) {
1472 for (x = 0; x < (int32)
width; x++) {
1480 for (y = 1; y <= (int32)
height; y++) {
1482 for (x = 0; x < (int32)
width; x++) {
1498 if ( (bitmap == NULL) || (bitmap->
data == NULL) || (bitmap ==
this) )
1506 int byteWidth =
width*4;
1507 int srcByteWidth = bitmap->
width * 4;
1509 int srcStartX = srcx;
1514 int srcStartY = srcy;
1520 if (w > bitmap->
width - srcStartX)
1521 w = bitmap->
width - srcStartX;
1522 if (h > bitmap->
height - srcStartY)
1523 h = bitmap->
height - srcStartY;
1525 if (w + dstx >
width)
1529 if ( (w < 0) || (h < 0) )
1533 int copybytes = w * 4;
1534 char* src = bitmap->
data + (srcStartY*srcByteWidth + (srcStartX*4));
1535 char* dst =
data + (dsty*byteWidth + (dstx*4));
1537 for (uint32 n=0; n < h; n++) {
1538 memcpy(dst, src, copybytes);
1539 src += srcByteWidth;
1558 if ( (bitmap == NULL) || (bitmap->
data == NULL) || (bitmap ==
this) )
1909 const char* src = dat;
1912 memcpy(&bmfh, src,
sizeof(bmfh));
1915 memcpy(&bmih, src,
sizeof(bmih));
2011 if ( (len <= 0) && (buffer == NULL) ) {
2118 uint32 srcPixelSize = (uint32)(linestep /
width);
2119 if ((srcPixelSize > 4) || (srcPixelSize < 1))
2121 else if (srcPixelSize == 4)
2123 else if (srcPixelSize == 3)
2125 else if (srcPixelSize == 1)
2142 uint32 padding = 4 - ((
width * 3) % 4);
2143 if (padding == 4) padding = 0;
2146 char* buffer =
new char[len];
2148 memset(dst, 0, headersize);
2175 uint32 srcPadding = 0;
2181 uint32 srcPixelSize;
2182 bool isUnsigned =
true;
2183 uint8 floatSize = 0;
2184 double minVal = 0, maxVal = 0;
2185 if (
stricmp(encoding,
"rgba") == 0)
2187 else if (
stricmp(encoding,
"rgb8") == 0)
2189 else if (
stricmp(encoding,
"bgr8") == 0)
2191 else if (
stricmp(encoding,
"16UC1") == 0) {
2194 srcPadding = linestep - (srcPixelSize *
width);
2196 maxVal = -1000000000.0;
2197 minVal = 1000000000.0;
2198 for (l = 0; l <
height; l++) {
2199 for (c = 0; c <
width; c++) {
2200 if ((*(uint16*)src) < minVal)
2201 minVal = *(uint16*)src;
2202 else if ((*(uint16*)src) > maxVal)
2203 maxVal = *(uint16*)src;
2209 else if (
stricmp(encoding,
"32FC1") == 0) {
2212 srcPadding = linestep - (srcPixelSize *
width);
2214 maxVal = -1000000000.0;
2215 minVal = 1000000000.0;
2217 for (l = 0; l <
height; l++) {
2218 for (c = 0; c <
width; c++) {
2219 if ((*(float32*)src) < minVal)
2220 minVal = *(float32*)src;
2221 else if ((*(float32*)src) > maxVal)
2222 maxVal = *(float32*)src;
2228 else if ((
stricmp(encoding,
"8PC1") == 0) || (
stricmp(encoding,
"8PC1R") == 0)) {
2231 srcPadding = linestep - (srcPixelSize *
width);
2232 maxVal = -1000000000.0;
2233 minVal = 1000000000.0;
2235 for (l = 0; l <
height; l++) {
2236 for (c = 0; c <
width; c++) {
2237 if ((*(int8*)src) < minVal)
2238 minVal = *(int8*)src;
2239 else if ((*(int8*)src) > maxVal)
2240 maxVal = *(int8*)src;
2247 srcPixelSize = (uint32)(linestep /
width);
2254 linestep =
width * srcPixelSize;
2255 srcPadding = linestep - (srcPixelSize *
width);
2256 src =
data + ((
height - 1) * linestep) - srcPadding;
2259 if (
stricmp(encoding,
"16UC1") == 0) {
2260 if (minVal < maxVal)
2261 scaleFactor = 1 / (maxVal - minVal)*255.0;
2264 for (l = 0; l <
height; l++) {
2265 for (c = 0; c <
width; c++) {
2266 *dst = dst[1] = dst[2] = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
2271 src -= linestep + linestep - srcPadding;
2274 else if (
stricmp(encoding,
"32FC1") == 0) {
2275 if (minVal < maxVal)
2276 scaleFactor = 1 / (maxVal - minVal)*255.0;
2279 for (l = 0; l <
height; l++) {
2280 for (c = 0; c <
width; c++) {
2281 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2286 src -= linestep + linestep - srcPadding;
2289 else if (
stricmp(encoding,
"8PC1") == 0) {
2290 if (minVal < maxVal)
2291 scaleFactor = 1 / (maxVal - 0)*255.0;
2294 for (l = 0; l <
height; l++) {
2295 for (c = 0; c <
width; c++) {
2296 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2297 if (*(int8*)src >= 0) {
2299 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2310 src -= linestep + linestep - srcPadding;
2313 else if (
stricmp(encoding,
"8PC1R") == 0) {
2314 if (minVal < maxVal)
2315 scaleFactor = 1 / (maxVal - 0)*255.0;
2320 for (l = 0; l <
height; l++) {
2321 for (c = 0; c <
width; c++) {
2322 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2323 if (*(int8*)src >= 0) {
2325 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2339 else if (srcPixelSize == 4) {
2340 for (l = 0; l <
height; l++) {
2342 for (c = 0; c <
width; c++) {
2344 *dst++ = src[x + 2];
2345 *dst++ = src[x + 1];
2352 else if (
stricmp(encoding,
"bgr8") == 0) {
2353 for (l = 0; l <
height; l++) {
2355 for (c = 0; c <
width; c++) {
2356 *dst++ = src[x + 2];
2357 *dst++ = src[x + 0];
2358 *dst++ = src[x + 1];
2365 else if (srcPixelSize == 3) {
2366 for (l = 0; l <
height; l++) {
2368 for (c = 0; c <
width; c++) {
2370 *dst++ = src[x + 2];
2371 *dst++ = src[x + 1];
2378 else if (srcPixelSize == 2) {
2379 for (l = 0; l <
height; l++) {
2381 for (c = 0; c <
width; c++) {
2383 *dst++ = src[x + 1];
2391 else if (srcPixelSize == 1) {
2392 for (l = 0; l <
height; l++) {
2394 for (c = 0; c <
width; c++) {
2410 uint32
height,
const char* srcEncoding, uint32 linestep,
const char* dstEncoding, uint32& len) {
2419 uint32 dstPixelSize;
2420 if (
stricmp(dstEncoding,
"rgba") == 0)
2422 else if (
stricmp(dstEncoding,
"rgb8") == 0)
2424 else if (
stricmp(dstEncoding,
"bgr8") == 0)
2426 else if (
stricmp(dstEncoding,
"grey") == 0)
2434 char* buffer =
new char[len];
2443 uint32 srcPixelSize;
2444 bool isUnsigned =
true;
2445 uint8 floatSize = 0;
2446 double minVal = 0, maxVal = 0;
2447 if (
stricmp(srcEncoding,
"rgba") == 0)
2449 else if (
stricmp(srcEncoding,
"rgb8") == 0)
2451 else if (
stricmp(srcEncoding,
"bgr8") == 0)
2453 else if (
stricmp(srcEncoding,
"16UC1") == 0) {
2455 srcPadding = linestep - (srcPixelSize *
width);
2457 maxVal = -1000000000.0;
2458 minVal = 1000000000.0;
2459 for (l = 0; l <
height; l++) {
2460 for (c = 0; c <
width; c++) {
2461 if ((*(uint16*)src) < minVal)
2462 minVal = *(uint16*)src;
2463 else if ((*(uint16*)src) > maxVal)
2464 maxVal = *(uint16*)src;
2470 else if (
stricmp(srcEncoding,
"32FC1") == 0) {
2472 srcPadding = linestep - (srcPixelSize *
width);
2474 maxVal = -1000000000.0;
2475 minVal = 1000000000.0;
2477 for (l = 0; l <
height; l++) {
2478 for (c = 0; c <
width; c++) {
2479 if ((*(float32*)src) < minVal)
2480 minVal = *(float32*)src;
2481 else if ((*(float32*)src) > maxVal)
2482 maxVal = *(float32*)src;
2488 else if ((
stricmp(srcEncoding,
"8PC1") == 0) || (
stricmp(srcEncoding,
"8PC1R") == 0)) {
2490 srcPadding = linestep - (srcPixelSize *
width);
2491 maxVal = -1000000000.0;
2492 minVal = 1000000000.0;
2494 for (l = 0; l <
height; l++) {
2495 for (c = 0; c <
width; c++) {
2496 if ((*(int8*)src) < minVal)
2497 minVal = *(int8*)src;
2498 else if ((*(int8*)src) > maxVal)
2499 maxVal = *(int8*)src;
2506 srcPixelSize = (uint32)(linestep /
width);
2508 srcPadding = linestep - (srcPixelSize *
width);
2512 if (
stricmp(srcEncoding,
"16UC1") == 0) {
2513 if (minVal < maxVal)
2514 scaleFactor = 1 / (maxVal - minVal)*255.0;
2517 for (l = 0; l <
height; l++) {
2518 for (c = 0; c <
width; c++) {
2519 if (dstPixelSize == 4) {
2520 *dst = dst[1] = dst[2] = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
2524 else if (dstPixelSize == 3) {
2525 *dst = dst[1] = dst[2] = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
2528 else if (dstPixelSize == 1) {
2529 *dst = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
2538 else if (
stricmp(srcEncoding,
"32FC1") == 0) {
2539 if (minVal < maxVal)
2540 scaleFactor = 1 / (maxVal - minVal)*255.0;
2543 for (l = 0; l <
height; l++) {
2544 for (c = 0; c <
width; c++) {
2545 if (dstPixelSize == 4) {
2546 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2550 else if (dstPixelSize == 3) {
2551 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2554 else if (dstPixelSize == 1) {
2555 *dst = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2564 else if (
stricmp(srcEncoding,
"8PC1") == 0) {
2565 if (minVal < maxVal)
2566 scaleFactor = 1 / (maxVal - 0)*255.0;
2569 for (l = 0; l <
height; l++) {
2570 for (c = 0; c <
width; c++) {
2572 if (dstPixelSize == 4) {
2573 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2574 if (*(int8*)src >= 0) {
2576 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2586 else if (dstPixelSize == 3) {
2587 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2588 if (*(int8*)src >= 0) {
2590 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2599 else if (dstPixelSize == 1) {
2600 *dst = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2601 if (*(int8*)src >= 0) {
2602 *dst = (uint8)(((*(int8*)src)) * scaleFactor);
2615 else if (
stricmp(srcEncoding,
"8PC1R") == 0) {
2616 if (minVal < maxVal)
2617 scaleFactor = 1 / (maxVal - 0)*255.0;
2621 src =
data + ((
height - 1) * linestep) - srcPadding;
2623 for (l = 0; l <
height; l++) {
2624 for (c = 0; c <
width; c++) {
2626 if (dstPixelSize == 4) {
2627 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2628 if (*(int8*)src >= 0) {
2630 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2640 else if (dstPixelSize == 3) {
2641 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2642 if (*(int8*)src >= 0) {
2644 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2653 else if (dstPixelSize == 1) {
2654 *dst = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2655 if (*(int8*)src >= 0) {
2656 *dst = (uint8)(((*(int8*)src)) * scaleFactor);
2667 src -= linestep + linestep - srcPadding;
2670 else if (
stricmp(srcEncoding,
"bgr8") == 0) {
2671 for (l = 0; l <
height; l++) {
2673 for (c = 0; c <
width; c++) {
2674 if (dstPixelSize == 4) {
2675 *dst++ = src[x + 2];
2676 *dst++ = src[x + 1];
2680 else if (dstPixelSize == 3) {
2681 *dst++ = src[x + 2];
2682 *dst++ = src[x + 1];
2685 else if (dstPixelSize == 1) {
2686 *dst++ = (uint8)(((uint32)src[x] + (uint32)src[x + 1] + (uint32)src[x + 2]) / 3);
2694 else if (srcPixelSize >= 3) {
2695 for (l = 0; l <
height; l++) {
2697 for (c = 0; c <
width; c++) {
2698 if (dstPixelSize == 4) {
2700 *dst++ = src[x + 1];
2701 *dst++ = src[x + 2];
2704 else if (dstPixelSize == 3) {
2706 *dst++ = src[x + 1];
2707 *dst++ = src[x + 2];
2709 else if (dstPixelSize == 1) {
2710 *dst++ = (uint8)(((uint32)src[x] + (uint32)src[x + 1] + (uint32)src[x + 2])/3);
2718 else if (srcPixelSize == 2) {
2719 for (l = 0; l <
height; l++) {
2721 for (c = 0; c <
width; c++) {
2722 if (dstPixelSize == 4) {
2724 *dst++ = src[x + 1];
2728 else if (dstPixelSize == 3) {
2730 *dst++ = src[x + 1];
2733 else if (dstPixelSize == 1) {
2734 *dst++ = (uint8)(((uint32)src[x] + (uint32)src[x + 1]) / 2);
2742 else if (srcPixelSize == 1) {
2743 for (l = 0; l <
height; l++) {
2745 for (c = 0; c <
width; c++) {
2746 if (dstPixelSize == 4) {
2752 else if (dstPixelSize == 3) {
2757 else if (dstPixelSize == 1) {
2777 double f = floor(d);
2779 if ((d - f) < 0.5000)
2853 uint32 len =
width*depth;
2854 uint32 padding = 4 - (len%4);
2855 if (padding == 4) padding = 0;
2856 uint32 lineWidth = len + padding;
2857 int32 offset = ((int32)padding) - (2*lineWidth);
2859 unsigned char* newsrc = (
unsigned char*) (src + ((
height-1) * lineWidth));
2860 unsigned int* newdst = (
unsigned int*) dst;
2862 for (uint32 l = 0; l <
height; l++)
2864 for (c = 0; c <
width; c++) {
2865 *(newdst++) = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
2883 uint32 padding = 4 - ((
width*depth)%4);
2884 if (padding == 4) padding = 0;
2885 uint32 lineWidth =
width*depth + padding;
2886 uint32 offset = padding - (2*lineWidth);
2888 unsigned char* newsrc = (
unsigned char*) (src + ((
height-1) * lineWidth));
2889 uint32* newdst = (
unsigned int*) dst;
2890 uint32* lastCtrl = newdst;
2895 bool isInRL =
false;
2905 for (uint32 l = 0; l <
height; l++)
2907 for (c = 0; c <
width; c++) {
2908 newdst[pos] = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
2911 if (newdst[pos-1] == newdst[pos]) {
2917 *lastCtrl = (uint32)((
RLECTRL << 24) | length);
2922 newdst[pos] = newdst[pos-1];
2927 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
2934 *lastCtrl = (uint32)((
DATACTRL << 24) | (length - 2));
2936 lastCtrl += length - 1;
2953 *lastCtrl = (uint32)((
RLECTRL << 24) | length);
2957 *lastCtrl = (uint32)((
DATACTRL << 24) | length);
3032 uint32 padding = 4 - ((
width*depth)%4);
3033 if (padding == 4) padding = 0;
3034 uint32 lineWidth =
width*depth + padding;
3035 uint32 offset = padding - (2*lineWidth);
3037 unsigned char* newsrc = (
unsigned char*) (src + ((
height-1) * lineWidth));
3038 uint32* newdst = (uint32*) dst;
3039 uint32* org = (uint32*) orig;
3041 uint32* lastCtrl = newdst;
3047 bool isInDif =
false;
3055 for (uint32 l = 0; l <
height; l++)
3057 for (c = 0; c <
width; c++) {
3058 newdst[pos] = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
3067 if (*org == newdst[pos]) {
3073 *lastCtrl = (uint32)((
DIFCTRL << 24) | length);
3078 newdst[pos] = newdst[pos-1];
3083 if (*org == newdst[pos]) {
3090 *lastCtrl = (uint32)((
DATACTRL << 24) | (length));
3092 lastCtrl += length + 1;
3110 *lastCtrl = (uint32)((
DIFCTRL << 24) | length);
3114 *lastCtrl = (uint32)((
DATACTRL << 24) | length);
3158 uint32 padding = 4 - ((
width*depth)%4);
3159 if (padding == 4) padding = 0;
3160 uint32 lineWidth =
width*depth + padding;
3161 uint32 offset = padding - (2*lineWidth);
3163 unsigned char* newsrc = (
unsigned char*) (src + ((
height-1) * lineWidth));
3164 uint32* newdst = (uint32*) dst;
3165 uint32* org = (uint32*) orig;
3166 uint32* lastCtrl = newdst;
3172 bool isInRL =
false;
3173 bool isInDif =
false;
3176 for (uint32 l = 0; l <
height; l++)
3178 for (c = 0; c <
width; c++) {
3179 newdst[pos] = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
3182 if (*org == newdst[pos]) {
3188 *lastCtrl = (uint32)((
DIFCTRL << 24) | length);
3193 newdst[pos] = newdst[pos-1];
3198 if (newdst[pos-1] == newdst[pos]) {
3204 *lastCtrl = (uint32)((
RLECTRL << 24) | length);
3209 newdst[pos] = newdst[pos-1];
3214 if (*org == newdst[pos]) {
3220 *lastCtrl = (uint32)((
DATACTRL << 24) | (length));
3222 lastCtrl += length + 1;
3228 else if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3235 *lastCtrl = (uint32)((
DATACTRL << 24) | (length - 2));
3237 lastCtrl += length - 1;
3255 *lastCtrl = (uint32)((
DIFCTRL << 24) | length);
3259 *lastCtrl = (uint32)((
RLECTRL << 24) | length);
3263 *lastCtrl = (uint32)((
DATACTRL << 24) | length);
3284 int byteWidth =
width*4;
3288 unsigned int* newsrc = (
unsigned int*) this->
data;
3289 unsigned int* newdst = (
unsigned int*) dst;
3290 unsigned int* org = (
unsigned int*) bitmap.
data;
3291 unsigned int* lastCtrl = newdst;
3297 bool isInRL =
false;
3298 bool isInDif =
false;
3302 while ((newsrc < endsrc) && (pos <= maxpos)) {
3304 newdst[pos] = *newsrc;
3307 if (*org == newdst[pos]) {
3313 *lastCtrl = (
unsigned int)((
DIFCTRL << 24) | length);
3318 newdst[pos] = newdst[pos-1];
3323 if (newdst[pos-1] == newdst[pos]) {
3329 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3334 newdst[pos] = newdst[pos-1];
3339 if (*org == newdst[pos]) {
3345 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | (length));
3347 lastCtrl += length + 1;
3353 else if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3360 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | (length - 2));
3362 lastCtrl += length - 1;
3390 *lastCtrl = (
unsigned int)((
DIFCTRL << 24) | length);
3394 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3398 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | length);
3404 update->
size = pos * 4;
3418 int byteWidth =
width*4;
3422 unsigned int* newsrc = (
unsigned int*) this->
data;
3423 unsigned int* newdst = (
unsigned int*) dst;
3424 unsigned int* lastCtrl = newdst;
3430 bool isInRL =
false;
3434 while (newsrc < endsrc) {
3435 newdst[pos] = *newsrc;
3438 if (newdst[pos-1] == newdst[pos]) {
3444 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3449 newdst[pos] = newdst[pos-1];
3454 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3461 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | (length - 2));
3463 lastCtrl += length - 1;
3479 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3483 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | length);
3489 update->
size = pos * 4;
3499 int byteWidth =
width*4;
3503 unsigned int* newsrc = (
unsigned int*) this->
data;
3504 unsigned int* newdst = (
unsigned int*) dst;
3505 unsigned int* lastCtrl = newdst;
3511 bool isInRL =
false;
3514 unsigned int* endsrc1 = endsrc - 2;
3516 while (newsrc < endsrc1) {
3520 if (newdst[pos-1] == newdst[pos]) {
3526 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3531 newdst[pos] = newdst[pos-1];
3536 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3543 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | (length - 2));
3545 lastCtrl += length - 1;
3559 if (endsrc-newsrc == 2)
3565 if (newdst[pos-1] == newdst[pos]) {
3571 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3576 newdst[pos] = newdst[pos-1];
3581 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3588 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | (length - 2));
3590 lastCtrl += length - 1;
3605 *lastCtrl = (
unsigned int)((
RLECTRL << 24) | length);
3609 *lastCtrl = (
unsigned int)((
DATACTRL << 24) | length);
3615 update->
size = pos * 4;
3628 char* bytedest =
new char[cols*rows*4];
3630 unsigned int* source = (
unsigned int*) bytesource;
3631 unsigned int* dest = (
unsigned int*) bytedest;
3652 unsigned int** shrows =
new unsigned int*[rows];
3655 for (uint32 n=1; n<rows; n++) {
3656 shrows[n] = shrows[n-1] + cols;
3686 int newcols = (int)((2.0*cols)/3.0);
3687 int newrows = (int)((2.0*rows)/3.0);
3689 if (newcols != (2.0*cols/3.0))
3691 if (newrows != (2.0*cols/3.0))
3694 unsigned int *r1 = dest;
3695 unsigned int *r2 = dest + newcols;
3700 for(uint32 i = 0, k = 0; i < rows; i += 3, k += 2) {
3718 r1 = dest + (newcols * k);
3724 if (newrows - k < 1)
3730 for(j = 0; j < cols-3; j += 3) {
3811 int newcols = (int)((3.0*(
double)cols)/2.0);
3812 int newrows = (int)((3.0*(
double)rows)/2.0);
3813 if ((
double)newcols != (3.0*cols)/2.0)
3815 if ((
double)newrows != (3.0*rows)/2.0)
3818 char* bytedest =
new char[newcols*newrows*4];
3819 unsigned int* source = (
unsigned int*) bytesource;
3820 unsigned int* dest = (
unsigned int*) bytedest;
3822 unsigned int** dhrows =
new unsigned int*[newrows];
3825 for (
int n=1; n<newrows; n++) {
3826 dhrows[n] = dhrows[n-1] + newcols;
3839 unsigned int *r1 = source;
3840 unsigned int *r2 = source + cols;
3844 int realrows = newrows-3;
3845 int realcols = newcols-3;
3848 for(i = 0, k = 0; i <= realrows; i += 3, k += 2) {
3860 r1 = source + (cols * k);
3869 for(j = 0; j <= realcols; j += 3) {
3888 if (newcols - j == 2) {
3894 else if (newcols - j == 1) {
3899 if (newrows - i == 2) {
3908 r1 = source + (cols * k);
3917 for(j = 0; j <= realcols; j += 3) {
3936 if (newcols - j == 2) {
3942 else if (newcols - j == 1) {
3947 else if (newrows - i == 1) {
3953 r1 = source + (cols * k);
3962 for(j = 0; j <= realcols; j += 3) {
3979 if (newcols - j == 2) {
3983 else if (newcols - j == 1) {
3998 int factor2 = factor*factor;
4000 int newcols = (int)((
double)cols/factor);
4001 int newrows = (int)((
double)rows/factor);
4002 if ((
double)newcols != ((
double)cols/factor))
4004 if ((
double)newrows != ((
double)rows/factor))
4007 char* bytedest =
new char[newcols*newrows*4];
4010 memcpy(bytedest, bytesource, cols*rows*4);
4014 unsigned int* source = (
unsigned int*) bytesource;
4015 unsigned int* dest = (
unsigned int*) bytedest;
4019 unsigned int* srcStartPixel = source;
4021 unsigned char* srcPixelByte;
4026 int step = (cols - factor)*4;
4027 int linestep = (factor-1)*cols;
4029 int rowmax = rows-factor;
4030 int colmax = cols-factor;
4034 int factorX, factorY;
4036 double dfactor2 = 1.0/((double)factor2);
4038 unsigned char* destPixelByte = (
unsigned char*) dest;
4040 for (
int y=0; y<=rowmax; y+=factor) {
4041 factorY =
clmin(factor, rows-y);
4042 for (
int x=0; x<=colmax; x+=factor) {
4043 factorX =
clmin(factor, cols-x);
4046 factor2 = factorY*factorX;
4047 srcPixelByte = (
unsigned char*)srcStartPixel;
4048 for (n=0; n<factorY; n++) {
4049 for (m=0; m<factorX; m++) {
4050 r += *srcPixelByte++;
4051 g += *srcPixelByte++;
4052 b += *srcPixelByte++;
4055 srcPixelByte += step;
4057 *destPixelByte++ = (
unsigned char) (r*dfactor2);
4058 *destPixelByte++ = (
unsigned char) (g*dfactor2);
4059 *destPixelByte++ = (
unsigned char) (b*dfactor2);
4060 *destPixelByte++ = 0;
4065 srcStartPixel += factorX;
4067 srcStartPixel += linestep;
4080char*
ImageResizeUp(
char* bytesource, uint32 &cols, uint32 &rows, uint32 factor) {
4085 int factor2 = factor*factor;
4086 int newcols = cols*factor;
4087 int newrows = rows*factor;
4089 char* bytedest =
new char[newcols*newrows*4];
4091 memcpy(bytedest, bytesource, cols*rows*4);
4095 unsigned int* source = (
unsigned int*) bytesource;
4096 unsigned int* dest = (
unsigned int*) bytedest;
4098 int destCols = cols*factor;
4100 unsigned int* destStartPixel = dest;
4101 unsigned int* destPixel;
4102 unsigned int* srcPixel = source;
4103 int step = destCols - factor;
4104 int linestep = (factor-1)*destCols;
4108 for (uint32 x=0; x<rows; x++) {
4109 for (uint32 y=0; y<cols; y++) {
4110 destPixel = destStartPixel;
4112 for (n=0; n<factor; n++) {
4113 for (m=0; m<factor; m++) {
4114 *destPixel++ = pixel;
4118 destStartPixel += factor;
4120 destStartPixel += linestep;
4228 if ((bitmap == NULL) || (bitmap->
data == NULL))
4254 char* src = (
char*)dat;
4323 char* src = (
char*)dat;
4383 char* src = (
char*)dat;
4435 char* src = (
char*)dat;
4501 const uint32 W = 64;
4502 const uint32 H = 48;
4512 if (bmp.
size != W * H * 4) {
4516 if (bmp.
data == NULL) {
4529 if (c.
r != 10 || c.
g != 20 || c.
b != 30) {
4530 unittest::fail(
"erase colour mismatch at (0,0): got %u,%u,%u expected 10,20,30", c.
r, c.
g, c.
b);
4534 if (c.
r != 10 || c.
g != 20 || c.
b != 30) {
4535 unittest::fail(
"erase colour mismatch at far corner: got %u,%u,%u expected 10,20,30", c.
r, c.
g, c.
b);
4542 if (!bmp.
setPixel((uint32)5, (uint32)7, (uint8)200, (uint8)100, (uint8)50, (uint8)0)) {
4547 if (c.
r != 200 || c.
g != 100 || c.
b != 50) {
4548 unittest::fail(
"setPixel readback mismatch: got %u,%u,%u expected 200,100,50", c.
r, c.
g, c.
b);
4553 if (c.
r != 10 || c.
g != 20 || c.
b != 30) {
4554 unittest::fail(
"neighbour pixel was disturbed: got %u,%u,%u expected 10,20,30", c.
r, c.
g, c.
b);
4559 if (bmp.
setPixel((uint32)(W + 10), (uint32)0, (uint8)1, (uint8)2, (uint8)3, (uint8)0)) {
4560 unittest::fail(
"setPixel accepted an out-of-range x coordinate");
4567 if (bmp.
getPos(0, 0) != 0) {
4571 if (bmp.
getPos(3, 2) != (2 * W + 3) * 4) {
4580 Color fillCol(123, 45, 67);
4581 if (!bmp.
fillBox((uint32)10, (uint32)10, (uint32)20, (uint32)15, fillCol)) {
4586 if (c.
r != 123 || c.
g != 45 || c.
b != 67) {
4587 unittest::fail(
"fillBox top-left mismatch: got %u,%u,%u expected 123,45,67", c.
r, c.
g, c.
b);
4591 if (c.
r != 123 || c.
g != 45 || c.
b != 67) {
4592 unittest::fail(
"fillBox bottom-right mismatch: got %u,%u,%u expected 123,45,67", c.
r, c.
g, c.
b);
4597 if (c.
r != 0 || c.
g != 0 || c.
b != 0) {
4598 unittest::fail(
"fillBox leaked outside box at (9,10): got %u,%u,%u", c.
r, c.
g, c.
b);
4602 if (c.
r != 0 || c.
g != 0 || c.
b != 0) {
4603 unittest::fail(
"fillBox leaked outside box at (30,25): got %u,%u,%u", c.
r, c.
g, c.
b);
4615 if (c.
r != 9 || c.
g != 9 || c.
b != 9) {
4616 unittest::fail(
"replaceColor mismatch: got %u,%u,%u expected 9,9,9", c.
r, c.
g, c.
b);
4624 bmp.
setPixel((uint32)12, (uint32)12, (uint8)77, (uint8)88, (uint8)99, (uint8)0);
4637 if (c.
r != 77 || c.
g != 88 || c.
b != 99) {
4638 unittest::fail(
"getCopy pixel mismatch at (2,2): got %u,%u,%u expected 77,88,99", c.
r, c.
g, c.
b);
4648 bmp.
setPixel((uint32)1, (uint32)1, (uint8)111, (uint8)112, (uint8)113, (uint8)0);
4657 unittest::fail(
"roundtrip dimensions/size mismatch: %ux%u size %u vs %ux%u size %u",
4662 if (c.
r != 111 || c.
g != 112 || c.
b != 113) {
4663 unittest::fail(
"roundtrip pixel mismatch at (1,1): got %u,%u,%u expected 111,112,113", c.
r, c.
g, c.
b);
4667 if (c.
r != 40 || c.
g != 41 || c.
b != 42) {
4668 unittest::fail(
"roundtrip background mismatch at (0,0): got %u,%u,%u expected 40,41,42", c.
r, c.
g, c.
b);
4677 const uint32 sweeps = 50;
4680 for (uint32 s = 0; s < sweeps; s++) {
4681 for (uint32 yy = 0; yy < H; yy++) {
4682 for (uint32 xx = 0; xx < W; xx++) {
4683 perf.
setPixel(xx, yy, (uint8)(xx & 0xFF), (uint8)(yy & 0xFF), (uint8)(s & 0xFF), (uint8)0);
4690 unittest::metric(
"setpixel_throughput", (
double)ops / us * 1e6,
"px/s",
true);
4691 unittest::detail(
"setPixel sweep: %llu ops in %.0f us", (
unsigned long long)ops, us);
4695 if (c.
r != (3 & 0xFF) || c.
g != (4 & 0xFF) || c.
b != ((sweeps - 1) & 0xFF)) {
4696 unittest::fail(
"throughput sweep produced wrong final pixel at (3,4): got %u,%u,%u", c.
r, c.
g, c.
b);
4707 "Bitmap image: construct, set/get pixels, erase, fillBox, replaceColor, getCopy, DataMessage roundtrip",
"util");
In-memory RGBA raster image (Bitmap) with drawing primitives, resizing, BMP file I/O and delta/RLE co...
#define GET_SECONDRGB_FROM_DRGB(a)
#define GET_FIRSTRGB_FROM_DRGB(a)
#define GET_B_FROM_RGBA(a)
#define GET_G_FROM_RGBA(a)
#define GET_RGB_FROM_RGBA(a)
#define GET_RGB_FROM_GRAY(a)
#define GET_GRAY_FROM_RGB(a)
#define GET_R_FROM_RGBA(a)
#define GET_DRGB_FROM_2RGBS(a, b)
CMSDK time: µs-resolution 64-bit timestamps and the Time Mapping Constant (TMC).
Small, dependency-free unit test harness used by all CMSDK object tests.
32-bit RGBA raster image with drawing, compositing, scaling, BMP I/O and update-region tracking.
static char * convertBitmapFileDataRunLength(const char *src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen)
As convertBitmapFileData() but RLE-compressing on the fly.
bool putQuadPixel(uint32 xCenter, uint32 yCenter, uint32 x, uint32 y, const Color &color, double weight)
Plot the 4 symmetric points of a circle octant (internal helper for drawCircle()).
bool addBitmapUpdateRegion(const Box &updateBox)
Grow the dirty region to include updateBox.
bool init(uint32 w, uint32 h)
(Re)allocate as w x h.
bool setPixelXOR(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha=0)
XOR the color into the pixel at (x,y) (reversible marker drawing).
bool hasBitmapBeenTotallyChanged()
bool fillBox(const Box &box, const Color &color)
Fill a rectangle (clipped to the image).
Bitmap * getCopy(const Box &box)
Extract a sub-image (caller owns).
double getBestResizeFactors(double factor, int &scaleUp, int &scaleDown, int &scale66)
Decompose factor into up/down/66% passes used by createResizedData().
bool copyGrayScaleData(char *src, uint32 len)
Fill this RGBA image from an 8-bit grayscale buffer of matching size.
bool drawCircle(uint32 xCenter, uint32 yCenter, uint32 radius, const Color &color, double weight, double lineWidth, bool filled=false)
Draw a circle.
Pixel getXY(uint32 pos)
Inverse of getPos(): coordinates for a linear index.
bool mirror(bool horizontal, bool vertical)
Flip in place along the requested axes.
bool drawLine(const Line &line, const Color &color)
Draw a (possibly anti-aliased) line segment.
bool hasBitmapBeenUpdated()
static bool UnitTest()
Self test for Bitmap and BitmapUpdate.
Color getPixelColor(uint32 x, uint32 y)
Pixel color at (x,y) as a Color value (black when out of bounds).
bool setPixel(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha=0)
Set the pixel at (x,y).
bool setBitmapUpdated()
Mark the whole image as changed.
uint32 height
Height in pixels.
uint32 width
Width in pixels.
BitmapUpdate * operator-(const Bitmap &bitmap) const
Difference update transforming bitmap into this image.
DataMessage * toMessage()
Serialize into a new DataMessage (caller owns).
BitmapUpdate * getCompressedUpdate(bool destructive) const
Full-frame update, RLE compressed.
bool resizeTo(uint32 w, uint32 h, bool proportional)
Resize in place.
bool takeDataFromBitmap(Bitmap *bitmap)
Steal the pixel buffer from bitmap (which becomes empty); no copy.
static char * differenceBitmapFileDataRunLength(char *orig, char *src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen)
Difference encoding + RLE compression.
double getBestResizeFactor(double factor)
Snap factor to the nearest factor achievable by the fast integer resizers.
bool eraseBitmap()
Fill with black/zero.
Box updateRegion
Accumulated dirty region since the last resetBitmapUpdates().
BitmapUpdate * runLengthDestructiveEncode() const
RLE-compress, allowed to modify this image's buffer for speed.
bool copyDataFromBitmap(Bitmap *bitmap, bool shouldResize=false)
Copy pixels from bitmap; optionally resize this image to fit.
bool putTransPixel(uint32 x, uint32 y, const Color &color, double weight)
Alpha-blend color onto the pixel with fraction weight [0,1] (anti-aliasing helper).
bool updateBitmap(BitmapUpdate *update, bool takeData)
Apply a full/RLE/diff update.
uint32 size
Data buffer size in bytes (width*height*4).
static char * differenceBitmapFileData(char *orig, char *src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen)
Encode the difference between two frames.
Bitmap()
Empty 0x0 bitmap.
char * createResizedData(uint32 newWidth, uint32 newHeight, int32 scaleUp, int32 scaleDown, int32 scale66)
Produce a resized pixel buffer using the given pass counts (caller frees).
bool resetBitmapUpdates()
Clear the dirty-region tracking.
Bitmap * getResizedCopy(uint32 w, uint32 h, bool proportional)
Resized copy (caller owns).
bool readFromMemory(const char *data, uint32 size)
Parse a BMP file image from memory.
uint32 getPos(uint32 x, uint32 y)
Linear pixel index of (x,y) = y*width+x.
char * data
Pixel data, 32-bit RGBA, row-major top-down.
bool replaceColor(const Color &oldColor, const Color &newColor)
Replace every exact occurrence of oldColor with newColor.
int32 round(double d)
Round to nearest integer (helper for pixel math).
bool reset()
Release pixel data and return to the empty state.
bool canBeResizedTo(uint32 width, uint32 height)
Check whether the integer-ratio resizer supports this target size.
char * toBitmapFileFormat(uint32 &len)
Serialize this image as a complete BMP file in memory.
Pixel getPixel(uint32 x, uint32 y)
Get a Pixel referencing (x,y); value pointer is NULL when out of bounds.
static char * DataToEncodingFormat(const char *data, uint32 size, uint32 width, uint32 height, const char *srcEncoding, uint32 linestep, const char *targetEncoding, uint32 &len)
General pixel-format converter between named encodings.
bool drawBitmap(Bitmap *bitmap, uint32 x, uint32 y)
Blit bitmap with its upper-left corner at (x,y).
char * getGrayScaleDataCopy(uint32 &len)
8-bit grayscale copy of the image.
static bool convertBitmapFileData(const char *src, uint32 width, uint32 height, uint32 depth, char *dst, uint32 dstlen)
Convert raw BMP pixel rows (bottom-up, padded) into the internal top-down RGBA layout.
double getDPos(double x, double y)
Fractional linear index for sub-pixel coordinates.
bool saveToFile(const char *filename)
Save as a BMP file.
BitmapUpdate * runLengthEncode() const
RLE-compress the full image.
bool readFromFile(const char *filename)
Load a BMP file.
static char * DataToBitmapFileFormat(const char *data, uint32 size, uint32 width, uint32 height, uint32 &len)
Convert raw RGBA data into a BMP file image in memory.
bool drawBox(const Box &box, const Color &color)
Draw a rectangle outline.
Transportable image update: either a full frame or a compressed (RLE and/or difference) delta against...
uint32 size
Payload size in bytes.
BitmapUpdate::Type getUpdateType()
Bitmap * toBitmap()
Decode into a new full Bitmap (caller owns); requires a FULL-equivalent payload.
uint32 height
Frame height in pixels.
BitmapUpdate()
Empty update.
bool reset()
Release the payload.
uint32 width
Frame width in pixels.
bool update(BitmapUpdate *update)
Merge a newer update into this one.
char * data
Encoded payload (interpretation depends on type).
bool setUpdateType(BitmapUpdate::Type updateType)
Set the payload encoding tag.
bool readFromFile(const char *filename)
Load a BMP file as a FULL update.
bool setFullUpdate(Bitmap *bitmap)
Fill as an uncompressed full frame from bitmap.
bool init(uint32 w, uint32 h)
(Re)initialize for a w x h frame.
bool readFromFileRLEDiff(const char *filename, Bitmap *oldBitmap)
Load, difference against oldBitmap and RLE-compress.
bool readFromFileDiff(const char *filename, Bitmap *oldBitmap)
Load a BMP file and store the difference against oldBitmap.
bool readFromFileRLE(const char *filename)
Load a BMP file and RLE-compress it.
enum cmlabs::BitmapUpdate::Type type
Type
Payload encoding: FULL raw frame, RUNLENGTH RLE frame, RL16 16-bit RLE, DIF raw difference,...
Axis-aligned rectangle defined by an upper-left corner and a Size, with overlap/containment math.
double getLineWidth() const
PointFloat getLowerLeft() const
PointFloat getUpperLeft() const
PointFloat upperLeft
Upper-left corner.
PointFloat getLowerRight() const
PointFloat getUpperRight() const
24-bit RGB color with mixing, inversion, distance and palette-generation helpers.
The central Psyclone data container: a self-contained binary message with typed, named user entries.
bool getInt(const char *key, int64 &value)
getInt(const char* key, int64& value)
bool setInt(const char *key, int64 value)
setInt(const char* key, int64 value)
char * getDataCopy(const char *key, uint32 &size)
getDataCopy(const char* key, uint32& size)
bool setData(const char *key, const char *value, uint32 size)
setData(const char* key, const char* value, uint32 size)
Line segment between two PointFloat endpoints with a drawing width.
double lineWidth
Stroke width (drawing hint).
PointFloat startPoint
First endpoint.
PointFloat endPoint
Second endpoint.
Reference to one pixel: coordinates plus a pointer directly into the owning Bitmap's data (no copy).
Integer 3D point with an optional attached Size; interoperates with PointFloat and vectors.
Ordered collection of Line segments (not necessarily connected).
uint32 getLineCount() const
Line getLine(uint32 pos) const
static UnitTestRunner & instance()
Access the singleton (created on first use).
void registerTest(const char *name, UnitTestFunc func, const char *description="", const char *category="", bool inDefaultRun=true)
Register a test with the runner.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
bool WriteAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Write (create/overwrite) a file.
char * ReadAFile(const char *filename, uint32 &length, bool binary=false)
Read an entire file into a new buffer.
void fail(const char *fmt,...)
Set an explanatory reason shown on the FAIL line.
void metric(const char *name, double value, const char *unit="", bool higherIsBetter=true)
Record a performance metric.
void detail(const char *fmt,...)
Verbose-only indented diagnostic line (shown only when verbose=1).
void progress(int percent, const char *action)
Report progress with a short description of the current action.
char * ImageResizeUp66(char *bytesource, uint32 &cols, uint32 &rows)
Enlarge an RGBA image to 3/2 size (2→3 pixel interpolation).
char * ImageResizeUp(char *bytesource, uint32 &cols, uint32 &rows, uint32 factor)
Enlarge an RGBA image by an integer factor (pixel replication).
void Register_Bitmap_Tests()
struct cmlabs::tagBITMAPFILEHEADER_CM BITMAPFILEHEADER_CM
BMP file header (14 bytes), local packed definition so no windows.h dependency is needed.
char * ImageResizeDown66(char *bytesource, uint32 &cols, uint32 &rows)
Shrink an RGBA image to 2/3 size (3→2 pixel averaging).
struct cmlabs::tagBITMAPINFOHEADER_CM BITMAPINFOHEADER_CM
BMP info header (40 bytes, BITMAPINFOHEADER equivalent), packed to 2-byte alignment for direct file m...
char * ImageResizeDown(char *bytesource, uint32 &cols, uint32 &rows, uint32 factor)
Shrink an RGBA image by an integer factor (box averaging).