- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-ILU/src/ilu_region.c

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Utility Sources
    00004 // Copyright (C) 2000-2002 by Denton Woods
    00005 // Last modified: 07/09/2002 <--Y2K Compliant! =]
    00006 //
    00007 // Filename: src-ILU/src/ilu_region.c
    00008 //
    00009 // Description: Creates an image region.
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "ilu_internal.h"
    00015 #include "ilu_region.h"
    00016
    00017 ILpointi        *RegionPointsi = NULL;
    00018 ILpointf        *RegionPointsf = NULL;
    00019 ILuint          PointNum = 0;
    00020 ILubyte         *iRegionMask = NULL;
    00021
    00022 void ILAPIENTRY iluRegionfv(ILpointf *Points, ILuint n)
    00023 {
    00024         if (Points == NULL || n == 0) {
    00025                 ifree(RegionPointsi);
    00026                 ifree(RegionPointsf);
    00027                 RegionPointsf = NULL;
    00028                 PointNum = 0;
    00029                 return;
    00030         }
    00031         if (n < 3) {
    00032                 ilSetError(ILU_INVALID_PARAM);
    00033                 return;
    00034         }
    00035         ifree(RegionPointsi);
    00036         ifree(RegionPointsf);
    00037         RegionPointsf = (ILpointf*)ialloc(sizeof(ILpointf) * n);
    00038         if (RegionPointsf == NULL)
    00039                 return;
    00040         memcpy(RegionPointsf, Points, sizeof(ILpointi) * n);
    00041         PointNum = n;
    00042         return;
    00043 }
    00044
    00045
    00046 void ILAPIENTRY iluRegioniv(ILpointi *Points, ILuint n)
    00047 {
    00048         if (Points == NULL || n == 0) {
    00049                 ifree(RegionPointsi);
    00050                 ifree(RegionPointsf);
    00051                 RegionPointsi = NULL;
    00052                 PointNum = 0;
    00053                 return;
    00054         }
    00055         if (n < 3) {
    00056                 ilSetError(ILU_INVALID_PARAM);
    00057                 return;
    00058         }
    00059         ifree(RegionPointsi);
    00060         ifree(RegionPointsf);
    00061         RegionPointsi = (ILpointi*)ialloc(sizeof(ILpointi) * n);
    00062         if (RegionPointsi == NULL)
    00063                 return;
    00064         memcpy(RegionPointsi, Points, sizeof(ILpointi) * n);
    00065         PointNum = n;
    00066         return;
    00067 }
    00068
    00069
    00070 // Inserts edge into list in order of increasing xIntersect field.
    00071 void InsertEdge(Edge *list, Edge *edge)
    00072 {
    00073         Edge *p, *q = list;
    00074
    00075         p = q->next;
    00076         while (p != NULL) {
    00077                 if (edge->xIntersect < p->xIntersect) {
    00078                         p = NULL;
    00079                 }
    00080                 else {
    00081                         q = p;
    00082                         p = p->next;
    00083                 }
    00084         }
    00085         edge->next = q->next;
    00086         q->next = edge;
    00087 }
    00088
    00089
    00090 // For an index, return y-coordinate of next nonhorizontal line
    00091 ILint yNext(ILint k, ILint cnt, ILpointi *pts)
    00092 {
    00093         ILint j;
    00094
    00095         if ((k+1) > (cnt-1))
    00096                 j = 0;
    00097         else
    00098                 j = k + 1;
    00099
    00100         while (pts[k].y == pts[j].y) {
    00101                 if ((j+1) > (cnt-1))
    00102                         j = 0;
    00103                 else
    00104                         j++;
    00105         }
    00106
    00107         return pts[j].y;
    00108 }
    00109
    00110
    00111 // Store lower-y coordinate and inverse slope for each edge.  Adjust
    00112 //      and store upper-y coordinate for edges that are the lower member
    00113 //      of a monotonically increasing or decreasing pair of edges
    00114 void MakeEdgeRec(ILpointi lower, ILpointi upper, ILint yComp, Edge *edge, Edge *edges[])
    00115 {
    00116         edge->dxPerScan = (ILfloat)(upper.x - lower.x) / (upper.y - lower.y);
    00117         edge->xIntersect = (ILfloat)lower.x;
    00118         if (upper.y < yComp)
    00119                 edge->yUpper = upper.y - 1;
    00120         else
    00121                 edge->yUpper = upper.y;
    00122
    00123         InsertEdge(edges[lower.y], edge);
    00124 }
    00125
    00126
    00127 void BuildEdgeList(ILuint cnt, ILpointi *pts, Edge **edges)
    00128 {
    00129         Edge *edge;
    00130         ILpointi v1, v2;
    00131         ILuint i;
    00132         ILint yPrev = pts[cnt - 2].y;
    00133
    00134         v1.x = pts[cnt-1].x;
    00135         v1.y = pts[cnt-1].y;
    00136
    00137         for (i = 0; i < cnt; i++) {
    00138                 v2 = pts[i];
    00139                 if (v1.y != v2.y) {                     // nonhorizontal line
    00140                         edge = (Edge*)ialloc(sizeof(Edge));
    00141                         if (v1.y < v2.y) {              // up-going edge
    00142                                 MakeEdgeRec(v1, v2, yNext(i, cnt, pts), edge, edges);
    00143                         }
    00144                         else {                                  // down-going edge
    00145                                 MakeEdgeRec(v2, v1, yPrev, edge, edges);
    00146                         }
    00147                 }
    00148                 yPrev = v1.y;
    00149                 v1 = v2;
    00150         }
    00151 }
    00152
    00153
    00154 void BuildActiveList(ILint scan, Edge *active, Edge *edges[])
    00155 {
    00156         Edge *p, *q;
    00157
    00158         p = edges[scan]->next;
    00159         while (p) {
    00160                 q = p->next;
    00161                 InsertEdge(active, p);
    00162                 p = q;
    00163         }
    00164 }
    00165
    00166
    00167 #define iRegionSetPixel(x,y) (iRegionMask[y * iluCurImage->Width + x] = 1 )
    00168
    00169
    00170 void FillScan(ILint scan, Edge *active)
    00171 {
    00172         Edge *p1, *p2;
    00173         ILint i;
    00174
    00175         p1 = active->next;
    00176         while (p1) {
    00177                 p2 = p1->next;
    00178                 for (i = (ILuint)p1->xIntersect; i < p2->xIntersect; i++) {
    00179                         iRegionSetPixel((ILuint)i, scan);
    00180                 }
    00181                 p1 = p2->next;
    00182         }
    00183 }
    00184
    00185
    00186 void DeleteAfter(Edge *q)
    00187 {
    00188         Edge *p = q->next;
    00189         q->next = p->next;
    00190         free(p);
    00191 }
    00192
    00193
    00194 // Delete completed edges.  Update 'xIntersect' field for others
    00195 void UpdateActiveList(ILint scan, Edge *active)
    00196 {
    00197         Edge *q = active, *p = active->next;
    00198
    00199         while (p) {
    00200                 if (scan >= p->yUpper) {
    00201                         p = p->next;
    00202                         DeleteAfter(q);
    00203                 }
    00204                 else {
    00205                         p->xIntersect = p->xIntersect + p->dxPerScan;
    00206                         q = p;
    00207                         p = p->next;
    00208                 }
    00209         }
    00210 }
    00211
    00212
    00213 void ResortActiveList(Edge *active)
    00214 {
    00215         Edge *q, *p = active->next;
    00216
    00217         active->next = NULL;
    00218         while (p) {
    00219                 q = p->next;
    00220                 InsertEdge(active, p);
    00221                 p = q;
    00222         }
    00223 }
    00224
    00225
    00226 ILubyte *iScanFill()
    00227 {
    00228         Edge    **edges = NULL, *active = NULL/*, *temp*/;
    00229         ILuint  i, scan;
    00230
    00231         iRegionMask = NULL;
    00232
    00233         if ((RegionPointsi == NULL && RegionPointsf == NULL) || PointNum == 0)
    00234                 return NULL;
    00235
    00236         if (RegionPointsf) {
    00237                 RegionPointsi = (ILpointi*)ialloc(sizeof(ILpointi) * PointNum);
    00238                 if (RegionPointsi == NULL)
    00239                         goto error;
    00240         }
    00241
    00242         for (i = 0; i < PointNum; i++) {
    00243                 if (RegionPointsf) {
    00244                         RegionPointsi[i].x = (ILuint)(iluCurImage->Width * RegionPointsf[i].x);
    00245                         RegionPointsi[i].y = (ILuint)(iluCurImage->Height * RegionPointsf[i].y);
    00246                 }
    00247                 if (RegionPointsi[i].x >= (ILint)iluCurImage->Width || RegionPointsi[i].y >= (ILint)iluCurImage->Height)
    00248                         goto error;
    00249         }
    00250
    00251         edges = (Edge**)ialloc(sizeof(Edge*) * iluCurImage->Height);
    00252         iRegionMask = (ILubyte*)ialloc(iluCurImage->Width * iluCurImage->Height * iluCurImage->Depth);
    00253         if (edges == NULL || iRegionMask == NULL)
    00254                 goto error;
    00255         imemclear(iRegionMask, iluCurImage->Width * iluCurImage->Height * iluCurImage->Depth);
    00256
    00257         for (i = 0; i < iluCurImage->Height; i++) {
    00258                 edges[i] = (Edge*)ialloc(sizeof(Edge));
    00259                 edges[i]->next = NULL;
    00260         }
    00261         BuildEdgeList(PointNum, RegionPointsi, edges);
    00262         active = (Edge*)ialloc(sizeof(Edge));
    00263         active->next = NULL;
    00264
    00265         for (scan = 0; scan < iluCurImage->Height; scan++) {
    00266                 BuildActiveList(scan, active, edges);
    00267                 if (active->next) {
    00268                         FillScan(scan, active);
    00269                         UpdateActiveList(scan, active);
    00270                         ResortActiveList(active);
    00271                 }
    00272         }
    00273
    00274         // Free edge records that have been allocated.
    00275         /*for (i = 0; i < iluCurImage->Height; i++) {
    00276                 while (edges[i]) {
    00277                         temp = edges[i]->next;
    00278                         ifree(edges[i]);
    00279                         edges[i] = temp;
    00280                 }
    00281         }*/
    00282
    00283         ifree(edges);
    00284
    00285         if (RegionPointsf) {
    00286                 ifree(RegionPointsi);
    00287                 RegionPointsi = NULL;
    00288         }
    00289
    00290         return iRegionMask;
    00291
    00292 error:
    00293         if (RegionPointsf) {
    00294                 ifree(RegionPointsi);
    00295                 RegionPointsi = NULL;
    00296         }
    00297
    00298         // Free edge records that have been allocated.
    00299
    00300         ifree(edges);
    00301         ifree(iRegionMask);
    00302         return NULL;
    00303 }
    00304