Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Diff of /panTools.cpp [9be1ae] .. [c033de] Maximize Restore

  Switch to unified view

a/panTools.cpp b/panTools.cpp
...
...
41
* @param[in] func the name of the function to retrieve the address
41
* @param[in] func the name of the function to retrieve the address
42
* @return the funtion if it exist
42
* @return the funtion if it exist
43
**/
43
**/
44
static dllEntry getAddr(char *func)
44
static dllEntry getAddr(char *func)
45
{
45
{
46
  dllEntry addr = (dllEntry) GetProcAddress(DLL.hpano13, func); 
46
  dllEntry addr = (dllEntry) GetProcAddress(gData->dll.hpano13, func); 
47
  if (addr == NULL)
47
  if (addr == NULL)
48
  {
48
  {
49
    FreeLibrary(DLL.hpano13);
49
    FreeLibrary(gData->gData->dll.hpano13);
50
    display("Pano13.dll is invalid (%s).", func);
50
    display("Pano13.dll is invalid (%s).", func);
51
  }
51
  }
52
  return addr;
52
  return addr;
53
}
53
}
54
54
55
/**
55
/**
56
* macro used to locate the funtions in pano13.dll libreary
56
* macro used to locate the funtions in pano13.dll libreary
57
* @param[in] x the name of the function to retrieve the address
57
* @param[in] x the name of the function to retrieve the address
58
**/
58
**/
59
#define SETFUNC(x)\
59
#define SETFUNC(x)\
60
  DLL. ## x = (x ## _proc)getAddr(#x);\
60
  gData->dll. ## x = (x ## _proc)getAddr(#x);\
61
  if (DLL. ## x == NULL) goto err_exit
61
  if (gData->dll. ## x == NULL) goto err_exit
62
62
63
#else
64
extern  HINSTANCE hDllInstance;
63
#endif
65
#endif
64
65
//extern  HINSTANCE hDllInstance;
66
//extern void SetWindowOwner(HWND owner);
67
extern "C" BOOL APIENTRY DLLInit(HANDLE hInstance, DWORD fdwReason, LPVOID lpReserved);
68
/*
69
extern "C" void FourToThreeBPP(Image *im);
70
extern "C" void CopyImageData(Image *dest, Image *src);
71
extern "C" void SetImageDefaults(Image *im);
72
extern "C" void filter_main(TrformStr *TrPtr, struct stitcher_Prefs *spref);
73
extern "C" int writePSD(Image *im, fullPath* fname);
74
extern "C" void myfree(void **hdl);
75
*/
76
66
77
/**
67
/**
78
* Load pano13.dll and initilize funtions needed.
68
* Load pano13.dll and initilize funtions needed.
79
* @return 0 if successful, 1 on error
69
* @return 0 if successful, 1 on error
80
**/
70
**/
81
static int loadLibrary()
71
static int loadLibrary()
82
{
72
{
83
#if defined pano13DYNAMICLINK
73
#if defined pano13DYNAMICLINK
84
  {
85
    // Get a handle to the DLL module.
74
  // Get a handle to the DLL module.
86
    DLL.hpano13 = LoadLibrary("pano13.dll");
75
  gData->dll.hpano13 = LoadLibrary("pano13.dll");
87
    if (DLL.hpano13 == NULL)
76
  if (gData->dll.hpano13 == NULL)
88
    {
77
  {
89
      DWORD  err      = GetLastError();
78
    DWORD  err      = GetLastError();
90
      LPVOID lpMsgBuf = NULL;
79
    LPVOID lpMsgBuf = NULL;
91
      FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
80
    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
92
                     NULL, err, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
81
                    NULL, err, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
93
      // This problem is happening sometimes on different systems, but not all the time.
82
    // This problem is happening sometimes on different systems, but not all the time.
94
      // It is not because pano13 is not properly installed.  Hopefully by adding the Last Error 
83
    // It is not because pano13 is not properly installed.  Hopefully by adding the Last Error 
95
      // we can track down the problme.
84
    // we can track down the problme.
96
      display("Unable to load the pano13.dll file.\n%s", (LPCTSTR)lpMsgBuf);
85
    display("Unable to load the pano13.dll file.\n%s", (LPCTSTR)lpMsgBuf);
97
      // Free the buffer.
86
    // Free the buffer.
98
      LocalFree( lpMsgBuf );
87
    LocalFree( lpMsgBuf );
99
      return 1;
88
    return 1;
100
    }
89
  }
101
    // initialize all function pointers
90
  // initialize all function pointers
102
    SETFUNC(FourToThreeBPP);
91
  SETFUNC(FourToThreeBPP);
103
    SETFUNC(SetWindowOwner);
92
  SETFUNC(SetWindowOwner);
104
    SETFUNC(CopyImageData);
93
  SETFUNC(CopyImageData);
105
    SETFUNC(SetImageDefaults);
94
  SETFUNC(SetImageDefaults);
106
    SETFUNC(filter_main);
95
  SETFUNC(filter_main);
107
    SETFUNC(writePSD);
96
  SETFUNC(writePSD);
97
  SETFUNC(writePSDwithLayer);
108
    SETFUNC(myfree);
98
  SETFUNC(myfree);
109
99
110
    return 0;
100
  return 0;
111
101
112
err_exit:
102
err_exit:
113
  FreeLibrary(DLL.hpano13);    
103
  FreeLibrary(gData->dll.hpano13);
114
  return 1;
104
  return 1;
115
  }
105
116
#else
106
#else
117
  {
118
    DLL.FourToThreeBPP = FourToThreeBPP;
107
  gData->dll.FourToThreeBPP = FourToThreeBPP;
119
    DLL.SetWindowOwner = SetWindowOwner;
108
  gData->dll.SetWindowOwner = SetWindowOwner;
120
    DLL.CopyImageData = CopyImageData;
109
  gData->dll.CopyImageData = CopyImageData;
121
    DLL.SetImageDefaults = SetImageDefaults;
110
  gData->dll.SetImageDefaults = SetImageDefaults;
122
    DLL.filter_main = filter_main;
111
  gData->dll.filter_main = filter_main;
123
    DLL.writePSD = writePSD;
112
  gData->dll.writePSD = writePSD;
113
  gData->dll.writePSDwithLayer = writePSDwithLayer;
124
    DLL.myfree = myfree;
114
  gData->dll.myfree = myfree;
115
  hDllInstance = GetDLLInstance();
125
116
126
    return 0;
117
  return 0;
127
  }
128
#endif
118
#endif
129
}
119
}
130
120
131
/**
121
/**
132
* Retrieve the name of the next tempory file
122
* Retrieve the name of the next tempory file
...
...
160
  // find filename
150
  // find filename
161
  int i = 0;
151
  int i = 0;
162
  while(1)
152
  while(1)
163
  {
153
  {
164
#if _MSC_VER >= 1400
154
#if _MSC_VER >= 1400
165
    sprintf_s(buf, bufSize, "%s%d.%d.psd", PAN.sprefs.sFile.name, pre, i++);
155
    sprintf_s(buf, bufSize, "%s%d.%d.psd", gData->pan.sprefs.sFile.name, pre, i++);
166
#else
156
#else
167
    sprintf(buf, "%s%d.%d.psd", PAN.sprefs.sFile.name, pre, i++);
157
    sprintf(buf, "%s%d.%d.psd", gData->pan.sprefs.sFile.name, pre, i++);
168
#endif
158
#endif
169
    HANDLE hFile = CreateFile(
159
    HANDLE hFile = CreateFile(
170
        buf,                            // file name
160
        buf,                      // file name
171
        GENERIC_READ,             // access mode
161
        GENERIC_READ,             // access mode
172
        FILE_SHARE_READ,          // share mode
162
        FILE_SHARE_READ,          // share mode
173
        NULL,                     // security
163
        NULL,                     // security
174
        OPEN_EXISTING,            // how to create
164
        OPEN_EXISTING,            // how to create
175
        0,                        // flags & attributes
165
        0,                        // flags & attributes
...
...
192
{
182
{
193
  void         *buf       = NULL;
183
  void         *buf       = NULL;
194
  void         *alpha     = NULL;
184
  void         *alpha     = NULL;
195
  PlatformData *platform  = NULL;
185
  PlatformData *platform  = NULL;
196
186
187
#ifdef pano13DYNAMICLINK
197
  if (!DLL.initDLL) 
188
  if (!gData->dll.initDLL) 
189
  // If linking staticaly then we will call loadLibrary each time to ensure we are always in sync.
190
#endif
198
  {
191
  {
199
    if (loadLibrary())
192
    if (loadLibrary())
200
    {
193
    {
201
      return 1;
194
      return 1;
202
    }
195
    }
203
    DLL.initDLL = true;
196
    gData->dll.initDLL = true;
204
  }
197
  }
205
198
206
  platform = (PlatformData*)(gFr->platformData);
199
  platform = (PlatformData*)(gFr->platformData);
200
  gData->dll.SetWindowOwner((HWND)platform->hwnd);
207
201
202
208
  // initialize PHOtoshop settings
203
  // initialize Photoshop settings
209
  PHO.imageWidth = gFr->imageSize.h;
204
  gData->pho.imageWidth  = gFr->wholeSize.h;
210
  PHO.imageHeight = gFr->imageSize.v; 
205
  gData->pho.imageHeight = gFr->wholeSize.v;
211
  PHO.imageDepth = gFr->depth;
206
  gData->pho.imageDepth  = gFr->depth;
207
  gData->pho.imagePlanes = gFr->planes<=4?gFr->planes:4;// At most add just one Alpha Channel(image mask, clip mask)
212
208
213
  // PSP sets depth to zero!
209
  // PSP sets depth to zero!
214
  if (PHO.imageDepth != 16)
210
  if (gData->pho.imageDepth != 16)
211
  {
212
    gData->pho.imageDepth = 8;
213
  }
215
  {
214
  
216
    PHO.imageDepth = 8;
215
  gData->pho.imageChannelSize = gData->pho.imageWidth * gData->pho.imageHeight * (gData->pho.imageDepth/8);
217
  }
216
  gData->pho.imageSize = gData->pho.imageChannelSize * gData->pho.imagePlanes;
218
219
  PHO.imageChannelSize = PHO.imageWidth * PHO.imageHeight * (PHO.imageDepth/8);
220
  PHO.imageSize = PHO.imageChannelSize * 3;
221
217
222
  // initialize images
218
  // initialize images
223
  DLL.SetImageDefaults(&PAN.image1);
219
  gData->dll.SetImageDefaults(&gData->pan.image1);
224
  DLL.SetImageDefaults(&PAN.image2);
220
  gData->dll.SetImageDefaults(&gData->pan.image2);
225
221
226
  // assume no alpha channel needed
222
  // assume no alpha channel needed
227
  PAN.image1.width = PHO.imageWidth;
223
  gData->pan.image1.width         = gData->pho.imageWidth;
228
  PAN.image1.height = PHO.imageHeight;
224
  gData->pan.image1.height        = gData->pho.imageHeight;
229
  PAN.image1.bitsPerPixel = PHO.imageDepth * 3;
225
  gData->pan.image1.bitsPerPixel  = gData->pho.imageDepth * gData->pho.imagePlanes;
230
  PAN.image1.bytesPerLine = PHO.imageWidth * PAN.image1.bitsPerPixel/8;
226
  gData->pan.image1.bytesPerLine  = gData->pho.imageWidth * gData->pan.image1.bitsPerPixel/8;
231
  PAN.image1.dataSize = PHO.imageHeight * PAN.image1.bytesPerLine;
227
  gData->pan.image1.dataSize      = gData->pho.imageHeight * gData->pan.image1.bytesPerLine;
232
  PAN.image1.dataformat = _RGB;
228
  gData->pan.image1.dataformat    = _RGB;
233
  PAN.image1.format = _rectilinear;
229
  gData->pan.image1.format        = _rectilinear;
234
  PAN.image1.data = (unsigned char **)&buf;
230
  gData->pan.image1.data          = (unsigned char **)&buf;
235
231
236
  // setup tr
232
  // setup tr
237
  memset(&PAN.tr, 0, sizeof(TrformStr));
233
  memset(&gData->pan.tr, 0, sizeof(TrformStr));
238
  PAN.tr.tool = tool;
234
  gData->pan.tr.tool    = tool;
239
  PAN.tr.success = 1;
235
  gData->pan.tr.success = 1;
240
  PAN.tr.data = &PAN.prefs;
236
  gData->pan.tr.data    = &gData->pan.prefs;
241
  PAN.tr.src = &PAN.image1;
237
  gData->pan.tr.src     = &gData->pan.image1;
242
  PAN.tr.dest = &PAN.image2;
238
  gData->pan.tr.dest    = &gData->pan.image2;
243
239
244
  if (!PAN.initPrefs)
240
  if (!gData->pan.initPrefs)
245
  {
241
  {
246
    // 1st call to filter_main
242
    // 1st call to filter_main
247
    PAN.tr.mode = _setprefs;
243
    gData->pan.tr.mode = _setprefs;
248
    DLL.SetWindowOwner((HWND)platform->hwnd);
244
    gData->dll.filter_main(&gData->pan.tr, &gData->pan.sprefs);
249
    #ifndef pano13DYNAMICLINK
250
      DLLInit(GetDLLInstance(), DLL_PROCESS_ATTACH, NULL);
251
    #endif
252
    DLL.filter_main(&PAN.tr, &PAN.sprefs);
253
    if (!PAN.tr.success)
245
    if (!gData->pan.tr.success)
254
    {
246
    {
255
      *gResult = userCanceledErr;
247
      *gResult = userCanceledErr;
256
      return 1;
248
      return 1;
257
    }
249
    }
258
    PAN.initPrefs = true;
250
    gData->pan.initPrefs = true;
259
  }
251
  }
260
252
261
  // update tr info
253
  // update tr info
262
  PAN.tr.gamma        = PAN.sprefs.gamma;
254
  gData->pan.tr.gamma        = gData->pan.sprefs.gamma;
263
  PAN.tr.interpolator = PAN.sprefs.interpolator;
255
  gData->pan.tr.interpolator = gData->pan.sprefs.interpolator;
264
  PAN.tr.fastStep     = PAN.sprefs.fastStep;
256
  gData->pan.tr.fastStep     = gData->pan.sprefs.fastStep;
265
257
266
  // get image from photoshop
258
  // get image from photoshop
267
  buf = memAlloc(memDynamic, PHO.imageSize);
259
  buf = memAlloc(memDynamic, gData->pho.imageSize);
268
  if (buf == NULL) goto err_exit;
260
  if (buf == NULL) goto err_exit;
269
  if (cpyPsToBuf(buf)) goto err_exit;
261
  if (cpyPsToBuf(buf)) goto err_exit;
270
262
271
  // convert add alpha channel to image1
263
  // convert add alpha channel to image1 if it does not have one already
272
  if (tool == _adjust)
264
  if (tool == _adjust && gData->pho.imagePlanes == 3)
273
  {
265
  {
274
    PAN.image2 = PAN.image1;
266
    gData->pan.image2 = gData->pan.image1;
275
267
276
    // add alpha channel to image1
268
    // add alpha channel to image1
277
    PAN.image1.bitsPerPixel = PHO.imageDepth * 4;
269
    gData->pan.image1.bitsPerPixel = gData->pho.imageDepth * 4;
278
    PAN.image1.bytesPerLine = PHO.imageWidth * PAN.image1.bitsPerPixel/8;
270
    gData->pan.image1.bytesPerLine = gData->pho.imageWidth * gData->pan.image1.bitsPerPixel/8;
279
    PAN.image1.dataSize = PHO.imageHeight * PAN.image1.bytesPerLine;
271
    gData->pan.image1.dataSize = gData->pho.imageHeight * gData->pan.image1.bytesPerLine;
280
272
281
    // allocate buffer
273
    // allocate buffer
282
    alpha = memAlloc(memDynamic, PAN.image1.dataSize);
274
    alpha = memAlloc(memDynamic, gData->pan.image1.dataSize);
283
    if (alpha == NULL)
275
    if (alpha == NULL)
284
    {
276
    {
285
      goto err_exit;
277
      goto err_exit;
286
    }
278
    }
287
    PAN.image1.data = (unsigned char **)&alpha;
279
    gData->pan.image1.data = (unsigned char **)&alpha;
288
280
289
    DLL.CopyImageData(&PAN.image1, &PAN.image2);
281
    gData->dll.CopyImageData(&gData->pan.image1, &gData->pan.image2);
290
    memFree(memDynamic, *PAN.image2.data);
282
    memFree(memDynamic, *gData->pan.image2.data);
291
  }
283
  }
292
284
293
  // 2nd call to filter_main
285
  // 2nd call to filter_main
294
  // for compability with 2.6b1, don't use _destSupplied
286
  // for compability with 2.6b1, don't use _destSupplied
295
  PAN.tr.mode = _useprefs | _show_progress;
287
  gData->pan.tr.mode = _useprefs | _show_progress;
296
  DLL.SetWindowOwner((HWND)platform->hwnd);
288
  gData->dll.filter_main(&gData->pan.tr, &gData->pan.sprefs);
297
  DLL.filter_main(&PAN.tr, &PAN.sprefs);
298
289
299
  // don't call myfree... PT cleans up after itself
290
  // don't call myfree... PT cleans up after itself
300
  if (!PAN.tr.success)
291
  if (!gData->pan.tr.success)
301
  {
292
  {
302
    return 1;
293
    return 1;
303
  }
294
  }
304
295
305
  // restore image1 for return to PS
296
  // restore image1 for return to PS
306
  PAN.image1.bitsPerPixel = PHO.imageDepth * 3;
297
  gData->pan.image1.bitsPerPixel = gData->pho.imageDepth * gData->pho.imagePlanes;
307
  PAN.image1.bytesPerLine = PHO.imageWidth * PAN.image1.bitsPerPixel/8;
298
  gData->pan.image1.bytesPerLine = gData->pho.imageWidth * gData->pan.image1.bitsPerPixel/8;
308
  PAN.image1.dataSize = PHO.imageHeight * PAN.image1.bytesPerLine;
299
  gData->pan.image1.dataSize = gData->pho.imageHeight * gData->pan.image1.bytesPerLine;
309
300
310
  // determine images for file and display
301
  // determine images for file and display
311
  Image *imageFile, *imageDisplay;
302
  Image *imageFile, *imageDisplay;
312
  if (tool == _adjust)
303
  if (tool == _adjust)
313
  {
304
  {
314
    // resize for display, removing alpha channel
305
    // resize for display, removing alpha channel
315
    DLL.CopyImageData(&PAN.image1, &PAN.image2);
306
    gData->dll.CopyImageData(&gData->pan.image1, &gData->pan.image2);
316
    if (PAN.sprefs.noAlpha)
307
    if (gData->pan.sprefs.noAlpha)
317
    {
318
      DLL.FourToThreeBPP(&PAN.image2);
319
    }
308
    {
309
      gData->dll.FourToThreeBPP(&gData->pan.image2);
310
    }
320
    imageFile = &PAN.image2;
311
    imageFile = &gData->pan.image2;
321
    imageDisplay = &PAN.image1;
312
    imageDisplay = &gData->pan.image1;
322
  }
313
  }
323
  else
314
  else
324
  {
315
  {
325
    imageFile = &PAN.image2;
316
    imageFile = &gData->pan.image2;
326
317
327
    if ( PAN.tr.src->width != PAN.tr.dest->width
318
    if ( gData->pan.tr.src->width != gData->pan.tr.dest->width
328
      || PAN.tr.src->height != PAN.tr.dest->height )
319
      || gData->pan.tr.src->height != gData->pan.tr.dest->height )
329
    {
320
    {
330
        // resize for display
321
        // resize for display
331
        DLL.CopyImageData(&PAN.image1, &PAN.image2);
322
        gData->dll.CopyImageData(&gData->pan.image1, &gData->pan.image2);
332
        imageDisplay = &PAN.image1;
323
        imageDisplay = &gData->pan.image1;
333
    }
324
    }
334
    else
325
    else
335
    {
326
    {
336
      imageDisplay = &PAN.image2;
327
      imageDisplay = &gData->pan.image2;
337
    }
328
    }
338
  }
329
  }
339
330
340
  // if change in file size, we've got extra processing to do
331
  // if change in file size, we've got extra processing to do
341
  if ( PAN.tr.src->width == PAN.tr.dest->width
332
  if ( gData->pan.tr.src->width == gData->pan.tr.dest->width
342
    && PAN.tr.src->height == PAN.tr.dest->height )
333
    && gData->pan.tr.src->height == gData->pan.tr.dest->height )
343
  {
334
  {
344
      if (cpyBufToPs(*imageDisplay->data))
335
      if (cpyBufToPs(*imageDisplay->data))
345
      {
336
      {
346
        goto err_exit;
337
        goto err_exit;
347
      }
338
      }
348
  }
339
  }
349
  else
340
  else
350
  {
341
  {
351
    if (PAN.sprefs.displayPart)
342
    if (gData->pan.sprefs.displayPart)
352
    {
343
    {
353
      if (cpyBufToPs(*imageDisplay->data))
344
      if (cpyBufToPs(*imageDisplay->data))
354
      {
345
      {
355
        goto err_exit;
346
        goto err_exit;
356
      }
347
      }
357
    }
348
    }
358
    if (PAN.sprefs.saveFile)
349
    if (gData->pan.sprefs.saveFile)
359
    {
350
    {
360
      int BuffSize = 0;
351
      int BuffSize = 0;
361
      fullPath path;
352
      fullPath path;
362
      BuffSize = sizeof(path)/sizeof(char);
353
      BuffSize = sizeof(path)/sizeof(char);
363
      fileName(path.name, BuffSize);
354
      fileName(path.name, BuffSize);
355
356
      if ( tool==_adjust && gData->pan.sprefs.noAlpha )
357
      {
364
      DLL.writePSD(imageFile, &path);
358
        gData->dll.writePSD(imageFile, &path);
359
      }
360
      else
361
      {
362
        gData->dll.writePSDwithLayer(imageFile, &path);
363
      }
365
364
366
      if (PAN.sprefs.launchApp)
365
      if (gData->pan.sprefs.launchApp)
367
      {
366
      {
368
        char command[300];
367
        char command[300];
369
        STARTUPINFO si;
368
        STARTUPINFO si;
370
        PROCESS_INFORMATION pi;
369
        PROCESS_INFORMATION pi;
371
370
...
...
373
        si.cb = sizeof(STARTUPINFO);
372
        si.cb = sizeof(STARTUPINFO);
374
373
375
        // build command-line
374
        // build command-line
376
        BuffSize = sizeof(command)/sizeof(char);
375
        BuffSize = sizeof(command)/sizeof(char);
377
#if _MSC_VER >= 1400
376
#if _MSC_VER >= 1400
378
        sprintf_s(command, BuffSize, "%s \"%s\"", PAN.sprefs.lApp.name, path.name);
377
        sprintf_s(command, BuffSize, "%s \"%s\"", gData->pan.sprefs.lApp.name, path.name);
379
#else
378
#else
380
        sprintf(command, "%s \"%s\"", PAN.sprefs.lApp.name, path.name);
379
        sprintf(command, "%s \"%s\"", gData->pan.sprefs.lApp.name, path.name);
381
#endif
380
#endif
382
381
383
        CreateProcess(
382
        CreateProcess(
384
          NULL,           // name of executable module
383
          NULL,           // name of executable module
385
          command,        // command line string
384
          command,        // command line string
...
...
394
      }
393
      }
395
    }
394
    }
396
  }
395
  }
397
396
398
  // believe it or not, image2 still has pano13's allocated memory
397
  // believe it or not, image2 still has pano13's allocated memory
399
  DLL.myfree((void **)PAN.image2.data);
398
  gData->dll.myfree((void **)gData->pan.image2.data);
400
399
401
  return 0;
400
  return 0;
402
401
403
err_exit:
402
err_exit:
404
  if (PAN.image2.data)
403
  if (gData->pan.image2.data)
405
  {
404
  {
406
    DLL.myfree((void **)PAN.image2.data);
405
    gData->dll.myfree((void **)gData->pan.image2.data);
407
  }
406
  }
408
407
409
  FreeLibrary(DLL.hpano13);
408
  FreeLibrary(gData->dll.hpano13);
410
  DLL.initDLL = false;
409
  gData->dll.initDLL = false;
411
  return 1;
410
  return 1;
412
}
411
}