source: liacs/MIR2010/SourceCode/cximage/ximasel.cpp@ 133

Last change on this file since 133 was 95, checked in by Rick van der Zwet, 15 years ago

Bad boy, improper move of directory

File size: 21.6 KB
Line 
1// xImaSel.cpp : Selection functions
2/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
3 * CxImage version 6.0.0 02/Feb/2008
4 */
5
6#include "ximage.h"
7
8#if CXIMAGE_SUPPORT_SELECTION
9
10////////////////////////////////////////////////////////////////////////////////
11/**
12 * Checks if the image has a valid selection.
13 */
14bool CxImage::SelectionIsValid()
15{
16 return pSelection!=0;
17}
18////////////////////////////////////////////////////////////////////////////////
19/**
20 * Gets the smallest rectangle that contains the selection
21 */
22void CxImage::SelectionGetBox(RECT& r)
23{
24 memcpy(&r,&info.rSelectionBox,sizeof(RECT));
25}
26////////////////////////////////////////////////////////////////////////////////
27/**
28 * Empties the selection.
29 */
30bool CxImage::SelectionClear(BYTE level)
31{
32 if (pSelection){
33 if (level==0){
34 memset(pSelection,0,head.biWidth * head.biHeight);
35 info.rSelectionBox.left = head.biWidth;
36 info.rSelectionBox.bottom = head.biHeight;
37 info.rSelectionBox.right = info.rSelectionBox.top = 0;
38 } else {
39 memset(pSelection,level,head.biWidth * head.biHeight);
40 info.rSelectionBox.right = head.biWidth;
41 info.rSelectionBox.top = head.biHeight;
42 info.rSelectionBox.left = info.rSelectionBox.bottom = 0;
43 }
44 return true;
45 }
46 return false;
47}
48////////////////////////////////////////////////////////////////////////////////
49/**
50 * Allocates an empty selection.
51 */
52bool CxImage::SelectionCreate()
53{
54 SelectionDelete();
55 pSelection = (BYTE*)calloc(head.biWidth * head.biHeight, 1);
56 return (pSelection!=0);
57}
58////////////////////////////////////////////////////////////////////////////////
59/**
60 * Deallocates the selction.
61 */
62bool CxImage::SelectionDelete()
63{
64 if (pSelection){
65 free(pSelection);
66 pSelection=NULL;
67 }
68 info.rSelectionBox.left = head.biWidth;
69 info.rSelectionBox.bottom = head.biHeight;
70 info.rSelectionBox.right = info.rSelectionBox.top = 0;
71 return true;
72}
73////////////////////////////////////////////////////////////////////////////////
74/**
75 * Checks if the coordinates are inside the selection.
76 */
77bool CxImage::SelectionIsInside(long x, long y)
78{
79 if (IsInside(x,y)){
80 if (pSelection==NULL) return true;
81 return pSelection[x+y*head.biWidth]!=0;
82 }
83 return false;
84}
85////////////////////////////////////////////////////////////////////////////////
86/**
87 * Checks if the coordinates are inside the selection.
88 * "blind" version assumes that (x,y) is inside to the image.
89 */
90bool CxImage::BlindSelectionIsInside(long x, long y)
91{
92#ifdef _DEBUG
93 if (!IsInside(x,y))
94 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
95 throw 0;
96 #else
97 return 0;
98 #endif
99#endif
100 if (pSelection==NULL) return true;
101 return pSelection[x+y*head.biWidth]!=0;
102}
103////////////////////////////////////////////////////////////////////////////////
104/**
105 * Adds a rectangle to the existing selection.
106 */
107bool CxImage::SelectionAddRect(RECT r, BYTE level)
108{
109 if (pSelection==NULL) SelectionCreate();
110 if (pSelection==NULL) return false;
111
112 RECT r2;
113 if (r.left<r.right) {r2.left=r.left; r2.right=r.right; } else {r2.left=r.right ; r2.right=r.left; }
114 if (r.bottom<r.top) {r2.bottom=r.bottom; r2.top=r.top; } else {r2.bottom=r.top ; r2.top=r.bottom; }
115
116 if (info.rSelectionBox.top <= r2.top) info.rSelectionBox.top = max(0L,min(head.biHeight,r2.top+1));
117 if (info.rSelectionBox.left > r2.left) info.rSelectionBox.left = max(0L,min(head.biWidth,r2.left));
118 if (info.rSelectionBox.right <= r2.right) info.rSelectionBox.right = max(0L,min(head.biWidth,r2.right+1));
119 if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0L,min(head.biHeight,r2.bottom));
120
121 long ymin = max(0L,min(head.biHeight,r2.bottom));
122 long ymax = max(0L,min(head.biHeight,r2.top+1));
123 long xmin = max(0L,min(head.biWidth,r2.left));
124 long xmax = max(0L,min(head.biWidth,r2.right+1));
125
126 for (long y=ymin; y<ymax; y++)
127 memset(pSelection + xmin + y * head.biWidth, level, xmax-xmin);
128
129 return true;
130}
131////////////////////////////////////////////////////////////////////////////////
132/**
133 * Adds an ellipse to the existing selection.
134 */
135bool CxImage::SelectionAddEllipse(RECT r, BYTE level)
136{
137 if (pSelection==NULL) SelectionCreate();
138 if (pSelection==NULL) return false;
139
140 long xradius = abs(r.right - r.left)/2;
141 long yradius = abs(r.top - r.bottom)/2;
142 if (xradius==0 || yradius==0) return false;
143
144 long xcenter = (r.right + r.left)/2;
145 long ycenter = (r.top + r.bottom)/2;
146
147 if (info.rSelectionBox.left > (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius)));
148 if (info.rSelectionBox.right <= (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius + 1)));
149 if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius)));
150 if (info.rSelectionBox.top <= (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius + 1)));
151
152 long xmin = max(0L,min(head.biWidth,xcenter - xradius));
153 long xmax = max(0L,min(head.biWidth,xcenter + xradius + 1));
154 long ymin = max(0L,min(head.biHeight,ycenter - yradius));
155 long ymax = max(0L,min(head.biHeight,ycenter + yradius + 1));
156
157 long y,yo;
158 for (y=ymin; y<min(ycenter,ymax); y++){
159 for (long x=xmin; x<xmax; x++){
160 yo = (long)(ycenter - yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2)));
161 if (yo<y) pSelection[x + y * head.biWidth] = level;
162 }
163 }
164 for (y=ycenter; y<ymax; y++){
165 for (long x=xmin; x<xmax; x++){
166 yo = (long)(ycenter + yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2)));
167 if (yo>y) pSelection[x + y * head.biWidth] = level;
168 }
169 }
170 return true;
171}
172////////////////////////////////////////////////////////////////////////////////
173/**
174 * Inverts the selection.
175 * Note: the SelectionBox is set to "full image", call SelectionGetBox before (if necessary)
176 */
177bool CxImage::SelectionInvert()
178{
179 if (pSelection) {
180 BYTE *iSrc=pSelection;
181 long n=head.biHeight*head.biWidth;
182 for(long i=0; i < n; i++){
183 *iSrc=(BYTE)~(*(iSrc));
184 iSrc++;
185 }
186
187 SelectionRebuildBox();
188
189 return true;
190 }
191 return false;
192}
193////////////////////////////////////////////////////////////////////////////////
194/**
195 * Imports an existing region from another image with the same width and height.
196 */
197bool CxImage::SelectionCopy(CxImage &from)
198{
199 if (from.pSelection == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
200 if (pSelection==NULL) pSelection = (BYTE*)malloc(head.biWidth * head.biHeight);
201 if (pSelection==NULL) return false;
202 memcpy(pSelection,from.pSelection,head.biWidth * head.biHeight);
203 memcpy(&info.rSelectionBox,&from.info.rSelectionBox,sizeof(RECT));
204 return true;
205}
206////////////////////////////////////////////////////////////////////////////////
207/**
208 * Adds a polygonal region to the existing selection. points points to an array of POINT structures.
209 * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon.
210 * npoints specifies the number of POINT structures in the array pointed to by points.
211 */
212bool CxImage::SelectionAddPolygon(POINT *points, long npoints, BYTE level)
213{
214 if (points==NULL || npoints<3) return false;
215
216 if (pSelection==NULL) SelectionCreate();
217 if (pSelection==NULL) return false;
218
219 BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1);
220 RECT localbox = {head.biWidth,0,0,head.biHeight};
221
222 long x,y,i=0;
223 POINT *current;
224 POINT *next = NULL;
225 POINT *start = NULL;
226 //trace contour
227 while (i < npoints){
228 current = &points[i];
229 if (current->x!=-1){
230 if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i];
231
232 if ((i+1)==npoints || points[i+1].x==-1)
233 next = start;
234 else
235 next = &points[i+1];
236
237 float beta;
238 if (current->x != next->x){
239 beta = (float)(next->y - current->y)/(float)(next->x - current->x);
240 if (current->x < next->x){
241 for (x=current->x; x<=next->x; x++){
242 y = (long)(current->y + (x - current->x) * beta);
243 if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
244 }
245 } else {
246 for (x=current->x; x>=next->x; x--){
247 y = (long)(current->y + (x - current->x) * beta);
248 if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
249 }
250 }
251 }
252 if (current->y != next->y){
253 beta = (float)(next->x - current->x)/(float)(next->y - current->y);
254 if (current->y < next->y){
255 for (y=current->y; y<=next->y; y++){
256 x = (long)(current->x + (y - current->y) * beta);
257 if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
258 }
259 } else {
260 for (y=current->y; y>=next->y; y--){
261 x = (long)(current->x + (y - current->y) * beta);
262 if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
263 }
264 }
265 }
266 }
267
268 RECT r2;
269 if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; }
270 if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; }
271 if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1));
272 if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1));
273 if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1));
274 if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1));
275
276 i++;
277 }
278
279 //fill the outer region
280 long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom);
281 POINT* pix = (POINT*)calloc(npix,sizeof(POINT));
282 BYTE back=0, mark=1;
283 long fx, fy, fxx, fyy, first, last;
284 long xmin = 0;
285 long xmax = 0;
286 long ymin = 0;
287 long ymax = 0;
288
289 for (int side=0; side<4; side++){
290 switch(side){
291 case 0:
292 xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1;
293 break;
294 case 1:
295 xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1;
296 break;
297 case 2:
298 xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1;
299 break;
300 case 3:
301 xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1;
302 break;
303 }
304 //fill from the border points
305 for(y=ymin;y<ymax;y++){
306 for(x=xmin;x<xmax;x++){
307 if (plocal[x+y*head.biWidth]==0){
308 // Subject: FLOOD FILL ROUTINE Date: 12-23-97 (00:57)
309 // Author: Petter Holmberg Code: QB, QBasic, PDS
310 // Origin: petter.holmberg@usa.net Packet: GRAPHICS.ABC
311 first=0;
312 last=1;
313 while(first!=last){
314 fx = pix[first].x;
315 fy = pix[first].y;
316 fxx = fx + x;
317 fyy = fy + y;
318 for(;;)
319 {
320 if ((plocal[fxx + fyy*head.biWidth] == back) &&
321 fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top )
322 {
323 plocal[fxx + fyy*head.biWidth] = mark;
324 if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){
325 pix[last].x = fx;
326 pix[last].y = fy - 1;
327 last++;
328 if (last == npix) last = 0;
329 }
330 if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){
331 pix[last].x = fx;
332 pix[last].y = fy + 1;
333 last++;
334 if (last == npix) last = 0;
335 }
336 } else {
337 break;
338 }
339 fx++;
340 fxx++;
341 };
342
343 fx = pix[first].x - 1;
344 fy = pix[first].y;
345 fxx = fx + x;
346 fyy = fy + y;
347
348 for( ;; )
349 {
350 if ((plocal[fxx + fyy*head.biWidth] == back) &&
351 fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top )
352 {
353 plocal[fxx + (y + fy)*head.biWidth] = mark;
354 if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){
355 pix[last].x = fx;
356 pix[last].y = fy - 1;
357 last++;
358 if (last == npix) last = 0;
359 }
360 if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){
361 pix[last].x = fx;
362 pix[last].y = fy + 1;
363 last++;
364 if (last == npix) last = 0;
365 }
366 } else {
367 break;
368 }
369 fx--;
370 fxx--;
371 }
372
373 first++;
374 if (first == npix) first = 0;
375 }
376 }
377 }
378 }
379 }
380
381 //transfer the region
382 long yoffset;
383 for (y=localbox.bottom; y<=localbox.top; y++){
384 yoffset = y * head.biWidth;
385 for (x=localbox.left; x<=localbox.right; x++)
386 if (plocal[x + yoffset]!=1) pSelection[x + yoffset]=level;
387 }
388 if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = min(head.biHeight,localbox.top + 1);
389 if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = min(head.biWidth,localbox.left);
390 if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = min(head.biWidth,localbox.right + 1);
391 if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = min(head.biHeight,localbox.bottom);
392
393 free(plocal);
394 free(pix);
395
396 return true;
397}
398////////////////////////////////////////////////////////////////////////////////
399/**
400 * Adds to the selection all the pixels matching the specified color.
401 */
402bool CxImage::SelectionAddColor(RGBQUAD c, BYTE level)
403{
404 if (pSelection==NULL) SelectionCreate();
405 if (pSelection==NULL) return false;
406
407 RECT localbox = {head.biWidth,0,0,head.biHeight};
408
409 for (long y = 0; y < head.biHeight; y++){
410 for (long x = 0; x < head.biWidth; x++){
411 RGBQUAD color = BlindGetPixelColor(x, y);
412 if (color.rgbRed == c.rgbRed &&
413 color.rgbGreen == c.rgbGreen &&
414 color.rgbBlue == c.rgbBlue)
415 {
416 pSelection[x + y * head.biWidth] = level;
417
418 if (localbox.top < y) localbox.top = y;
419 if (localbox.left > x) localbox.left = x;
420 if (localbox.right < x) localbox.right = x;
421 if (localbox.bottom > y) localbox.bottom = y;
422 }
423 }
424 }
425
426 if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = localbox.top + 1;
427 if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left;
428 if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = localbox.right + 1;
429 if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom;
430
431 return true;
432}
433////////////////////////////////////////////////////////////////////////////////
434/**
435 * Adds a single pixel to the existing selection.
436 */
437bool CxImage::SelectionAddPixel(long x, long y, BYTE level)
438{
439 if (pSelection==NULL) SelectionCreate();
440 if (pSelection==NULL) return false;
441
442 if (IsInside(x,y)) {
443 pSelection[x + y * head.biWidth] = level; // set the correct mask bit
444
445 if (info.rSelectionBox.top <= y) info.rSelectionBox.top = y+1;
446 if (info.rSelectionBox.left > x) info.rSelectionBox.left = x;
447 if (info.rSelectionBox.right <= x) info.rSelectionBox.right = x+1;
448 if (info.rSelectionBox.bottom > y) info.rSelectionBox.bottom = y;
449
450 return true;
451 }
452
453 return false;
454}
455////////////////////////////////////////////////////////////////////////////////
456/**
457 * Exports the selection channel in a 8bpp grayscale image.
458 */
459bool CxImage::SelectionSplit(CxImage *dest)
460{
461 if (!pSelection || !dest) return false;
462
463 CxImage tmp(head.biWidth,head.biHeight,8);
464 if (!tmp.IsValid()){
465 strcpy(info.szLastError,tmp.GetLastError());
466 return false;
467 }
468
469 for(long y=0; y<head.biHeight; y++){
470 for(long x=0; x<head.biWidth; x++){
471 tmp.BlindSetPixelIndex(x,y,pSelection[x+y*head.biWidth]);
472 }
473 }
474
475 tmp.SetGrayPalette();
476 dest->Transfer(tmp);
477
478 return true;
479}
480////////////////////////////////////////////////////////////////////////////////
481/**
482 * Creates the selection channel from a gray scale image.
483 * black = unselected
484 */
485bool CxImage::SelectionSet(CxImage &from)
486{
487 if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight){
488 strcpy(info.szLastError,"CxImage::SelectionSet: wrong width or height, or image is not gray scale");
489 return false;
490 }
491
492 if (pSelection==NULL) pSelection = (BYTE*)malloc(head.biWidth * head.biHeight);
493
494 BYTE* src = from.info.pImage;
495 BYTE* dst = pSelection;
496 if (src==NULL || dst==NULL){
497 strcpy(info.szLastError,"CxImage::SelectionSet: null pointer");
498 return false;
499 }
500
501 for (long y=0; y<head.biHeight; y++){
502 memcpy(dst,src,head.biWidth);
503 dst += head.biWidth;
504 src += from.info.dwEffWidth;
505 }
506
507 SelectionRebuildBox();
508
509 return true;
510}
511////////////////////////////////////////////////////////////////////////////////
512/**
513 * Sets the Selection level for a single pixel
514 * internal use only: doesn't set SelectionBox. Use SelectionAddPixel
515 */
516void CxImage::SelectionSet(const long x,const long y,const BYTE level)
517{
518 if (pSelection && IsInside(x,y)) pSelection[x+y*head.biWidth]=level;
519}
520////////////////////////////////////////////////////////////////////////////////
521/**
522 * Gets the Selection level for a single pixel
523 */
524BYTE CxImage::SelectionGet(const long x,const long y)
525{
526 if (pSelection && IsInside(x,y)) return pSelection[x+y*head.biWidth];
527 return 0;
528}
529////////////////////////////////////////////////////////////////////////////////
530/**
531 * Rebuilds the SelectionBox
532 */
533void CxImage::SelectionRebuildBox()
534{
535 info.rSelectionBox.left = head.biWidth;
536 info.rSelectionBox.bottom = head.biHeight;
537 info.rSelectionBox.right = info.rSelectionBox.top = 0;
538
539 if (!pSelection)
540 return;
541
542 long x,y;
543
544 for (y=0; y<head.biHeight; y++){
545 for (x=0; x<info.rSelectionBox.left; x++){
546 if (pSelection[x+y*head.biWidth]){
547 info.rSelectionBox.left = x;
548 continue;
549 }
550 }
551 }
552
553 for (y=0; y<head.biHeight; y++){
554 for (x=head.biWidth-1; x>=info.rSelectionBox.right; x--){
555 if (pSelection[x+y*head.biWidth]){
556 info.rSelectionBox.right = x+1;
557 continue;
558 }
559 }
560 }
561
562 for (x=0; x<head.biWidth; x++){
563 for (y=0; y<info.rSelectionBox.bottom; y++){
564 if (pSelection[x+y*head.biWidth]){
565 info.rSelectionBox.bottom = y;
566 continue;
567 }
568 }
569 }
570
571 for (x=0; x<head.biWidth; x++){
572 for (y=head.biHeight-1; y>=info.rSelectionBox.top; y--){
573 if (pSelection[x+y*head.biWidth]){
574 info.rSelectionBox.top = y+1;
575 continue;
576 }
577 }
578 }
579
580}
581////////////////////////////////////////////////////////////////////////////////
582/**
583 * Gets the Selection level for a single pixel
584 * "blind" version assumes that (x,y) is inside to the image.
585 */
586BYTE CxImage::BlindSelectionGet(const long x,const long y)
587{
588#ifdef _DEBUG
589 if (!IsInside(x,y) || (pSelection==0))
590 #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
591 throw 0;
592 #else
593 return 0;
594 #endif
595#endif
596 return pSelection[x+y*head.biWidth];
597}
598////////////////////////////////////////////////////////////////////////////////
599/**
600 * Returns pointer to selection data for pixel (x,y).
601 */
602BYTE* CxImage::SelectionGetPointer(const long x,const long y)
603{
604 if (pSelection && IsInside(x,y)) return pSelection+x+y*head.biWidth;
605 return 0;
606}
607////////////////////////////////////////////////////////////////////////////////
608bool CxImage::SelectionFlip()
609{
610 if (!pSelection) return false;
611
612 BYTE *buff = (BYTE*)malloc(head.biWidth);
613 if (!buff) return false;
614
615 BYTE *iSrc,*iDst;
616 iSrc = pSelection + (head.biHeight-1)*head.biWidth;
617 iDst = pSelection;
618 for (long i=0; i<(head.biHeight/2); ++i)
619 {
620 memcpy(buff, iSrc, head.biWidth);
621 memcpy(iSrc, iDst, head.biWidth);
622 memcpy(iDst, buff, head.biWidth);
623 iSrc-=head.biWidth;
624 iDst+=head.biWidth;
625 }
626
627 free(buff);
628
629 long top = info.rSelectionBox.top;
630 info.rSelectionBox.top = head.biHeight - info.rSelectionBox.bottom;
631 info.rSelectionBox.bottom = head.biHeight - top;
632 return true;
633}
634////////////////////////////////////////////////////////////////////////////////
635bool CxImage::SelectionMirror()
636{
637 if (!pSelection) return false;
638 BYTE* pSelection2 = (BYTE*)malloc(head.biWidth * head.biHeight);
639 if (!pSelection2) return false;
640
641 BYTE *iSrc,*iDst;
642 long wdt=head.biWidth-1;
643 iSrc=pSelection + wdt;
644 iDst=pSelection2;
645 for(long y=0; y < head.biHeight; y++){
646 for(long x=0; x <= wdt; x++)
647 *(iDst+x)=*(iSrc-x);
648 iSrc+=head.biWidth;
649 iDst+=head.biWidth;
650 }
651 free(pSelection);
652 pSelection=pSelection2;
653
654 long left = info.rSelectionBox.left;
655 info.rSelectionBox.left = head.biWidth - info.rSelectionBox.right;
656 info.rSelectionBox.right = head.biWidth - left;
657 return true;
658}
659////////////////////////////////////////////////////////////////////////////////
660#if CXIMAGE_SUPPORT_WINDOWS
661/**
662 * Converts the selection in a HRGN object.
663 */
664bool CxImage::SelectionToHRGN(HRGN& region)
665{
666 if (pSelection && region){
667 for(int y = 0; y < head.biHeight; y++){
668 HRGN hTemp = NULL;
669 int iStart = -1;
670 int x = 0;
671 for(; x < head.biWidth; x++){
672 if (pSelection[x + y * head.biWidth] != 0){
673 if (iStart == -1) iStart = x;
674 continue;
675 }else{
676 if (iStart >= 0){
677 hTemp = CreateRectRgn(iStart, y, x, y + 1);
678 CombineRgn(region, hTemp, region, RGN_OR);
679 DeleteObject(hTemp);
680 iStart = -1;
681 }
682 }
683 }
684 if (iStart >= 0){
685 hTemp = CreateRectRgn(iStart, y, x, y + 1);
686 CombineRgn(region, hTemp, region, RGN_OR);
687 DeleteObject(hTemp);
688 iStart = -1;
689 }
690 }
691 return true;
692 }
693 return false;
694}
695#endif //CXIMAGE_SUPPORT_WINDOWS
696////////////////////////////////////////////////////////////////////////////////
697#endif //CXIMAGE_SUPPORT_SELECTION
Note: See TracBrowser for help on using the repository browser.