00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "Bitmap.h"
00026
00027
00028 #ifdef WIN32
00029 #include "win32/Bitmap_Win32.cpp"
00030 #else
00031 #include "linux/Bitmap_Linux.cpp"
00032 #endif
00033
00034 namespace cmlabs {
00035
00036
00037
00038
00039
00040 Bitmap::Bitmap() : DataSample("Bitmap") {
00041 init(0, 0);
00042 }
00043
00044 Bitmap::Bitmap(const JString& filename) : DataSample("Bitmap") {
00045 init(0, 0);
00046 if (!this->readFromFile(filename)) {
00047 printf("Error initialising Bitmap from file '%s'...\n", (char*) filename);
00048 }
00049 }
00050
00051 Bitmap::Bitmap(int w, int h) : DataSample("Bitmap") {
00052 init(w, h);
00053 }
00054
00055 Bitmap::Bitmap(char* imgData, int w, int h, bool takeData) : DataSample("Bitmap") {
00056 if (takeData) {
00057 width = w;
00058 height = h;
00059 size = w * h * 4;
00060 data = imgData;
00061 setMaxUpdates(0);
00062 setBitmapUpdated();
00063 }
00064 else {
00065 init(w, h);
00066 memcpy(data, imgData, size);
00067 }
00068 }
00069
00070 Object* Bitmap::clone() const {
00071 Bitmap* bm = new Bitmap(data, width, height);
00072 bm->name = name;
00073 bm->id = id;
00074 bm->type = type;
00075 bm->width = width;
00076 bm->height = height;
00077 bm->timestamp = timestamp;
00078 bm->params.removeAll();
00079 bm->params.copyAll(params);
00080 bm->setDuration(duration);
00081 return (Object*) bm;
00082 }
00083
00084 Bitmap::~Bitmap() {
00085 reset();
00086 }
00087
00088 Bitmap::Bitmap(BitmapUpdate* update) {
00089 if (update == NULL) {
00090 init(0, 0);
00091 return;
00092 }
00093
00094 char* updateData = update->getDataLink();
00095 long updateSize = update->getDataSize();
00096
00097
00098
00099 int width = update->width;
00100 int height = update->height;
00101
00102 if ((width <= 0) || (height <= 0) ) {
00103 init(0, 0);
00104 return;
00105 }
00106
00107 if (!update->getUpdateType().equalsIgnoreCase("Full")) {
00108 init(width, height);
00109 this->fillBox(0, 0, width, height, Color(0,0,0));
00110 updateBitmap(update, false);
00111 }
00112 else
00113 updateBitmap(update, true);
00114 }
00115
00116 bool Bitmap::init(int w, int h) {
00117 width = w;
00118 height = h;
00119 size = w * h * 4;
00120 data = NULL;
00121 if (w > 0) {
00122 data = new char[size];
00123 }
00124
00125 setMaxUpdates(0);
00126 setBitmapUpdated();
00127
00128 return true;
00129 }
00130
00131
00132
00133
00134
00135 int Bitmap::getMaxUpdates() {
00136 return params.get("MaxUpdates").toInt();
00137 }
00138
00139 bool Bitmap::setMaxUpdates(int max) {
00140 params.put("MaxUpdates", JString(max));
00141 if (aux != NULL) {
00142 ObjectCollection* dict = (ObjectCollection*) aux;
00143 if (dict->getCount() > max) {
00144 dict->removeAll();
00145 }
00146 }
00147 return true;
00148 }
00149
00150 bool Bitmap::addBitmapUpdateRegion(const Box& updateBox) {
00151 if (hasBitmapBeenTotallyChanged())
00152 return true;
00153
00154 return addBitmapUpdateRegion((Box*) updateBox.clone());
00155 }
00156
00157 bool Bitmap::addBitmapUpdateRegion(Box* box) {
00158 if (hasBitmapBeenTotallyChanged()) {
00159 delete(box);
00160 return true;
00161 }
00162 if (aux == NULL)
00163 aux = new ObjectCollection();
00164 ObjectCollection* dict = (ObjectCollection*) aux;
00165 if (dict->getCount() >= getMaxUpdates()) {
00166 dict->removeAll();
00167 delete(box);
00168 return true;
00169 }
00170
00171 double x, y;
00172 if ( (x = box->getLeftX()) < 0) {
00173 box->grow(x, 0);
00174 box->move(-1*x, 0);
00175 }
00176 if ( (y = box->getUpperY()) < 0) {
00177 box->grow(0, y);
00178 box->move(0, -1*y);
00179 }
00180
00181 Box* b;
00182 for (int n=0; n<dict->getCount(); n++) {
00183 if ( ( (b = (Box*)dict->get(n)) != NULL) && (b->percentOverlap(*box) > 0) ) {
00184 b->growToBoundingBox(*box);
00185 delete(box);
00186 return true;
00187 }
00188 }
00189 return dict->add(box);
00190 }
00191
00192
00193 bool Bitmap::resetBitmapUpdates() {
00194 if (aux != NULL)
00195 delete(aux);
00196 aux = NULL;
00197 return true;
00198 }
00199
00200 bool Bitmap::setBitmapUpdated() {
00201 if (aux == NULL)
00202 aux = new ObjectDictionary();
00203 return true;
00204 }
00205
00206 bool Bitmap::hasBitmapBeenUpdated() {
00207 return (aux != NULL);
00208 }
00209
00210 bool Bitmap::hasBitmapBeenTotallyChanged() {
00211 return ((aux != NULL) && ( ((ObjectDictionary*)aux)->getCount() == 0));
00212 }
00213
00214
00215
00216
00217 bool Bitmap::reset() {
00218 if (aux != NULL)
00219 delete(aux);
00220 aux = NULL;
00221 delete [] data;
00222 data = NULL;
00223 return true;
00224 }
00225
00226 Bitmap* Bitmap::getCopy(const Box& box) {
00227 Bitmap* bitmap;
00228 int x = (int) box.upperLeft.x;
00229 int y = (int) box.upperLeft.y;
00230 int w = (int) box.size.w;
00231 int h = (int) box.size.h;
00232
00233 if (box.upperLeft.x != (int) box.upperLeft.x)
00234 w++;
00235 if (box.upperLeft.y != (int) box.upperLeft.y)
00236 h++;
00237 if (box.size.w != (int) box.size.w)
00238 w++;
00239 if (box.size.h != (int) box.size.h)
00240 h++;
00241
00242 bitmap = new Bitmap(w, h);
00243 bitmap->drawBitmap(this, x, y, 0, 0, w, h);
00244 return bitmap;
00245 }
00246
00247
00248 char* Bitmap::getGrayScaleDataCopy(int &len) {
00249 if (size <= 0)
00250 return NULL;
00251 len = width*height;
00252 char* output = new char[len];
00253 unsigned int* src = (unsigned int*) data;
00254 char* dst = output;
00255
00256 for (int n=0; n<len; n++) {
00257 *dst++ = GET_GRAY_FROM_RGB(*src);
00258 src++;
00259 }
00260 return output;
00261 }
00262
00263 bool Bitmap::copyGrayScaleData(char* src, int len) {
00264 if (len < width*height)
00265 return false;
00266 unsigned int* dst = (unsigned int*) data;
00267
00268 for (int n=0; n<len; n++) {
00269 *dst++ = GET_RGB_FROM_GRAY(*src);
00270 src++;
00271 }
00272 return true;
00273 }
00274
00275 bool Bitmap::updateBitmap(BitmapUpdate* update, bool takeData) {
00276
00277 if (update == NULL)
00278 return false;
00279
00280 int updateWidth = update->width;
00281 int updateHeight = update->height;
00282 long updateSize = update->getDataSize();
00283 char* updateData = update->getDataLink();
00284
00285 JString updateType = update->getUpdateType();
00286 if (updateType.length() == 0)
00287 return false;
00288 else if (updateType.equalsIgnoreCase("Full")) {
00289 if (updateSize != (updateWidth * updateHeight * 4))
00290 return false;
00291 reset();
00292 if (takeData) {
00293 width = updateWidth;
00294 height = updateHeight;
00295 size = updateSize;
00296 data = updateData;
00297 update->clearDataFields();
00298 }
00299 else {
00300 if ( (updateWidth != width) || (updateHeight != height) ) {
00301 reset();
00302 init(updateWidth, updateHeight);
00303 }
00304 memcpy(data, updateData, size);
00305 }
00306 }
00307 else if (updateType.equalsIgnoreCase("RunLength")) {
00308
00309 if ( (updateWidth != width) || (updateHeight != height) ) {
00310 reset();
00311 init(updateWidth, updateHeight);
00312 }
00313
00314 unsigned int* src = (unsigned int*) updateData;
00315 unsigned int* dst = (unsigned int*) data;
00316 int ctrl;
00317 int len = 0;
00318 int totallen = 0;
00319 int pos = 0;
00320 int tsize = updateSize/4;
00321 int n;
00322 while (pos < tsize) {
00323 ctrl = (*src >> 24);
00324 len = (*src & 0xFFFFFF);
00325 src++;
00326 pos++;
00327 switch(ctrl) {
00328 case DATACTRL:
00329 memcpy(dst, src, len*4);
00330 src += len;
00331 dst += len;
00332 totallen += len;
00333 pos += len;
00334 break;
00335 case RLECTRL:
00336 for (n=0; n<len; n++)
00337 *dst++ = src[0];
00338 src++;
00339
00340 totallen += len;
00341 pos++;
00342 break;
00343 default:
00344 printf("Wrong CTRL: %d ", ctrl);
00345 pos++;
00346 break;
00347 }
00348 }
00349 }
00350 else if (updateType.equalsIgnoreCase("RL16")) {
00351
00352 if ( (updateWidth != width) || (updateHeight != height) ) {
00353 reset();
00354 init(updateWidth, updateHeight);
00355 }
00356
00357 unsigned int* src = (unsigned int*) updateData;
00358 unsigned int* dst = (unsigned int*) data;
00359 int ctrl;
00360 int len = 0;
00361 int totallen = 0;
00362 int pos = 0;
00363 int tsize = updateSize/4;
00364 int n;
00365 unsigned int i1, i2;
00366 while (pos < tsize) {
00367 ctrl = (*src >> 24);
00368 len = (*src & 0xFFFFFF);
00369 src++;
00370 pos++;
00371 switch(ctrl) {
00372 case DATACTRL:
00373 for (n=0; n<len; n++) {
00374 *dst++ = GET_FIRSTRGB_FROM_DRGB(*src);
00375 *dst++ = GET_SECONDRGB_FROM_DRGB(*src);
00376 src++;
00377 }
00378
00379
00380
00381 pos+=len;
00382 totallen+=len+len;
00383 break;
00384 case RLECTRL:
00385 i1 = GET_FIRSTRGB_FROM_DRGB(*src);
00386 i2 = GET_SECONDRGB_FROM_DRGB(*src);
00387 src++;
00388 for (n=0; n<len; n++) {
00389 *dst++ = i1;
00390 *dst++ = i2;
00391 }
00392 totallen+=len+len;
00393 pos++;
00394 break;
00395 default:
00396 printf("Wrong CTRL: %d ", ctrl);
00397 pos++;
00398 break;
00399 }
00400 }
00401 }
00402 else if (updateType.equalsIgnoreCase("Dif")) {
00403
00404 if ( (updateWidth != width) || (updateHeight != height) ) {
00405 reset();
00406 init(updateWidth, updateHeight);
00407 }
00408
00409 unsigned int* src = (unsigned int*) updateData;
00410 unsigned int* dst = (unsigned int*) data;
00411 int ctrl;
00412 int len = 0;
00413 int totallen = 0;
00414 int pos = 0;
00415 int tsize = updateSize/4;
00416 while (pos < tsize) {
00417 ctrl = (*src >> 24);
00418 len = (*src & 0xFFFFFF);
00419 src++;
00420 pos++;
00421 switch(ctrl) {
00422 case DATACTRL:
00423 memcpy(dst, src, len*4);
00424 src += len;
00425 dst += len;
00426 totallen += len;
00427 pos += len;
00428 break;
00429 case DIFCTRL:
00430 dst += len;
00431
00432 totallen += len;
00433
00434 break;
00435 default:
00436 printf("Wrong CTRL: %d ", ctrl);
00437 pos++;
00438 break;
00439 }
00440 }
00441 }
00442 else if (updateType.equalsIgnoreCase("DifRunLength")) {
00443
00444 if ( (updateWidth != width) || (updateHeight != height) ) {
00445 reset();
00446 init(updateWidth, updateHeight);
00447 }
00448
00449 unsigned int* src = (unsigned int*) updateData;
00450 unsigned int* dst = (unsigned int*) data;
00451 int ctrl;
00452 int len = 0;
00453 int totallen = 0;
00454 int pos = 0;
00455 int tsize = updateSize/4;
00456 while (pos < tsize) {
00457 ctrl = (*src >> 24);
00458 len = (*src & 0xFFFFFF);
00459 src++;
00460 pos++;
00461 int n;
00462 switch(ctrl) {
00463 case DATACTRL:
00464 memcpy(dst, src, len*4);
00465 src += len;
00466 dst += len;
00467 totallen += len;
00468 pos += len;
00469 break;
00470 case RLECTRL:
00471 for (n=0; n<len; n++)
00472 *dst++ = src[0];
00473 src++;
00474
00475 totallen += len;
00476 pos++;
00477 break;
00478 case DIFCTRL:
00479 dst += len;
00480
00481 totallen += len;
00482
00483 break;
00484 default:
00485 printf("Wrong CTRL: %d ", ctrl);
00486 pos++;
00487 break;
00488 }
00489 }
00490 }
00491
00492 setBitmapUpdated();
00493 return true;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503 bool Bitmap::setPixel(int x, int y, int red, int green, int blue, int alpha) {
00504 if (data == NULL)
00505 return false;
00506
00507 if ((y < 0) || (y >= height) || (x < 0) || (x >= width))
00508 return false;
00509
00510 unsigned int* dst = ((unsigned int*) data) + y*width + x;
00511 *dst = red + (green << 8) + (blue << 16) + (alpha << 24);
00512 return true;
00513 }
00514
00515 bool Bitmap::setPixel(long pos, int red, int green, int blue, int alpha) {
00516 if (data == NULL)
00517 return false;
00518 if (pos >= size)
00519 return false;
00520 *(data+pos) = red;
00521 *(data+pos+1) = green;
00522 *(data+pos+2) = blue;
00523 *(data+pos+3) = alpha;
00524 setBitmapUpdated();
00525 return true;
00526 }
00527
00528 bool Bitmap::setPixelXOR(int x, int y, int red, int green, int blue, int alpha) {
00529 if (data == NULL)
00530 return false;
00531
00532 if ((y < 0) || (y >= height) || (x < 0) || (x >= width))
00533 return false;
00534
00535 unsigned int* dst = ((unsigned int*) data) + y*width + x;
00536 *dst |= red + (green << 8) + (blue << 16) + (alpha << 24);
00537 return true;
00538 }
00539
00540 bool Bitmap::setPixelXOR(long pos, int red, int green, int blue, int alpha) {
00541 if (data == NULL)
00542 return false;
00543 if (pos >= size)
00544 return false;
00545 *(data+pos) |= red;
00546 *(data+pos+1) |= green;
00547 *(data+pos+2) |= blue;
00548 *(data+pos+3) |= alpha;
00549 setBitmapUpdated();
00550 return true;
00551 }
00552
00553 Pixel Bitmap::getPixel(int x, int y) {
00554 Pixel p;
00555 p.x = x;
00556 p.y = y;
00557 p.value = NULL;
00558 getPixel(&p);
00559 return p;
00560 }
00561
00562 bool Bitmap::getPixel(Pixel* pixel) {
00563 if (pixel == NULL)
00564 return false;
00565 if ( (pixel->x < 0) || (pixel->y < 0) || (pixel->x >= width) || (pixel->y >= height) )
00566 return false;
00567 pixel->value = (unsigned int*)(data + (pixel->y*width*4) + (pixel->x * 4));
00568 return true;
00569 }
00570
00571
00572 long Bitmap::getPos(int x, int y) {
00573 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
00574 return false;
00575 return (y * width*4) + (x * 4);
00576 }
00577
00578 double Bitmap::getDPos(double x, double y) {
00579 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
00580 return false;
00581 return (y * width*4) + (x * 4);
00582 }
00583
00584 Pixel Bitmap::getXY(long pos) {
00585 Pixel p;
00586 ldiv_t d;
00587 d = ldiv(pos, width);
00588 p.y = d.quot;
00589 p.x = d.rem;
00590 p.value = (unsigned int*)(data + (p.y*width*4) + (p.x * 4));
00591 return p;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 bool Bitmap::eraseBitmap() {
00605 return eraseBitmap(255, 255, 255);
00606 }
00607
00608 bool Bitmap::eraseBitmap(int r, int g, int b, int a) {
00609 long n;
00610
00611 BYTE c[4];
00612
00613 int byteWidth = width*4;
00614 char* eraseLine = new char[byteWidth];
00615 c[0] = (BYTE) r;
00616 c[1] = (BYTE) g;
00617 c[2] = (BYTE) b;
00618 c[3] = (BYTE) a;
00619
00620
00621
00622
00623
00624
00625
00626
00627 for (n=0; n<byteWidth; n+=4)
00628 memcpy(eraseLine+n, c, 4);
00629
00630
00631 for (n=0; n < size; n+=(byteWidth))
00632 memcpy(data+n, eraseLine, byteWidth);
00633
00634 delete [] eraseLine;
00635 setBitmapUpdated();
00636 return true;
00637 }
00638
00639 bool Bitmap::eraseBitmap(const Color& color) {
00640 return eraseBitmap(color.r, color.g, color.b);
00641 }
00642
00643 bool Bitmap::replaceColor(const Color& oldColor, const Color& newColor) {
00644 if (data == NULL)
00645 return false;
00646
00647 unsigned int oldcolval = oldColor.r + (oldColor.g << 8) + (oldColor.b << 16);
00648 unsigned int newcolval = newColor.r + (newColor.g << 8) + (newColor.b << 16);
00649
00650 unsigned int* src = (unsigned int*) data;
00651 int len = width * height;
00652 for (int n=0; n<len; n++) {
00653 if ((*src & 0xffffff) == oldcolval)
00654 *src++ = (*src & 0xff000000) + newcolval;
00655 else
00656 src++;
00657 }
00658 return true;
00659 }
00660
00661
00662 bool Bitmap::fillBox(const Box& box, const Color& color) {
00663 return fillBox((int) box.getLeftX(), (int) box.getUpperY(), (int) box.getWidth(), (int) box.getHeight(), color);
00664 }
00665
00666 bool Bitmap::fillBox(int x, int y, int w, int h, const Color& color) {
00667
00668 int byteWidth = width*4;
00669
00670 if (x < 0) {
00671 w += x;
00672 x = 0;
00673 }
00674 if (y < 0) {
00675 h += y;
00676 y = 0;
00677 }
00678
00679 if (w + x > width)
00680 w = width - x;
00681 if (h + y > height)
00682 h = height - y;
00683 if ( (w <= 0) || (h <= 0) )
00684 return false;
00685
00686 int n;
00687 int copybytes = w * 4;
00688 char* src = new char[copybytes];
00689
00690 for (n=0; n < copybytes; n+=4) {
00691 src[n] = color.r;
00692 src[n+1] = color.g;
00693 src[n+2] = color.b;
00694 src[n+3] = 0;
00695 }
00696
00697 char* dst = data + (y*byteWidth + x*4);
00698 for (n=0; n < h; n++) {
00699 memcpy(dst, src, copybytes);
00700 dst += byteWidth;
00701 }
00702 delete [] src;
00703 addBitmapUpdateRegion(Box(x, y, w, h));
00704 return true;
00705 }
00706
00707 Color Bitmap::getPixelColor(int x, int y) {
00708 Color resColor;
00709 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
00710 return Color();
00711 long pos = getPos(x, y);
00712 resColor.r = *(unsigned char*)(data + pos);
00713 resColor.g = *(unsigned char*)(data + pos + 1);
00714 resColor.b = *(unsigned char*)(data + pos + 2);
00715 return resColor;
00716 }
00717
00718
00719
00720
00721 bool Bitmap::putTransPixel(int x, int y, const Color& color, double weight) {
00722 if ( (x < 0) || (y < 0) || (x >= width) || (y >= height) )
00723 return false;
00724 unsigned char* ppix = (unsigned char*)data + (y*width*4) + (x*4);
00725 ppix[0]=(unsigned char)((weight*color.r)+(1-weight)*ppix[0]);
00726 ppix[1]=(unsigned char)((weight*color.g)+(1-weight)*ppix[1]);
00727 ppix[2]=(unsigned char)((weight*color.b)+(1-weight)*ppix[2]);
00728 return true;
00729 }
00730
00731 bool Bitmap::drawLine(const Line& line, const Color& color) {
00732
00733 int x1 = (int) line.startPoint.x;
00734 int y1 = (int) line.startPoint.y;
00735 int x2 = (int) line.endPoint.x;
00736 int y2 = (int) line.endPoint.y;
00737
00738
00739 double const dw=x2-x1;
00740 double const dh=y2-y1;
00741 double const slx=dh/dw;
00742 double const sly=dw/dh;
00743
00744 int extras = 0;
00745 double alpha;
00746
00747
00748 if(fabs(slx)<1.0)
00749 {
00750 if (line.lineWidth <= 1)
00751 extras = 0;
00752 else if ((dh != 0) && (dw != 0)) {
00753 alpha = atan((double)dw/dh);
00754 extras = (int)(line.lineWidth / cos((clPI*0.5) - alpha));
00755 }
00756
00757
00758 int tx1=x1;
00759 int tx2=x2;
00760 double raster=y1;
00761
00762 if(x1>x2)
00763 {
00764 tx1=x2;
00765 tx2=x1;
00766 raster=y2;
00767 }
00768
00769 for(int x=tx1;x<=tx2;x++)
00770 {
00771 int const ri=int(raster);
00772
00773 double const in_y0=1.0-(raster-ri);
00774 double const in_y1=1.0-(ri+1-raster);
00775
00776 putTransPixel(x, ri+0 ,color, in_y0);
00777 for (int n=0; n<extras; n++)
00778 putTransPixel(x, ri+n+1 ,color, 1.0);
00779 putTransPixel(x, ri+extras+1 ,color, in_y1);
00780
00781 raster+=slx;
00782 }
00783 }
00784 else
00785 {
00786 if (line.lineWidth <= 1)
00787 extras = 0;
00788 else if ((dh != 0) && (dw != 0)) {
00789 alpha = atan((double)dw/dh);
00790 extras = (int)(line.lineWidth / sin((clPI*0.5) - alpha));
00791 }
00792
00793
00794 int ty1=y1;
00795 int ty2=y2;
00796 double raster=x1;
00797
00798 if(y1>y2)
00799 {
00800 ty1=y2;
00801 ty2=y1;
00802 raster=x2;
00803 }
00804
00805 for(int y=ty1;y<=ty2;y++)
00806 {
00807 int const ri=int(raster);
00808
00809 double const in_x0=1.0-(raster-ri);
00810 double const in_x1=1.0-(ri+1-raster);
00811
00812 putTransPixel(ri+0, y, color, in_x0);
00813 for (int n=0; n<extras; n++)
00814 putTransPixel(ri+n+1, y ,color, 1.0);
00815 putTransPixel(ri+extras+1, y, color, in_x1);
00816
00817 raster+=sly;
00818 }
00819 }
00820 return true;
00821 }
00822
00823
00824
00825 bool Bitmap::canBeResizedTo(int w, int h) {
00826 double factor = 1.0;
00827
00828
00829 if (w > 0) {
00830
00831 if (w < this->width) {
00832 factor = getBestResizeFactor((double)w/this->width);
00833 }
00834
00835 else if (w > this->width) {
00836 factor = getBestResizeFactor((double)w/this->width);
00837 }
00838 else
00839 return false;
00840 }
00841 else {
00842
00843 if (h < this->height) {
00844 factor = getBestResizeFactor((double)h/this->height);
00845 }
00846
00847 else if (h > this->height) {
00848 factor = getBestResizeFactor((double)h/this->height);
00849 }
00850 else
00851 return false;
00852 }
00853
00854 int newWidth = (int)(this->width * factor);
00855 int newHeight = (int)(this->height * factor);
00856
00857 if ((newWidth == 0) || (newHeight == 0) )
00858 return false;
00859 else if ((newWidth == this->width) || (newHeight == this->height) )
00860 return false;
00861 else
00862 return true;
00863 }
00864
00865 Bitmap* Bitmap::getResizedCopy(double scale) {
00866
00867 if ( (scale <= 0) || (this->width == 0) || (this->height == 0) )
00868 return NULL;
00869 int newWidth, newHeight;
00870 double factor = 1.0;
00871
00872 int scaleUp = 0;
00873 int scaleDown = 0;
00874 int scale66 = 0;
00875 factor = getBestResizeFactors(scale, scaleUp, scaleDown, scale66);
00876
00877 newWidth = (int)(this->width * factor);
00878 if ((double)newWidth != (this->width * factor))
00879 newWidth++;
00880 newHeight = (int)(this->height * factor);
00881 if ((double)newHeight != (this->height * factor))
00882 newHeight++;
00883
00884 if ((newWidth == 0) || (newHeight == 0) )
00885 return NULL;
00886 char* newData = this->createResizedData(newWidth, newHeight, scaleUp, scaleDown, scale66);
00887 if (newData == NULL)
00888 return NULL;
00889
00890 Bitmap* bitmap = new Bitmap(newData, newWidth, newHeight, true);
00891 return bitmap;
00892 }
00893
00894 Bitmap* Bitmap::getResizedCopy(int w, int h, bool proportional) {
00895
00896 if ( (w == 0) || (h == 0) || (this->width == 0) || (this->height == 0) )
00897 return NULL;
00898
00899
00900 if (!proportional)
00901 return NULL;
00902
00903 return getResizedCopy((double)w/this->width);
00904 }
00905
00906 bool Bitmap::resizeTo(int w, int h, bool proportional) {
00907 Bitmap* bitmap = getResizedCopy(w, h, proportional);
00908 if (bitmap == NULL)
00909 return false;
00910 takeDataFromBitmap(bitmap);
00911 delete(bitmap);
00912 return true;
00913 }
00914
00915 double Bitmap::getBestResizeFactors(double factor, int &scaleUp, int &scaleDown, int &scale66) {
00916
00917
00918
00919
00920
00921
00922
00923 double penalty;
00924 double err;
00925 double f;
00926 int max = (int)fabs(factor) + 5;
00927
00928 double best_penalty = 9999;
00929 double best_factor = 0;
00930 int best_a = 0;
00931 int best_b = 0;
00932 int best_c = 0;
00933
00934 for (int a=1; a<max; a++) {
00935 for (int b=1; b<max; b++) {
00936 for (int c=-1; c<=1; c++) {
00937 f = ((double)a/b) * pow(1.5, (double)c);
00938 err = fabs(f - factor);
00939
00940 penalty = err * max * max;
00941 if (c > 0)
00942 penalty += 0.5*c;
00943 else if (c < 0)
00944 penalty += abs(c);
00945 if (b > 0)
00946 penalty += a+b-2;
00947 if (penalty < best_penalty) {
00948 best_a = (a-1);
00949 best_b = b;
00950 best_c = c;
00951 best_penalty = penalty;
00952 best_factor = f;
00953 }
00954 }
00955 }
00956 }
00957 if (best_penalty < 9999) {
00958 scaleUp = best_a;
00959 scaleDown = best_b;
00960 scale66 = best_c;
00961 return best_factor;
00962 }
00963 else
00964 return 0.0;
00965 }
00966
00967 double Bitmap::getBestResizeFactor(double factor) {
00968 int scaleUp = 0;
00969 int scaleDown = 0;
00970 int scale66 = 0;
00971 double answer = getBestResizeFactors(factor, scaleUp, scaleDown, scale66);
00972 if (answer == 0)
00973 return factor;
00974 else
00975 return answer;
00976 }
00977
00978 char* Bitmap::createResizedData(int newWidth, int newHeight, int scaleUp, int scaleDown, int scale66) {
00979
00980 int w = this->width;
00981 int h = this->height;
00982 if ((scaleUp == 0) && (scaleDown == 0) && (scale66 == 0))
00983 return ImageResizeUp(this->data, w, h, 1);
00984
00985 char* newData = NULL;
00986 char* tempData = NULL;
00987
00988 if (scaleUp > 0) {
00989 newData = ImageResizeUp(this->data, w, h, scaleUp+1);
00990 if (scale66 == 1) {
00991 tempData = newData;
00992 newData = ImageResizeUp66(tempData, w, h);
00993 delete [] tempData;
00994 }
00995 else if (scale66 == -1) {
00996 tempData = newData;
00997 newData = ImageResizeDown66(tempData, w, h);
00998 delete [] tempData;
00999 }
01000 if (scaleDown > 1) {
01001 tempData = newData;
01002 newData = ImageResizeDown(tempData, w, h, scaleDown);
01003 delete [] tempData;
01004 }
01005 return newData;
01006 }
01007 else if (scale66 == 1) {
01008 newData = ImageResizeUp66(this->data, w, h);
01009 if (scaleDown > 1) {
01010 tempData = newData;
01011 newData = ImageResizeDown(tempData, w, h, scaleDown);
01012 delete [] tempData;
01013 }
01014 return newData;
01015 }
01016 else if (scale66 == -1) {
01017 newData = ImageResizeDown66(this->data, w, h);
01018 if (scaleDown > 1) {
01019 tempData = newData;
01020 newData = ImageResizeDown(tempData, w, h, scaleDown);
01021 delete [] tempData;
01022 }
01023 return newData;
01024 }
01025 else if (scaleDown > 1) {
01026 newData = ImageResizeDown(this->data, w, h, scaleDown);
01027 return newData;
01028 }
01029 else
01030 return NULL;
01031 }
01032
01033
01034 bool Bitmap::copyDataFromBitmap(Bitmap* bitmap, bool shouldResize) {
01035 if (bitmap == NULL)
01036 return false;
01037
01038 if ( (bitmap->width == this->width) && (bitmap->height == this->height) && (bitmap->size == this->size) ) {
01039 memcpy(this->data, bitmap->data, size);
01040 return true;
01041 }
01042 else if ( (bitmap->width == this->width) && (bitmap->height == this->height) ) {
01043 delete [] this->data;
01044 this->size = bitmap->size;
01045 this->data = new char[size];
01046 memcpy(this->data, bitmap->data, size);
01047 return true;
01048 }
01049 else if (!shouldResize) {
01050 delete [] this->data;
01051 this->size = bitmap->size;
01052 this->data = new char[size];
01053 memcpy(this->data, bitmap->data, size);
01054 return true;
01055 }
01056 else {
01057 Bitmap* bitmap2 = bitmap->getResizedCopy(this->width, this->height, true);
01058 if (bitmap2 == NULL)
01059 return false;
01060 takeDataFromBitmap(bitmap2);
01061 delete(bitmap2);
01062 return true;
01063 }
01064 }
01065
01066 bool Bitmap::takeDataFromBitmap(Bitmap* bitmap) {
01067 if (bitmap == NULL)
01068 return false;
01069 delete [] this->data;
01070 this->size = bitmap->size;
01071 this->width = bitmap->width;
01072 this->height = bitmap->height;
01073 this->data = bitmap->data;
01074 bitmap->data = NULL;
01075 bitmap->size = 0;
01076 bitmap->width = 0;
01077 bitmap->height = 0;
01078 return true;
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 bool Bitmap::drawLine(const PolyLine& polyline, const Color& color) {
01179 for (int n=0; n<polyline.getLineCount(); n++) {
01180 drawLine(polyline.getLine(n), color);
01181 }
01182 setBitmapUpdated();
01183 return true;
01184 }
01185
01186 bool Bitmap::drawBox(const Box& box, const Color& color) {
01187 Line line = Line(box.getUpperLeft(), box.getUpperRight());
01188 drawLine(line, color);
01189 line = Line(box.getUpperRight(), box.getLowerRight());
01190 drawLine(line, color);
01191 line = Line(box.getLowerRight(), box.getLowerLeft());
01192 drawLine(line, color);
01193 line = Line(box.getLowerLeft(), box.getUpperLeft());
01194 drawLine(line, color);
01195 addBitmapUpdateRegion(box);
01196 return true;
01197 }
01198
01199
01200
01201 bool Bitmap::putQuadPixel(int xCenter, int yCenter, int x, int y, const Color& color, double weight) {
01202 putTransPixel(xCenter + y, yCenter + x, color, weight);
01203 putTransPixel(xCenter - y, yCenter + x, color, weight);
01204 putTransPixel(xCenter + y, yCenter - x, color, weight);
01205 putTransPixel(xCenter - y, yCenter - x, color, weight);
01206 putTransPixel(xCenter + x, yCenter + y, color, weight);
01207 putTransPixel(xCenter - x, yCenter + y, color, weight);
01208 putTransPixel(xCenter + x, yCenter - y, color, weight);
01209 putTransPixel(xCenter - x, yCenter - y, color, weight);
01210 return true;
01211 }
01212
01213
01214 bool Bitmap::drawCircle(int xCenter, int yCenter, int radius, const Color& color, double weight, double lineWidth, bool filled) {
01215
01216 if ((((int)lineWidth) > 1) && (!filled)) {
01217 for (int n=0-(round(lineWidth/2)); n<round(lineWidth/2); n++) {
01218 drawCircle(xCenter, yCenter, radius+n, color, weight, 1);
01219 }
01220 return true;
01221 }
01222
01223 #define D(r,y) (ceil(sqrt((double)r*r - y*y)) - sqrt((double)r*r - y*y))
01224
01225 int x = radius;
01226 int y = 0;
01227 int ax;
01228 double T = 0;
01229 double I = 0.93;
01230 if (filled)
01231 for(ax=0; ax<x; ++ax)
01232 putQuadPixel(xCenter, yCenter, ax, y, color, 1.0);
01233
01234 putQuadPixel(xCenter, yCenter, x, y, color, I);
01235
01236 while (x>y)
01237 {
01238 ++y;
01239 if (D(radius,y) < T) --x;
01240 putQuadPixel(xCenter, yCenter, x, y, color, I*(1-D(radius,y)));
01241 if (!filled) {
01242 putQuadPixel(xCenter, yCenter, x-1, y, color, I*(1-D(radius,y)));
01243 }
01244 if (filled) {
01245 for(ax=0; ax<x; ++ax)
01246 putQuadPixel(xCenter, yCenter, ax, y, color, 1.0);
01247 }
01248 T = D(radius,y);
01249 }
01250
01251 return true;
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 }
01287
01288
01289
01290 bool Bitmap::drawBitmap(Bitmap* bitmap, int srcx, int srcy, int dstx, int dsty, int w, int h) {
01291 if ( (bitmap == NULL) || (bitmap->data == NULL) || (bitmap == this) )
01292 return false;
01293
01294 if (srcx < 0)
01295 srcx = 0;
01296 if (srcy < 0)
01297 srcy = 0;
01298
01299 int byteWidth = width*4;
01300 int srcByteWidth = bitmap->width * 4;
01301
01302 int srcStartX = srcx;
01303 if (dstx < 0) {
01304 srcStartX -= dstx;
01305 dstx = 0;
01306 }
01307 int srcStartY = srcy;
01308 if (dsty < 0) {
01309 srcStartY -= dsty;
01310 dsty = 0;
01311 }
01312
01313 if (w > bitmap->width - srcStartX)
01314 w = bitmap->width - srcStartX;
01315 if (h > bitmap->height - srcStartY)
01316 h = bitmap->height - srcStartY;
01317
01318 if (w + dstx > width)
01319 w = width - dstx;
01320 if (h + dsty > height)
01321 h = height - dsty;
01322 if ( (w < 0) || (h < 0) )
01323 return false;
01324
01325
01326 int copybytes = w * 4;
01327 char* src = bitmap->data + (srcStartY*srcByteWidth + (srcStartX*4));
01328 char* dst = data + (dsty*byteWidth + (dstx*4));
01329
01330 for (int n=0; n < h; n++) {
01331 memcpy(dst, src, copybytes);
01332 src += srcByteWidth;
01333 dst += byteWidth;
01334 }
01335 addBitmapUpdateRegion(Box(dstx, dsty, w, h));
01336 return true;
01337 }
01338
01339
01340
01341
01342
01343 bool Bitmap::drawBitmap(Bitmap* bitmap, int x, int y) {
01344 if (bitmap == NULL)
01345 return false;
01346 bitmap->addBitmapUpdateRegion(Box(x, y, bitmap->width, bitmap->height));
01347 return drawBitmap(bitmap, x, y, bitmap->width, bitmap->height);
01348 }
01349
01350 bool Bitmap::drawBitmap(Bitmap* bitmap, int x, int y, int w, int h) {
01351 if ( (bitmap == NULL) || (bitmap->data == NULL) || (bitmap == this) )
01352 return false;
01353
01354 return drawBitmap(bitmap, 0, 0, x, y, w, h);
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 }
01394
01395 bool Bitmap::drawBitmap(Bitmap* bitmap, const Point& p) {
01396 return drawBitmap(bitmap, p.x, p.y);
01397 }
01398
01399 bool Bitmap::drawBitmap(Bitmap* bitmap, const Box& box) {
01400 return drawBitmap(bitmap, (int) box.getLeftX(), (int) box.getUpperY(), (int) box.getWidth(), (int) box.getHeight());
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691 bool Bitmap::readFromFile(const JString& filename) {
01692
01693 BITMAPFILEHEADER bmfh ={0};
01694 BITMAPINFOHEADER bmih ={0};
01695 long count = 0;
01696
01697 int len;
01698 char* dat = JFile::readAFileBinary(filename, len);
01699 if (dat == NULL) {
01700
01701 return false;
01702 }
01703
01704 char* src = dat;
01705
01706
01707 memcpy(&bmfh, src, sizeof(bmfh));
01708 src += sizeof(BITMAPFILEHEADER);
01709
01710 memcpy(&bmih, src, sizeof(bmih));
01711 src += sizeof(BITMAPINFOHEADER);
01712
01713
01714
01715
01716
01717
01718 if (bmih.biCompression != 0) {
01719
01720 delete [] dat;
01721
01722 return false;
01723 }
01724
01725
01726 if (bmih.biBitCount != 24) {
01727
01728 delete [] dat;
01729
01730 return false;
01731 }
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754 int depth = bmih.biBitCount;
01755 int planes = bmih.biPlanes;
01756 int width = bmih.biWidth;
01757 int height = bmih.biHeight;
01758
01759
01760
01761
01762 if(bmih.biSizeImage==0)
01763 bmih.biSizeImage=bmfh.bfSize - bmfh.bfOffBits;
01764
01765
01766
01767
01768
01769 init(width, height);
01770 if (data == NULL) {
01771
01772 return false;
01773 }
01774
01775
01776 convertBitmapFileData(src, width, height, (int)(bmih.biBitCount/8), data, size);
01777
01778
01779 delete [] dat;
01780 setBitmapUpdated();
01781 return true;
01782 }
01783
01784 bool Bitmap::saveToFile(const JString& filename) {
01785 FILE *fp;
01786
01787
01788 if((fp=fopen(filename,"wb"))==NULL)
01789 return false;
01790
01791 int len = 0;
01792 char* buffer = toBitmapFileFormat(len);
01793 if ( (len <= 0) && (buffer == NULL) ) {
01794 delete [] buffer;
01795 fclose(fp);
01796 return false;
01797 }
01798
01799 if (fwrite(buffer, len, 1, fp) != 1) {
01800 delete [] buffer;
01801 fclose(fp);
01802 return false;
01803 }
01804
01805 delete [] buffer;
01806 fclose(fp);
01807 return true;
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891 }
01892
01893 char* Bitmap::toBitmapFileFormat(int& len) {
01894 BITMAPFILEHEADER bmfh={0};
01895 BITMAPINFOHEADER* info;
01896 int infosize = sizeof(BITMAPINFOHEADER) + 2;
01897
01898 long count = 0;
01899 int byteWidth = width*4;
01900
01901 int padding = 4 - ((width*3)%4);
01902 if (padding == 4) padding = 0;
01903
01904 len = sizeof(BITMAPFILEHEADER) + infosize + (height * width * 3) + (padding * height);
01905 char* buffer = new char[len];
01906 char* dst = buffer;
01907
01908
01909 bmfh.bfType = 19778;
01910
01911 bmfh.bfSize = len;
01912 bmfh.bfReserved1 = 0;
01913 bmfh.bfReserved2 = 0;
01914 bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
01915
01916 info = (BITMAPINFOHEADER*) malloc(infosize);
01917 memset(info, 0, infosize);
01918
01919 info->biSize = sizeof(BITMAPINFOHEADER);
01920 info->biWidth = width;
01921 info->biHeight = height;
01922 info->biPlanes = 1;
01923 info->biCompression = 0;
01924 info->biBitCount = 24;
01925 info->biSizeImage = 0;
01926 info->biXPelsPerMeter = 2834;
01927 info->biYPelsPerMeter = 2834;
01928 info->biClrUsed = 0;
01929 info->biClrImportant = 0;
01930
01931
01932
01933 memcpy(dst, &bmfh, sizeof(BITMAPFILEHEADER));
01934 dst += sizeof(BITMAPFILEHEADER);
01935
01936 memcpy(dst, info, sizeof(BITMAPINFOHEADER));
01937 dst += sizeof(BITMAPINFOHEADER);
01938
01939 free(info);
01940
01941
01942 int c, x;
01943 char* src = data + (height-1) * byteWidth;
01944 for (int l = 0; l < height; l++)
01945 {
01946 x = 0;
01947 for (c = 0; c < width; c++) {
01948 *dst++ = src[x+2];
01949 *dst++ = src[x+1];
01950 *dst++ = src[x];
01951 x += 4;
01952 }
01953 for (c=0; c < padding; c++) {
01954 *dst++ = 0;
01955 }
01956 src -= byteWidth;
01957 }
01958 return buffer;
01959 }
01960
01961
01962
01963
01964
01965
01966 int Bitmap::round(double d) {
01967
01968 double f = floor(d);
01969
01970 if ((d - f) < 0.5000)
01971 return (int) f;
01972 else
01973 return (int) (f+1);
01974 }
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 HTMLPage* Bitmap::toHTMLBitmap() {
01999 return new HTMLPage(this);
02000 }
02001
02002 JString Bitmap::toHTML() {
02003 return JString::format("Bitmap size %d bytes, time %s", size, (char*) timestamp.print());
02004 }
02005
02006
02007 JString Bitmap::toXML() {
02008 return "<bitmap />";
02009 }
02010
02011 bool Bitmap::fromXML(XMLNode* node) {
02012
02013 if (node == NULL)
02014 return false;
02015
02016 if (!node->getTag().equalsIgnoreCase("bitmap"))
02017 return false;
02018
02019 return true;
02020 }
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041 bool Bitmap::convertBitmapFileData(char* src, int width, int height, int depth, char* dst, long dstlen) {
02042
02043 int c;
02044 int len = width*depth;
02045 int padding = 4 - (len%4);
02046 if (padding == 4) padding = 0;
02047 int lineWidth = len + padding;
02048 int offset = padding - (2*lineWidth);
02049
02050 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
02051 unsigned int* newdst = (unsigned int*) dst;
02052
02053 for (int l = 0; l < height; l++)
02054 {
02055 for (c = 0; c < width; c++) {
02056 *(newdst++) = ((unsigned int)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
02057 newsrc += depth;
02058 }
02059 newsrc += offset;
02060 }
02061
02062 return true;
02063 }
02064
02065 char* Bitmap::convertBitmapFileDataRunLength(char* src, int width, int height, int depth, long &dstlen) {
02066
02067
02068
02069
02070
02071 char* dst = new char[width*height*4 + 100];
02072
02073 int c;
02074 int padding = 4 - ((width*depth)%4);
02075 if (padding == 4) padding = 0;
02076 int lineWidth = width*depth + padding;
02077 int offset = padding - (2*lineWidth);
02078
02079 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
02080 unsigned int* newdst = (unsigned int*) dst;
02081 unsigned int* lastCtrl = newdst;
02082
02083 int pos = 1;
02084 int length = 0;
02085
02086 bool isInRL = false;
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096 for (int l = 0; l < height; l++)
02097 {
02098 for (c = 0; c < width; c++) {
02099 newdst[pos] = ((unsigned int)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
02100
02101 if (isInRL) {
02102 if (newdst[pos-1] == newdst[pos]) {
02103
02104 pos--;
02105 }
02106 else {
02107
02108 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02109
02110 length = 0;
02111 lastCtrl += 2;
02112 pos++;
02113 newdst[pos] = newdst[pos-1];
02114 isInRL = false;
02115 }
02116 }
02117 else {
02118 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
02119 if (length == 2) {
02120
02121 pos -= 2;
02122 }
02123 else {
02124
02125 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
02126
02127 lastCtrl += length - 1;
02128 length = 2;
02129 pos--;
02130 }
02131 isInRL = true;
02132 }
02133 else {
02134
02135 }
02136 }
02137 pos++;
02138 length++;
02139 newsrc += depth;
02140 }
02141 newsrc += offset;
02142 }
02143 if (isInRL) {
02144 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02145
02146 }
02147 else {
02148 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
02149
02150 }
02151 dstlen = pos * 4;
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210 return dst;
02211 }
02212
02213 char* Bitmap::differenceBitmapFileData(char* orig, char* src, int width, int height, int depth, long &dstlen) {
02214
02215
02216
02217
02218
02219
02220 char* dst = new char[width*height*4 + 100];
02221
02222 int c;
02223 int padding = 4 - ((width*depth)%4);
02224 if (padding == 4) padding = 0;
02225 int lineWidth = width*depth + padding;
02226 int offset = padding - (2*lineWidth);
02227
02228 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
02229 unsigned int* newdst = (unsigned int*) dst;
02230 unsigned int* org = (unsigned int*) orig;
02231
02232 unsigned int* lastCtrl = newdst;
02233
02234 int pos = 1;
02235 int length = 0;
02236 int dlength = 0;
02237
02238 bool isInDif = false;
02239
02240
02241
02242
02243
02244
02245
02246 for (int l = 0; l < height; l++)
02247 {
02248 for (c = 0; c < width; c++) {
02249 newdst[pos] = ((unsigned int)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
02250
02251
02252
02253
02254
02255
02256
02257 if (isInDif) {
02258 if (*org == newdst[pos]) {
02259
02260 pos--;
02261 }
02262 else {
02263
02264 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
02265
02266 length = 0;
02267 lastCtrl++;
02268 pos++;
02269 newdst[pos] = newdst[pos-1];
02270 isInDif = false;
02271 }
02272 }
02273 else {
02274 if (*org == newdst[pos]) {
02275 if (pos == 1) {
02276 pos--;
02277 isInDif = true;
02278 }
02279 else {
02280
02281 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length));
02282
02283 lastCtrl += length + 1;
02284 length = 0;
02285
02286 isInDif = true;
02287 }
02288 }
02289 else {
02290
02291 }
02292 }
02293 pos++;
02294 length++;
02295 newsrc += depth;
02296 org++;
02297 }
02298 newsrc += offset;
02299 }
02300 if (isInDif) {
02301 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
02302
02303 }
02304 else {
02305 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
02306
02307 }
02308 dstlen = pos * 4;
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341 return dst;
02342 }
02343
02344 char* Bitmap::differenceBitmapFileDataRunLength(char* orig, char* src, int width, int height, int depth, long &dstlen) {
02345
02346 char* dst = new char[width*height*4 + 100];
02347
02348 int c;
02349 int padding = 4 - ((width*depth)%4);
02350 if (padding == 4) padding = 0;
02351 int lineWidth = width*depth + padding;
02352 int offset = padding - (2*lineWidth);
02353
02354 unsigned char* newsrc = (unsigned char*) (src + ((height-1) * lineWidth));
02355 unsigned int* newdst = (unsigned int*) dst;
02356 unsigned int* org = (unsigned int*) orig;
02357 unsigned int* lastCtrl = newdst;
02358
02359 int pos = 1;
02360 int length = 0;
02361 int dlength = 0;
02362
02363 bool isInRL = false;
02364 bool isInDif = false;
02365
02366
02367 for (int l = 0; l < height; l++)
02368 {
02369 for (c = 0; c < width; c++) {
02370 newdst[pos] = ((unsigned int)((newsrc[0] << 16) | (newsrc[1] << 8) | (newsrc[2] << 0)));
02371
02372 if (isInDif) {
02373 if (*org == newdst[pos]) {
02374
02375 pos--;
02376 }
02377 else {
02378
02379 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
02380
02381 length = 0;
02382 lastCtrl++;
02383 pos++;
02384 newdst[pos] = newdst[pos-1];
02385 isInDif = false;
02386 }
02387 }
02388 else if (isInRL) {
02389 if (newdst[pos-1] == newdst[pos]) {
02390
02391 pos--;
02392 }
02393 else {
02394
02395 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02396
02397 length = 0;
02398 lastCtrl += 2;
02399 pos++;
02400 newdst[pos] = newdst[pos-1];
02401 isInRL = false;
02402 }
02403 }
02404 else {
02405 if (*org == newdst[pos]) {
02406 if (pos == 1) {
02407 pos--;
02408 }
02409 else {
02410
02411 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length));
02412
02413 lastCtrl += length + 1;
02414 length = 0;
02415
02416 }
02417 isInDif = true;
02418 }
02419 else if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
02420 if (length == 2) {
02421
02422 pos -= 2;
02423 }
02424 else {
02425
02426 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
02427
02428 lastCtrl += length - 1;
02429 length = 2;
02430 pos--;
02431 }
02432 isInRL = true;
02433 }
02434 else {
02435
02436 }
02437 }
02438 pos++;
02439 length++;
02440 org++;
02441 newsrc += depth;
02442 }
02443 newsrc += offset;
02444 }
02445 if (isInDif) {
02446 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
02447
02448 }
02449 else if (isInRL) {
02450 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02451
02452 }
02453 else {
02454 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
02455
02456 }
02457 dstlen = pos * 4;
02458
02459 return dst;
02460 }
02461
02462 BitmapUpdate* Bitmap::getCompressedUpdate(bool destructive) const {
02463 if (!destructive)
02464 return runLengthEncode();
02465 else
02466 return runLengthDestructiveEncode();
02467 }
02468
02469
02470 BitmapUpdate* Bitmap::operator -( const Bitmap &bitmap ) const {
02471
02472 if ( (this->width != bitmap.width) || (this->height != bitmap.height) )
02473 return NULL;
02474
02475 int byteWidth = width*4;
02476
02477 char* dst = new char[width*height*4 + 100];
02478
02479 unsigned int* newsrc = (unsigned int*) this->data;
02480 unsigned int* newdst = (unsigned int*) dst;
02481 unsigned int* org = (unsigned int*) bitmap.data;
02482 unsigned int* lastCtrl = newdst;
02483
02484 int pos = 1;
02485
02486 int length = 0;
02487
02488 bool isInRL = false;
02489 bool isInDif = false;
02490
02491 int maxpos = (int)(width*height*0.9);
02492 unsigned int* endsrc = newsrc + (width*height);
02493 while ((newsrc < endsrc) && (pos <= maxpos)) {
02494
02495 newdst[pos] = *newsrc;
02496
02497 if (isInDif) {
02498 if (*org == newdst[pos]) {
02499
02500 pos--;
02501 }
02502 else {
02503
02504 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
02505
02506 length = 0;
02507 lastCtrl++;
02508 pos++;
02509 newdst[pos] = newdst[pos-1];
02510 isInDif = false;
02511 }
02512 }
02513 else if (isInRL) {
02514 if (newdst[pos-1] == newdst[pos]) {
02515
02516 pos--;
02517 }
02518 else {
02519
02520 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02521
02522 length = 0;
02523 lastCtrl += 2;
02524 pos++;
02525 newdst[pos] = newdst[pos-1];
02526 isInRL = false;
02527 }
02528 }
02529 else {
02530 if (*org == newdst[pos]) {
02531 if (pos == 1) {
02532 pos--;
02533 }
02534 else {
02535
02536 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length));
02537
02538 lastCtrl += length + 1;
02539 length = 0;
02540
02541 }
02542 isInDif = true;
02543 }
02544 else if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
02545 if (length == 2) {
02546
02547 pos -= 2;
02548 }
02549 else {
02550
02551 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
02552
02553 lastCtrl += length - 1;
02554 length = 2;
02555 pos--;
02556 }
02557 isInRL = true;
02558 }
02559 else {
02560
02561 }
02562 }
02563 pos++;
02564 length++;
02565 org++;
02566 newsrc++;
02567 }
02568
02569
02570 if (pos > maxpos) {
02571 delete [] dst;
02572 return this->getCompressedUpdate(false);
02573 }
02574
02575
02576 if (isInDif) {
02577 if (pos <= 1) {
02578 delete [] dst;
02579 return NULL;
02580 }
02581 *lastCtrl = (unsigned int)((DIFCTRL << 24) | length);
02582
02583 }
02584 else if (isInRL) {
02585 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02586
02587 }
02588 else {
02589 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
02590
02591 }
02592
02593 BitmapUpdate* update = new BitmapUpdate(width, height);
02594 update->giveData(dst, pos * 4);
02595 update->setUpdateType("DifRunLength");
02596 return update;
02597 }
02598
02599
02600
02601
02602
02603 BitmapUpdate* Bitmap::runLengthEncode() const {
02604
02605 if ( (this->width <= 0) || (this->height <= 0) )
02606 return NULL;
02607
02608 int byteWidth = width*4;
02609
02610 char* dst = new char[width*height*4 + 100];
02611
02612 unsigned int* newsrc = (unsigned int*) this->data;
02613 unsigned int* newdst = (unsigned int*) dst;
02614 unsigned int* lastCtrl = newdst;
02615
02616 int pos = 1;
02617
02618 int length = 0;
02619
02620 bool isInRL = false;
02621
02622 unsigned int* endsrc = newsrc + (width*height);
02623
02624 while (newsrc < endsrc) {
02625 newdst[pos] = *newsrc;
02626
02627 if (isInRL) {
02628 if (newdst[pos-1] == newdst[pos]) {
02629
02630 pos--;
02631 }
02632 else {
02633
02634 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02635
02636 length = 0;
02637 lastCtrl += 2;
02638 pos++;
02639 newdst[pos] = newdst[pos-1];
02640 isInRL = false;
02641 }
02642 }
02643 else {
02644 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
02645 if (length == 2) {
02646
02647 pos -= 2;
02648 }
02649 else {
02650
02651 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
02652
02653 lastCtrl += length - 1;
02654 length = 2;
02655 pos--;
02656 }
02657 isInRL = true;
02658 }
02659 else {
02660
02661 }
02662 }
02663 pos++;
02664 length++;
02665 newsrc++;
02666 }
02667
02668 if (isInRL) {
02669 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02670
02671 }
02672 else {
02673 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
02674
02675 }
02676
02677 BitmapUpdate* update = new BitmapUpdate(width, height);
02678 update->giveData(dst, pos * 4);
02679 update->setUpdateType("RunLength");
02680 return update;
02681 }
02682
02683 BitmapUpdate* Bitmap::runLengthDestructiveEncode() const {
02684
02685 if ( (this->width <= 0) || (this->height <= 0) )
02686 return NULL;
02687
02688 int byteWidth = width*4;
02689
02690 char* dst = new char[width*height*2 + 100];
02691
02692 unsigned int* newsrc = (unsigned int*) this->data;
02693 unsigned int* newdst = (unsigned int*) dst;
02694 unsigned int* lastCtrl = newdst;
02695
02696 int pos = 1;
02697
02698 int length = 0;
02699
02700 bool isInRL = false;
02701
02702 unsigned int* endsrc = newsrc + (width*height);
02703 unsigned int* endsrc1 = endsrc - 2;
02704
02705 while (newsrc < endsrc1) {
02706 newdst[pos] = GET_DRGB_FROM_2RGBS(*newsrc,*(newsrc+1));
02707 newsrc+=2;
02708 if (isInRL) {
02709 if (newdst[pos-1] == newdst[pos]) {
02710
02711 pos--;
02712 }
02713 else {
02714
02715 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02716
02717 length = 0;
02718 lastCtrl += 2;
02719 pos++;
02720 newdst[pos] = newdst[pos-1];
02721 isInRL = false;
02722 }
02723 }
02724 else {
02725 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
02726 if (length == 2) {
02727
02728 pos -= 2;
02729 }
02730 else {
02731
02732 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
02733
02734 lastCtrl += length - 1;
02735 length = 2;
02736 pos--;
02737 }
02738 isInRL = true;
02739 }
02740 else {
02741
02742 }
02743 }
02744 pos++;
02745 length++;
02746
02747 }
02748 if (endsrc-newsrc == 2)
02749 newdst[pos] = GET_DRGB_FROM_2RGBS(*newsrc,*(newsrc+1));
02750 else
02751 newdst[pos] = GET_DRGB_FROM_2RGBS(*newsrc,0);
02752
02753 if (isInRL) {
02754 if (newdst[pos-1] == newdst[pos]) {
02755
02756 pos--;
02757 }
02758 else {
02759
02760 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02761
02762 length = 0;
02763 lastCtrl += 2;
02764 pos++;
02765 newdst[pos] = newdst[pos-1];
02766 isInRL = false;
02767 }
02768 }
02769 else {
02770 if ( (length > 1) && (newdst[pos-2] == newdst[pos-1]) && (newdst[pos-1] == newdst[pos]) ) {
02771 if (length == 2) {
02772
02773 pos -= 2;
02774 }
02775 else {
02776
02777 *lastCtrl = (unsigned int)((DATACTRL << 24) | (length - 2));
02778
02779 lastCtrl += length - 1;
02780 length = 2;
02781 pos--;
02782 }
02783 isInRL = true;
02784 }
02785 else {
02786
02787 }
02788 }
02789 pos++;
02790 length++;
02791 newsrc+=2;
02792
02793 if (isInRL) {
02794 *lastCtrl = (unsigned int)((RLECTRL << 24) | length);
02795
02796 }
02797 else {
02798 *lastCtrl = (unsigned int)((DATACTRL << 24) | length);
02799
02800 }
02801
02802 BitmapUpdate* update = new BitmapUpdate(width, height);
02803 update->giveData(dst, pos * 4);
02804 update->setUpdateType("RL16");
02805 return update;
02806 }
02807
02808
02809
02810 char* ImageResizeDown66(char* bytesource, int &cols, int &rows)
02811 {
02812
02813
02814
02815
02816 char* bytedest = new char[cols*rows*4];
02817
02818 unsigned int* source = (unsigned int*) bytesource;
02819 unsigned int* dest = (unsigned int*) bytedest;
02820
02821
02822
02823
02824
02825
02826 unsigned int *p;
02827 unsigned int *q;
02828 unsigned int *r;
02829 unsigned int *s;
02830 unsigned int *t;
02831 unsigned int *u;
02832 unsigned int *v;
02833 unsigned int *w;
02834 unsigned int *x;
02835 unsigned int *a;
02836 unsigned int *b;
02837 unsigned int *c;
02838 unsigned int *d;
02839
02840 unsigned int** shrows = new unsigned int*[rows];
02841
02842 shrows[0] = source;
02843 for (int n=1; n<rows; n++) {
02844 shrows[n] = shrows[n-1] + cols;
02845 }
02846
02847 q = shrows[0] + 1;
02848 s = shrows[1];
02849 t = s + 1;
02850 u = t + 1;
02851 w = shrows[2] + 1;
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874 int newcols = (int)((2.0*cols)/3.0);
02875 int newrows = (int)((2.0*rows)/3.0);
02876
02877 if (newcols != (2.0*cols/3.0))
02878 newcols++;
02879 if (newrows != (2.0*cols/3.0))
02880 newrows++;
02881
02882 unsigned int *r1 = dest;
02883 unsigned int *r2 = dest + newcols;
02884
02885
02886
02887 int j;
02888 for(int i = 0, k = 0; i < rows; i += 3, k += 2) {
02889 p = shrows[i];
02890 q = p+1;
02891 r = q+1;
02892 if (rows - i > 2)
02893 s = shrows[i+1];
02894 else
02895 s = p;
02896 t = s+1;
02897 u = t+1;
02898 if (rows - i > 2)
02899 v = shrows[i+2];
02900 else
02901 v = p;
02902 w = v+1;
02903 x = w+1;
02904
02905
02906 r1 = dest + (newcols * k);
02907
02908 r2 = r1 + newcols;
02909
02910 a = r1;
02911 b = a+1;
02912 if (newrows - k < 1)
02913 c = a;
02914 else
02915 c = r2;
02916 d = c+1;
02917
02918 for(j = 0; j < cols-3; j += 3) {
02919 *a = GET_RGB_FROM_RGBA(*p);
02920 *b = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*q) + (double)GET_R_FROM_RGBA(*r))/2)) << 0) +
02921 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*q) + (double)GET_G_FROM_RGBA(*r))/2)) << 8) +
02922 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*q) + (double)GET_B_FROM_RGBA(*r))/2)) << 16);
02923 *c = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*s) + (double)GET_R_FROM_RGBA(*v))/2)) << 0) +
02924 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*s) + (double)GET_G_FROM_RGBA(*v))/2)) << 8) +
02925 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*s) + (double)GET_B_FROM_RGBA(*v))/2)) << 16);
02926 *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) +
02927 (((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) +
02928 (((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);
02929
02930 p += 3;
02931 q += 3;
02932 r += 3;
02933 s += 3;
02934 t += 3;
02935 u += 3;
02936 v += 3;
02937 w += 3;
02938 x += 3;
02939 a += 2;
02940 b += 2;
02941 c += 2;
02942 d += 2;
02943 }
02944 if (cols - j > 0)
02945 *a = GET_RGB_FROM_RGBA(*p);
02946 else
02947 *a = *(a-2);
02948 if (cols - j > 1)
02949 *b = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*q) + (double)GET_R_FROM_RGBA(*r))/2)) << 0) +
02950 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*q) + (double)GET_G_FROM_RGBA(*r))/2)) << 8) +
02951 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*q) + (double)GET_B_FROM_RGBA(*r))/2)) << 16);
02952 else
02953 *b = *(b-2);
02954 if (cols - j > 2)
02955 *c = (((unsigned int)((1+(double)GET_R_FROM_RGBA(*s) + (double)GET_R_FROM_RGBA(*v))/2)) << 0) +
02956 (((unsigned int)((1+(double)GET_G_FROM_RGBA(*s) + (double)GET_G_FROM_RGBA(*v))/2)) << 8) +
02957 (((unsigned int)((1+(double)GET_B_FROM_RGBA(*s) + (double)GET_B_FROM_RGBA(*v))/2)) << 16);
02958 else
02959 *c = *(c-2);
02960 if (cols - j > 3)
02961 *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) +
02962 (((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) +
02963 (((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);
02964 else
02965 *d = *(d-2);
02966
02967 }
02968
02969 delete [] shrows;
02970 cols = newcols;
02971 rows = newrows;
02972 return bytedest;
02973 }
02974
02975 char* ImageResizeUp66(char* bytesource, int &cols, int &rows) {
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985 unsigned int *p;
02986 unsigned int *q;
02987 unsigned int *r;
02988 unsigned int *s;
02989 unsigned int *t;
02990 unsigned int *u;
02991 unsigned int *v;
02992 unsigned int *w;
02993 unsigned int *x;
02994 unsigned int *a;
02995 unsigned int *b;
02996 unsigned int *c;
02997 unsigned int *d;
02998
02999 int newcols = (int)((3.0*(double)cols)/2.0);
03000 int newrows = (int)((3.0*(double)rows)/2.0);
03001 if ((double)newcols != (3.0*cols)/2.0)
03002 newcols++;
03003 if ((double)newrows != (3.0*rows)/2.0)
03004 newrows++;
03005
03006 char* bytedest = new char[newcols*newrows*4];
03007 unsigned int* source = (unsigned int*) bytesource;
03008 unsigned int* dest = (unsigned int*) bytedest;
03009
03010 unsigned int** dhrows = new unsigned int*[newrows];
03011
03012 dhrows[0] = dest;
03013 for (int n=1; n<newrows; n++) {
03014 dhrows[n] = dhrows[n-1] + newcols;
03015 }
03016
03017 q = dhrows[0] + 1;
03018 s = dhrows[1];
03019 t = s + 1;
03020 u = t + 1;
03021 w = dhrows[2] + 1;
03022
03023
03024
03025
03026
03027 unsigned int *r1 = source;
03028 unsigned int *r2 = source + cols;
03029
03030
03031
03032 int realrows = newrows-3;
03033 int realcols = newcols-3;
03034
03035 int i, j, k;
03036 for(i = 0, k = 0; i <= realrows; i += 3, k += 2) {
03037 p = dhrows[i];
03038 q = p+1;
03039 r = q+1;
03040 s = dhrows[i+1];
03041 t = s+1;
03042 u = t+1;
03043 v = dhrows[i+2];
03044 w = v+1;
03045 x = w+1;
03046
03047
03048 r1 = source + (cols * k);
03049
03050 r2 = r1 + cols;
03051
03052 a = r1;
03053 b = a+1;
03054 c = r2;
03055 d = c+1;
03056
03057 for(j = 0; j <= realcols; j += 3) {
03058 *p = GET_RGB_FROM_RGBA(*a);
03059 *q = *r = GET_RGB_FROM_RGBA(*b);
03060 *s = *v = GET_RGB_FROM_RGBA(*c);
03061 *t = *u = *w = *x = GET_RGB_FROM_RGBA(*d);;
03062 p += 3;
03063 q += 3;
03064 r += 3;
03065 s += 3;
03066 t += 3;
03067 u += 3;
03068 v += 3;
03069 w += 3;
03070 x += 3;
03071 a += 2;
03072 b += 2;
03073 c += 2;
03074 d += 2;
03075 }
03076 if (newcols - j == 2) {
03077 *p = GET_RGB_FROM_RGBA(*a);
03078 *q= GET_RGB_FROM_RGBA(*b);
03079 *s = *v = GET_RGB_FROM_RGBA(*c);
03080 *t= *w = GET_RGB_FROM_RGBA(*d);;
03081 }
03082 else if (newcols - j == 1) {
03083 *p = GET_RGB_FROM_RGBA(*a);
03084 *s = *v = GET_RGB_FROM_RGBA(*c);
03085 }
03086 }
03087 if (newrows - i == 2) {
03088 p = dhrows[i];
03089 q = p+1;
03090 r = q+1;
03091 s = dhrows[i+1];
03092 t = s+1;
03093 u = t+1;
03094
03095
03096 r1 = source + (cols * k);
03097
03098 r2 = r1 + cols;
03099
03100 a = r1;
03101 b = a+1;
03102 c = r2;
03103 d = c+1;
03104
03105 for(j = 0; j <= realcols; j += 3) {
03106 *p = GET_RGB_FROM_RGBA(*a);
03107 *q = *r = GET_RGB_FROM_RGBA(*b);
03108 *s = GET_RGB_FROM_RGBA(*c);
03109 *t = *u = GET_RGB_FROM_RGBA(*d);;
03110 p += 3;
03111 q += 3;
03112 r += 3;
03113 s += 3;
03114 t += 3;
03115 u += 3;
03116 v += 3;
03117 w += 3;
03118 x += 3;
03119 a += 2;
03120 b += 2;
03121 c += 2;
03122 d += 2;
03123 }
03124 if (newcols - j == 2) {
03125 *p = GET_RGB_FROM_RGBA(*a);
03126 *q= GET_RGB_FROM_RGBA(*b);
03127 *s =GET_RGB_FROM_RGBA(*c);
03128 *t= GET_RGB_FROM_RGBA(*d);;
03129 }
03130 else if (newcols - j == 1) {
03131 *p = GET_RGB_FROM_RGBA(*a);
03132 *s = GET_RGB_FROM_RGBA(*c);
03133 }
03134 }
03135 else if (newrows - i == 1) {
03136 p = dhrows[i];
03137 q = p+1;
03138 r = q+1;
03139
03140
03141 r1 = source + (cols * k);
03142
03143 r2 = r1 + cols;
03144
03145 a = r1;
03146 b = a+1;
03147 c = r2;
03148 d = c+1;
03149
03150 for(j = 0; j <= realcols; j += 3) {
03151 *p = GET_RGB_FROM_RGBA(*a);
03152 *q = *r = GET_RGB_FROM_RGBA(*b);
03153 p += 3;
03154 q += 3;
03155 r += 3;
03156 s += 3;
03157 t += 3;
03158 u += 3;
03159 v += 3;
03160 w += 3;
03161 x += 3;
03162 a += 2;
03163 b += 2;
03164 c += 2;
03165 d += 2;
03166 }
03167 if (newcols - j == 2) {
03168 *p = GET_RGB_FROM_RGBA(*a);
03169 *q= GET_RGB_FROM_RGBA(*b);
03170 }
03171 else if (newcols - j == 1) {
03172 *p = GET_RGB_FROM_RGBA(*a);
03173 }
03174 }
03175
03176 delete [] dhrows;
03177 cols = newcols;
03178 rows = newrows;
03179 return bytedest;
03180 }
03181
03182 char* ImageResizeDown(char* bytesource, int &cols, int &rows, int factor) {
03183 if (factor <= 0) {
03184 return NULL;
03185 }
03186 int factor2 = factor*factor;
03187
03188 int newcols = (int)((double)cols/factor);
03189 int newrows = (int)((double)rows/factor);
03190 if ((double)newcols != ((double)cols/factor))
03191 newcols++;
03192 if ((double)newrows != ((double)rows/factor))
03193 newrows++;
03194
03195 char* bytedest = new char[newcols*newrows*4];
03196
03197 if (factor == 1) {
03198 memcpy(bytedest, bytesource, cols*rows*4);
03199 return bytedest;
03200 }
03201
03202 unsigned int* source = (unsigned int*) bytesource;
03203 unsigned int* dest = (unsigned int*) bytedest;
03204
03205 int n, m;
03206
03207 unsigned int* srcStartPixel = source;
03208
03209 unsigned char* srcPixelByte;
03210
03211 double r;
03212 double g;
03213 double b;
03214 int step = (cols - factor)*4;
03215 int linestep = (factor-1)*cols;
03216
03217 int rowmax = rows-factor;
03218 int colmax = cols-factor;
03219
03220
03221
03222 int factorX, factorY;
03223
03224 double dfactor2 = 1.0/((double)factor2);
03225
03226 unsigned char* destPixelByte = (unsigned char*) dest;
03227
03228 for (int y=0; y<=rowmax; y+=factor) {
03229 factorY = clmin(factor, rows-y);
03230 for (int x=0; x<=colmax; x+=factor) {
03231 factorX = clmin(factor, cols-x);
03232
03233 r = g = b = 0;
03234 factor2 = factorY*factorX;
03235 srcPixelByte = (unsigned char*)srcStartPixel;
03236 for (n=0; n<factorY; n++) {
03237 for (m=0; m<factorX; m++) {
03238 r += *srcPixelByte++;
03239 g += *srcPixelByte++;
03240 b += *srcPixelByte++;
03241 srcPixelByte++;
03242 }
03243 srcPixelByte += step;
03244 }
03245 *destPixelByte++ = (unsigned char) (r*dfactor2);
03246 *destPixelByte++ = (unsigned char) (g*dfactor2);
03247 *destPixelByte++ = (unsigned char) (b*dfactor2);
03248 *destPixelByte++ = 0;
03249
03250
03251
03252
03253 srcStartPixel += factorX;
03254 }
03255 srcStartPixel += linestep;
03256
03257
03258
03259
03260
03261
03262 }
03263 cols = newcols;
03264 rows = newrows;
03265 return bytedest;
03266 }
03267
03268 char* ImageResizeUp(char* bytesource, int &cols, int &rows, int factor) {
03269
03270 if (factor <= 0) {
03271 return NULL;
03272 }
03273 int factor2 = factor*factor;
03274 int newcols = cols*factor;
03275 int newrows = rows*factor;
03276
03277 char* bytedest = new char[newcols*newrows*4];
03278 if (factor == 1) {
03279 memcpy(bytedest, bytesource, cols*rows*4);
03280 return bytedest;
03281 }
03282
03283 unsigned int* source = (unsigned int*) bytesource;
03284 unsigned int* dest = (unsigned int*) bytedest;
03285
03286 int destCols = cols*factor;
03287 int n, m, pixel;
03288 unsigned int* destStartPixel = dest;
03289 unsigned int* destPixel;
03290 unsigned int* srcPixel = source;
03291 int step = destCols - factor;
03292 int linestep = (factor-1)*destCols;
03293
03294
03295
03296 for (int x=0; x<rows; x++) {
03297 for (int y=0; y<cols; y++) {
03298 destPixel = destStartPixel;
03299 pixel = GET_RGB_FROM_RGBA(*srcPixel++);
03300 for (n=0; n<factor; n++) {
03301 for (m=0; m<factor; m++) {
03302 *destPixel++ = pixel;
03303 }
03304 destPixel += step;
03305 }
03306 destStartPixel += factor;
03307 }
03308 destStartPixel += linestep;
03309 }
03310
03311 cols = newcols;
03312 rows = newrows;
03313 return bytedest;
03314 }
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324 }