Diff of /seamer_.c [000000] .. [2a97a8] Maximize Restore

  Switch to unified view

a b/seamer_.c
1
2
// Modify transparency channel to indicate distance from image area
3
// 255 = in image; distance = 255-alpha
4
5
#ifdef SET_TO_EDGE
6
#undef SET_TO_EDGE
7
#endif
8
#ifdef SET_TO_DISTANCE
9
#undef SET_TO_DISTANCE
10
#endif
11
12
#define SET_TO_EDGE( a )      { ch = a; if( *(PIXEL_TYPE*)ch == 1 ) *(PIXEL_TYPE*)ch = (PIXEL_TYPE)254;}
13
#define SET_TO_DISTANCE( a )  { ch = a; if( *(PIXEL_TYPE*)ch && *(PIXEL_TYPE*)ch < setdist ) *(PIXEL_TYPE*)ch = (PIXEL_TYPE)setdist;}
14
15
16
#ifdef BYTES_PER_CHANNEL
17
#undef BYTES_PER_CHANNEL
18
#endif
19
20
#define BYTES_PER_CHANNEL sizeof(PIXEL_TYPE)
21
22
void _SetDistance ( Image* im, Image* pano, PTRect *theRect, int showprogress )
23
{
24
  int                     x,y,bpp,bppa, bpl, bpla, skip=0,setdist,dist;
25
  unsigned char           *data = *(im->data), *alpha = *(pano->data), *idata, *adata;
26
  register unsigned char  *ch;
27
  char                    *progressMessage, percent[24];
28
  PTRect                  OLRect;
29
  
30
  bpp     = im->bitsPerPixel/8;
31
  bppa    = pano->bitsPerPixel/8;
32
  bpl     = im->bytesPerLine;
33
  bpla    = pano->bytesPerLine;
34
  
35
  OLRect.left     = theRect->right;
36
  OLRect.right    = theRect->left;
37
  OLRect.top      = theRect->bottom;
38
  OLRect.bottom   = theRect->top;
39
40
  if( showprogress )
41
  {
42
      progressMessage = "Merging Images";
43
      Progress( _initProgress, progressMessage );
44
  }
45
46
  
47
  // First, set alpha channel in overlap region to 1, find minimum overlap rectangle
48
  
49
  for(y=theRect->top; y<theRect->bottom; y++)
50
  {
51
      idata = data  + bpl  * y + theRect->left * bpp; 
52
      adata = alpha + bpla * y + theRect->left * bppa;
53
      for(x=theRect->left; x<theRect->right; x++, idata+=bpp, adata+=bppa)
54
      {
55
          if( *(PIXEL_TYPE*)idata == PIXEL_MAX && *(PIXEL_TYPE*)adata == PIXEL_MAX ) // Point in  overlap
56
          {
57
              *(PIXEL_TYPE*)idata = 1; *(PIXEL_TYPE*)adata = 1;
58
              if(x>OLRect.right)  OLRect.right = x;
59
              if(x<OLRect.left )  OLRect.left = x;
60
              if(y>OLRect.bottom) OLRect.bottom = y;
61
              if(y<OLRect.top )   OLRect.top = y;
62
          }
63
      }
64
  }
65
  OLRect.right++;  OLRect.bottom++;
66
  // Set frame
67
  
68
  for(y=theRect->top; y<theRect->bottom; y++)
69
  {
70
      idata = data  + bpl  * y + theRect->left * bpp; 
71
      adata = alpha + bpla * y + theRect->left * bppa;
72
      for(x=theRect->left; x<theRect->right; x++, idata+=bpp, adata+=bppa)
73
      {
74
          if( *(PIXEL_TYPE*)idata  && !*(PIXEL_TYPE*)adata )
75
          {
76
              if  ( x > theRect->left     && *(PIXEL_TYPE*)(adata - bppa))    SET_TO_EDGE( idata - bpp );
77
              if  ( x < theRect->right-1  && *(PIXEL_TYPE*)(adata + bppa))    SET_TO_EDGE( idata + bpp );
78
              if  ( y > theRect->top      && *(PIXEL_TYPE*)(adata - bpla))    SET_TO_EDGE( idata - bpl );
79
              if  ( y < theRect->bottom-1 && *(PIXEL_TYPE*)(adata + bpla))    SET_TO_EDGE( idata + bpl );
80
          }
81
              
82
          if(!*(PIXEL_TYPE*)idata  &&  *(PIXEL_TYPE*)adata )
83
          {   
84
              if  ( x > theRect->left     && *(PIXEL_TYPE*)(idata - bpp))     SET_TO_EDGE( adata - bppa );
85
              if  ( x < theRect->right-1  && *(PIXEL_TYPE*)(idata + bpp))     SET_TO_EDGE( adata + bppa );
86
              if  ( y > theRect->top      && *(PIXEL_TYPE*)(idata - bpl))     SET_TO_EDGE( adata - bpla );
87
              if  ( y < theRect->bottom-1 && *(PIXEL_TYPE*)(idata + bpl))     SET_TO_EDGE( adata + bpla );
88
          }
89
      }
90
  }
91
  
92
93
              
94
  // Set distances    
95
  
96
  for( dist = 2; dist<255; dist++)
97
  {
98
          // Update Progress report and check for cancel every 5 lines.
99
      skip++;
100
      if( showprogress && skip == 5 )
101
      {
102
          
103
          sprintf( percent, "%d", (int) (dist* 100)/255) ;
104
          if( ! Progress( _setProgress, percent ) )
105
                      return;
106
          skip = 0;
107
      }
108
      setdist = 255-dist;
109
110
      for(y=OLRect.top; y<OLRect.bottom; y++)
111
      {
112
          idata = data  + bpl  * y + OLRect.left * bpp; 
113
          adata = alpha + bpla * y + OLRect.left * bppa;
114
          for(x=OLRect.left; x<OLRect.right; x++, idata+=bpp, adata+=bppa)
115
          {
116
              if( *(PIXEL_TYPE*)idata     == setdist + 1 )
117
              {
118
                  if  ( x > OLRect.left       && *(PIXEL_TYPE*)(adata - bppa))    SET_TO_DISTANCE( idata - bpp );
119
                  if  ( x < OLRect.right-1    && *(PIXEL_TYPE*)(adata + bppa))    SET_TO_DISTANCE( idata + bpp );
120
                  if  ( y > OLRect.top        && *(PIXEL_TYPE*)(adata - bpla))    SET_TO_DISTANCE( idata - bpl );
121
                  if  ( y < OLRect.bottom-1   && *(PIXEL_TYPE*)(adata + bpla))    SET_TO_DISTANCE( idata + bpl );
122
              }               
123
              if( *(PIXEL_TYPE*)adata     == setdist + 1 )
124
              {   
125
                  if  ( x > OLRect.left       && *(PIXEL_TYPE*)(idata - bpp))     SET_TO_DISTANCE( adata - bppa );
126
                  if  ( x < OLRect.right-1    && *(PIXEL_TYPE*)(idata + bpp))     SET_TO_DISTANCE( adata + bppa );
127
                  if  ( y > OLRect.top        && *(PIXEL_TYPE*)(idata - bpl))     SET_TO_DISTANCE( adata - bpla );
128
                  if  ( y < OLRect.bottom-1   && *(PIXEL_TYPE*)(idata + bpl))     SET_TO_DISTANCE( adata + bpla );
129
              }
130
          }
131
      }
132
  }
133
134
  if( showprogress )
135
      Progress( _disposeProgress, percent );
136
}
137
138
void _SetDistanceImage ( Image* im, Image* pano, PTRect *theRect, int showprogress, int feather )
139
{
140
  int                     x,y,bpp,bppa, bpl, bpla, skip=0,setdist,dist;
141
  unsigned char           *data = *(im->data), *alpha = *(pano->data), *idata, *adata;
142
  register unsigned char  *ch;
143
  char                    *progressMessage, percent[24];
144
  PTRect                  OLRect;
145
  
146
  bpp     = im->bitsPerPixel/8;
147
  bppa    = pano->bitsPerPixel/8;
148
  bpl     = im->bytesPerLine;
149
  bpla    = pano->bytesPerLine;
150
  
151
  OLRect.left     = theRect->right;
152
  OLRect.right    = theRect->left;
153
  OLRect.top      = theRect->bottom;
154
  OLRect.bottom   = theRect->top;
155
156
  if( showprogress )
157
  {
158
      progressMessage = "Merging Images";
159
      Progress( _initProgress, progressMessage );
160
  }
161
162
  
163
  // First, set alpha channel in overlap region to 1, find minimum overlap rectangle
164
  
165
  for(y=theRect->top; y<theRect->bottom; y++)
166
  {
167
      idata = data  + bpl  * y + theRect->left * bpp; 
168
      adata = alpha + bpla * y + theRect->left * bppa;
169
      for(x=theRect->left; x<theRect->right; x++, idata+=bpp, adata+=bppa)
170
      {
171
          if( *(PIXEL_TYPE*)idata == PIXEL_MAX && *(PIXEL_TYPE*)adata == PIXEL_MAX ) // Point in  overlap
172
          {
173
              *(PIXEL_TYPE*)adata = 1; 
174
              if(x>OLRect.right)  OLRect.right = x;
175
              if(x<OLRect.left )  OLRect.left = x;
176
              if(y>OLRect.bottom) OLRect.bottom = y;
177
              if(y<OLRect.top )   OLRect.top = y;
178
          }
179
      }
180
  }
181
  OLRect.right++;  OLRect.bottom++;
182
  // Set frame
183
  
184
  for(y=theRect->top; y<theRect->bottom; y++)
185
  {
186
      idata = data  + bpl  * y + theRect->left * bpp; 
187
      adata = alpha + bpla * y + theRect->left * bppa;
188
      for(x=theRect->left; x<theRect->right; x++, idata+=bpp, adata+=bppa)
189
      {
190
          if(!*(PIXEL_TYPE*)idata  &&  *(PIXEL_TYPE*)adata )
191
          {   
192
              if  ( x > theRect->left     && *(PIXEL_TYPE*)(idata - bpp))         SET_TO_EDGE( adata - bppa );
193
              if  ( x < theRect->right-1  && *(PIXEL_TYPE*)(idata + bpp))         SET_TO_EDGE( adata + bppa );
194
              if  ( y > theRect->top      && *(PIXEL_TYPE*)(idata - bpl))         SET_TO_EDGE( adata - bpla );
195
              if  ( y < theRect->bottom-1 && *(PIXEL_TYPE*)(idata + bpl))         SET_TO_EDGE( adata + bpla );
196
          }
197
      }
198
  }
199
  
200
201
              
202
  // Set distances    
203
  
204
  feather+=2;
205
  if(feather > 255) feather = 255;
206
  for( dist = 2; dist<feather; dist++)
207
  {
208
          // Update Progress report and check for cancel every 5 lines.
209
      skip++;
210
      if( showprogress && skip == 5 )
211
      {
212
          
213
          sprintf( percent, "%d", (int) (dist* 100)/255) ;
214
          if( ! Progress( _setProgress, percent ) )
215
                      return;
216
          skip = 0;
217
      }
218
      setdist = 255-dist;
219
220
      for(y=OLRect.top; y<OLRect.bottom; y++)
221
      {
222
          idata = data  + bpl  * y + OLRect.left * bpp; 
223
          adata = alpha + bpla * y + OLRect.left * bppa;
224
          for(x=OLRect.left; x<OLRect.right; x++, idata+=bpp, adata+=bppa)
225
          {
226
              if( *(PIXEL_TYPE*)adata     == setdist + 1 )
227
              {   
228
                  if  ( x > OLRect.left       && *(PIXEL_TYPE*)(idata - bpp))         SET_TO_DISTANCE( adata - bppa );
229
                  if  ( x < OLRect.right-1    && *(PIXEL_TYPE*)(idata + bpp))         SET_TO_DISTANCE( adata + bppa );
230
                  if  ( y > OLRect.top        && *(PIXEL_TYPE*)(idata - bpl))         SET_TO_DISTANCE( adata - bpla );
231
                  if  ( y < OLRect.bottom-1   && *(PIXEL_TYPE*)(idata + bpl))         SET_TO_DISTANCE( adata + bpla );
232
              }
233
          }
234
      }
235
  }
236
237
  if( showprogress )
238
      Progress( _disposeProgress, percent );
239
}
240
                  
241
242
// Add image src to dst; use alpha channel
243
// seam is placed in the middle between edges of valid 
244
// image portions.
245
// feather specifies width of soft edge (in pixels)
246
// showprogress = 1: Progressbar is displayed
247
// return 0 on success, -1 on failure
248
249
int _merge (  Image *dst, Image *src,  int feather, int showprogress, int seam )
250
{
251
  register int            x,y, i;
252
  register unsigned char *dest, *source;  // Pointer to rgb-data
253
    double                    sfactor = 1.0;
254
  register double         result;
255
  PTRect                  theRect;
256
  int                     bps,bpd;
257
  
258
259
  // Do all sorts of checks (size, etc)
260
261
  if( (dst->bytesPerLine != src->bytesPerLine) ||
262
      (dst->width        != src->width)        ||
263
      (dst->height       != src->height)       ||
264
      (dst->dataSize     != src->dataSize)     ||
265
      (dst->bitsPerPixel != src->bitsPerPixel) ||
266
      (dst->bitsPerPixel != 32 && dst->bitsPerPixel != 64)    ||
267
      (dst->data         == NULL)              ||
268
      (src->data         == NULL))
269
  {
270
      return -1;
271
  }
272
      
273
  theRect.left    = 0;
274
  theRect.right   = dst->width;
275
  theRect.top     = 0;
276
  theRect.bottom  = dst->height;
277
  
278
  bps = src->bitsPerPixel/8;
279
  bpd = dst->bitsPerPixel/8;
280
281
  if( seam == _middle ){
282
      _SetDistance ( src, dst, &theRect, showprogress );
283
284
      for(y=0; y<dst->height; y++){   
285
          dest    = *(dst->data) + y*dst->bytesPerLine;
286
          source  = *(src->data) + y*src->bytesPerLine;
287
          for(x=0; x<dst->width; x++, dest+=bpd, source+=bps){
288
              if( *(PIXEL_TYPE*)source ) {// alpha channel set
289
                  if( !*(PIXEL_TYPE*)dest ) {// No data in dest, so copy source to dest
290
                      *(PIXEL_TYPE*)dest = 1; 
291
                      *(PIXEL_TYPE*)(dest+BYTES_PER_CHANNEL)      = *(PIXEL_TYPE*)(source+BYTES_PER_CHANNEL);
292
                      *(PIXEL_TYPE*)(dest+2*BYTES_PER_CHANNEL)    = *(PIXEL_TYPE*)(source+2*BYTES_PER_CHANNEL);
293
                      *(PIXEL_TYPE*)(dest+3*BYTES_PER_CHANNEL)    = *(PIXEL_TYPE*)(source+3*BYTES_PER_CHANNEL);
294
                  }
295
                  else{
296
                      int d = 255 - (int)*(PIXEL_TYPE*)source, s = 255 - (int)*(PIXEL_TYPE*)dest;
297
                      
298
                      if( d==254 || d > s + feather )
299
                      ; // Use dest
300
                      else if( s > d + feather ) // Use just source
301
                      {
302
                          *(PIXEL_TYPE*)(dest+BYTES_PER_CHANNEL)      = *(PIXEL_TYPE*)(source+BYTES_PER_CHANNEL);
303
                          *(PIXEL_TYPE*)(dest+2*BYTES_PER_CHANNEL)    = *(PIXEL_TYPE*)(source+2*BYTES_PER_CHANNEL);
304
                          *(PIXEL_TYPE*)(dest+3*BYTES_PER_CHANNEL)    = *(PIXEL_TYPE*)(source+3*BYTES_PER_CHANNEL);
305
                      }
306
                      else
307
                      {
308
                          sfactor = GetBlendfactor( d, s, feather );
309
                          for( i=1; i<=3; i++)
310
                          {
311
                              result = sfactor * *(PIXEL_TYPE*)(source+ i*BYTES_PER_CHANNEL)  + 
312
                                      ( 1.0 - sfactor ) * *(PIXEL_TYPE*)(dest+i*BYTES_PER_CHANNEL);
313
                              DBL_TO_PIX( *(PIXEL_TYPE*)(dest+i*BYTES_PER_CHANNEL) , result );
314
                          }
315
                      }
316
                  }
317
              }
318
          }
319
      }
320
  }
321
  else if( seam == _dest ){
322
      _SetDistanceImage ( dst, src, &theRect, showprogress, feather );
323
      for(y=0; y<dst->height; y++){   
324
          dest    = *(dst->data) + y*dst->bytesPerLine;
325
          source  = *(src->data) + y*src->bytesPerLine;
326
          for(x=0; x<dst->width; x++, dest+=bpd, source+=bps){
327
              if( *(PIXEL_TYPE*)source ) {// alpha channel set
328
                  if( !*(PIXEL_TYPE*)dest ) {// No data in dest, so copy source to dest
329
                      *(PIXEL_TYPE*)dest = 1; 
330
                      *(PIXEL_TYPE*)(dest+BYTES_PER_CHANNEL)  = *(PIXEL_TYPE*)(source+BYTES_PER_CHANNEL);
331
                      *(PIXEL_TYPE*)(dest+2*BYTES_PER_CHANNEL)    = *(PIXEL_TYPE*)(source+2*BYTES_PER_CHANNEL);
332
                      *(PIXEL_TYPE*)(dest+3*BYTES_PER_CHANNEL)    = *(PIXEL_TYPE*)(source+3*BYTES_PER_CHANNEL);
333
                  }
334
                  else{
335
                      int d = 255 - (int)*(PIXEL_TYPE*)source; 
336
                      
337
                      if( d > feather ) 
338
                      ; // Use dest
339
                      else{ // blend
340
                          sfactor = ((double) d / (double) feather) * ( 1.0 - BLEND_RANDOMIZE * rand() / (double)RAND_MAX );
341
                          for( i=1; i<=3; i++){
342
                              result = sfactor * *(PIXEL_TYPE*)(dest+ i*BYTES_PER_CHANNEL)  + 
343
                                      ( 1.0 - sfactor ) * *(PIXEL_TYPE*)(source+i*BYTES_PER_CHANNEL);
344
                              DBL_TO_UC( *(PIXEL_TYPE*)(dest+i*BYTES_PER_CHANNEL) , result );
345
                          }
346
                      }
347
                  }
348
              }
349
          }
350
      }
351
      
352
  }
353
  else
354
  {
355
      PrintError("Error in function merge");
356
      return -1;
357
  }
358
      
359
  // Set alpha channel
360
  
361
  LOOP_IMAGE( dst, {if( *(PIXEL_TYPE*)idata ) *(PIXEL_TYPE*)idata = PIXEL_MAX;} );
362
363
  return 0;
364
}
365
366
367
368
369
370
371
372
373
374
375
376
void _mergeAlpha ( Image *im, unsigned char *alpha, int feather, PTRect *theRect )
377
{
378
  register int            x,y;
379
  double              sfactor;
380
  unsigned char           *data = *(im->data), *idata, *adata;
381
  int             channels, BitsPerChannel,bpp;
382
  Image               aImage;  // Dummy for transfering alpha data
383
  
384
  
385
  GetChannels( im, channels );
386
  GetBitsPerChannel( im, BitsPerChannel );
387
  bpp = im->bitsPerPixel/8;
388
389
  memcpy( &aImage, im, sizeof( Image ));
390
  aImage.bitsPerPixel = BitsPerChannel;
391
  aImage.bytesPerLine = im->width*BYTES_PER_CHANNEL;
392
  aImage.data = &alpha;
393
  
394
  
395
  _SetDistance ( im, &aImage, theRect, 1 );
396
397
  for(y=theRect->top; y<theRect->bottom; y++){
398
      idata = data + im->bytesPerLine * y + theRect->left * bpp;
399
      adata = alpha + im->width * y * BYTES_PER_CHANNEL + theRect->left * BYTES_PER_CHANNEL;
400
      for(x=theRect->left; x<theRect->right; x++, idata+=bpp, adata+=BYTES_PER_CHANNEL){
401
          if( *(PIXEL_TYPE*)idata ){ // alpha channel of image set
402
              if( !*(PIXEL_TYPE*)adata ) {// No data in pano, so copy source to dest
403
                  *(PIXEL_TYPE*)idata = PIXEL_MAX;
404
                  }
405
              else{
406
                  int d = 255 - (int)*(PIXEL_TYPE*)idata, s = 255 - (int)*(PIXEL_TYPE*)adata;
407
                      
408
                  if( d==254 || d > s + feather ){
409
                          *(PIXEL_TYPE*)idata = 0;
410
                  }
411
                  else if( s > d + feather ){ // Use just source
412
                          *(PIXEL_TYPE*)idata = PIXEL_MAX;
413
                  }
414
                  else{
415
                      sfactor = 255.0 * GetBlendfactor( d, s, feather );
416
                      DBL_TO_PIX( *(PIXEL_TYPE*)idata , sfactor );
417
                  }
418
              }
419
          }
420
      }
421
  }
422
}
423
424
                  
425
426
427