CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
Bitmap.cpp
Go to the documentation of this file.
1
7#include "Bitmap.h"
8#include "PsyTime.h"
9#include "UnitTestFramework.h"
10
11
12namespace cmlabs {
13
15// Construction/Destruction
17
19 init(0, 0);
20}
21
22Bitmap::Bitmap(const char* filename) {
23 init(0, 0);
24 if (!this->readFromFile(filename)) {
25 printf("Error initialising Bitmap from file '%s'...\n", (char*) filename);
26 }
27}
28
29Bitmap::Bitmap(uint32 w, uint32 h) {
30 init(w, h);
31}
32
33Bitmap::Bitmap(char* imgData, uint32 w, uint32 h, bool takeData) {
34 if (takeData) {
35 width = w;
36 height = h;
37 size = w * h * 4;
38 data = imgData;
39 //setMaxUpdates(0);
41 }
42 else {
43 init(w, h);
44 memcpy(data, imgData, size);
45 }
46}
47
48Bitmap::Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, uint32 linestep) {
49 init(imgData, size, w, h, "RGBA", linestep);
50}
51Bitmap::Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding) {
52 init(imgData, size, w, h, encoding, size/h);
53}
54Bitmap::Bitmap(const char* imgData, uint32 size, uint32 w, uint32 h, const char* encoding, uint32 linestep) {
55 init(imgData, size, w, h, encoding, linestep);
56}
57
58bool Bitmap::init(const char* imgData, uint32 size, uint32 width, uint32 height, const char* encoding, uint32 linestep) {
59 if ((stricmp(encoding, "RGBA") == 0) && (linestep == width * 4)) {
61 memcpy(data, imgData, size);
62 return true;
63 }
64
65 uint32 len = 0;
66 char* newData = DataToEncodingFormat(imgData, size, width, height, encoding, linestep, "rgba", len);
67
68 if (!newData || !len)
69 return false;
70
71 this->width = width;
72 this->height = height;
73 this->size = len;
74 this->data = newData;
75 //setMaxUpdates(0);
77 return true;
78
79 //uint32 dstBytesPerLine = width * 4;
80
81 //const char* src;
82 //char* dst = this->data;
83 //uint32 c, l, x;
84 //uint32 srcPadding;
85 //double scaleFactor;
86
88 //uint32 srcPixelSize;
89 //bool isUnsigned = true;
90 //uint8 floatSize = 0;
91 //double minVal = 0, maxVal = 0;
92 //if (stricmp(encoding, "rgba") == 0)
93 // srcPixelSize = 4;
94 //else if (stricmp(encoding, "rgb8") == 0)
95 // srcPixelSize = 3;
96 //else if (stricmp(encoding, "16UC1") == 0) {
97 // srcPixelSize = 2;
98 // srcPadding = linestep - (srcPixelSize * width);
99 // src = imgData;
100 // maxVal = -1000000000.0;
101 // minVal = 1000000000.0;
102 // for (l = 0; l < height; l++) {
103 // for (c = 0; c < width; c++) {
104 // if ((*(uint16*)src) < minVal)
105 // minVal = *(uint16*)src;
106 // else if ((*(uint16*)src) > maxVal)
107 // maxVal = *(uint16*)src;
108 // src += 2;
109 // }
110 // src += srcPadding;
111 // }
112 //}
113 //else if (stricmp(encoding, "32FC1") == 0) {
114 // srcPixelSize = 4;
115 // srcPadding = linestep - (srcPixelSize * width);
116 // floatSize = 4;
117 // maxVal = -1000000000.0;
118 // minVal = 1000000000.0;
119 // src = imgData;
120 // for (l = 0; l < height; l++) {
121 // for (c = 0; c < width; c++) {
122 // if ((*(float32*)src) < minVal)
123 // minVal = *(float32*)src;
124 // else if ((*(float32*)src) > maxVal)
125 // maxVal = *(float32*)src;
126 // src += 4;
127 // }
128 // src += srcPadding;
129 // }
130 //}
131 //else if (stricmp(encoding, "8PC1") == 0) {
132 // srcPixelSize = 1;
133 // srcPadding = linestep - (srcPixelSize * width);
134 // maxVal = -1000000000.0;
135 // minVal = 1000000000.0;
136 // src = imgData;
137 // for (l = 0; l < height; l++) {
138 // for (c = 0; c < width; c++) {
139 // if ((*(int8*)src) < minVal)
140 // minVal = *(int8*)src;
141 // else if ((*(int8*)src) > maxVal)
142 // maxVal = *(int8*)src;
143 // src += 1;
144 // }
145 // src += srcPadding;
146 // }
147 //}
148 //else
149 // srcPixelSize = (uint32)(linestep / width);
150
151 //srcPadding = linestep - (srcPixelSize * width);
152 //src = imgData;
153
154 //if (stricmp(encoding, "16UC1") == 0) {
155 // if (minVal < maxVal)
156 // scaleFactor = 1 / (maxVal - minVal)*255.0;
157 // else
158 // scaleFactor = 1;
159 // for (l = 0; l < height; l++) {
160 // for (c = 0; c < width; c++) {
161 // *dst = dst[1] = dst[2] = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
162 // dst[3] = 0;
163 // dst += 4;
164 // src += 2;
165 // }
166 // src += srcPadding;
167 // }
168 //}
169 //else if (stricmp(encoding, "32FC1") == 0) {
170 // if (minVal < maxVal)
171 // scaleFactor = 1 / (maxVal - minVal)*255.0;
172 // else
173 // scaleFactor = 1;
174 // for (l = 0; l < height; l++) {
175 // for (c = 0; c < width; c++) {
176 // *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
177 // dst[3] = 0;
178 // dst += 4;
179 // src += 4;
180 // }
181 // src += srcPadding;
182 // }
183 //}
184 //else if (stricmp(encoding, "8PC1") == 0) {
185 // if (minVal < maxVal)
186 // scaleFactor = 1 / (maxVal - 0)*255.0;
187 // else
188 // scaleFactor = 1;
189 // for (l = 0; l < height; l++) {
190 // for (c = 0; c < width; c++) {
191 // if (*(int8*)src >= 0) {
192 // dst[0] = 0;
193 // dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
194 // }
195 // else {
196 // dst[0] = 50;
197 // dst[1] = 0;
198 // }
199 // dst[2] = dst[3] = 0;
200 // dst += 4;
201 // src += 1;
202 // }
203 // src += srcPadding;
204 // }
205 //}
206 //else if (srcPixelSize == 4) {
207 // for (l = 0; l < height; l++) {
208 // memcpy(dst, src, dstBytesPerLine);
209 // src += linestep;
210 // dst += dstBytesPerLine;
211 // }
212 //}
213 //else if (srcPixelSize == 3) {
214 // for (l = 0; l < height; l++) {
215 // x = 0;
216 // for (c = 0; c < width; c++) {
217 // *dst++ = src[x];
218 // *dst++ = src[x + 1];
219 // *dst++ = src[x + 2];
220 // *dst++ = 0;
221 // x += srcPixelSize;
222 // }
223 // src += linestep;
224 // }
225 //}
226 //else if (srcPixelSize == 2) {
227 // for (l = 0; l < height; l++) {
228 // x = 0;
229 // for (c = 0; c < width; c++) {
230 // *dst++ = 0;
231 // *dst++ = src[x + 1];
232 // *dst++ = src[x];
233 // *dst++ = 0;
234 // x += srcPixelSize;
235 // }
236 // src += linestep;
237 // }
238 //}
239 //else if (srcPixelSize == 1) {
240 // for (l = 0; l < height; l++) {
241 // x = 0;
242 // for (c = 0; c < width; c++) {
243 // *dst = dst[1] = dst[2] = src[x];
244 // dst[3] = 0;
245 // dst += 4;
246 // x += srcPixelSize;
247 // }
248 // src += linestep;
249 // }
250 //}
251 //else
252 // return false;
253 //return true;
254}
255
257 reset();
258}
259
261 if (update == NULL) {
262 init(0, 0);
263 return;
264 }
265
266 int width = update->width;
267 int height = update->height;
268
269 if ((width <= 0) || (height <= 0) ) {
270 init(0, 0);
271 return;
272 }
273
274 if (!update->type == BitmapUpdate::FULL) {
275 init(width, height);
276 this->fillBox(0, 0, width, height, Color(0,0,0));
277 updateBitmap(update, false);
278 }
279 else
280 updateBitmap(update, true);
281}
282
284 bool ok;
285 width = (uint32)msg->getInt("Width", ok);
286 height = (uint32)msg->getInt("Height", ok);
287 data = msg->getDataCopy("BitmapData", size);
288 if (!data || !width || !height || !size)
289 reset();
290 else
292}
293
295 if (!data || !width || !height || !size)
296 return NULL;
297
298 DataMessage* msg = new DataMessage();
299 msg->setData("BitmapData", data, size);
300 msg->setInt("Width", width);
301 msg->setInt("Height", height);
302 return msg;
303}
304
305bool Bitmap::init(uint32 w, uint32 h) {
306 width = w;
307 height = h;
308 size = w * h * 4;
309 data = NULL;
310 if (w > 0)
311 data = new char[size];
312 //setMaxUpdates(0);
314 return true;
315}
316
317
318
319
320
321//int Bitmap::getMaxUpdates() {
322// return params.get("MaxUpdates").toInt();
323//}
324//
325//bool Bitmap::setMaxUpdates(int max) {
326// params.put("MaxUpdates", JString(max));
327// if (aux != NULL) {
328// ObjectCollection* dict = (ObjectCollection*) aux;
329// if (dict->getCount() > max) {
330// dict->removeAll();
331// }
332// }
333// return true;
334//}
335
336bool Bitmap::addBitmapUpdateRegion(const Box& updateBox) {
338 return true;
339 }
340 double x, y;
341 if ( (x = updateBox.getLeftX()) < 0) {
342 updateRegion.grow(x, 0);
343 updateRegion.move(-1*x, 0);
344 }
345 if ( (y = updateBox.getUpperY()) < 0) {
346 updateRegion.grow(0, y);
347 updateRegion.move(0, -1*y);
348 }
349 updateRegion.growToBoundingBox(updateBox);
350 return true;
351}
352
353
355 updateRegion = Box();
356 return true;
357}
358
360 updateRegion = Box(0,0,(double)width, (double)height);
361 return true;
362}
363
365 return (updateRegion.getArea() > 0);
366}
367
369 return (updateRegion.getArea() > 0);
370}
371
372
373
374
376 delete [] data;
377 data = NULL;
378 return true;
379}
380
382 Bitmap* bitmap;
383 uint32 x = (uint32) box.upperLeft.x;
384 uint32 y = (uint32) box.upperLeft.y;
385 uint32 w = (uint32) box.size.w;
386 uint32 h = (uint32) box.size.h;
387
388 if (box.upperLeft.x != (uint32) box.upperLeft.x)
389 w++;
390 if (box.upperLeft.y != (uint32) box.upperLeft.y)
391 h++;
392 if (box.size.w != (uint32) box.size.w)
393 w++;
394 if (box.size.h != (uint32) box.size.h)
395 h++;
396
397 bitmap = new Bitmap(w, h);
398 bitmap->drawBitmap(this, x, y, 0, 0, w, h);
399 return bitmap;
400}
401
402
404 if (size <= 0)
405 return NULL;
406 len = width*height;
407 char* output = new char[len];
408 uint32* src = (uint32*) data;
409 char* dst = output;
410
411 for (uint32 n=0; n<len; n++) {
412 *dst++ = GET_GRAY_FROM_RGB(*src);
413 src++;
414 }
415 return output;
416}
417
418bool Bitmap::copyGrayScaleData(char* src, uint32 len) {
419 if (len < width*height)
420 return false;
421 uint32* dst = (uint32*) data;
422
423 for (uint32 n=0; n<len; n++) {
424 *dst++ = GET_RGB_FROM_GRAY(*src);
425 src++;
426 }
427 return true;
428}
429
430bool Bitmap::updateBitmap(BitmapUpdate* update, bool takeData) {
431
432 if (update == NULL)
433 return false;
434
435 //int updateWidth = update->width;
436 //int updateHeight = update->height;
437 //long updateSize = update->getDataSize();
438 //char* updateData = update->getDataLink();
439
440 if (update->type == BitmapUpdate::FULL) {
441 if (update->size != (update->width * update->height * 4))
442 return false;
443 reset();
444 if (takeData) {
445 width = update->width;
446 height = update->height;
447 size = update->size;
448 data = update->data;
449 update->width = update->height = 0;
450 update->size = 0;
451 update->data = NULL;
452 //update->clearDataFields();
453 }
454 else {
455 if ( (update->width != width) || (update->height != height) ) {
456 reset();
457 init(update->width, update->height);
458 }
459 memcpy(data, update->data, size);
460 }
461 }
462 else if (update->type == BitmapUpdate::RUNLENGTH) {
463
464 if ((update->width != width) || (update->height != height)) {
465 reset();
466 init(update->width, update->height);
467 }
468
469 uint32* src = (uint32*) update->data;
470 uint32* dst = (uint32*) data;
471 int ctrl;
472 int len = 0;
473 int totallen = 0;
474 int pos = 0;
475 int tsize = update->size/4;
476 int n;
477 while (pos < tsize) {
478 ctrl = (*src >> 24);
479 len = (*src & 0xFFFFFF);
480 src++;
481 pos++;
482 switch(ctrl) {
483 case DATACTRL:
484 memcpy(dst, src, len*4);
485 src += len;
486 dst += len;
487 totallen += len;
488 pos += len;
489 break;
490 case RLECTRL:
491 for (n=0; n<len; n++)
492 *dst++ = src[0];
493 src++;
494 // dst += len;
495 totallen += len;
496 pos++;
497 break;
498 default:
499 printf("Wrong CTRL: %d ", ctrl);
500 pos++;
501 break;
502 }
503 }
504 }
505 else if (update->type == BitmapUpdate::RL16) {
506
507 if ((update->width != width) || (update->height != height)) {
508 reset();
509 init(update->width, update->height);
510 }
511
512 uint32* src = (uint32*)update->data;
513 uint32* dst = (uint32*)data;
514 int ctrl;
515 int len = 0;
516 int totallen = 0;
517 int pos = 0;
518 int tsize = update->size/4;
519 int n;
520 unsigned int i1, i2;
521 while (pos < tsize) {
522 ctrl = (*src >> 24);
523 len = (*src & 0xFFFFFF);
524 src++;
525 pos++;
526 switch(ctrl) {
527 case DATACTRL:
528 for (n=0; n<len; n++) {
529 *dst++ = GET_FIRSTRGB_FROM_DRGB(*src);
530 *dst++ = GET_SECONDRGB_FROM_DRGB(*src);
531 src++;
532 }
533 // memcpy(dst, src, len*4);
534 // src += len;
535 // dst += len;
536 pos+=len;
537 totallen+=len+len;
538 break;
539 case RLECTRL:
540 i1 = GET_FIRSTRGB_FROM_DRGB(*src);
541 i2 = GET_SECONDRGB_FROM_DRGB(*src);
542 src++;
543 for (n=0; n<len; n++) {
544 *dst++ = i1;
545 *dst++ = i2;
546 }
547 totallen+=len+len;
548 pos++;
549 break;
550 default:
551 printf("Wrong CTRL: %d ", ctrl);
552 pos++;
553 break;
554 }
555 }
556 }
557 else if (update->type == BitmapUpdate::DIF) {
558
559 if ((update->width != width) || (update->height != height)) {
560 reset();
561 init(update->width, update->height);
562 }
563
564 uint32* src = (uint32*)update->data;
565 uint32* dst = (uint32*)data;
566 int ctrl;
567 int len = 0;
568 int totallen = 0;
569 int pos = 0;
570 int tsize = update->size/4;
571 while (pos < tsize) {
572 ctrl = (*src >> 24);
573 len = (*src & 0xFFFFFF);
574 src++;
575 pos++;
576 switch(ctrl) {
577 case DATACTRL:
578 memcpy(dst, src, len*4);
579 src += len;
580 dst += len;
581 totallen += len;
582 pos += len;
583 break;
584 case DIFCTRL:
585 dst += len;
586 // dst += len;
587 totallen += len;
588 // pos++;
589 break;
590 default:
591 printf("Wrong CTRL: %d ", ctrl);
592 pos++;
593 break;
594 }
595 }
596 }
597 else if (update->type == BitmapUpdate::DIFRUNLENGTH) {
598
599 if ((update->width != width) || (update->height != height)) {
600 reset();
601 init(update->width, update->height);
602 }
603
604 uint32* src = (uint32*)update->data;
605 uint32* dst = (uint32*)data;
606 int ctrl;
607 int len = 0;
608 int totallen = 0;
609 int pos = 0;
610 int tsize = update->size/4;
611 while (pos < tsize) {
612 ctrl = (*src >> 24);
613 len = (*src & 0xFFFFFF);
614 src++;
615 pos++;
616 int n;
617 switch(ctrl) {
618 case DATACTRL:
619 memcpy(dst, src, len*4);
620 src += len;
621 dst += len;
622 totallen += len;
623 pos += len;
624 break;
625 case RLECTRL:
626 for (n=0; n<len; n++)
627 *dst++ = src[0];
628 src++;
629 // dst += len;
630 totallen += len;
631 pos++;
632 break;
633 case DIFCTRL:
634 dst += len;
635 // dst += len;
636 totallen += len;
637 // pos++;
638 break;
639 default:
640 printf("Wrong CTRL: %d ", ctrl);
641 pos++;
642 break;
643 }
644 }
645 }
646
648 return true;
649}
650
651
652
653
655// Basic Functions
657
658bool Bitmap::setPixel(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha) {
659 if (data == NULL)
660 return false;
661
662 if ((y < 0) || (y >= height) || (x < 0) || (x >= width))
663 return false;
664
665 uint32* dst = ((uint32*) data) + y*width + x;
666 *dst = red + (((uint32)green) << 8) + (((uint32)blue) << 16) + (((uint32)alpha) << 24);
667 return true;
668}
669
670bool Bitmap::setPixel(uint32 pos, uint8 red, uint8 green, uint8 blue, uint8 alpha) {
671 if (data == NULL)
672 return false;
673 if (pos >= size)
674 return false;
675 *(data+pos) = red;
676 *(data+pos+1) = green;
677 *(data+pos+2) = blue;
678 *(data+pos+3) = alpha;
680 return true;
681}
682
683bool Bitmap::setPixelXOR(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha) {
684 if (data == NULL)
685 return false;
686
687 if ((y < 0) || (y >= height) || (x < 0) || (x >= width))
688 return false;
689
690 unsigned int* dst = ((unsigned int*) data) + y*width + x;
691 *dst |= red + (((uint32)green) << 8) + (((uint32)blue) << 16) + (((uint32)alpha) << 24);
692 return true;
693}
694
695bool Bitmap::setPixelXOR(uint32 pos, uint8 red, uint8 green, uint8 blue, uint8 alpha) {
696 if (data == NULL)
697 return false;
698 if (pos >= size)
699 return false;
700 *(data+pos) |= red;
701 *(data+pos+1) |= green;
702 *(data+pos+2) |= blue;
703 *(data+pos+3) |= alpha;
705 return true;
706}
707
708Pixel Bitmap::getPixel(uint32 x, uint32 y) {
709 Pixel p;
710 p.x = x;
711 p.y = y;
712 p.value = NULL;
713 getPixel(&p);
714 return p;
715}
716
718 if (pixel == NULL)
719 return false;
720 if ( (pixel->x < 0) || (pixel->y < 0) || (pixel->x >= width) || (pixel->y >= height) )
721 return false;
722 pixel->value = (unsigned int*)(data + (pixel->y*width*4) + (pixel->x * 4));
723 return true;
724}
725
726
727uint32 Bitmap::getPos(uint32 x, uint32 y) {
728 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
729 return false;
730 return (y * width*4) + (x * 4);
731}
732
733double Bitmap::getDPos(double x, double y) {
734 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
735 return false;
736 return (y * width*4) + (x * 4);
737}
738
739Pixel Bitmap::getXY(uint32 pos) {
740 Pixel p;
741 ldiv_t d;
742 d = ldiv(pos, width);
743 p.y = d.quot;
744 p.x = d.rem;
745 p.value = (unsigned int*)(data + (p.y*width*4) + (p.x * 4));
746 return p;
747}
748
749
750
751
752
753
754
756// Bitmap Functions
758
760 return eraseBitmap(255, 255, 255);
761}
762
763bool Bitmap::eraseBitmap(uint8 r, uint8 g, uint8 b, uint8 a) {
764 uint32 n;
765
766 CMBYTE c[4];
767 // if (eraseLine == NULL)
768 uint32 byteWidth = width*4;
769 char* eraseLine = new char[byteWidth];
770 c[0] = (CMBYTE) r;
771 c[1] = (CMBYTE) g;
772 c[2] = (CMBYTE) b;
773 c[3] = (CMBYTE) a;
774
775/* if (r == 255)
776 c[0] = (CMBYTE) 254;
777 if (g == 255)
778 c[1] = (CMBYTE) 254;
779 if (b == 255)
780 c[2] = (CMBYTE) 254;*/
781
782 for (n=0; n<byteWidth; n+=4)
783 memcpy(eraseLine+n, c, 4);
784
785// for (n=0; n < size; n+=ymax)
786 for (n=0; n < size; n+=(byteWidth))
787 memcpy(data+n, eraseLine, byteWidth);
788
789 delete [] eraseLine;
791 return true;
792}
793
794bool Bitmap::eraseBitmap(const Color& color) {
795 return eraseBitmap(color.r, color.g, color.b);
796}
797
798bool Bitmap::replaceColor(const Color& oldColor, const Color& newColor) {
799 if (data == NULL)
800 return false;
801
802 unsigned int oldcolval = oldColor.r + (oldColor.g << 8) + (oldColor.b << 16);
803 unsigned int newcolval = newColor.r + (newColor.g << 8) + (newColor.b << 16);
804
805 unsigned int* src = (unsigned int*) data;
806 int len = width * height;
807 for (int n = 0; n < len; n++) {
808 unsigned int pixel = *src;
809 if ((pixel & 0xffffff) == oldcolval)
810 *src = (pixel & 0xff000000) + newcolval;
811 src++;
812 }
813 return true;
814}
815
816
817bool Bitmap::fillBox(const Box& box, const Color& color) {
818 return fillBox((int) box.getLeftX(), (int) box.getUpperY(), (int) box.getWidth(), (int) box.getHeight(), color);
819}
820
821bool Bitmap::fillBox(uint32 x, uint32 y, uint32 w, uint32 h, const Color& color) {
822
823 uint32 byteWidth = width*4;
824
825 if (x < 0) {
826 w += x;
827 x = 0;
828 }
829 if (y < 0) {
830 h += y;
831 y = 0;
832 }
833
834 if (w + x > width)
835 w = width - x;
836 if (h + y > height)
837 h = height - y;
838 if ( (w <= 0) || (h <= 0) )
839 return false;
840
841 uint32 n;
842 uint32 copybytes = w * 4;
843 char* src = new char[copybytes];
844
845 for (n=0; n < copybytes; n+=4) {
846 src[n] = color.r;
847 src[n+1] = color.g;
848 src[n+2] = color.b;
849 src[n+3] = 0;
850 }
851
852 char* dst = data + (y*byteWidth + x*4);
853 for (n=0; n < h; n++) {
854 memcpy(dst, src, copybytes);
855 dst += byteWidth;
856 }
857 delete [] src;
858 addBitmapUpdateRegion(Box(x, y, w, h));
859 return true;
860}
861
862Color Bitmap::getPixelColor(uint32 x, uint32 y) {
863 Color resColor;
864 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
865 return Color();
866 long pos = getPos(x, y);
867 resColor.r = *(unsigned char*)(data + pos);
868 resColor.g = *(unsigned char*)(data + pos + 1);
869 resColor.b = *(unsigned char*)(data + pos + 2);
870 return resColor;
871}
872
873
874
875
876bool Bitmap::putTransPixel(uint32 x, uint32 y, const Color& color, double weight) {
877 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
878 return false;
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]);
883 return true;
884}
885
886bool Bitmap::drawLine(const Line& line, const Color& color) {
887
888 int x1 = (int) line.startPoint.x;
889 int y1 = (int) line.startPoint.y;
890 int x2 = (int) line.endPoint.x;
891 int y2 = (int) line.endPoint.y;
892
893 // some useful constants first
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);
898
899 int extras = 0;
900 double alpha;
901
902 // determine wichever raster scanning behaviour to use
903 if(fabs(slx)<1.0)
904 {
905 if (line.lineWidth <= 1)
906 extras = 0;
907 else if ((dh != 0) && (dw != 0)) {
908 alpha = atan((double)dw/dh);
909 extras = (int)(line.lineWidth / cos((clPI*0.5) - alpha));
910 }
911 else
912 extras = (int)line.lineWidth;
913
914 // x scan
915 int tx1=x1;
916 int tx2=x2;
917 double raster=y1;
918
919 if(x1>x2)
920 {
921 tx1=x2;
922 tx2=x1;
923 raster=y2;
924 }
925
926 for(int x=tx1;x<=tx2;x++)
927 {
928 int const ri=int(raster);
929
930 double const in_y0=1.0-(raster-ri);
931 double const in_y1=1.0-(ri+1-raster);
932
933 putTransPixel(x, ri+0 ,color, in_y0);
934 for (int n=0; n<extras; n++)
935 putTransPixel(x, ri+n+1 ,color, 1.0);
936 putTransPixel(x, ri+extras+1 ,color, in_y1);
937
938 raster+=slx;
939 }
940 }
941 else
942 {
943 if (line.lineWidth <= 1)
944 extras = 0;
945 else if ((dh != 0) && (dw != 0)) {
946 alpha = atan((double)dw/dh);
947 extras = (int)(line.lineWidth / sin((clPI*0.5) - alpha));
948 }
949 else
950 extras = (int)line.lineWidth;
951
952 // y scan
953 int ty1=y1;
954 int ty2=y2;
955 double raster=x1;
956
957 if(y1>y2)
958 {
959 ty1=y2;
960 ty2=y1;
961 raster=x2;
962 }
963
964 for(int y=ty1;y<=ty2;y++)
965 {
966 int const ri=int(raster);
967
968 double const in_x0=1.0-(raster-ri);
969 double const in_x1=1.0-(ri+1-raster);
970
971 putTransPixel(ri+0, y, color, in_x0);
972 for (int n=0; n<extras; n++)
973 putTransPixel(ri+n+1, y ,color, 1.0);
974 putTransPixel(ri+extras+1, y, color, in_x1);
975
976 raster+=sly;
977 }
978 }
979 return true;
980}
981
982
983
984bool Bitmap::canBeResizedTo(uint32 w, uint32 h) {
985 double factor = 1.0;
986 // Scale down
987
988 if (w > 0) {
989 // Scale down
990 if (w < this->width) {
991 factor = getBestResizeFactor((double)w/this->width);
992 }
993 // Scale up
994 else if (w > this->width) {
995 factor = getBestResizeFactor((double)w/this->width);
996 }
997 else
998 return false;
999 }
1000 else {
1001 // Scale down
1002 if (h < this->height) {
1003 factor = getBestResizeFactor((double)h/this->height);
1004 }
1005 // Scale up
1006 else if (h > this->height) {
1007 factor = getBestResizeFactor((double)h/this->height);
1008 }
1009 else
1010 return false;
1011 }
1012
1013 int newWidth = (int)(this->width * factor);
1014 int newHeight = (int)(this->height * factor);
1015
1016 if ((newWidth == 0) || (newHeight == 0) )
1017 return false;
1018 else if ((newWidth == this->width) || (newHeight == this->height) )
1019 return false;
1020 else
1021 return true;
1022}
1023
1025
1026 if ( (scale <= 0) || (this->width == 0) || (this->height == 0) )
1027 return NULL;
1028 int newWidth, newHeight;
1029 double factor = 1.0;
1030
1031 int scaleUp = 0;
1032 int scaleDown = 0;
1033 int scale66 = 0;
1034 factor = getBestResizeFactors(scale, scaleUp, scaleDown, scale66);
1035
1036 newWidth = (int)(this->width * factor);
1037 if ((double)newWidth != (this->width * factor))
1038 newWidth++;
1039 newHeight = (int)(this->height * factor);
1040 if ((double)newHeight != (this->height * factor))
1041 newHeight++;
1042
1043 if ((newWidth == 0) || (newHeight == 0) )
1044 return NULL;
1045 char* newData = this->createResizedData(newWidth, newHeight, scaleUp, scaleDown, scale66);
1046 if (newData == NULL)
1047 return NULL;
1048
1049 Bitmap* bitmap = new Bitmap(newData, newWidth, newHeight, true);
1050 return bitmap;
1051}
1052
1053Bitmap* Bitmap::getResizedCopy(uint32 w, uint32 h, bool proportional) {
1054
1055 if ( (w == 0) || (h == 0) || (this->width == 0) || (this->height == 0) )
1056 return NULL;
1057
1058 // Not yet...
1059 if (!proportional)
1060 return NULL;
1061
1062 return getResizedCopy((double)w/this->width);
1063}
1064
1065bool Bitmap::resizeTo(uint32 w, uint32 h, bool proportional) {
1066 Bitmap* bitmap = getResizedCopy(w, h, proportional);
1067 if (bitmap == NULL)
1068 return false;
1069 takeDataFromBitmap(bitmap);
1070 delete(bitmap);
1071 return true;
1072}
1073
1074double Bitmap::getBestResizeFactors(double factor, int &scaleUp, int &scaleDown, int &scale66) {
1075 // in search of best 2^a * (3/2)^b = factor
1076 // penalties: a > 0 : 0
1077 // penalties: b > 0 : a+b
1078 // penalties: c > 0 : 0.5*c
1079 // penalties: c < 0 : c
1080 // penalties: err * max
1081
1082 double penalty;
1083 double err;
1084 double f;
1085 int max = (int)fabs(factor) + 5;
1086
1087 double best_penalty = 9999;
1088 double best_factor = 0;
1089 int best_a = 0;
1090 int best_b = 0;
1091 int best_c = 0;
1092
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);
1098
1099 penalty = err * max * max;
1100 if (c > 0)
1101 penalty += 0.5*c;
1102 else if (c < 0)
1103 penalty += abs(c);
1104 if (b > 0)
1105 penalty += a+b-2;
1106 if (penalty < best_penalty) {
1107 best_a = (a-1);
1108 best_b = b;
1109 best_c = c;
1110 best_penalty = penalty;
1111 best_factor = f;
1112 }
1113 }
1114 }
1115 }
1116 if (best_penalty < 9999) {
1117 scaleUp = best_a;
1118 scaleDown = best_b;
1119 scale66 = best_c;
1120 return best_factor;
1121 }
1122 else
1123 return 0.0;
1124}
1125
1126double Bitmap::getBestResizeFactor(double factor) {
1127 int scaleUp = 0;
1128 int scaleDown = 0;
1129 int scale66 = 0;
1130 double answer = getBestResizeFactors(factor, scaleUp, scaleDown, scale66);
1131 if (answer == 0)
1132 return factor;
1133 else
1134 return answer;
1135}
1136
1137char* Bitmap::createResizedData(uint32 newWidth, uint32 newHeight, int32 scaleUp, int32 scaleDown, int32 scale66) {
1138
1139 uint32 w = this->width;
1140 uint32 h = this->height;
1141 if ((scaleUp == 0) && (scaleDown == 0) && (scale66 == 0))
1142 return ImageResizeUp(this->data, w, h, 1);
1143
1144 char* newData = NULL;
1145 char* tempData = NULL;
1146
1147 if (scaleUp > 0) {
1148 newData = ImageResizeUp(this->data, w, h, scaleUp+1);
1149 if (scale66 == 1) {
1150 tempData = newData;
1151 newData = ImageResizeUp66(tempData, w, h);
1152 delete [] tempData;
1153 }
1154 else if (scale66 == -1) {
1155 tempData = newData;
1156 newData = ImageResizeDown66(tempData, w, h);
1157 delete [] tempData;
1158 }
1159 if (scaleDown > 1) {
1160 tempData = newData;
1161 newData = ImageResizeDown(tempData, w, h, scaleDown);
1162 delete [] tempData;
1163 }
1164 return newData;
1165 }
1166 else if (scale66 == 1) {
1167 newData = ImageResizeUp66(this->data, w, h);
1168 if (scaleDown > 1) {
1169 tempData = newData;
1170 newData = ImageResizeDown(tempData, w, h, scaleDown);
1171 delete [] tempData;
1172 }
1173 return newData;
1174 }
1175 else if (scale66 == -1) {
1176 newData = ImageResizeDown66(this->data, w, h);
1177 if (scaleDown > 1) {
1178 tempData = newData;
1179 newData = ImageResizeDown(tempData, w, h, scaleDown);
1180 delete [] tempData;
1181 }
1182 return newData;
1183 }
1184 else if (scaleDown > 1) {
1185 newData = ImageResizeDown(this->data, w, h, scaleDown);
1186 return newData;
1187 }
1188 else
1189 return NULL;
1190}
1191
1192
1193bool Bitmap::copyDataFromBitmap(Bitmap* bitmap, bool shouldResize) {
1194 if (bitmap == NULL)
1195 return false;
1196
1197 if ( (bitmap->width == this->width) && (bitmap->height == this->height) && (bitmap->size == this->size) ) {
1198 memcpy(this->data, bitmap->data, size);
1199 return true;
1200 }
1201 else if ( (bitmap->width == this->width) && (bitmap->height == this->height) ) {
1202 delete [] this->data;
1203 this->size = bitmap->size;
1204 this->data = new char[size];
1205 memcpy(this->data, bitmap->data, size);
1206 return true;
1207 }
1208 else if (!shouldResize) {
1209 delete [] this->data;
1210 this->size = bitmap->size;
1211 this->data = new char[size];
1212 memcpy(this->data, bitmap->data, size);
1213 return true;
1214 }
1215 else {
1216 Bitmap* bitmap2 = bitmap->getResizedCopy(this->width, this->height, true);
1217 if (bitmap2 == NULL)
1218 return false;
1219 takeDataFromBitmap(bitmap2);
1220 delete(bitmap2);
1221 return true;
1222 }
1223}
1224
1226 if (bitmap == NULL)
1227 return false;
1228 delete [] this->data;
1229 this->size = bitmap->size;
1230 this->width = bitmap->width;
1231 this->height = bitmap->height;
1232 this->data = bitmap->data;
1233 bitmap->data = NULL;
1234 bitmap->size = 0;
1235 bitmap->width = 0;
1236 bitmap->height = 0;
1237 return true;
1238}
1239
1240
1241
1242
1243/*
1244bool Bitmap::drawLine(Line line, Color color) {
1245
1246 int x0 = (int) line.startPoint.x;
1247 int y0 = (int) line.startPoint.y;
1248 int x1 = (int) line.endPoint.x;
1249 int y1 = (int) line.endPoint.y;
1250
1251// int pix = color.getRGB();
1252 int dy = y1 - y0;
1253 int dx = x1 - x0;
1254 int stepx, stepy;
1255 double invD = ((dx==0)&&(dy==0)) ? 0.0 : 1.0/(2.0*sqrt((double)dx*dx+dy*dy));
1256
1257 if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
1258 if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
1259
1260 dy <<= 1; // dy is now 2*dy
1261 dx <<= 1; // dx is now 2*dx
1262
1263 int fraction;
1264 int v2dx, v2dy;
1265 double dd, invD2dx, invD2dy;
1266 Color paintColor;
1267 Color backColor;
1268
1269 if (dx > dy) {
1270 fraction = dy - (dx >> 1);
1271 v2dx = 0;
1272 invD2dx = dx * invD;
1273 backColor = getPixelColor(x0, y0);
1274 paintColor = color.mixOn(backColor, 1);
1275 setPixel(x0, y0, paintColor.r, paintColor.g, paintColor.b);
1276 backColor = getPixelColor(x0, y0 + stepy);
1277 paintColor = color.mixOn(backColor, 1 - invD2dx);
1278 setPixel(x0, y0 + stepy, paintColor.r, paintColor.g, paintColor.b);
1279 backColor = getPixelColor(x0, y0 - stepy);
1280 paintColor = color.mixOn(backColor, 1 - invD2dx);
1281 setPixel(x0, y0 - stepy, paintColor.r, paintColor.g, paintColor.b);
1282 while (x0 != x1) {
1283 v2dx = fraction;
1284 if (fraction >= 0) {
1285 y0 += stepy;
1286 v2dx -= dx;
1287 fraction -= dx;
1288 }
1289 x0 += stepx;
1290 v2dx += (dx >> 1);
1291 fraction += dy;
1292 dd = v2dx * invD;
1293
1294 backColor = getPixelColor(x0, y0);
1295 paintColor = color.mixOn(backColor, 1 - dd);
1296 setPixel(x0, y0, paintColor.r, paintColor.g, paintColor.b);
1297 backColor = getPixelColor(x0, y0 + stepy);
1298 paintColor = color.mixOn(backColor, 1 - (invD2dx - dd));
1299 setPixel(x0, y0 + stepy, paintColor.r, paintColor.g, paintColor.b);
1300 backColor = getPixelColor(x0, y0 - stepy);
1301 paintColor = color.mixOn(backColor, 1 - (invD2dx + dd));
1302 setPixel(x0, y0 - stepy, paintColor.r, paintColor.g, paintColor.b);
1303 }
1304 }
1305 else {
1306 fraction = dx - (dy >> 1);
1307 v2dy = 0;
1308 invD2dy = dy * invD;
1309 setPixel(x0, y0, 0, 0, 0);
1310 setPixel(x0, y0 + stepy, (int) invD2dy, (int) invD2dy, (int) invD2dy);
1311 setPixel(x0, y0 - stepy, (int) invD2dy, (int) invD2dy, (int) invD2dy);
1312 while (y0 != y1) {
1313 v2dy = fraction;
1314 if (fraction >= 0) {
1315 x0 += stepx;
1316 v2dy -= dy;
1317 fraction -= dy;
1318 }
1319 y0 += stepy;
1320 v2dy += (dy >> 1);
1321 fraction += dx;
1322 dd = v2dy * invD;
1323 setPixel(x0, y0, (int) dd, (int) dd, (int) dd);
1324 setPixel(x0 + stepx, y0, (int) (invD2dy - dd), (int) (invD2dy - dd), (int) (invD2dy - dd));
1325 setPixel(x0 - stepx, y0, (int) (invD2dy + dd), (int) (invD2dy + dd), (int) (invD2dy + dd));
1326 // setPixel(x0, y0, 0, 0, 0);
1327 // setPixel(x0 + stepx, y0, 0, 0, 0);
1328 // setPixel(x0 - stepx, y0, 0, 0, 0);
1329 }
1330 }
1331
1332 setBitmapChanged();
1333 return true;
1334}
1335*/
1336
1337bool Bitmap::drawLine(const PolyLine& polyline, const Color& color) {
1338 for (uint32 n=0; n<polyline.getLineCount(); n++) {
1339 drawLine(polyline.getLine(n), color);
1340 }
1342 return true;
1343}
1344
1345bool Bitmap::drawBox(const Box& box, const Color& color) {
1346 Line line = Line(box.getUpperLeft(), box.getUpperRight(), box.getLineWidth());
1347 drawLine(line, color);
1348 line = Line(box.getUpperRight(), box.getLowerRight(), box.getLineWidth());
1349 drawLine(line, color);
1350 line = Line(box.getLowerRight(), box.getLowerLeft(), box.getLineWidth());
1351 drawLine(line, color);
1352 line = Line(box.getLowerLeft(), box.getUpperLeft(), box.getLineWidth());
1353 drawLine(line, color);
1355 return true;
1356}
1357
1358// static void WUCircle(int cx,int cy, int R, int filled, int c)
1359
1360bool Bitmap::putQuadPixel(uint32 xCenter, uint32 yCenter, uint32 x, uint32 y, const Color& color, double weight) {
1361 putTransPixel(xCenter + y, yCenter + x, color, weight);
1362 putTransPixel(xCenter - y, yCenter + x, color, weight);
1363 putTransPixel(xCenter + y, yCenter - x, color, weight);
1364 putTransPixel(xCenter - y, yCenter - x, color, weight);
1365 putTransPixel(xCenter + x, yCenter + y, color, weight);
1366 putTransPixel(xCenter - x, yCenter + y, color, weight);
1367 putTransPixel(xCenter + x, yCenter - y, color, weight);
1368 putTransPixel(xCenter - x, yCenter - y, color, weight);
1369 return true;
1370}
1371
1372
1373bool Bitmap::drawCircle(uint32 xCenter, uint32 yCenter, uint32 radius, const Color& color, double weight, double lineWidth, bool filled) {
1374
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);
1378 }
1379 return true;
1380 }
1381
1382 #define D(r,y) (ceil(sqrt((double)r*r - y*y)) - sqrt((double)r*r - y*y))
1383
1384 int x = radius;
1385 int y = 0;
1386 int ax;
1387 double T = 0;
1388 double I = 0.93;
1389 if (filled)
1390 for(ax=0; ax<x; ++ax)
1391 putQuadPixel(xCenter, yCenter, ax, y, color, 1.0);
1392
1393 putQuadPixel(xCenter, yCenter, x, y, color, I);
1394
1395 while (x>y)
1396 {
1397 ++y;
1398 if (D(radius,y) < T) --x;
1399 putQuadPixel(xCenter, yCenter, x, y, color, I*(1-D(radius,y)));
1400 if (!filled) {
1401 putQuadPixel(xCenter, yCenter, x-1, y, color, I*(1-D(radius,y)));
1402 }
1403 if (filled) {
1404 for(ax=0; ax<x; ++ax)
1405 putQuadPixel(xCenter, yCenter, ax, y, color, 1.0);
1406 }
1407 T = D(radius,y);
1408 }
1409
1410 return true;
1411/*
1412 int x=0;
1413 int y=radius;
1414 int p=(5-(radius<<2))>>2; //Midpoint Algorithm
1415
1416 putTransPixel(xCenter , yCenter+y, color, weight);
1417 putTransPixel(xCenter , yCenter-y, color, weight);
1418 putTransPixel(xCenter+y, yCenter , color, weight);
1419 putTransPixel(xCenter-y, yCenter , color, weight);
1420
1421 while(x++ < y) {
1422 if(p<0)
1423 p+=1+(x<<1);
1424 else
1425 p+=1+((x- --y)<<1);
1426
1427 if(x<y) {
1428 putTransPixel(xCenter+x, yCenter+y, color, weight);
1429 putTransPixel(xCenter-x, yCenter+y, color, weight);
1430 putTransPixel(xCenter+x, yCenter-y, color, weight);
1431 putTransPixel(xCenter-x, yCenter-y, color, weight);
1432 putTransPixel(xCenter+y, yCenter+x, color, weight);
1433 putTransPixel(xCenter-y, yCenter+x, color, weight);
1434 putTransPixel(xCenter+y, yCenter-x, color, weight);
1435 putTransPixel(xCenter-y, yCenter-x, color, weight);
1436 }
1437 else if(x==y) {
1438 putTransPixel(xCenter+x, yCenter+y, color, weight);
1439 putTransPixel(xCenter-x, yCenter+y, color, weight);
1440 putTransPixel(xCenter+x, yCenter-y, color, weight);
1441 putTransPixel(xCenter-x, yCenter-y, color, weight);
1442 }
1443 }
1444 return true;*/
1445}
1446
1447bool Bitmap::mirror(bool horizontal, bool vertical) {
1448 if (!data || !size || !width || !height)
1449 return false;
1450
1451 if (!horizontal && !vertical)
1452 return true;
1453
1454 char* newData = new char[size];
1455 int32* src;
1456 int32* dst = (int32*)newData;
1457 int32 x, y;
1458
1459 if (vertical && !horizontal) {
1460 for (y = height-1; y >= 0; y--) {
1461 src = ((int32*)data) + (y*width);
1462 for (x = 0; x < (int32)width; x++) {
1463 *dst = *src;
1464 dst++;
1465 src++;
1466 }
1467 }
1468 }
1469 else if (vertical && horizontal) {
1470 for (y = height; y > 0; y--) {
1471 src = ((int32*)data) + (y*width);
1472 for (x = 0; x < (int32)width; x++) {
1473 src--;
1474 *dst = *src;
1475 dst++;
1476 }
1477 }
1478 }
1479 else { // if only horizontal
1480 for (y = 1; y <= (int32)height; y++) {
1481 src = ((int32*)data) + (y*width);
1482 for (x = 0; x < (int32)width; x++) {
1483 src--;
1484 *dst = *src;
1485 dst++;
1486 }
1487 }
1488 }
1489
1490 delete[] data;
1491 data = newData;
1492
1493 return true;
1494}
1495
1496
1497bool Bitmap::drawBitmap(Bitmap* bitmap, uint32 srcx, uint32 srcy, uint32 dstx, uint32 dsty, uint32 w, uint32 h) {
1498 if ( (bitmap == NULL) || (bitmap->data == NULL) || (bitmap == this) )
1499 return false;
1500
1501 if (srcx < 0)
1502 srcx = 0;
1503 if (srcy < 0)
1504 srcy = 0;
1505
1506 int byteWidth = width*4;
1507 int srcByteWidth = bitmap->width * 4;
1508
1509 int srcStartX = srcx;
1510 if (dstx < 0) {
1511 srcStartX -= dstx;
1512 dstx = 0;
1513 }
1514 int srcStartY = srcy;
1515 if (dsty < 0) {
1516 srcStartY -= dsty;
1517 dsty = 0;
1518 }
1519
1520 if (w > bitmap->width - srcStartX)
1521 w = bitmap->width - srcStartX;
1522 if (h > bitmap->height - srcStartY)
1523 h = bitmap->height - srcStartY;
1524
1525 if (w + dstx > width)
1526 w = width - dstx;
1527 if (h + dsty > height)
1528 h = height - dsty;
1529 if ( (w < 0) || (h < 0) )
1530 return false;
1531
1532// int copybytes = (w - srcStartX) * 4;
1533 int copybytes = w * 4;
1534 char* src = bitmap->data + (srcStartY*srcByteWidth + (srcStartX*4));
1535 char* dst = data + (dsty*byteWidth + (dstx*4));
1536// for (int n=0; n < h - srcStartY; n++) {
1537 for (uint32 n=0; n < h; n++) {
1538 memcpy(dst, src, copybytes);
1539 src += srcByteWidth;
1540 dst += byteWidth;
1541 }
1542 addBitmapUpdateRegion(Box(dstx, dsty, w, h));
1543 return true;
1544}
1545
1546
1547
1548
1549
1550bool Bitmap::drawBitmap(Bitmap* bitmap, uint32 x, uint32 y) {
1551 if (bitmap == NULL)
1552 return false;
1553 bitmap->addBitmapUpdateRegion(Box(x, y, bitmap->width, bitmap->height));
1554 return drawBitmap(bitmap, x, y, bitmap->width, bitmap->height);
1555}
1556
1557bool Bitmap::drawBitmap(Bitmap* bitmap, uint32 x, uint32 y, uint32 w, uint32 h) {
1558 if ( (bitmap == NULL) || (bitmap->data == NULL) || (bitmap == this) )
1559 return false;
1560
1561 return drawBitmap(bitmap, 0, 0, x, y, w, h);
1562/*
1563
1564 int byteWidth = width*4;
1565 int srcByteWidth = bitmap->width * 4;
1566
1567 int srcStartX = 0;
1568 if (x < 0) {
1569 srcStartX -= x;
1570 x = 0;
1571 }
1572 int srcStartY = 0;
1573 if (y < 0) {
1574 srcStartY -= y;
1575 y = 0;
1576 }
1577
1578 if (w > bitmap->width + srcStartX)
1579 w = bitmap->width - srcStartX;
1580 if (h > bitmap->height + srcStartY)
1581 h = bitmap->height - srcStartY;
1582
1583 if (w + x > width)
1584 w = width - x;
1585 if (h + y > height)
1586 h = height - y;
1587 if ( (w < 0) || (h < 0) )
1588 return false;
1589
1590 int copybytes = (w - srcStartX) * 4;
1591 char* src = bitmap->data + (srcStartY*srcByteWidth + (srcStartX*4));;
1592 char* dst = data + (y*byteWidth + (x*4));
1593 for (int n=0; n < h - srcStartY; n++) {
1594 memcpy(dst, src, copybytes);
1595 src += srcByteWidth;
1596 dst += byteWidth;
1597 }
1598 bitmap->addBitmapUpdateRegion(Box(x, y, w, h));
1599 return true;*/
1600}
1601
1602bool Bitmap::drawBitmap(Bitmap* bitmap, const Point& p) {
1603 return drawBitmap(bitmap, p.x, p.y);
1604}
1605
1606bool Bitmap::drawBitmap(Bitmap* bitmap, const Box& box) {
1607 return drawBitmap(bitmap, (int) box.getLeftX(), (int) box.getUpperY(), (int) box.getWidth(), (int) box.getHeight());
1608}
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1625// Advanced Functions
1627
1628/*
1629// Rotate around the center point
1630bool Bitmap::rotate(double angle) {
1631
1632 double a, b, c;
1633 int x1, y1, x2, y2, x3, y3;
1634
1635 long tdiff = 0;
1636
1637 double r = sqrt((double)width*width + height*height);
1638 int cr = (int) ceil(r) + 8;
1639
1640 if (altBitmap == NULL)
1641 altBitmap = new Bitmap(cr, cr);
1642
1643 if ( (altBitmap->width != cr) ||
1644 (altBitmap->height != cr) ) {
1645 delete(altBitmap);
1646 altBitmap = new Bitmap(cr, cr);
1647 }
1648 altBitmap->eraseBitmap(bgColor.r, bgColor.g, bgColor.b);
1649// altBitmap->eraseBitmap(200, 200, 200);
1650// altBitmap->eraseBitmap(255, 0, 0);
1651
1652 r = (r/2); // - (r/8);
1653// r = (r/3); // - (r/8);
1654// angle = (clPI/4.0);
1655
1656 double alpha = asin(width/(2.0*r));
1657 double beta = 2.0*acos(width/(2.0*r));
1658
1659 a = angle + (clPI/2) + alpha;
1660 if (a > clPI) a = a - (2*clPI);
1661
1662 b = angle + (clPI/2) - alpha;
1663 if (b > clPI) b = b - (2*clPI);
1664
1665 c = angle + (clPI/2) + alpha + beta;
1666 if (c > clPI) c = c - (2*clPI);
1667
1668 x1 = round(r * (1.0 + cos(a))) + 4;
1669 y1 = round(r * (1.0 - sin(a))) + 4;
1670 x2 = round(r * (1.0 + cos(b))) + 4;
1671 y2 = round(r * (1.0 - sin(b))) + 4;
1672 x3 = round(r * (1.0 + cos(c))) + 4;
1673 y3 = round(r * (1.0 - sin(c))) + 4;
1674
1675 // shapeSlow(x1, y1, x2, y2, x3, y3);
1676 shape(x1, y1, x2, y2, x3, y3);
1677
1678 return true;
1679}
1680
1681
1682// Rotate around the center point
1683bool Bitmap::rotateSlow(double angle) {
1684
1685 double a, b, c;
1686 int x1, y1, x2, y2, x3, y3;
1687
1688 long tdiff = 0;
1689
1690 double r = sqrt((double)width*width + height*height);
1691 int cr = (int) ceil(r) + 8;
1692
1693 if (altBitmap == NULL)
1694 altBitmap = new Bitmap(cr, cr);
1695
1696 if ( (altBitmap->width != cr) ||
1697 (altBitmap->height != cr) ) {
1698 delete(altBitmap);
1699 altBitmap = new Bitmap(cr, cr);
1700 }
1701 altBitmap->eraseBitmap(bgColor.r, bgColor.g, bgColor.b);
1702// altBitmap->eraseBitmap(200, 200, 200);
1703// altBitmap->eraseBitmap(255, 0, 0);
1704
1705 r = (r/2); // - (r/8);
1706// r = (r/3); // - (r/8);
1707// angle = (clPI/4.0);
1708
1709 double alpha = asin(width/(2.0*r));
1710 double beta = 2.0*acos(width/(2.0*r));
1711
1712 a = angle + (clPI/2) + alpha;
1713 if (a > clPI) a = a - (2*clPI);
1714
1715 b = angle + (clPI/2) - alpha;
1716 if (b > clPI) b = b - (2*clPI);
1717
1718 c = angle + (clPI/2) + alpha + beta;
1719 if (c > clPI) c = c - (2*clPI);
1720
1721 x1 = round(r * (1.0 + cos(a))) + 4;
1722 y1 = round(r * (1.0 - sin(a))) + 4;
1723 x2 = round(r * (1.0 + cos(b))) + 4;
1724 y2 = round(r * (1.0 - sin(b))) + 4;
1725 x3 = round(r * (1.0 + cos(c))) + 4;
1726 y3 = round(r * (1.0 - sin(c))) + 4;
1727
1728 shapeSlow(x1, y1, x2, y2, x3, y3);
1729 // shape(x1, y1, x2, y2, x3, y3);
1730
1731 return true;
1732}
1733
1734
1735bool Bitmap::shapeSlow(int x1, int y1, int x2, int y2, int x3, int y3) {
1736
1737 double px, py;
1738 long pos, n, altbyteWidth;
1739
1740// byteWidth = width * byteDepth + padding;
1741 altbyteWidth = (altBitmap->width*altBitmap->byteDepth);
1742
1743 CMBYTE c[6];
1744 c[0] = (CMBYTE) 0;
1745 c[1] = (CMBYTE) 0;
1746 c[2] = (CMBYTE) 0;
1747 c[3] = (CMBYTE) 0;
1748 c[4] = (CMBYTE) 0;
1749 c[5] = (CMBYTE) 0;
1750
1751 double d1x = ((double)(x2 - x1)) / width;
1752 double d1y = ((double)(y2 - y1)) / width;
1753
1754 double d2x = ((double)(x3 - x1)) / height;
1755 double d2y = ((double)(y3 - y1)) / height;
1756
1757 double ppx, ppy;
1758
1759 long startLine = size;
1760
1761 px = ppx = x1;// + (y * d2x) + (x * d1x);
1762 py = ppy = y1;// + (y * d2y) + (x * d1y);
1763 for (int y=0; y < height; y++) {
1764 n = (startLine -= byteWidth); // y * byteWidth;
1765 for (int x=0; x < width; x++) {
1766 if ((n == 0) || (x == 0)) {
1767 pos = ((altBitmap->height-(long)py) * altbyteWidth) + ((long)px * byteDepth);
1768 memcpy(altBitmap->data+pos, data+n, 3);
1769 }
1770 else if ((n > 0) && (n < size)) {
1771 pos = ((altBitmap->height-(long)py) * altbyteWidth) + ((long)px * byteDepth);
1772 memcpy(altBitmap->data+pos-3, data+n-3, 6);
1773 // memcpy(altBitmap->data+pos-3, c, 6);
1774 }
1775 n += 3;
1776 px += d1x; // + (x * d1x);
1777 py += d1y; // + (x * d1y);
1778 }
1779 px = (ppx += d2x);
1780 py = (ppy += d2y);
1781 }
1782
1783// int x4 = x3 + (x2-x1);
1784// int y4 = y3 - (y1-y2);
1785// for (int k=-5; k<5; k++) {
1786// altBitmap->setPixel(x1+k, y1+k, 0, 255, 0);
1787// altBitmap->setPixel(x2+k, y2+k, 255, 0, 0);
1788// altBitmap->setPixel(x3+k, y3+k, 255, 0, 0);
1789// altBitmap->setPixel(x4+k, y4+k, 255, 0, 0);
1790// altBitmap->setPixel(x1+k, y1-k, 0, 255, 0);
1791// altBitmap->setPixel(x2+k, y2-k, 255, 0, 0);
1792// altBitmap->setPixel(x3+k, y3-k, 255, 0, 0);
1793// altBitmap->setPixel(x4+k, y4-k, 255, 0, 0);
1794// }
1795 return true;
1796}
1797
1798
1799
1800
1801bool Bitmap::shape(int x1, int y1, int x2, int y2, int x3, int y3) {
1802 double px, py;
1803// double ppx, ppy;
1804 long pos, oldpy, n;
1805
1806// long byteWidth = width * byteDepth + padding;
1807 long altbyteWidth = (altBitmap->width*altBitmap->byteDepth);
1808
1809// double d1x = ((double)(x2 - x1)) / width;
1810// double d1y = ((double)(y2 - y1)) / height;
1811
1812// double d2x = ((double)(x3 - x1)) / width;
1813// double d2y = ((double)(y3 - y1)) / height;
1814
1815 double d1x = ((double)(x2 - x1)) / width;
1816 double d1y = ((double)(y2 - y1)) / width;
1817
1818 double d2x = ((double)(x3 - x1)) / height;
1819 double d2y = ((double)(y3 - y1)) / height;
1820
1821 long startLine = size;
1822 long nStart, posStart;
1823 int length;
1824 bool inverted = false;
1825
1826// altBitmap->eraseBitmap(200, 200, 200);
1827
1828 // nStart is upper left corner of original bitmap
1829 nStart = size - byteWidth;
1830 // posStart is the equivalent rotated upper left corner = (x1,y1)
1831 posStart = ((altBitmap->height-y1) * altbyteWidth) + (x1 * byteDepth);
1832
1833 length = 0;
1834 px = x1 + (0 * d2x);// + (y * d2x) + (x * d1x);
1835 py = y1 + (0 * d2y);// + (y * d2y) + (x * d1y);
1836 n = nStart;
1837 for (int x=0; x < width; x++) {
1838 if ((n >= 0) && (n < size)) {
1839 pos = ((altBitmap->height-(long)py) * altbyteWidth) + ((long)px * byteDepth);
1840 if ((oldpy == (long)py) && ((y3 - y1) > 0)) {
1841 length--;
1842 L[length] += 3;
1843 }
1844 else {
1845 N[length] = n - nStart;
1846 P[length] = pos - posStart;
1847 L[length] = 3;
1848 }
1849 length++;
1850 }
1851 n += 3;
1852 oldpy = (long)py;
1853 px += d1x; // + (x * d1x);
1854 py += d1y; // + (x * d1y);
1855 }
1856 // Make sure first pixel does not get black from outside
1857 if (length > 0) {
1858 N[0] += 3;
1859 L[0] -= 3;
1860 // P[0] += 3;
1861 }
1862
1863 long posLineStart = posStart;
1864 long nLineStart = nStart;
1865 px = x1; // + d2x; // + (0 * d2x);
1866 py = y1; // + d2y; // + (0 * d2y);
1867 for (int y=0; y < height; y++) {
1868 for (n=0; n<length; n++) {
1869 memcpy(altBitmap->data+P[n]+posLineStart-3, data+N[n]+nLineStart-3, L[n]+3);
1870 }
1871 nLineStart -= byteWidth;
1872 px += d2x;
1873 py += d2y;
1874 posLineStart = ((altBitmap->height-(long)py) * altbyteWidth) + ((long)px * byteDepth);
1875 }
1876
1877// int x4 = x3 + (x2-x1);
1878// int y4 = y3 - (y1-y2);
1879// for (int k=-5; k<5; k++) {
1880// altBitmap->setPixel(x1+k, y1+k, 0, 0, 255);
1881// altBitmap->setPixel(x2+k, y2+k, 255, 0, 0);
1882// altBitmap->setPixel(x3+k, y3+k, 255, 0, 0);
1883// altBitmap->setPixel(x4+k, y4+k, 255, 0, 0);
1884// altBitmap->setPixel(x1+k, y1-k, 0, 0, 255);
1885// altBitmap->setPixel(x2+k, y2-k, 255, 0, 0);
1886// altBitmap->setPixel(x3+k, y3-k, 255, 0, 0);
1887// altBitmap->setPixel(x4+k, y4-k, 255, 0, 0);
1888// }
1889 return true;
1890}
1891*/
1892
1893
1895// File Routines
1897
1898bool Bitmap::readFromMemory(const char* dat, uint32 len) {
1899
1900 BITMAPFILEHEADER_CM bmfh = { 0 };
1901 BITMAPINFOHEADER_CM bmih = { 0 };
1902 uint32 count = 0;
1903
1904 if (!dat || !len) {
1905 // printf("No file data\n");
1906 return false;
1907 }
1908
1909 const char* src = dat;
1910
1911 // bmfh = (BITMAPFILEHEADER_CM*) src;
1912 memcpy(&bmfh, src, sizeof(bmfh)); /* read bitmap file header */
1913 src += sizeof(BITMAPFILEHEADER_CM);
1914 // bmih = (BITMAPINFOHEADER_CM*) src;
1915 memcpy(&bmih, src, sizeof(bmih)); /* read bitmap info header */
1916 src += sizeof(BITMAPINFOHEADER_CM);
1917
1918 // MessageBox(NULL, JString::format("Read binary file len %d [%d %d]", len, (int)bmfh, (int)bmih), JString("WinClient"), MB_OK);
1919 // MessageBox(NULL, JString::format("Bitmap: %d %d %d %d \n", sizeof(BITMAPFILEHEADER_CM), sizeof(BITMAPINFOHEADER_CM), bmfh.bfSize, bmfh.bfOffBits), JString("WinClient"), MB_OK);
1920 // printf("Bitmap: %d %d %d %d %d \n", sizeof(BITMAPFILEHEADER_CM), sizeof(BITMAPINFOHEADER_CM), bmfh->bfSize, bmfh->bfType, bmfh->bfOffBits);
1921
1922 // MessageBox(NULL, JString("Analysing binary file "), JString("WinClient"), MB_OK);
1923 if (bmih.biCompression != 0) {
1924 // MessageBox(NULL, JString("auch, compression"), JString("WinClient"), MB_OK);
1925 delete[] dat;
1926 // printf("Compression\n");
1927 return false;
1928 }
1929
1930 // MessageBox(NULL, JString("Is it 24 bit?"), JString("WinClient"), MB_OK);
1931 if (bmih.biBitCount != 24) {
1932 // MessageBox(NULL, JString("auch, !24"), JString("WinClient"), MB_OK);
1933 delete[] dat;
1934 // printf("Not 24 bits: %d\n", bmih.biBitCount);
1935 return false;
1936 }
1937
1938 /* if (bmih.biBitCount <= 8) {
1939 // determine type of window bitmaps
1940 if(bmih.biBitCount==8) bmpcolour=256;
1941 if(bmih.biBitCount==4) bmpcolour=16;
1942 if(bmih.biBitCount==1) bmpcolour=2;
1943
1944 // * * * * * * * * * * * * * * * * * *
1945 read the palette information
1946 from MSB b,g,r,i (i=ignore)
1947 // * * * * * * * * * * * * * * * * * * *
1948
1949 for(index=0;index<bmpcolour;index++)
1950 {
1951 pal3[index].b = fgetc(fp) >> 2;
1952 pal3[index].g = fgetc(fp) >> 2;
1953 pal3[index].r = fgetc(fp) >> 2;
1954 fgetc(fp);
1955 }
1956 }*/
1957
1958 // MessageBox(NULL, JString("24 bit OK"), JString("WinClient"), MB_OK);
1959 int depth = bmih.biBitCount;
1960 int planes = bmih.biPlanes;
1961 int width = bmih.biWidth;
1962 int height = bmih.biHeight;
1963 // MessageBox(NULL, JString::format("D: %d, P: %d, W: %d, H: %d", depth, planes, width, height), JString("WinClient"), MB_OK);
1964 // byteDepth = (int) (depth/8);
1965 // byteWidth = width * byteDepth + padding;
1966
1967 if (bmih.biSizeImage == 0)
1968 bmih.biSizeImage = bmfh.bfSize - bmfh.bfOffBits;
1969
1970 // div_t d = div(width, 4);
1971 // int padding = d.rem;
1972
1973 // MessageBox(NULL, JString("Reinit bitmap "), JString("WinClient"), MB_OK);
1974 init(width, height);
1975 if (data == NULL) {
1976 // printf("No data\n");
1977 return false;
1978 }
1979
1980 // MessageBox(NULL, JString("Converting data "), JString("WinClient"), MB_OK);
1981 convertBitmapFileData(src, width, height, (int)(bmih.biBitCount / 8), data, size);
1982 // MessageBox(NULL, JString("Converted data "), JString("WinClient"), MB_OK);
1983
1985 return true;
1986}
1987
1988
1989bool Bitmap::readFromFile(const char* filename) {
1990
1991 uint32 len;
1992 char* dat = utils::ReadAFile(filename, len, true);
1993 if (!dat || !len) {
1994 delete[] dat;
1995 // printf("No file data\n");
1996 return false;
1997 }
1998 bool res = readFromMemory(dat, len);
1999 delete[] dat;
2000 return res;
2001}
2002
2003bool Bitmap::saveToFile(const char* filename) {
2004
2005 // Open file
2006 //if((fp=fopen(filename,"wb"))==NULL)
2007 // return false;
2008
2009 uint32 len = 0;
2010 char* buffer = toBitmapFileFormat(len);
2011 if ( (len <= 0) && (buffer == NULL) ) {
2012 delete [] buffer;
2013 //fclose(fp);
2014 return false;
2015 }
2016
2017 if (!utils::WriteAFile(filename, buffer, len, true)) {
2018 delete [] buffer;
2019 return false;
2020 }
2021
2022 delete [] buffer;
2023 return true;
2024
2025/*
2026 BITMAPFILEHEADER_CM bmfh={0};
2027 // BITMAPINFOHEADER_CM bmih={0};
2028 BITMAPINFOHEADER_CM* info;
2029// int infosize = sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM) + 2; // + 2 for rounding
2030 int infosize = sizeof(BITMAPINFOHEADER_CM) + 2; // + 2 for rounding
2031
2032// CMDWORD index;
2033// CMBYTE ch;
2034 long count = 0;
2035
2036 int byteWidth = width*4;
2037
2038 // Fill out structures
2039 bmfh.bfType = 19778; // 'BM'
2040 bmfh.bfSize = size + sizeof(BITMAPFILEHEADER_CM) + infosize; // might need padding...
2041 bmfh.bfReserved1 = 0;
2042 bmfh.bfReserved2 = 0;
2043 bmfh.bfOffBits = sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM);
2044
2045 info = (BITMAPINFOHEADER_CM*) malloc(infosize);
2046 memset(info, 0, infosize);
2047
2048 info->biSize = sizeof(BITMAPINFOHEADER_CM);
2049 info->biWidth = width;
2050 info->biHeight = height;
2051 info->biPlanes = 1;
2052 info->biCompression = 0;
2053 info->biBitCount = 24;
2054 info->biSizeImage = 0; // size;
2055 info->biXPelsPerMeter = 2834;
2056 info->biYPelsPerMeter = 2834;
2057 info->biClrUsed = 0;
2058 info->biClrImportant = 0;
2059
2060 // div_t d = div(width, 4);
2061 // int padding = d.rem;
2062 int padding = 4 - ((width*3)%4);
2063 if (padding == 4) padding = 0;
2064
2065 // write bitmap file header
2066 if (fwrite(&bmfh,sizeof(BITMAPFILEHEADER_CM),1,fp) != 1) {
2067 fclose(fp);
2068 free(info);
2069 return false;
2070 }
2071
2072 // write bitmap info header
2073// if (fwrite(&bmih,sizeof(bmih),1,fp) != 1) {
2074 if (fwrite(info, sizeof(BITMAPINFOHEADER_CM),1,fp) != 1) {
2075 fclose(fp);
2076 free(info);
2077 return false;
2078 }
2079
2080 free(info);
2081
2082// char* binline = new char[byteWidth];
2083// memset(binline, 0, byteWidth);
2084
2085 // Write bitmap data
2086 int c, x;
2087 char* src = data + (height-1) * byteWidth;
2088 for (int l = 0; l < height; l++)
2089 {
2090 // fwrite(binline, 1, byteWidth, fp);
2091 x = 0;
2092 for (c = 0; c < width; c++) {
2093 fputc(src[x+2], fp);
2094 fputc(src[x+1], fp);
2095 fputc(src[x], fp);
2096 x += 4;
2097 }
2098 for (c=0; c < padding; c++) {
2099 fputc(0, fp);
2100 }
2101 src -= byteWidth;
2102 }
2103
2104 // Close file
2105 fclose(fp);
2106 return true; */
2107}
2108
2109char* Bitmap::toBitmapFileFormat(uint32& len) {
2111}
2112
2113char* Bitmap::DataToBitmapFileFormat(const char* data, uint32 size, uint32 width, uint32 height, uint32& len) {
2114 return DataToBitmapFileFormat(data, size, width, height, "RGBA", width * 4, len);
2115}
2116
2117char* Bitmap::DataToBitmapFileFormat(const char* data, uint32 size, uint32 width, uint32 height, uint32 linestep, uint32& len) {
2118 uint32 srcPixelSize = (uint32)(linestep / width);
2119 if ((srcPixelSize > 4) || (srcPixelSize < 1))
2120 return NULL;
2121 else if (srcPixelSize == 4)
2122 return DataToBitmapFileFormat(data, size, width, height, "RGBA", linestep, len);
2123 else if (srcPixelSize == 3)
2124 return DataToBitmapFileFormat(data, size, width, height, "rgb8", linestep, len);
2125 else if (srcPixelSize == 1)
2126 return DataToBitmapFileFormat(data, size, width, height, "grey", linestep, len);
2127 else
2128 return NULL;
2129}
2130
2131char* Bitmap::DataToBitmapFileFormat(const char* data, uint32 size, uint32 width, uint32 height, const char* encoding, uint32& len) {
2132 return DataToBitmapFileFormat(data, size, width, height, encoding, 0, len);
2133}
2134
2135char* Bitmap::DataToBitmapFileFormat(const char* data, uint32 size, uint32 width, uint32 height, const char* encoding, uint32 linestep, uint32& len) {
2136
2137 uint32 infosize = sizeof(BITMAPINFOHEADER_CM) + 2; // + 2 for rounding
2138 uint32 headersize = sizeof(BITMAPFILEHEADER_CM) + infosize;
2139
2140 uint32 count = 0;
2141
2142 uint32 padding = 4 - ((width * 3) % 4);
2143 if (padding == 4) padding = 0;
2144
2145 len = headersize + (height * width * 3) + (padding * height);
2146 char* buffer = new char[len];
2147 char* dst = buffer;
2148 memset(dst, 0, headersize);
2149
2152
2153 // Fill out structures
2154 bmfh->bfType = 19778; // 'BM'
2155 // bmfh.bfSize = size + sizeof(BITMAPFILEHEADER_CM) + infosize; // might need padding...
2156 bmfh->bfSize = len;
2157 bmfh->bfReserved1 = 0;
2158 bmfh->bfReserved2 = 0;
2159 bmfh->bfOffBits = sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM);
2160
2161 info->biSize = sizeof(BITMAPINFOHEADER_CM);
2162 info->biWidth = width;
2163 info->biHeight = height;
2164 info->biPlanes = 1;
2165 info->biCompression = 0;
2166 info->biBitCount = 24;
2167 info->biSizeImage = 0; // size;
2168 info->biXPelsPerMeter = 2834;
2169 info->biYPelsPerMeter = 2834;
2170 info->biClrUsed = 0;
2171 info->biClrImportant = 0;
2172
2173 dst += headersize;
2174 const char* src;
2175 uint32 srcPadding = 0;
2176 double scaleFactor;
2177
2178 uint32 c, l, x;
2179
2180 // Write bitmap data
2181 uint32 srcPixelSize;
2182 bool isUnsigned = true;
2183 uint8 floatSize = 0;
2184 double minVal = 0, maxVal = 0;
2185 if (stricmp(encoding, "rgba") == 0)
2186 srcPixelSize = 4;
2187 else if (stricmp(encoding, "rgb8") == 0)
2188 srcPixelSize = 3;
2189 else if (stricmp(encoding, "bgr8") == 0)
2190 srcPixelSize = 3;
2191 else if (stricmp(encoding, "16UC1") == 0) {
2192 srcPixelSize = 2;
2193 if (linestep)
2194 srcPadding = linestep - (srcPixelSize * width);
2195 src = data;
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;
2204 src += 2;
2205 }
2206 src += srcPadding;
2207 }
2208 }
2209 else if (stricmp(encoding, "32FC1") == 0) {
2210 srcPixelSize = 4;
2211 if (linestep)
2212 srcPadding = linestep - (srcPixelSize * width);
2213 floatSize = 4;
2214 maxVal = -1000000000.0;
2215 minVal = 1000000000.0;
2216 src = data;
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;
2223 src += 4;
2224 }
2225 src += srcPadding;
2226 }
2227 }
2228 else if ((stricmp(encoding, "8PC1") == 0) || (stricmp(encoding, "8PC1R") == 0)) {
2229 srcPixelSize = 1;
2230 if (linestep)
2231 srcPadding = linestep - (srcPixelSize * width);
2232 maxVal = -1000000000.0;
2233 minVal = 1000000000.0;
2234 src = data;
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;
2241 src += 1;
2242 }
2243 src += srcPadding;
2244 }
2245 }
2246 else if (linestep)
2247 srcPixelSize = (uint32)(linestep / width);
2248 else {
2249 delete [] buffer;
2250 return NULL;
2251 }
2252
2253 if (!linestep)
2254 linestep = width * srcPixelSize;
2255 srcPadding = linestep - (srcPixelSize * width);
2256 src = data + ((height - 1) * linestep) - srcPadding;
2257
2258
2259 if (stricmp(encoding, "16UC1") == 0) {
2260 if (minVal < maxVal)
2261 scaleFactor = 1 / (maxVal - minVal)*255.0;
2262 else
2263 scaleFactor = 1;
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);
2267 dst += 3;
2268 src += 2;
2269 }
2270 dst += padding;
2271 src -= linestep + linestep - srcPadding;
2272 }
2273 }
2274 else if (stricmp(encoding, "32FC1") == 0) {
2275 if (minVal < maxVal)
2276 scaleFactor = 1 / (maxVal - minVal)*255.0;
2277 else
2278 scaleFactor = 1;
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);
2282 dst += 3;
2283 src += 4;
2284 }
2285 dst += padding;
2286 src -= linestep + linestep - srcPadding;
2287 }
2288 }
2289 else if (stricmp(encoding, "8PC1") == 0) {
2290 if (minVal < maxVal)
2291 scaleFactor = 1 / (maxVal - 0)*255.0;
2292 else
2293 scaleFactor = 1;
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) {
2298 dst[0] = 0;
2299 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2300 }
2301 else {
2302 dst[0] = 50;
2303 dst[1] = 0;
2304 }
2305 dst[2] = 0;
2306 dst += 3;
2307 src += 1;
2308 }
2309 dst += padding;
2310 src -= linestep + linestep - srcPadding;
2311 }
2312 }
2313 else if (stricmp(encoding, "8PC1R") == 0) {
2314 if (minVal < maxVal)
2315 scaleFactor = 1 / (maxVal - 0)*255.0;
2316 else
2317 scaleFactor = 1;
2318 // read vertically from the bottom up, just like the bitmap
2319 src = data;
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) {
2324 dst[0] = 0;
2325 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2326 }
2327 else {
2328 dst[0] = 50;
2329 dst[1] = 0;
2330 }
2331 dst[2] = 0;
2332 dst += 3;
2333 src += 1;
2334 }
2335 dst += padding;
2336 src += srcPadding;
2337 }
2338 }
2339 else if (srcPixelSize == 4) {
2340 for (l = 0; l < height; l++) {
2341 x = 0;
2342 for (c = 0; c < width; c++) {
2343 *dst++ = src[x];
2344 *dst++ = src[x + 2];
2345 *dst++ = src[x + 1];
2346 x += srcPixelSize;
2347 }
2348 dst += padding;
2349 src -= linestep;
2350 }
2351 }
2352 else if (stricmp(encoding, "bgr8") == 0) {
2353 for (l = 0; l < height; l++) {
2354 x = 0;
2355 for (c = 0; c < width; c++) {
2356 *dst++ = src[x + 2];
2357 *dst++ = src[x + 0];
2358 *dst++ = src[x + 1];
2359 x += srcPixelSize;
2360 }
2361 dst += padding;
2362 src -= linestep;
2363 }
2364 }
2365 else if (srcPixelSize == 3) {
2366 for (l = 0; l < height; l++) {
2367 x = 0;
2368 for (c = 0; c < width; c++) {
2369 *dst++ = src[x];
2370 *dst++ = src[x + 2];
2371 *dst++ = src[x + 1];
2372 x += srcPixelSize;
2373 }
2374 dst += padding;
2375 src -= linestep;
2376 }
2377 }
2378 else if (srcPixelSize == 2) {
2379 for (l = 0; l < height; l++) {
2380 x = 0;
2381 for (c = 0; c < width; c++) {
2382 *dst++ = 0;
2383 *dst++ = src[x + 1];
2384 *dst++ = src[x];
2385 x += srcPixelSize;
2386 }
2387 dst += padding;
2388 src -= linestep;
2389 }
2390 }
2391 else if (srcPixelSize == 1) {
2392 for (l = 0; l < height; l++) {
2393 x = 0;
2394 for (c = 0; c < width; c++) {
2395 *dst++ = src[x];
2396 *dst++ = src[x];
2397 *dst++ = src[x];
2398 x += srcPixelSize;
2399 }
2400 dst += padding;
2401 src -= linestep;
2402 }
2403 }
2404
2405 return buffer;
2406}
2407
2408
2409char* Bitmap::DataToEncodingFormat(const char* data, uint32 size, uint32 width,
2410 uint32 height, const char* srcEncoding, uint32 linestep, const char* dstEncoding, uint32& len) {
2411
2412 if (!data || !size || !width || !height) {
2413 len = 0;
2414 return NULL;
2415 }
2416
2417 uint32 count = 0;
2418
2419 uint32 dstPixelSize;
2420 if (stricmp(dstEncoding, "rgba") == 0)
2421 dstPixelSize = 4;
2422 else if (stricmp(dstEncoding, "rgb8") == 0)
2423 dstPixelSize = 3;
2424 else if (stricmp(dstEncoding, "bgr8") == 0)
2425 dstPixelSize = 3;
2426 else if (stricmp(dstEncoding, "grey") == 0)
2427 dstPixelSize = 1;
2428 else {
2429 len = 0;
2430 return NULL;
2431 }
2432
2433 len = (height * width * dstPixelSize);
2434 char* buffer = new char[len];
2435 char* dst = buffer;
2436
2437 const char* src;
2438 uint32 srcPadding;
2439 double scaleFactor;
2440
2441 uint32 c, l, x;
2442
2443 uint32 srcPixelSize;
2444 bool isUnsigned = true;
2445 uint8 floatSize = 0;
2446 double minVal = 0, maxVal = 0;
2447 if (stricmp(srcEncoding, "rgba") == 0)
2448 srcPixelSize = 4;
2449 else if (stricmp(srcEncoding, "rgb8") == 0)
2450 srcPixelSize = 3;
2451 else if (stricmp(srcEncoding, "bgr8") == 0)
2452 srcPixelSize = 3;
2453 else if (stricmp(srcEncoding, "16UC1") == 0) {
2454 srcPixelSize = 2;
2455 srcPadding = linestep - (srcPixelSize * width);
2456 src = data;
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;
2465 src += 2;
2466 }
2467 src += srcPadding;
2468 }
2469 }
2470 else if (stricmp(srcEncoding, "32FC1") == 0) {
2471 srcPixelSize = 4;
2472 srcPadding = linestep - (srcPixelSize * width);
2473 floatSize = 4;
2474 maxVal = -1000000000.0;
2475 minVal = 1000000000.0;
2476 src = data;
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;
2483 src += 4;
2484 }
2485 src += srcPadding;
2486 }
2487 }
2488 else if ((stricmp(srcEncoding, "8PC1") == 0) || (stricmp(srcEncoding, "8PC1R") == 0)) {
2489 srcPixelSize = 1;
2490 srcPadding = linestep - (srcPixelSize * width);
2491 maxVal = -1000000000.0;
2492 minVal = 1000000000.0;
2493 src = data;
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;
2500 src += 1;
2501 }
2502 src += srcPadding;
2503 }
2504 }
2505 else
2506 srcPixelSize = (uint32)(linestep / width);
2507
2508 srcPadding = linestep - (srcPixelSize * width);
2509 //src = data + ((height - 1) * linestep) - srcPadding;
2510 src = data;
2511
2512 if (stricmp(srcEncoding, "16UC1") == 0) {
2513 if (minVal < maxVal)
2514 scaleFactor = 1 / (maxVal - minVal)*255.0;
2515 else
2516 scaleFactor = 1;
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);
2521 dst[3] = 0;
2522 dst += 4;
2523 }
2524 else if (dstPixelSize == 3) {
2525 *dst = dst[1] = dst[2] = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
2526 dst += 3;
2527 }
2528 else if (dstPixelSize == 1) {
2529 *dst = (uint8)(((*(uint16*)src) - minVal) * scaleFactor);
2530 dst += 1;
2531 }
2532 src += 2;
2533 }
2534 //*dst += padding;
2535 src += srcPadding;
2536 }
2537 }
2538 else if (stricmp(srcEncoding, "32FC1") == 0) {
2539 if (minVal < maxVal)
2540 scaleFactor = 1 / (maxVal - minVal)*255.0;
2541 else
2542 scaleFactor = 1;
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);
2547 dst[3] = 0;
2548 dst += 4;
2549 }
2550 else if (dstPixelSize == 3) {
2551 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2552 dst += 3;
2553 }
2554 else if (dstPixelSize == 1) {
2555 *dst = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2556 dst += 1;
2557 }
2558 src += 4;
2559 }
2560 //*dst += padding;
2561 src += srcPadding;
2562 }
2563 }
2564 else if (stricmp(srcEncoding, "8PC1") == 0) {
2565 if (minVal < maxVal)
2566 scaleFactor = 1 / (maxVal - 0)*255.0;
2567 else
2568 scaleFactor = 1;
2569 for (l = 0; l < height; l++) {
2570 for (c = 0; c < width; c++) {
2571
2572 if (dstPixelSize == 4) {
2573 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2574 if (*(int8*)src >= 0) {
2575 dst[0] = 0;
2576 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2577 }
2578 else {
2579 dst[0] = 50;
2580 dst[1] = 0;
2581 }
2582 dst[2] = 0;
2583 dst[3] = 0;
2584 dst += 4;
2585 }
2586 else if (dstPixelSize == 3) {
2587 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2588 if (*(int8*)src >= 0) {
2589 dst[0] = 0;
2590 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2591 }
2592 else {
2593 dst[0] = 50;
2594 dst[1] = 0;
2595 }
2596 dst[2] = 0;
2597 dst += 3;
2598 }
2599 else if (dstPixelSize == 1) {
2600 *dst = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2601 if (*(int8*)src >= 0) {
2602 *dst = (uint8)(((*(int8*)src)) * scaleFactor);
2603 }
2604 else {
2605 *dst = 50;
2606 }
2607 dst += 1;
2608 }
2609 src += 1;
2610 }
2611 //*dst += padding;
2612 src += srcPadding;
2613 }
2614 }
2615 else if (stricmp(srcEncoding, "8PC1R") == 0) {
2616 if (minVal < maxVal)
2617 scaleFactor = 1 / (maxVal - 0)*255.0;
2618 else
2619 scaleFactor = 1;
2620 // read src vertically bottom up
2621 src = data + ((height - 1) * linestep) - srcPadding;
2622
2623 for (l = 0; l < height; l++) {
2624 for (c = 0; c < width; c++) {
2625
2626 if (dstPixelSize == 4) {
2627 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2628 if (*(int8*)src >= 0) {
2629 dst[0] = 0;
2630 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2631 }
2632 else {
2633 dst[0] = 50;
2634 dst[1] = 0;
2635 }
2636 dst[2] = 0;
2637 dst[3] = 0;
2638 dst += 4;
2639 }
2640 else if (dstPixelSize == 3) {
2641 *dst = dst[1] = dst[2] = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2642 if (*(int8*)src >= 0) {
2643 dst[0] = 0;
2644 dst[1] = (uint8)(((*(int8*)src)) * scaleFactor);
2645 }
2646 else {
2647 dst[0] = 50;
2648 dst[1] = 0;
2649 }
2650 dst[2] = 0;
2651 dst += 3;
2652 }
2653 else if (dstPixelSize == 1) {
2654 *dst = (uint8)(((*(float32*)src) - minVal) * scaleFactor);
2655 if (*(int8*)src >= 0) {
2656 *dst = (uint8)(((*(int8*)src)) * scaleFactor);
2657 }
2658 else {
2659 *dst = 50;
2660 }
2661 dst += 1;
2662 }
2663 src += 1;
2664 }
2665 //*dst += padding;
2666 //src += srcPadding;
2667 src -= linestep + linestep - srcPadding;
2668 }
2669 }
2670 else if (stricmp(srcEncoding, "bgr8") == 0) {
2671 for (l = 0; l < height; l++) {
2672 x = 0;
2673 for (c = 0; c < width; c++) {
2674 if (dstPixelSize == 4) {
2675 *dst++ = src[x + 2];
2676 *dst++ = src[x + 1];
2677 *dst++ = src[x];
2678 *dst++ = 0;
2679 }
2680 else if (dstPixelSize == 3) {
2681 *dst++ = src[x + 2];
2682 *dst++ = src[x + 1];
2683 *dst++ = src[x];
2684 }
2685 else if (dstPixelSize == 1) {
2686 *dst++ = (uint8)(((uint32)src[x] + (uint32)src[x + 1] + (uint32)src[x + 2]) / 3);
2687 }
2688 x += srcPixelSize;
2689 }
2690 //*dst += padding;
2691 src += linestep;
2692 }
2693 }
2694 else if (srcPixelSize >= 3) {
2695 for (l = 0; l < height; l++) {
2696 x = 0;
2697 for (c = 0; c < width; c++) {
2698 if (dstPixelSize == 4) {
2699 *dst++ = src[x];
2700 *dst++ = src[x + 1];
2701 *dst++ = src[x + 2];
2702 *dst++ = 0;
2703 }
2704 else if (dstPixelSize == 3) {
2705 *dst++ = src[x];
2706 *dst++ = src[x + 1];
2707 *dst++ = src[x + 2];
2708 }
2709 else if (dstPixelSize == 1) {
2710 *dst++ = (uint8)(((uint32)src[x] + (uint32)src[x + 1] + (uint32)src[x + 2])/3);
2711 }
2712 x += srcPixelSize;
2713 }
2714 //*dst += padding;
2715 src += linestep;
2716 }
2717 }
2718 else if (srcPixelSize == 2) {
2719 for (l = 0; l < height; l++) {
2720 x = 0;
2721 for (c = 0; c < width; c++) {
2722 if (dstPixelSize == 4) {
2723 *dst++ = 0;
2724 *dst++ = src[x + 1];
2725 *dst++ = src[x];
2726 *dst++ = 0;
2727 }
2728 else if (dstPixelSize == 3) {
2729 *dst++ = 0;
2730 *dst++ = src[x + 1];
2731 *dst++ = src[x];
2732 }
2733 else if (dstPixelSize == 1) {
2734 *dst++ = (uint8)(((uint32)src[x] + (uint32)src[x + 1]) / 2);
2735 }
2736 x += srcPixelSize;
2737 }
2738 //*dst += padding;
2739 src += linestep;
2740 }
2741 }
2742 else if (srcPixelSize == 1) {
2743 for (l = 0; l < height; l++) {
2744 x = 0;
2745 for (c = 0; c < width; c++) {
2746 if (dstPixelSize == 4) {
2747 *dst++ = src[x];
2748 *dst++ = src[x];
2749 *dst++ = src[x];
2750 *dst++ = 0;
2751 }
2752 else if (dstPixelSize == 3) {
2753 *dst++ = src[x];
2754 *dst++ = src[x];
2755 *dst++ = src[x];
2756 }
2757 else if (dstPixelSize == 1) {
2758 *dst++ = src[x];
2759 }
2760 x += srcPixelSize;
2761 }
2762 //*dst += padding;
2763 src += linestep;
2764 }
2765 }
2766
2767 return buffer;
2768}
2769
2770
2772// Math Helper Routines
2774
2775int Bitmap::round(double d) {
2776
2777 double f = floor(d);
2778
2779 if ((d - f) < 0.5000)
2780 return (int) f;
2781 else
2782 return (int) (f+1);
2783}
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807//HTMLPage* Bitmap::toHTMLBitmap() {
2808// return new HTMLPage(this);
2809//}
2810//
2811//JString Bitmap::toHTML() {
2812// return JString::format("Bitmap size %d bytes, time %s", size, (char*) timestamp.print());
2813//}
2814//
2815//
2816//JString Bitmap::toXML() {
2817// return "<bitmap />";
2818//}
2819//
2820//bool Bitmap::fromXML(XMLNode* node) {
2821//
2822// if (node == NULL)
2823// return false;
2824//
2825// if (!node->getTag().equalsIgnoreCase("bitmap"))
2826// return false;
2827//
2828// return true;
2829//}
2830//
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850bool Bitmap::convertBitmapFileData(const char* src, uint32 width, uint32 height, uint32 depth, char* dst, uint32 dstlen) {
2851
2852 uint32 c;
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);
2858
2859 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
2860 unsigned int* newdst = (unsigned int*) dst;
2861
2862 for (uint32 l = 0; l < height; l++)
2863 {
2864 for (c = 0; c < width; c++) {
2865 *(newdst++) = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
2866 newsrc += depth;
2867 }
2868 newsrc += offset;
2869 }
2870
2871 return true;
2872}
2873
2874char* Bitmap::convertBitmapFileDataRunLength(const char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen) {
2875
2876// src = "012345678900000000001234567890";
2877// height = 1;
2878// width = 30;
2879
2880 char* dst = new char[width*height*4 + 100];
2881
2882 uint32 c;
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);
2887
2888 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
2889 uint32* newdst = (unsigned int*) dst;
2890 uint32* lastCtrl = newdst;
2891
2892 uint32 pos = 1;
2893 uint32 length = 0;
2894
2895 bool isInRL = false;
2896
2897// int n;
2898/* for (n=0; n<30; n++) {
2899 printf("[ %c] ", (char)src[n]);
2900 }
2901 printf("\n");*/
2902
2903 //int len = 0;
2904
2905 for (uint32 l = 0; l < height; l++)
2906 {
2907 for (c = 0; c < width; c++) {
2908 newdst[pos] = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
2909
2910 if (isInRL) {
2911 if (newdst[pos-1] == newdst[pos]) {
2912 // Continue RL
2913 pos--;
2914 }
2915 else {
2916 // End RL
2917 *lastCtrl = (uint32)((RLECTRL << 24) | length);
2918 // len += length;
2919 length = 0;
2920 lastCtrl += 2;
2921 pos++;
2922 newdst[pos] = newdst[pos-1];
2923 isInRL = false;
2924 }
2925 }
2926 else {
2927 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
2928 if (length == 2) {
2929 // No data series, switch to RL
2930 pos -= 2;
2931 }
2932 else {
2933 // Close previous series
2934 *lastCtrl = (uint32)((DATACTRL << 24) | (length - 2));
2935 // len += length - 2;
2936 lastCtrl += length - 1;
2937 length = 2;
2938 pos--;
2939 }
2940 isInRL = true;
2941 }
2942 else {
2943 // Just continue
2944 }
2945 }
2946 pos++;
2947 length++;
2948 newsrc += depth;
2949 }
2950 newsrc += offset;
2951 }
2952 if (isInRL) {
2953 *lastCtrl = (uint32)((RLECTRL << 24) | length);
2954 // len += length;
2955 }
2956 else {
2957 *lastCtrl = (uint32)((DATACTRL << 24) | length);
2958 // len += length;
2959 }
2960 dstlen = pos * 4;
2961
2962/* for (n=0; n<30; n++) {
2963 printf("[ %c] ", (char)dst[n]);
2964 }
2965 printf("\n");*/
2966
2967/* int ctrl;
2968 len = 0;
2969 int totallen = 0;
2970 pos = 0;
2971 while (pos < (dstlen/4)) {
2972 ctrl = (newdst[pos] >> 24);
2973 len = (newdst[pos] & 0xFFFFFF);
2974 pos++;
2975 if (ctrl == 1) {
2976 // printf("Data[%d] ", len);
2977 // for (int k=0; k<len; k++)
2978 // printf("%c ", (char) newdst[pos+k]);
2979 totallen += len;
2980 pos += len;
2981 }
2982 else if (ctrl == 2) {
2983// printf("RLE[%d] %d ", len, (int) newdst[pos]);
2984 totallen += len;
2985 pos++;
2986 }
2987 else {
2988 printf("Wrong CTRL: %d ", ctrl);
2989 pos++;
2990 }
2991 }
2992*/
2993
2994/* pos = 0;
2995 totallen = 0;
2996 while (pos < dstlen) {
2997 ctrl = (newdst[pos] >> 24);
2998 len = (newdst[pos] & 0xFFFFFF);
2999 pos++;
3000 if (ctrl == 1) {
3001 totallen += len;
3002 printf("Data[%d] (%d) ", len, totallen);
3003 // for (int k=0; k<len; k++)
3004 // printf("%c ", (char) newdst[pos+k]);
3005 pos += len;
3006 }
3007 else if (ctrl == 2) {
3008 totallen += len;
3009 printf("RLE[%d] (%d) ", len, totallen);
3010 pos++;
3011 }
3012 else {
3013 printf("Wrong CTRL: %d ", ctrl);
3014 pos++;
3015 }
3016 }
3017*/
3018
3019 return dst;
3020}
3021
3022char* Bitmap::differenceBitmapFileData(char* orig, char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen) {
3023
3024/* orig = "987654321100000000009876543211";
3025 src = "012345678900000000001234567890";
3026 height = 1;
3027 width = 30;
3028*/
3029 char* dst = new char[width*height*4 + 100];
3030
3031 uint32 c;
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);
3036
3037 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
3038 uint32* newdst = (uint32*) dst;
3039 uint32* org = (uint32*) orig;
3040 // unsigned char* org = (unsigned char*) orig;
3041 uint32* lastCtrl = newdst;
3042
3043 uint32 pos = 1;
3044 uint32 length = 0;
3045 uint32 dlength = 0;
3046
3047 bool isInDif = false;
3048
3049/* int n;
3050 for (n=0; n<30; n++) {
3051 newdst[n] = 0;
3052 }*/
3053
3054 //int len = 0;
3055 for (uint32 l = 0; l < height; l++)
3056 {
3057 for (c = 0; c < width; c++) {
3058 newdst[pos] = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
3059 // newdst[pos] = src[c];
3060
3061 /* for (n=0; n<30; n++) {
3062 printf("[%.2d] ", newdst[n]);
3063 }
3064 printf("\n");*/
3065
3066 if (isInDif) {
3067 if (*org == newdst[pos]) {
3068 // Continue Dif
3069 pos--;
3070 }
3071 else {
3072 // End Dif
3073 *lastCtrl = (uint32)((DIFCTRL << 24) | length);
3074 // len += length;
3075 length = 0;
3076 lastCtrl++;
3077 pos++;
3078 newdst[pos] = newdst[pos-1];
3079 isInDif = false;
3080 }
3081 }
3082 else {
3083 if (*org == newdst[pos]) {
3084 if (pos == 1) {
3085 pos--;
3086 isInDif = true;
3087 }
3088 else {
3089 // Close previous series
3090 *lastCtrl = (uint32)((DATACTRL << 24) | (length));
3091 // len += length;
3092 lastCtrl += length + 1;
3093 length = 0;
3094 // pos--;
3095 isInDif = true;
3096 }
3097 }
3098 else {
3099 // Just continue
3100 }
3101 }
3102 pos++;
3103 length++;
3104 newsrc += depth;
3105 org++;
3106 }
3107 newsrc += offset;
3108 }
3109 if (isInDif) {
3110 *lastCtrl = (uint32)((DIFCTRL << 24) | length);
3111 // len += length;
3112 }
3113 else {
3114 *lastCtrl = (uint32)((DATACTRL << 24) | length);
3115 // len += length;
3116 }
3117 dstlen = pos * 4;
3118
3119
3120/* pos = 0;
3121 int totallen = 0;
3122 int ctrl;
3123 while (pos < (dstlen/4)) {
3124 ctrl = (newdst[pos] >> 24);
3125 len = (newdst[pos] & 0xFFFFFF);
3126 pos++;
3127 if (ctrl == 1) {
3128 totallen += len;
3129 printf("Data[%d] (%d) ", len, totallen);
3130 // for (int k=0; k<len; k++)
3131 // printf("%c ", (char) newdst[pos+k]);
3132 pos += len;
3133 }
3134 else if (ctrl == 2) {
3135 totallen += len;
3136 printf("RLE[%d] (%d) ", len, totallen);
3137 pos++;
3138 }
3139 else if (ctrl == 3) {
3140 totallen += len;
3141 printf("RLE[%d] (%d) ", len, totallen);
3142 // pos++;
3143 }
3144 else {
3145 printf("Wrong CTRL: %d ", ctrl);
3146 pos++;
3147 }
3148 }*/
3149
3150 return dst;
3151}
3152
3153char* Bitmap::differenceBitmapFileDataRunLength(char* orig, char* src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen) {
3154
3155 char* dst = new char[width*height*4 + 100];
3156
3157 uint32 c;
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);
3162
3163 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
3164 uint32* newdst = (uint32*) dst;
3165 uint32* org = (uint32*) orig;
3166 uint32* lastCtrl = newdst;
3167
3168 uint32 pos = 1;
3169 uint32 length = 0;
3170 uint32 dlength = 0;
3171
3172 bool isInRL = false;
3173 bool isInDif = false;
3174
3175// int len = 0;
3176 for (uint32 l = 0; l < height; l++)
3177 {
3178 for (c = 0; c < width; c++) {
3179 newdst[pos] = ((uint32)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
3180
3181 if (isInDif) {
3182 if (*org == newdst[pos]) {
3183 // Continue Dif
3184 pos--;
3185 }
3186 else {
3187 // End Dif
3188 *lastCtrl = (uint32)((DIFCTRL << 24) | length);
3189 //len += length;
3190 length = 0;
3191 lastCtrl++;
3192 pos++;
3193 newdst[pos] = newdst[pos-1];
3194 isInDif = false;
3195 }
3196 }
3197 else if (isInRL) {
3198 if (newdst[pos-1] == newdst[pos]) {
3199 // Continue RL
3200 pos--;
3201 }
3202 else {
3203 // End RL
3204 *lastCtrl = (uint32)((RLECTRL << 24) | length);
3205 //len += length;
3206 length = 0;
3207 lastCtrl += 2;
3208 pos++;
3209 newdst[pos] = newdst[pos-1];
3210 isInRL = false;
3211 }
3212 }
3213 else {
3214 if (*org == newdst[pos]) {
3215 if (pos == 1) {
3216 pos--;
3217 }
3218 else {
3219 // Close previous series
3220 *lastCtrl = (uint32)((DATACTRL << 24) | (length));
3221 // len += length;
3222 lastCtrl += length + 1;
3223 length = 0;
3224 // pos--;
3225 }
3226 isInDif = true;
3227 }
3228 else if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3229 if (length == 2) {
3230 // No data series, switch to RL
3231 pos -= 2;
3232 }
3233 else {
3234 // Close previous series
3235 *lastCtrl = (uint32)((DATACTRL << 24) | (length - 2));
3236 // len += length - 2;
3237 lastCtrl += length - 1;
3238 length = 2;
3239 pos--;
3240 }
3241 isInRL = true;
3242 }
3243 else {
3244 // Just continue
3245 }
3246 }
3247 pos++;
3248 length++;
3249 org++;
3250 newsrc += depth;
3251 }
3252 newsrc += offset;
3253 }
3254 if (isInDif) {
3255 *lastCtrl = (uint32)((DIFCTRL << 24) | length);
3256 // len += length;
3257 }
3258 else if (isInRL) {
3259 *lastCtrl = (uint32)((RLECTRL << 24) | length);
3260 // len += length;
3261 }
3262 else {
3263 *lastCtrl = (uint32)((DATACTRL << 24) | length);
3264 // len += length;
3265 }
3266 dstlen = pos * 4;
3267
3268 return dst;
3269}
3270
3272 if (!destructive)
3273 return runLengthEncode();
3274 else
3276}
3277
3278
3279BitmapUpdate* Bitmap::operator -( const Bitmap &bitmap ) const {
3280
3281 if ( (this->width != bitmap.width) || (this->height != bitmap.height) )
3282 return NULL;
3283
3284 int byteWidth = width*4;
3285
3286 char* dst = new char[width*height*4 + 100];
3287
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;
3292
3293 int pos = 1;
3294// int pos = 0;
3295 int length = 0;
3296
3297 bool isInRL = false;
3298 bool isInDif = false;
3299
3300 int maxpos = (int)(width*height*0.9);
3301 unsigned int* endsrc = newsrc + (width*height);
3302 while ((newsrc < endsrc) && (pos <= maxpos)) {
3303
3304 newdst[pos] = *newsrc;
3305
3306 if (isInDif) {
3307 if (*org == newdst[pos]) {
3308 // Continue Dif
3309 pos--;
3310 }
3311 else {
3312 // End Dif
3313 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
3314 //len += length;
3315 length = 0;
3316 lastCtrl++;
3317 pos++;
3318 newdst[pos] = newdst[pos-1];
3319 isInDif = false;
3320 }
3321 }
3322 else if (isInRL) {
3323 if (newdst[pos-1] == newdst[pos]) {
3324 // Continue RL
3325 pos--;
3326 }
3327 else {
3328 // End RL
3329 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3330 //len += length;
3331 length = 0;
3332 lastCtrl += 2;
3333 pos++;
3334 newdst[pos] = newdst[pos-1];
3335 isInRL = false;
3336 }
3337 }
3338 else {
3339 if (*org == newdst[pos]) {
3340 if (pos == 1) {
3341 pos--;
3342 }
3343 else {
3344 // Close previous series
3345 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length));
3346 // len += length;
3347 lastCtrl += length + 1;
3348 length = 0;
3349 // pos--;
3350 }
3351 isInDif = true;
3352 }
3353 else if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3354 if (length == 2) {
3355 // No data series, switch to RL
3356 pos -= 2;
3357 }
3358 else {
3359 // Close previous series
3360 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
3361 // len += length - 2;
3362 lastCtrl += length - 1;
3363 length = 2;
3364 pos--;
3365 }
3366 isInRL = true;
3367 }
3368 else {
3369 // Just continue
3370 }
3371 }
3372 pos++;
3373 length++;
3374 org++;
3375 newsrc++;
3376 }
3377
3378 // Forget it, difference is too big anyway...
3379 if (pos > maxpos) {
3380 delete [] dst;
3381 return this->getCompressedUpdate(false);
3382 }
3383
3384
3385 if (isInDif) {
3386 if (pos <= 1) {
3387 delete [] dst;
3388 return NULL;
3389 }
3390 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
3391 // len += length;
3392 }
3393 else if (isInRL) {
3394 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3395 // len += length;
3396 }
3397 else {
3398 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
3399 // len += length;
3400 }
3401
3402 BitmapUpdate* update = new BitmapUpdate(width, height);
3403 update->data = dst;
3404 update->size = pos * 4;
3406 return update;
3407}
3408
3409
3410
3411
3412
3414
3415 if ( (this->width <= 0) || (this->height <= 0) )
3416 return NULL;
3417
3418 int byteWidth = width*4;
3419
3420 char* dst = new char[width*height*4 + 100];
3421
3422 unsigned int* newsrc = (unsigned int*) this->data;
3423 unsigned int* newdst = (unsigned int*) dst;
3424 unsigned int* lastCtrl = newdst;
3425
3426 int pos = 1;
3427// int pos = 0;
3428 int length = 0;
3429
3430 bool isInRL = false;
3431
3432 unsigned int* endsrc = newsrc + (width*height);
3433
3434 while (newsrc < endsrc) {
3435 newdst[pos] = *newsrc;
3436
3437 if (isInRL) {
3438 if (newdst[pos-1] == newdst[pos]) {
3439 // Continue RL
3440 pos--;
3441 }
3442 else {
3443 // End RL
3444 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3445 //len += length;
3446 length = 0;
3447 lastCtrl += 2;
3448 pos++;
3449 newdst[pos] = newdst[pos-1];
3450 isInRL = false;
3451 }
3452 }
3453 else {
3454 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3455 if (length == 2) {
3456 // No data series, switch to RL
3457 pos -= 2;
3458 }
3459 else {
3460 // Close previous series
3461 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
3462 // len += length - 2;
3463 lastCtrl += length - 1;
3464 length = 2;
3465 pos--;
3466 }
3467 isInRL = true;
3468 }
3469 else {
3470 // Just continue
3471 }
3472 }
3473 pos++;
3474 length++;
3475 newsrc++;
3476 }
3477
3478 if (isInRL) {
3479 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3480 // len += length;
3481 }
3482 else {
3483 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
3484 // len += length;
3485 }
3486
3487 BitmapUpdate* update = new BitmapUpdate(width, height);
3488 update->data = dst;
3489 update->size = pos * 4;
3491 return update;
3492}
3493
3495
3496 if ( (this->width <= 0) || (this->height <= 0) )
3497 return NULL;
3498
3499 int byteWidth = width*4;
3500
3501 char* dst = new char[width*height*2 + 100];
3502
3503 unsigned int* newsrc = (unsigned int*) this->data;
3504 unsigned int* newdst = (unsigned int*) dst;
3505 unsigned int* lastCtrl = newdst;
3506
3507 int pos = 1;
3508// int pos = 0;
3509 int length = 0;
3510
3511 bool isInRL = false;
3512
3513 unsigned int* endsrc = newsrc + (width*height);
3514 unsigned int* endsrc1 = endsrc - 2;
3515
3516 while (newsrc < endsrc1) {
3517 newdst[pos] = GET_DRGB_FROM_2RGBS(*newsrc,*(newsrc+1));
3518 newsrc+=2;
3519 if (isInRL) {
3520 if (newdst[pos-1] == newdst[pos]) {
3521 // Continue RL
3522 pos--;
3523 }
3524 else {
3525 // End RL
3526 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3527 //len += length;
3528 length = 0;
3529 lastCtrl += 2;
3530 pos++;
3531 newdst[pos] = newdst[pos-1];
3532 isInRL = false;
3533 }
3534 }
3535 else {
3536 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3537 if (length == 2) {
3538 // No data series, switch to RL
3539 pos -= 2;
3540 }
3541 else {
3542 // Close previous series
3543 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
3544 // len += length - 2;
3545 lastCtrl += length - 1;
3546 length = 2;
3547 pos--;
3548 }
3549 isInRL = true;
3550 }
3551 else {
3552 // Just continue
3553 }
3554 }
3555 pos++;
3556 length++;
3557 // newsrc+=2;
3558 }
3559 if (endsrc-newsrc == 2)
3560 newdst[pos] = GET_DRGB_FROM_2RGBS(*newsrc,*(newsrc+1));
3561 else
3562 newdst[pos] = GET_DRGB_FROM_2RGBS(*newsrc,0);
3563
3564 if (isInRL) {
3565 if (newdst[pos-1] == newdst[pos]) {
3566 // Continue RL
3567 pos--;
3568 }
3569 else {
3570 // End RL
3571 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3572 //len += length;
3573 length = 0;
3574 lastCtrl += 2;
3575 pos++;
3576 newdst[pos] = newdst[pos-1];
3577 isInRL = false;
3578 }
3579 }
3580 else {
3581 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
3582 if (length == 2) {
3583 // No data series, switch to RL
3584 pos -= 2;
3585 }
3586 else {
3587 // Close previous series
3588 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
3589 // len += length - 2;
3590 lastCtrl += length - 1;
3591 length = 2;
3592 pos--;
3593 }
3594 isInRL = true;
3595 }
3596 else {
3597 // Just continue
3598 }
3599 }
3600 pos++;
3601 length++;
3602 newsrc+=2;
3603
3604 if (isInRL) {
3605 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
3606 // len += length;
3607 }
3608 else {
3609 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
3610 // len += length;
3611 }
3612
3613 BitmapUpdate* update = new BitmapUpdate(width, height);
3614 update->data = dst;
3615 update->size = pos * 4;
3617 return update;
3618}
3619
3620
3621
3622char* ImageResizeDown66(char* bytesource, uint32 &cols, uint32 &rows)
3623{
3624
3625 // This algorithm was written for single byte images,
3626 // we need this for 4 byte images, or integers
3627
3628 char* bytedest = new char[cols*rows*4];
3629
3630 unsigned int* source = (unsigned int*) bytesource;
3631 unsigned int* dest = (unsigned int*) bytedest;
3632
3633 // Pointer arrangment
3634 // p q r -> a b
3635 // s t u c d
3636 // v w x
3637
3638 unsigned int *p;
3639 unsigned int *q;
3640 unsigned int *r;
3641 unsigned int *s;
3642 unsigned int *t;
3643 unsigned int *u;
3644 unsigned int *v;
3645 unsigned int *w;
3646 unsigned int *x;
3647 unsigned int *a;
3648 unsigned int *b;
3649 unsigned int *c;
3650 unsigned int *d;
3651
3652 unsigned int** shrows = new unsigned int*[rows];
3653
3654 shrows[0] = source;
3655 for (uint32 n=1; n<rows; n++) {
3656 shrows[n] = shrows[n-1] + cols;
3657 }
3658
3659 q = shrows[0] + 1;
3660 s = shrows[1];
3661 t = s + 1;
3662 u = t + 1;
3663 w = shrows[2] + 1;
3664
3665 // Smooth - skip first and last rows, first and last cols
3666 // This is a bit of a cheat since the left pixel of each group
3667 // is smoothed with an already-smoothed pixel
3668 // ------------------------------------------------------
3669
3670 /* for(int i = 1; i < rows-1; i++)
3671 {
3672 q = shrows[i-1] + 1;
3673 s = shrows[i];
3674 t = s + 1;
3675 u = t + 1;
3676 w = shrows[i+1] + 1;
3677
3678 for(int j = 0; j < cols; j++, q++, s++, t++, u++, w++)
3679 *t = (AGPIXEL)(((int)(*q) + (int)(*w) + 4 * (int)(*t)) / 6);
3680 }
3681 */
3682
3683 // Now for the resizing
3684 // --------------------
3685
3686 int newcols = (int)((2.0*cols)/3.0);
3687 int newrows = (int)((2.0*rows)/3.0);
3688
3689 if (newcols != (2.0*cols/3.0))
3690 newcols++;
3691 if (newrows != (2.0*cols/3.0))
3692 newrows++;
3693
3694 unsigned int *r1 = dest;
3695 unsigned int *r2 = dest + newcols;
3696
3697 // printf("RESIZE\n Rows: %-3d->%-3d\n Cols %-3d->%-3d\n", rows, newrows, cols, newcols);
3698
3699 uint32 j;
3700 for(uint32 i = 0, k = 0; i < rows; i += 3, k += 2) {
3701 p = shrows[i];
3702 q = p+1;
3703 r = q+1;
3704 if (rows - i > 2)
3705 s = shrows[i+1];
3706 else
3707 s = p;
3708 t = s+1;
3709 u = t+1;
3710 if (rows - i > 2)
3711 v = shrows[i+2];
3712 else
3713 v = p;
3714 w = v+1;
3715 x = w+1;
3716
3717 // r1 = PIXEL[k];
3718 r1 = dest + (newcols * k);
3719 // r2 = r1+ cols64;
3720 r2 = r1 + newcols;
3721
3722 a = r1;
3723 b = a+1;
3724 if (newrows - k < 1)
3725 c = a;
3726 else
3727 c = r2;
3728 d = c+1;
3729
3730 for(j = 0; j < cols-3; j += 3) {
3731 *a = GET_RGB_FROM_RGBA(*p);
3732 *b = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*q) + (double)GET_R_FROM_RGBA(*r))/2)) << 0) +
3733 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*q) + (double)GET_G_FROM_RGBA(*r))/2)) << 8) +
3734 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*q) + (double)GET_B_FROM_RGBA(*r))/2)) << 16);
3735 *c = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*s) + (double)GET_R_FROM_RGBA(*v))/2)) << 0) +
3736 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*s) + (double)GET_G_FROM_RGBA(*v))/2)) << 8) +
3737 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*s) + (double)GET_B_FROM_RGBA(*v))/2)) << 16);
3738 *d = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*t) + (double)GET_R_FROM_RGBA(*u) + (double)GET_R_FROM_RGBA(*w) + (double)GET_R_FROM_RGBA(*x))/4)) << 0) +
3739 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*t) + (double)GET_G_FROM_RGBA(*u) + (double)GET_G_FROM_RGBA(*w) + (double)GET_G_FROM_RGBA(*x))/4)) << 8) +
3740 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*t) + (double)GET_B_FROM_RGBA(*u) + (double)GET_B_FROM_RGBA(*w) + (double)GET_B_FROM_RGBA(*x))/4)) << 16);
3741
3742 p += 3;
3743 q += 3;
3744 r += 3;
3745 s += 3;
3746 t += 3;
3747 u += 3;
3748 v += 3;
3749 w += 3;
3750 x += 3;
3751 a += 2;
3752 b += 2;
3753 c += 2;
3754 d += 2;
3755 }
3756 if (cols - j > 0)
3757 *a = GET_RGB_FROM_RGBA(*p);
3758 else
3759 *a = *(a-2);
3760 if (cols - j > 1)
3761 *b = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*q) + (double)GET_R_FROM_RGBA(*r))/2)) << 0) +
3762 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*q) + (double)GET_G_FROM_RGBA(*r))/2)) << 8) +
3763 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*q) + (double)GET_B_FROM_RGBA(*r))/2)) << 16);
3764 else
3765 *b = *(b-2);
3766 if (cols - j > 2)
3767 *c = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*s) + (double)GET_R_FROM_RGBA(*v))/2)) << 0) +
3768 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*s) + (double)GET_G_FROM_RGBA(*v))/2)) << 8) +
3769 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*s) + (double)GET_B_FROM_RGBA(*v))/2)) << 16);
3770 else
3771 *c = *(c-2);
3772 if (cols - j > 3)
3773 *d = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*t) + (double)GET_R_FROM_RGBA(*u) + (double)GET_R_FROM_RGBA(*w) + (double)GET_R_FROM_RGBA(*x))/4)) << 0) +
3774 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*t) + (double)GET_G_FROM_RGBA(*u) + (double)GET_G_FROM_RGBA(*w) + (double)GET_G_FROM_RGBA(*x))/4)) << 8) +
3775 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*t) + (double)GET_B_FROM_RGBA(*u) + (double)GET_B_FROM_RGBA(*w) + (double)GET_B_FROM_RGBA(*x))/4)) << 16);
3776 else
3777 *d = *(d-2);
3778
3779 }
3780// printf("Resize done");
3781 delete [] shrows;
3782 cols = newcols;
3783 rows = newrows;
3784 return bytedest;
3785}
3786
3787char* ImageResizeUp66(char* bytesource, uint32 &cols, uint32 &rows) {
3788
3789 // This algorithm was written for single byte images,
3790 // we need this for 4 byte images, or integers
3791
3792 // Pointer arrangment
3793 // p q r -> a b
3794 // s t u c d
3795 // v w x
3796
3797 unsigned int *p;
3798 unsigned int *q;
3799 unsigned int *r;
3800 unsigned int *s;
3801 unsigned int *t;
3802 unsigned int *u;
3803 unsigned int *v;
3804 unsigned int *w;
3805 unsigned int *x;
3806 unsigned int *a;
3807 unsigned int *b;
3808 unsigned int *c;
3809 unsigned int *d;
3810
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)
3814 newcols++;
3815 if ((double)newrows != (3.0*rows)/2.0)
3816 newrows++;
3817
3818 char* bytedest = new char[newcols*newrows*4];
3819 unsigned int* source = (unsigned int*) bytesource;
3820 unsigned int* dest = (unsigned int*) bytedest;
3821
3822 unsigned int** dhrows = new unsigned int*[newrows];
3823
3824 dhrows[0] = dest;
3825 for (int n=1; n<newrows; n++) {
3826 dhrows[n] = dhrows[n-1] + newcols;
3827 }
3828
3829 q = dhrows[0] + 1;
3830 s = dhrows[1];
3831 t = s + 1;
3832 u = t + 1;
3833 w = dhrows[2] + 1;
3834
3835 // Now for the resizing
3836 // --------------------
3837
3838
3839 unsigned int *r1 = source;
3840 unsigned int *r2 = source + cols;
3841
3842 // printf("RESIZE\n Rows: %-3d->%-3d\n Cols %-3d->%-3d\n", rows, newrows, cols, newcols);
3843
3844 int realrows = newrows-3;
3845 int realcols = newcols-3;
3846// int ii, kk, jj;
3847 int i, j, k;
3848 for(i = 0, k = 0; i <= realrows; i += 3, k += 2) {
3849 p = dhrows[i];
3850 q = p+1;
3851 r = q+1;
3852 s = dhrows[i+1];
3853 t = s+1;
3854 u = t+1;
3855 v = dhrows[i+2];
3856 w = v+1;
3857 x = w+1;
3858
3859 // r1 = PIXEL[k];
3860 r1 = source + (cols * k);
3861 // r2 = r1+ cols64;
3862 r2 = r1 + cols;
3863
3864 a = r1;
3865 b = a+1;
3866 c = r2;
3867 d = c+1;
3868
3869 for(j = 0; j <= realcols; j += 3) {
3870 *p = GET_RGB_FROM_RGBA(*a);
3871 *q = *r = GET_RGB_FROM_RGBA(*b);
3872 *s = *v = GET_RGB_FROM_RGBA(*c);
3873 *t = *u = *w = *x = GET_RGB_FROM_RGBA(*d);;
3874 p += 3;
3875 q += 3;
3876 r += 3;
3877 s += 3;
3878 t += 3;
3879 u += 3;
3880 v += 3;
3881 w += 3;
3882 x += 3;
3883 a += 2;
3884 b += 2;
3885 c += 2;
3886 d += 2;
3887 }
3888 if (newcols - j == 2) {
3889 *p = GET_RGB_FROM_RGBA(*a);
3890 *q= GET_RGB_FROM_RGBA(*b);
3891 *s = *v = GET_RGB_FROM_RGBA(*c);
3892 *t= *w = GET_RGB_FROM_RGBA(*d);;
3893 }
3894 else if (newcols - j == 1) {
3895 *p = GET_RGB_FROM_RGBA(*a);
3896 *s = *v = GET_RGB_FROM_RGBA(*c);
3897 }
3898 }
3899 if (newrows - i == 2) {
3900 p = dhrows[i];
3901 q = p+1;
3902 r = q+1;
3903 s = dhrows[i+1];
3904 t = s+1;
3905 u = t+1;
3906
3907 // r1 = PIXEL[k];
3908 r1 = source + (cols * k);
3909 // r2 = r1+ cols64;
3910 r2 = r1 + cols;
3911
3912 a = r1;
3913 b = a+1;
3914 c = r2;
3915 d = c+1;
3916
3917 for(j = 0; j <= realcols; j += 3) {
3918 *p = GET_RGB_FROM_RGBA(*a);
3919 *q = *r = GET_RGB_FROM_RGBA(*b);
3920 *s = GET_RGB_FROM_RGBA(*c);
3921 *t = *u = GET_RGB_FROM_RGBA(*d);;
3922 p += 3;
3923 q += 3;
3924 r += 3;
3925 s += 3;
3926 t += 3;
3927 u += 3;
3928 v += 3;
3929 w += 3;
3930 x += 3;
3931 a += 2;
3932 b += 2;
3933 c += 2;
3934 d += 2;
3935 }
3936 if (newcols - j == 2) {
3937 *p = GET_RGB_FROM_RGBA(*a);
3938 *q= GET_RGB_FROM_RGBA(*b);
3939 *s =GET_RGB_FROM_RGBA(*c);
3940 *t= GET_RGB_FROM_RGBA(*d);;
3941 }
3942 else if (newcols - j == 1) {
3943 *p = GET_RGB_FROM_RGBA(*a);
3944 *s = GET_RGB_FROM_RGBA(*c);
3945 }
3946 }
3947 else if (newrows - i == 1) {
3948 p = dhrows[i];
3949 q = p+1;
3950 r = q+1;
3951
3952 // r1 = PIXEL[k];
3953 r1 = source + (cols * k);
3954 // r2 = r1+ cols64;
3955 r2 = r1 + cols;
3956
3957 a = r1;
3958 b = a+1;
3959 c = r2;
3960 d = c+1;
3961
3962 for(j = 0; j <= realcols; j += 3) {
3963 *p = GET_RGB_FROM_RGBA(*a);
3964 *q = *r = GET_RGB_FROM_RGBA(*b);
3965 p += 3;
3966 q += 3;
3967 r += 3;
3968 s += 3;
3969 t += 3;
3970 u += 3;
3971 v += 3;
3972 w += 3;
3973 x += 3;
3974 a += 2;
3975 b += 2;
3976 c += 2;
3977 d += 2;
3978 }
3979 if (newcols - j == 2) {
3980 *p = GET_RGB_FROM_RGBA(*a);
3981 *q= GET_RGB_FROM_RGBA(*b);
3982 }
3983 else if (newcols - j == 1) {
3984 *p = GET_RGB_FROM_RGBA(*a);
3985 }
3986 }
3987// printf("Resize done");
3988 delete [] dhrows;
3989 cols = newcols;
3990 rows = newrows;
3991 return bytedest;
3992}
3993
3994char* ImageResizeDown(char* bytesource, uint32 &cols, uint32 &rows, uint32 factor) {
3995 if (factor <= 0) {
3996 return NULL;
3997 }
3998 int factor2 = factor*factor;
3999
4000 int newcols = (int)((double)cols/factor);
4001 int newrows = (int)((double)rows/factor);
4002 if ((double)newcols != ((double)cols/factor))
4003 newcols++;
4004 if ((double)newrows != ((double)rows/factor))
4005 newrows++;
4006
4007 char* bytedest = new char[newcols*newrows*4];
4008
4009 if (factor == 1) {
4010 memcpy(bytedest, bytesource, cols*rows*4);
4011 return bytedest;
4012 }
4013
4014 unsigned int* source = (unsigned int*) bytesource;
4015 unsigned int* dest = (unsigned int*) bytedest;
4016
4017 int n, m;
4018// unsigned int* destPixel = dest;
4019 unsigned int* srcStartPixel = source;
4020// unsigned int* srcPixel;
4021 unsigned char* srcPixelByte;
4022
4023 double r;
4024 double g;
4025 double b;
4026 int step = (cols - factor)*4;
4027 int linestep = (factor-1)*cols;
4028
4029 int rowmax = rows-factor;
4030 int colmax = cols-factor;
4031// int rowmax = rows;
4032// int colmax = cols;
4033
4034 int factorX, factorY;
4035
4036 double dfactor2 = 1.0/((double)factor2);
4037
4038 unsigned char* destPixelByte = (unsigned char*) dest;
4039 // Take a square of f*f pixels and average to produce 1 pixel
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);
4044// factorX = factor;
4045 r = g = b = 0;
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++;
4053 srcPixelByte++;
4054 }
4055 srcPixelByte += step;
4056 }
4057 *destPixelByte++ = (unsigned char) (r*dfactor2);
4058 *destPixelByte++ = (unsigned char) (g*dfactor2);
4059 *destPixelByte++ = (unsigned char) (b*dfactor2);
4060 *destPixelByte++ = 0;
4061 // ((unsigned char*)destPixel)[0] = (int) r/factor2;
4062 // ((unsigned char*)destPixel)[1] = (int) g/factor2;
4063 // ((unsigned char*)destPixel)[2] = (int) b/factor2;
4064 // *destPixel = (int) val/(factor*factor);
4065 srcStartPixel += factorX;
4066 }
4067 srcStartPixel += linestep;
4068/* if ( (x-colmax > 0) && (x-colmax <= (factor/2)) ) {
4069 *destPixelByte++ = (unsigned char) (r/factor2);
4070 *destPixelByte++ = (unsigned char) (g/factor2);
4071 *destPixelByte++ = (unsigned char) (b/factor2);
4072 *destPixelByte++ = 0;
4073 }*/
4074 }
4075 cols = newcols;
4076 rows = newrows;
4077 return bytedest;
4078}
4079
4080char* ImageResizeUp(char* bytesource, uint32 &cols, uint32 &rows, uint32 factor) {
4081
4082 if (factor <= 0) {
4083 return NULL;
4084 }
4085 int factor2 = factor*factor;
4086 int newcols = cols*factor;
4087 int newrows = rows*factor;
4088
4089 char* bytedest = new char[newcols*newrows*4];
4090 if (factor == 1) {
4091 memcpy(bytedest, bytesource, cols*rows*4);
4092 return bytedest;
4093 }
4094
4095 unsigned int* source = (unsigned int*) bytesource;
4096 unsigned int* dest = (unsigned int*) bytedest;
4097
4098 int destCols = cols*factor;
4099 uint32 n, m, pixel;
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;
4105 // int linestep = factor*cols;
4106
4107 // Take a pixel and make it a square of f*f pixels
4108 for (uint32 x=0; x<rows; x++) {
4109 for (uint32 y=0; y<cols; y++) {
4110 destPixel = destStartPixel;
4111 pixel = GET_RGB_FROM_RGBA(*srcPixel++);
4112 for (n=0; n<factor; n++) {
4113 for (m=0; m<factor; m++) {
4114 *destPixel++ = pixel;
4115 }
4116 destPixel += step;
4117 }
4118 destStartPixel += factor;
4119 }
4120 destStartPixel += linestep;
4121 }
4122 // Take a square of f*f pixels and average to produce 1 pixel
4123 cols = newcols;
4124 rows = newrows;
4125 return bytedest;
4126}
4127
4128
4129
4130
4131
4133// Construction/Destruction
4135
4137 init(0, 0);
4138}
4139
4140BitmapUpdate::BitmapUpdate(uint32 w, uint32 h) {
4141 init(w, h);
4142}
4143
4144BitmapUpdate::BitmapUpdate(const char* filename, bool compress) {
4145 init(0, 0);
4146 if (compress) {
4147 if (!readFromFileRLE(filename)) {
4148 }
4149 }
4150 else {
4151 if (!readFromFile(filename)) {
4152 }
4153 }
4154}
4155
4159
4160bool BitmapUpdate::init(uint32 w, uint32 h) {
4161 // setWidth(w);
4162 width = w;
4163 height = h;
4164 // setHeight(h);
4165 return true;
4166}
4167
4169 // setWidth(0);
4170 // setHeight(0);
4171 width = height = 0;
4173 delete(data);
4174 data = NULL;
4175 size = 0;
4176 return true;
4177}
4178/*
4179bool BitmapUpdate::setWidth(int width) {
4180return this->params.put("Width", JString(width));
4181}
4182
4183int BitmapUpdate::getWidth() {
4184return this->params.get("Width").toInt();
4185}
4186
4187bool BitmapUpdate::setHeight(int height) {
4188return this->params.put("Height", JString(height));
4189}
4190
4191int BitmapUpdate::getHeight() {
4192return this->params.get("Height").toInt();
4193}
4194*/
4195//bool BitmapUpdate::setUpdateType(JString updateType) {
4196// return this->params.put("Update", updateType);
4197//}
4198//
4199//JString BitmapUpdate::getUpdateType() {
4200// return this->params.get("Update");
4201//}
4202
4204 return new Bitmap(this);
4205}
4206
4208 type = updateType;
4209 return true;
4210}
4211
4215
4216//HTMLPage* BitmapUpdate::toHTMLBitmap() {
4217// Bitmap* bitmap = this->toBitmap();
4218// HTMLPage* page = NULL;
4219// if (bitmap != NULL) {
4220// page = new HTMLPage(bitmap);
4221// delete(bitmap);
4222// }
4223// return page;
4224//}
4225
4226
4228 if ((bitmap == NULL) || (bitmap->data == NULL))
4229 return false;
4230 reset();
4232 init(bitmap->width, bitmap->height);
4233 size = bitmap->size;
4234 data = new char[size];
4235 memcpy(data, bitmap->data, size);
4236 return true;
4237}
4238
4239bool BitmapUpdate::readFromFile(const char* filename) {
4240
4241 // JTime t1;
4242
4243 BITMAPFILEHEADER_CM* bmfh; // ={0};
4244 BITMAPINFOHEADER_CM* bmih; // ={0};
4245 uint32 count = 0;
4246
4247 uint32 len;
4248 char* dat = utils::ReadAFile(filename, len, true);
4249 if (dat == NULL)
4250 return false;
4251
4252 // JTime t2;
4253
4254 char* src = (char*)dat;
4255 bmfh = (BITMAPFILEHEADER_CM*)src;
4256 src += sizeof(BITMAPFILEHEADER_CM);
4257 bmih = (BITMAPINFOHEADER_CM*)src;
4258 src += sizeof(BITMAPINFOHEADER_CM);
4259
4260 if (bmih->biCompression != 0) {
4261 delete[] dat;
4262 return false;
4263 }
4264
4265 if (bmih->biBitCount != 24) {
4266 delete[] dat;
4267 return false;
4268 }
4269
4270 // JTime t3;
4271
4272 int depth = bmih->biBitCount;
4273 int planes = bmih->biPlanes;
4274 width = bmih->biWidth;
4275 height = bmih->biHeight;
4276
4277 if (bmih->biSizeImage == 0)
4278 bmih->biSizeImage = bmfh->bfSize - bmfh->bfOffBits;
4279
4280 if (len < (int)(sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM) + (width * height * ((int)(depth / 8))))) {
4281 delete[] dat;
4282 return false;
4283 }
4284
4285 // JTime t4;
4286
4287 // setWidth(width);
4288 // setHeight(height);
4289
4290 // JTime t5;
4291
4292 this->size = width * height * 4;
4293 data = new char[this->size];
4294 if (data == NULL) {
4295 this->size = 0;
4296 delete[] dat;
4297 return false;
4298 }
4299
4300 // JTime t6;
4301 Bitmap::convertBitmapFileData(src, width, height, (int)(bmih->biBitCount / 8), data, this->size);
4302 // JTime t7;
4303
4304 delete[] dat;
4306 // JTime t8;
4307 // printf(" Time: %s\n", (char*) JString::format("%d %d %d %d %d %d %d = %d",
4308 // t2.microDifference(t1), t3.microDifference(t2), t4.microDifference(t3), t5.microDifference(t4), t6.microDifference(t5), t7.microDifference(t6), t8.microDifference(t7), t8.microDifference(t1)));
4309 return true;
4310}
4311
4312bool BitmapUpdate::readFromFileRLE(const char* filename) {
4313
4314 BITMAPFILEHEADER_CM* bmfh; // ={0};
4315 BITMAPINFOHEADER_CM* bmih; // ={0};
4316 uint32 count = 0;
4317
4318 uint32 len;
4319 char* dat = utils::ReadAFile(filename, len, true);
4320 if (dat == NULL)
4321 return false;
4322
4323 char* src = (char*)dat;
4324 bmfh = (BITMAPFILEHEADER_CM*)src;
4325 src += sizeof(BITMAPFILEHEADER_CM);
4326 bmih = (BITMAPINFOHEADER_CM*)src;
4327 src += sizeof(BITMAPINFOHEADER_CM);
4328
4329 if (bmih->biCompression != 0) {
4330 delete[] dat;
4331 return false;
4332 }
4333
4334 if (bmih->biBitCount != 24) {
4335 delete[] dat;
4336 return false;
4337 }
4338
4339 int depth = bmih->biBitCount;
4340 int planes = bmih->biPlanes;
4341 width = bmih->biWidth;
4342 height = bmih->biHeight;
4343
4344 if (bmih->biSizeImage == 0)
4345 bmih->biSizeImage = bmfh->bfSize - bmfh->bfOffBits;
4346
4347 if (len < (int)(sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM) + (width * height * ((int)(depth / 8))))) {
4348 delete[] dat;
4349 return false;
4350 }
4351
4352 // setWidth(width);
4353 // setHeight(height);
4354
4355 /* this->size = width * height * 4;
4356 data = new char[this->size];
4357 if (data == NULL) {
4358 this->size = 0;
4359 delete [] dat;
4360 return false;
4361 }*/
4362
4363 data = Bitmap::convertBitmapFileDataRunLength(src, width, height, (int)(bmih->biBitCount / 8), this->size);
4364
4365 delete[] dat;
4366 if (data == NULL)
4367 return false;
4368
4370 return true;
4371}
4372
4373bool BitmapUpdate::readFromFileDiff(const char* filename, Bitmap* oldBitmap) {
4374 BITMAPFILEHEADER_CM* bmfh; // ={0};
4375 BITMAPINFOHEADER_CM* bmih; // ={0};
4376 uint32 count = 0;
4377
4378 uint32 len;
4379 char* dat = utils::ReadAFile(filename, len, true);
4380 if (dat == NULL)
4381 return false;
4382
4383 char* src = (char*)dat;
4384 bmfh = (BITMAPFILEHEADER_CM*)src;
4385 src += sizeof(BITMAPFILEHEADER_CM);
4386 bmih = (BITMAPINFOHEADER_CM*)src;
4387 src += sizeof(BITMAPINFOHEADER_CM);
4388
4389 if (bmih->biCompression != 0) {
4390 delete[] dat;
4391 return false;
4392 }
4393
4394 if (bmih->biBitCount != 24) {
4395 delete[] dat;
4396 return false;
4397 }
4398
4399 int depth = bmih->biBitCount;
4400 int planes = bmih->biPlanes;
4401 width = bmih->biWidth;
4402 height = bmih->biHeight;
4403
4404 if (bmih->biSizeImage == 0)
4405 bmih->biSizeImage = bmfh->bfSize - bmfh->bfOffBits;
4406
4407 if (len < (int)(sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM) + (width * height * ((int)(depth / 8))))) {
4408 delete[] dat;
4409 return false;
4410 }
4411
4412 // setWidth(width);
4413 // setHeight(height);
4414
4415 data = Bitmap::differenceBitmapFileData(oldBitmap->data, src, width, height, (int)(bmih->biBitCount / 8), this->size);
4416
4417 delete[] dat;
4418 if (data == NULL)
4419 return false;
4420
4422 return true;
4423}
4424
4425bool BitmapUpdate::readFromFileRLEDiff(const char* filename, Bitmap* oldBitmap) {
4426 BITMAPFILEHEADER_CM* bmfh; // ={0};
4427 BITMAPINFOHEADER_CM* bmih; // ={0};
4428 uint32 count = 0;
4429
4430 uint32 len;
4431 char* dat = utils::ReadAFile(filename, len, true);
4432 if (dat == NULL)
4433 return false;
4434
4435 char* src = (char*)dat;
4436 bmfh = (BITMAPFILEHEADER_CM*)src;
4437 src += sizeof(BITMAPFILEHEADER_CM);
4438 bmih = (BITMAPINFOHEADER_CM*)src;
4439 src += sizeof(BITMAPINFOHEADER_CM);
4440
4441 if (bmih->biCompression != 0) {
4442 delete[] dat;
4443 return false;
4444 }
4445
4446 if (bmih->biBitCount != 24) {
4447 delete[] dat;
4448 return false;
4449 }
4450
4451 int depth = bmih->biBitCount;
4452 int planes = bmih->biPlanes;
4453 width = bmih->biWidth;
4454 height = bmih->biHeight;
4455
4456 if (bmih->biSizeImage == 0)
4457 bmih->biSizeImage = bmfh->bfSize - bmfh->bfOffBits;
4458
4459 if (len < (int)(sizeof(BITMAPFILEHEADER_CM) + sizeof(BITMAPINFOHEADER_CM) + (width * height * ((int)(depth / 8))))) {
4460 delete[] dat;
4461 return false;
4462 }
4463
4464 // setWidth(width);
4465 // setHeight(height);
4466
4467 data = Bitmap::differenceBitmapFileDataRunLength(oldBitmap->data, src, width, height, (int)(bmih->biBitCount / 8), this->size);
4468
4469 delete[] dat;
4470 if (data == NULL)
4471 return false;
4472
4474 return true;
4475}
4476
4477
4479 return false;
4480}
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498// ################# Unit Test #################
4499
4501 const uint32 W = 64;
4502 const uint32 H = 48;
4503
4504 unittest::progress(0, "construct");
4505
4506 // --- Construction and dimensions ---
4507 Bitmap bmp(W, H);
4508 if (bmp.width != W || bmp.height != H) {
4509 unittest::fail("constructed dimensions wrong: got %ux%u expected %ux%u", bmp.width, bmp.height, W, H);
4510 return false;
4511 }
4512 if (bmp.size != W * H * 4) {
4513 unittest::fail("size wrong: got %u expected %u", bmp.size, W * H * 4);
4514 return false;
4515 }
4516 if (bmp.data == NULL) {
4517 unittest::fail("data buffer was not allocated");
4518 return false;
4519 }
4520
4521 unittest::progress(15, "erase");
4522
4523 // --- Erase whole bitmap to a known colour, verify via getPixelColor ---
4524 if (!bmp.eraseBitmap(10, 20, 30)) {
4525 unittest::fail("eraseBitmap returned false");
4526 return false;
4527 }
4528 Color c = bmp.getPixelColor(0, 0);
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);
4531 return false;
4532 }
4533 c = bmp.getPixelColor(W - 1, H - 1);
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);
4536 return false;
4537 }
4538
4539 unittest::progress(30, "setPixel/getPixelColor");
4540
4541 // --- setPixel then read back via getPixelColor ---
4542 if (!bmp.setPixel((uint32)5, (uint32)7, (uint8)200, (uint8)100, (uint8)50, (uint8)0)) {
4543 unittest::fail("setPixel(5,7) returned false");
4544 return false;
4545 }
4546 c = bmp.getPixelColor(5, 7);
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);
4549 return false;
4550 }
4551 // neighbour pixel must be untouched (still the erase colour)
4552 c = bmp.getPixelColor(6, 7);
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);
4555 return false;
4556 }
4557
4558 // --- Out-of-range setPixel must be rejected ---
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");
4561 return false;
4562 }
4563
4564 unittest::progress(45, "getPos");
4565
4566 // --- getPos addressing sanity ---
4567 if (bmp.getPos(0, 0) != 0) {
4568 unittest::fail("getPos(0,0) should be 0, got %u", bmp.getPos(0, 0));
4569 return false;
4570 }
4571 if (bmp.getPos(3, 2) != (2 * W + 3) * 4) {
4572 unittest::fail("getPos(3,2) wrong: got %u expected %u", bmp.getPos(3, 2), (2 * W + 3) * 4);
4573 return false;
4574 }
4575
4576 unittest::progress(55, "fillBox");
4577
4578 // --- fillBox fills a rectangle; corners inside set, outside untouched ---
4579 bmp.eraseBitmap(0, 0, 0);
4580 Color fillCol(123, 45, 67);
4581 if (!bmp.fillBox((uint32)10, (uint32)10, (uint32)20, (uint32)15, fillCol)) {
4582 unittest::fail("fillBox returned false");
4583 return false;
4584 }
4585 c = bmp.getPixelColor(10, 10);
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);
4588 return false;
4589 }
4590 c = bmp.getPixelColor(29, 24);
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);
4593 return false;
4594 }
4595 // just outside the box must still be black
4596 c = bmp.getPixelColor(9, 10);
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);
4599 return false;
4600 }
4601 c = bmp.getPixelColor(30, 25);
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);
4604 return false;
4605 }
4606
4607 unittest::progress(65, "replaceColor");
4608
4609 // --- replaceColor swaps the filled colour for another ---
4610 if (!bmp.replaceColor(fillCol, Color(9, 9, 9))) {
4611 unittest::fail("replaceColor returned false");
4612 return false;
4613 }
4614 c = bmp.getPixelColor(15, 15);
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);
4617 return false;
4618 }
4619
4620 unittest::progress(72, "getCopy");
4621
4622 // --- getCopy extracts a sub-region with matching pixels ---
4623 bmp.eraseBitmap(0, 0, 0);
4624 bmp.setPixel((uint32)12, (uint32)12, (uint8)77, (uint8)88, (uint8)99, (uint8)0);
4625 Bitmap* sub = bmp.getCopy(Box(10, 10, 8, 8));
4626 if (!sub) {
4627 unittest::fail("getCopy returned NULL");
4628 return false;
4629 }
4630 if (sub->width != 8 || sub->height != 8) {
4631 unittest::fail("getCopy dimensions wrong: got %ux%u expected 8x8", sub->width, sub->height);
4632 delete sub;
4633 return false;
4634 }
4635 // the pixel at bmp(12,12) maps to sub(2,2)
4636 c = sub->getPixelColor(2, 2);
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);
4639 delete sub;
4640 return false;
4641 }
4642 delete sub;
4643
4644 unittest::progress(80, "DataMessage roundtrip");
4645
4646 // --- toMessage / Bitmap(DataMessage*) roundtrip ---
4647 bmp.eraseBitmap(40, 41, 42);
4648 bmp.setPixel((uint32)1, (uint32)1, (uint8)111, (uint8)112, (uint8)113, (uint8)0);
4649 DataMessage* msg = bmp.toMessage();
4650 if (!msg) {
4651 unittest::fail("toMessage returned NULL");
4652 return false;
4653 }
4654 Bitmap restored(msg);
4655 delete msg;
4656 if (restored.width != W || restored.height != H || restored.size != bmp.size) {
4657 unittest::fail("roundtrip dimensions/size mismatch: %ux%u size %u vs %ux%u size %u",
4658 restored.width, restored.height, restored.size, W, H, bmp.size);
4659 return false;
4660 }
4661 c = restored.getPixelColor(1, 1);
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);
4664 return false;
4665 }
4666 c = restored.getPixelColor(0, 0);
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);
4669 return false;
4670 }
4671
4672 unittest::progress(88, "throughput");
4673
4674 // --- Throughput metric: measure setPixel rate over a full sweep ---
4675 Bitmap perf(W, H);
4676 perf.eraseBitmap(0, 0, 0);
4677 const uint32 sweeps = 50;
4678 uint64 t0 = GetTimeNow();
4679 uint64 ops = 0;
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);
4684 ops++;
4685 }
4686 }
4687 }
4688 double us = (double)(GetTimeNow() - t0);
4689 if (us > 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);
4692
4693 // verify a representative pixel from the last sweep
4694 c = perf.getPixelColor(3, 4);
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);
4697 return false;
4698 }
4699
4700 unittest::progress(100, "done");
4701 return true;
4702}
4703
4706 "bitmap", Bitmap::UnitTest,
4707 "Bitmap image: construct, set/get pixels, erase, fillBox, replaceColor, getCopy, DataMessage roundtrip", "util");
4708}
4709
4710
4711} // namespace cmlabs
#define D(r, y)
In-memory RGBA raster image (Bitmap) with drawing primitives, resizing, BMP file I/O and delta/RLE co...
#define GET_SECONDRGB_FROM_DRGB(a)
Definition Bitmap.h:39
#define RLECTRL
Definition Bitmap.h:42
#define GET_FIRSTRGB_FROM_DRGB(a)
Definition Bitmap.h:38
#define DIFCTRL
Definition Bitmap.h:43
#define GET_B_FROM_RGBA(a)
Definition Bitmap.h:31
#define GET_G_FROM_RGBA(a)
Definition Bitmap.h:30
#define GET_RGB_FROM_RGBA(a)
Definition Bitmap.h:19
#define GET_RGB_FROM_GRAY(a)
Definition Bitmap.h:32
#define GET_GRAY_FROM_RGB(a)
Definition Bitmap.h:34
#define DATACTRL
Definition Bitmap.h:41
#define GET_R_FROM_RGBA(a)
Definition Bitmap.h:29
#define GET_DRGB_FROM_2RGBS(a, b)
Definition Bitmap.h:37
CMSDK time: µs-resolution 64-bit timestamps and the Time Mapping Constant (TMC).
#define clmin(a, b)
Definition Standard.h:115
#define clPI
Definition Standard.h:113
Small, dependency-free unit test harness used by all CMSDK object tests.
#define stricmp
Definition Utils.h:132
32-bit RGBA raster image with drawing, compositing, scaling, BMP I/O and update-region tracking.
Definition Bitmap.h:139
static char * convertBitmapFileDataRunLength(const char *src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen)
As convertBitmapFileData() but RLE-compressing on the fly.
Definition Bitmap.cpp:2874
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()).
Definition Bitmap.cpp:1360
bool addBitmapUpdateRegion(const Box &updateBox)
Grow the dirty region to include updateBox.
Definition Bitmap.cpp:336
bool init(uint32 w, uint32 h)
(Re)allocate as w x h.
Definition Bitmap.cpp:305
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).
Definition Bitmap.cpp:683
bool hasBitmapBeenTotallyChanged()
Definition Bitmap.cpp:368
bool fillBox(const Box &box, const Color &color)
Fill a rectangle (clipped to the image).
Definition Bitmap.cpp:817
Bitmap * getCopy(const Box &box)
Extract a sub-image (caller owns).
Definition Bitmap.cpp:381
double getBestResizeFactors(double factor, int &scaleUp, int &scaleDown, int &scale66)
Decompose factor into up/down/66% passes used by createResizedData().
Definition Bitmap.cpp:1074
bool copyGrayScaleData(char *src, uint32 len)
Fill this RGBA image from an 8-bit grayscale buffer of matching size.
Definition Bitmap.cpp:418
bool drawCircle(uint32 xCenter, uint32 yCenter, uint32 radius, const Color &color, double weight, double lineWidth, bool filled=false)
Draw a circle.
Definition Bitmap.cpp:1373
Pixel getXY(uint32 pos)
Inverse of getPos(): coordinates for a linear index.
Definition Bitmap.cpp:739
bool mirror(bool horizontal, bool vertical)
Flip in place along the requested axes.
Definition Bitmap.cpp:1447
bool drawLine(const Line &line, const Color &color)
Draw a (possibly anti-aliased) line segment.
Definition Bitmap.cpp:886
bool hasBitmapBeenUpdated()
Definition Bitmap.cpp:364
static bool UnitTest()
Self test for Bitmap and BitmapUpdate.
Definition Bitmap.cpp:4500
Color getPixelColor(uint32 x, uint32 y)
Pixel color at (x,y) as a Color value (black when out of bounds).
Definition Bitmap.cpp:862
bool setPixel(uint32 x, uint32 y, uint8 red, uint8 green, uint8 blue, uint8 alpha=0)
Set the pixel at (x,y).
Definition Bitmap.cpp:658
bool setBitmapUpdated()
Mark the whole image as changed.
Definition Bitmap.cpp:359
uint32 height
Height in pixels.
Definition Bitmap.h:249
uint32 width
Width in pixels.
Definition Bitmap.h:248
BitmapUpdate * operator-(const Bitmap &bitmap) const
Difference update transforming bitmap into this image.
Definition Bitmap.cpp:3279
DataMessage * toMessage()
Serialize into a new DataMessage (caller owns).
Definition Bitmap.cpp:294
BitmapUpdate * getCompressedUpdate(bool destructive) const
Full-frame update, RLE compressed.
Definition Bitmap.cpp:3271
bool resizeTo(uint32 w, uint32 h, bool proportional)
Resize in place.
Definition Bitmap.cpp:1065
bool takeDataFromBitmap(Bitmap *bitmap)
Steal the pixel buffer from bitmap (which becomes empty); no copy.
Definition Bitmap.cpp:1225
static char * differenceBitmapFileDataRunLength(char *orig, char *src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen)
Difference encoding + RLE compression.
Definition Bitmap.cpp:3153
double getBestResizeFactor(double factor)
Snap factor to the nearest factor achievable by the fast integer resizers.
Definition Bitmap.cpp:1126
bool eraseBitmap()
Fill with black/zero.
Definition Bitmap.cpp:759
Box updateRegion
Accumulated dirty region since the last resetBitmapUpdates().
Definition Bitmap.h:252
virtual ~Bitmap()
Definition Bitmap.cpp:256
BitmapUpdate * runLengthDestructiveEncode() const
RLE-compress, allowed to modify this image's buffer for speed.
Definition Bitmap.cpp:3494
bool copyDataFromBitmap(Bitmap *bitmap, bool shouldResize=false)
Copy pixels from bitmap; optionally resize this image to fit.
Definition Bitmap.cpp:1193
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).
Definition Bitmap.cpp:876
bool updateBitmap(BitmapUpdate *update, bool takeData)
Apply a full/RLE/diff update.
Definition Bitmap.cpp:430
uint32 size
Data buffer size in bytes (width*height*4).
Definition Bitmap.h:250
static char * differenceBitmapFileData(char *orig, char *src, uint32 width, uint32 height, uint32 depth, uint32 &dstlen)
Encode the difference between two frames.
Definition Bitmap.cpp:3022
Bitmap()
Empty 0x0 bitmap.
Definition Bitmap.cpp:18
char * createResizedData(uint32 newWidth, uint32 newHeight, int32 scaleUp, int32 scaleDown, int32 scale66)
Produce a resized pixel buffer using the given pass counts (caller frees).
Definition Bitmap.cpp:1137
bool resetBitmapUpdates()
Clear the dirty-region tracking.
Definition Bitmap.cpp:354
Bitmap * getResizedCopy(uint32 w, uint32 h, bool proportional)
Resized copy (caller owns).
Definition Bitmap.cpp:1053
bool readFromMemory(const char *data, uint32 size)
Parse a BMP file image from memory.
Definition Bitmap.cpp:1898
uint32 getPos(uint32 x, uint32 y)
Linear pixel index of (x,y) = y*width+x.
Definition Bitmap.cpp:727
char * data
Pixel data, 32-bit RGBA, row-major top-down.
Definition Bitmap.h:251
bool replaceColor(const Color &oldColor, const Color &newColor)
Replace every exact occurrence of oldColor with newColor.
Definition Bitmap.cpp:798
int32 round(double d)
Round to nearest integer (helper for pixel math).
Definition Bitmap.cpp:2775
bool reset()
Release pixel data and return to the empty state.
Definition Bitmap.cpp:375
bool canBeResizedTo(uint32 width, uint32 height)
Check whether the integer-ratio resizer supports this target size.
Definition Bitmap.cpp:984
char * toBitmapFileFormat(uint32 &len)
Serialize this image as a complete BMP file in memory.
Definition Bitmap.cpp:2109
Pixel getPixel(uint32 x, uint32 y)
Get a Pixel referencing (x,y); value pointer is NULL when out of bounds.
Definition Bitmap.cpp:708
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.
Definition Bitmap.cpp:2409
bool drawBitmap(Bitmap *bitmap, uint32 x, uint32 y)
Blit bitmap with its upper-left corner at (x,y).
Definition Bitmap.cpp:1550
char * getGrayScaleDataCopy(uint32 &len)
8-bit grayscale copy of the image.
Definition Bitmap.cpp:403
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.
Definition Bitmap.cpp:2850
double getDPos(double x, double y)
Fractional linear index for sub-pixel coordinates.
Definition Bitmap.cpp:733
bool saveToFile(const char *filename)
Save as a BMP file.
Definition Bitmap.cpp:2003
BitmapUpdate * runLengthEncode() const
RLE-compress the full image.
Definition Bitmap.cpp:3413
bool readFromFile(const char *filename)
Load a BMP file.
Definition Bitmap.cpp:1989
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.
Definition Bitmap.cpp:2113
bool drawBox(const Box &box, const Color &color)
Draw a rectangle outline.
Definition Bitmap.cpp:1345
Transportable image update: either a full frame or a compressed (RLE and/or difference) delta against...
Definition Bitmap.h:318
uint32 size
Payload size in bytes.
Definition Bitmap.h:346
BitmapUpdate::Type getUpdateType()
Definition Bitmap.cpp:4212
Bitmap * toBitmap()
Decode into a new full Bitmap (caller owns); requires a FULL-equivalent payload.
Definition Bitmap.cpp:4203
uint32 height
Frame height in pixels.
Definition Bitmap.h:345
BitmapUpdate()
Empty update.
Definition Bitmap.cpp:4136
bool reset()
Release the payload.
Definition Bitmap.cpp:4168
uint32 width
Frame width in pixels.
Definition Bitmap.h:344
bool update(BitmapUpdate *update)
Merge a newer update into this one.
Definition Bitmap.cpp:4478
virtual ~BitmapUpdate()
Definition Bitmap.cpp:4156
char * data
Encoded payload (interpretation depends on type).
Definition Bitmap.h:347
bool setUpdateType(BitmapUpdate::Type updateType)
Set the payload encoding tag.
Definition Bitmap.cpp:4207
bool readFromFile(const char *filename)
Load a BMP file as a FULL update.
Definition Bitmap.cpp:4239
bool setFullUpdate(Bitmap *bitmap)
Fill as an uncompressed full frame from bitmap.
Definition Bitmap.cpp:4227
bool init(uint32 w, uint32 h)
(Re)initialize for a w x h frame.
Definition Bitmap.cpp:4160
bool readFromFileRLEDiff(const char *filename, Bitmap *oldBitmap)
Load, difference against oldBitmap and RLE-compress.
Definition Bitmap.cpp:4425
bool readFromFileDiff(const char *filename, Bitmap *oldBitmap)
Load a BMP file and store the difference against oldBitmap.
Definition Bitmap.cpp:4373
bool readFromFileRLE(const char *filename)
Load a BMP file and RLE-compress it.
Definition Bitmap.cpp:4312
enum cmlabs::BitmapUpdate::Type type
Type
Payload encoding: FULL raw frame, RUNLENGTH RLE frame, RL16 16-bit RLE, DIF raw difference,...
Definition Bitmap.h:321
Axis-aligned rectangle defined by an upper-left corner and a Size, with overlap/containment math.
Size size
Extent.
double getWidth() const
double getLineWidth() const
PointFloat getLowerLeft() const
double getUpperY() const
double getHeight() const
PointFloat getUpperLeft() const
double getLeftX() 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).
Definition Bitmap.h:87
uint32 x
Definition Bitmap.h:90
uint32 * value
Definition Bitmap.h:92
uint32 y
Definition Bitmap.h:91
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
double h
Height.
double w
Width.
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.
Definition PsyTime.cpp:69
bool WriteAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Write (create/overwrite) a file.
Definition Utils.cpp:6877
char * ReadAFile(const char *filename, uint32 &length, bool binary=false)
Read an entire file into a new buffer.
Definition Utils.cpp:6818
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).
Definition Bitmap.cpp:3787
char * ImageResizeUp(char *bytesource, uint32 &cols, uint32 &rows, uint32 factor)
Enlarge an RGBA image by an integer factor (pixel replication).
Definition Bitmap.cpp:4080
void Register_Bitmap_Tests()
Definition Bitmap.cpp:4704
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).
Definition Bitmap.cpp:3622
unsigned char CMBYTE
Definition Bitmap.h:45
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).
Definition Bitmap.cpp:3994