00001
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #if HAVE_CONFIG_H
00039 #include <config.h>
00040 #endif
00041 #include <tcl.h>
00042 #include <tk.h>
00043 #include <string.h>
00044 #include <sadie.h>
00045 #include "tclsadie.h"
00046
00047
00048 static int
00049 MatchSADIE (Tcl_Obj * data, Tcl_Obj * format,
00050 int * widthPtr, int * heightPtr, Tcl_Interp * interp);
00051
00052
00053 static int
00054 ReadSADIE (Tcl_Interp * interp, Tcl_Obj * data, Tcl_Obj * format,
00055 Tk_PhotoHandle imageHandle,
00056 int destX, int destY, int width, int height,
00057 int srcX, int srcY);
00058
00059
00060 static int
00061 WriteSADIE (Tcl_Interp * interp, const char * fileName,
00062 Tcl_Obj * format, Tk_PhotoImageBlock * blockPtr);
00063
00065 Tk_PhotoImageFormat tkImgFmtSADIE =
00066 {
00067 "sadie",
00068 NULL,
00069 MatchSADIE,
00070 NULL,
00071 ReadSADIE,
00072 WriteSADIE,
00073 NULL
00074 };
00075
00088 static int
00089 MatchSADIE (Tcl_Obj *data, Tcl_Obj *format, int *widthPtr,
00090 int *heightPtr, Tcl_Interp *interp)
00091 {
00092 IMAGE *img;
00093
00094 if ((GetSadieImageFromObj (data, &img) != TCL_OK) || (!CHECKIMG (img)))
00095 return 0;
00096 else
00097 {
00098 *widthPtr = img->npix;
00099 *heightPtr = img->nlin;
00100 return 1;
00101 }
00102 }
00103
00108 static const double stretchMin = 0;
00109 static const double stretchMax = 255;
00110 static const double stretchTol = 1e-5;
00125 static void
00126 fill_bytes (void *pixelPtr, PIXEL corner, size_t n)
00127 {
00128 double scaled;
00129
00130 scaled = ((corner <= SMIN)
00131 ? 0
00132 : (((corner >= SMAX)
00133 ? SMAX
00134 : corner)
00135 - SMIN));
00136 memset (pixelPtr,
00137 (int)(floor ((scaled * (stretchMax - stretchMin))
00138 / (SMAX - SMIN))),
00139 n);
00140 }
00141
00149 static void
00150 stretch_rgb (unsigned char *pixelPtr, IMAGE *img)
00151 {
00152 size_t j, k;
00153 double factor, offset;
00154
00155 factor = (stretchMax - stretchMin) / (double)(img->gmax - img->gmin);
00156 offset = stretchMin - (img->gmin * factor);
00157 for (j = 0; j < img->nlin; j++)
00158 {
00159 for (k = 0; k < img->npix; k++)
00160 {
00161 *pixelPtr++ = (unsigned char)(factor * img->data[0][j][k] + offset);
00162 *pixelPtr++ = (unsigned char)(factor * img->data[1][j][k] + offset);
00163 *pixelPtr++ = (unsigned char)(factor * img->data[2][j][k] + offset);
00164 }
00165 }
00166 }
00167
00175 static void
00176 transcribe_rgb (unsigned char *pixelPtr, IMAGE *img)
00177 {
00178 size_t j, k;
00179
00180 for (j = 0; j < img->nlin; j++)
00181 {
00182 for (k = 0; k < img->npix; k++)
00183 {
00184 *pixelPtr++ = (unsigned char) img->data[0][j][k];
00185 *pixelPtr++ = (unsigned char) img->data[1][j][k];
00186 *pixelPtr++ = (unsigned char) img->data[2][j][k];
00187 }
00188 }
00189 }
00190
00198 static void
00199 stretch_greyscale (unsigned char *pixelPtr, IMAGE *img)
00200 {
00201 size_t j, k;
00202 double factor, offset;
00203
00204 factor = (stretchMax - stretchMin) / (double)(img->gmax - img->gmin);
00205 offset = stretchMin - (img->gmin * factor);
00206 for (j = 0; j < img->nlin; j++)
00207 {
00208 for (k = 0; k < img->npix; k++)
00209 *pixelPtr++ = (unsigned char)(factor * img->data[0][j][k] + offset);
00210 }
00211 }
00212
00220 static void
00221 transcribe_greyscale (unsigned char *pixelPtr, IMAGE *img)
00222 {
00223 size_t j, k;
00224
00225 for (j = 0; j < img->nlin; j++)
00226 {
00227 for (k = 0; k < img->npix; k++)
00228 *pixelPtr++ = (unsigned char) img->data[0][j][k];
00229 }
00230 }
00251 static int
00252 ReadSADIE (Tcl_Interp *interp, Tcl_Obj *data, Tcl_Obj *format,
00253 Tk_PhotoHandle imageHandle, int destX, int destY,
00254 int width, int height, int srcX, int srcY)
00255 {
00256 int option, need_stretch;
00257 size_t nbytes;
00258 Tk_PhotoImageBlock block;
00259 IMAGE *img;
00260 int err = TCL_OK;
00261 Tcl_Obj *arrayobjPtr = NULL;
00262 Tcl_Obj *indexobjPtr = NULL;
00263 Tcl_Obj *valueobjPtr = NULL;
00264
00265 arrayobjPtr = Tcl_NewStringObj (SADIEVAR_ARRAYNAME, -1);
00266 Tcl_IncrRefCount (arrayobjPtr);
00267 indexobjPtr = Tcl_NewStringObj ("getstretched", -1);
00268 Tcl_IncrRefCount (indexobjPtr);
00269 valueobjPtr = Tcl_ObjGetVar2 (interp, arrayobjPtr, indexobjPtr, 0);
00270 if (valueobjPtr == NULL)
00271 option = 1;
00272 else
00273 {
00274 Tcl_IncrRefCount (valueobjPtr);
00275 Tcl_GetIntFromObj (interp, valueobjPtr, &option);
00276 Tcl_DecrRefCount (valueobjPtr);
00277 }
00278 Tcl_DecrRefCount (indexobjPtr);
00279 Tcl_DecrRefCount (arrayobjPtr);
00280 if (GetSadieImageFromObj (data, &img) != TCL_OK)
00281 return TCL_ERROR;
00282 else
00283 Tcl_ResetResult (interp);
00284 if (!CHECKIMG (img))
00285 {
00286 Tcl_AppendStringsToObj (Tcl_GetObjResult (interp),
00287 "Couldn't identify SADIE image from input string.",
00288 NULL);
00289 err = TCL_ERROR;
00290 }
00291 if ((int) img->nbnd <= 0)
00292 {
00293 Tcl_AppendStringsToObj (Tcl_GetObjResult (interp),
00294 "Image bands not within display range.", NULL);
00295 err = TCL_ERROR;
00296 }
00297 if ((int) img->nlin <= 0)
00298 {
00299 Tcl_AppendStringsToObj (Tcl_GetObjResult (interp),
00300 "Image lines not within display range.", NULL);
00301 err = TCL_ERROR;
00302 }
00303 if ((int) img->npix <= 0)
00304 {
00305 Tcl_AppendStringsToObj (Tcl_GetObjResult (interp),
00306 "Image pixels not within display range.", NULL);
00307 err = TCL_ERROR;
00308 }
00309 if (err != TCL_OK)
00310 return TCL_ERROR;
00311 if (width > img->npix)
00312 width = img->npix;
00313 if (height > img->nlin)
00314 height = img->nlin;
00315 if ((width <= 0) || (height <= 0))
00316 return TCL_OK;
00317 block.width = width;
00318 block.height = height;
00319 if (img->nbnd != 3)
00320 {
00321 block.pixelSize = 1;
00322 block.offset[0] = 0;
00323 block.offset[1] = 0;
00324 block.offset[2] = 0;
00325 block.offset[3] = 0;
00326 }
00327 else
00328 {
00329 block.pixelSize = 3;
00330 block.offset[0] = 0;
00331 block.offset[1] = 1;
00332 block.offset[2] = 2;
00333 block.offset[3] = 0;
00334 }
00335 block.pitch = block.pixelSize * img->npix;
00336 nbytes = height * block.pitch;
00337 block.pixelPtr = (unsigned char *) ckalloc (nbytes);
00338 Tk_PhotoExpand(imageHandle, destX + width, destY + height);
00339 RANGE (img);
00340 need_stretch = ((option == 1)
00341 && ((fabs (stretchMin - img->gmin) > stretchTol)
00342 || (fabs (stretchMax - img->gmax) > stretchTol)));
00343 if (need_stretch && (img->gmin == img->gmax))
00344 fill_bytes (block.pixelPtr, img->data[0][0][0], nbytes);
00345 else
00346 {
00347 if (img->nbnd == 3)
00348 {
00349 if (need_stretch)
00350 stretch_rgb (block.pixelPtr, img);
00351 else
00352 transcribe_rgb (block.pixelPtr, img);
00353 }
00354 else
00355 {
00356 if (need_stretch)
00357 stretch_greyscale (block.pixelPtr, img);
00358 else
00359 transcribe_greyscale (block.pixelPtr, img);
00360 }
00361 }
00362 #if (TK_MAJOR_VERSION > 8) || ((TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION > 3))
00363 Tk_PhotoPutBlock (imageHandle, &block, destX, destY, width, height,
00364 TK_PHOTO_COMPOSITE_SET);
00365 #else
00366 Tk_PhotoPutBlock (imageHandle, &block, destX, destY, width, height);
00367 #endif
00368 return TCL_OK;
00369 }
00370
00375
00383 static void
00384 write_rgb_SADIE (IMAGE *img, Tk_PhotoImageBlock *blockPtr)
00385 {
00386 size_t h, w;
00387 unsigned char *bytePtr;
00388
00389 bytePtr = blockPtr->pixelPtr + blockPtr->offset[0];
00390 for (h = 0; h < blockPtr->height; h++)
00391 {
00392 for (w = 0; w < blockPtr->width; w++)
00393 {
00394 img->data[0][h][w] = (PIXEL) *(bytePtr++);
00395 img->data[1][h][w] = (PIXEL) *(bytePtr++);
00396 img->data[2][h][w] = (PIXEL) *(bytePtr++);
00397 bytePtr++;
00398 }
00399 }
00400 }
00401
00409 static void
00410 write_greyscale_SADIE (IMAGE *img, Tk_PhotoImageBlock *blockPtr)
00411 {
00412 size_t h, w;
00413 unsigned char *bytePtr;
00414
00415 bytePtr = blockPtr->pixelPtr + blockPtr->offset[0];
00416 for (h = 0; h < blockPtr->height; h++)
00417 {
00418 for (w = 0; w < blockPtr->width; w++)
00419 img->data[0][h][w] = (PIXEL) *(bytePtr++);
00420 }
00421 }
00437 static int
00438 WriteSADIE (Tcl_Interp *interp, const char *fileName,
00439 Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr)
00440 {
00441 char msg[SLEN];
00442 int greenOffset, blueOffset;
00443 Tcl_Obj *objPtr = NULL;
00444 IMAGE *img = NULL;
00445
00446 greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
00447 blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
00448 if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 4)
00449 && (blockPtr->pitch == (blockPtr->width * 4)))
00450 {
00451 GETMEM (3, blockPtr->height, blockPtr->width, &img);
00452 if (img == NULL)
00453 return TCL_ERROR;
00454 write_rgb_SADIE (img, blockPtr);
00455 }
00456 else if (blockPtr->pixelSize == 1)
00457 {
00458 GETMEM (1, blockPtr->height, blockPtr->width, &img);
00459 if (img == NULL)
00460 return TCL_ERROR;
00461 write_greyscale_SADIE (img, blockPtr);
00462 }
00463 else
00464 {
00465 return TCL_ERROR;
00466 }
00467 if (NAMES)
00468 {
00469 MESSAGE('I', "");
00470 MESSAGE('I', "TKIMGSADIE");
00471 MESSAGE('I', "");
00472 snprintf(msg, SLEN - 1,
00473 " Input file: %s", fileName);
00474 MESSAGE('I', msg);
00475 snprintf(msg, SLEN - 1,
00476 " Number of bands, lines, pixels: %lu, %lu, %lu",
00477 (unsigned long) img->nbnd,
00478 (unsigned long) img->nlin,
00479 (unsigned long) img->npix);
00480 MESSAGE('I', msg);
00481 snprintf(msg, SLEN - 1,
00482 " Number of bits/pixel/band: %d", 8);
00483 MESSAGE('I', msg);
00484 snprintf(msg, SLEN - 1,
00485 " Graylevel minimum, maximum: %10.4e, %10.4e",
00486 img->gmin, img->gmax);
00487 MESSAGE('I', msg);
00488 MESSAGE('I', " ...............");
00489 }
00490 strncpy (img->text, fileName, TLEN - 1);
00491 objPtr = NewSadieImageObj (img);
00492 if (objPtr != NULL)
00493 Tcl_SetObjResult (interp, objPtr);
00494 return TCL_OK;
00495 }
00496
00503 int
00504 Sadie_Image_Init (Tcl_Interp *interp)
00505 {
00506 Tk_CreatePhotoImageFormat (&tkImgFmtSADIE);
00507 return TCL_OK;
00508 }