00001 /*!@file Script/ImageScript.C */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Script/ImageScript.C $ 00035 // $Id: ImageScript.C 11876 2009-10-22 15:53:06Z icore $ 00036 // 00037 00038 #ifndef SCRIPT_IMAGESCRIPT_C_DEFINED 00039 #define SCRIPT_IMAGESCRIPT_C_DEFINED 00040 00041 #include "Script/ImageScript.H" 00042 00043 #include "Image/Image.H" 00044 #include "Image/Pixels.H" 00045 #include "Image/ShapeOps.H" 00046 #include "Raster/Raster.H" 00047 #include "Util/log.H" 00048 00049 #include "rutz/error.h" 00050 #include "rutz/fstring.h" 00051 #include "rutz/sfmt.h" 00052 00053 #include "tcl/conversions.h" 00054 #include "tcl/list.h" 00055 #include "tcl/obj.h" 00056 #include "tcl/pkg.h" 00057 00058 #include <cstdio> 00059 #include <cstdlib> 00060 #include <tcl.h> 00061 00062 template <class T> 00063 struct ImageObj 00064 { 00065 static Tcl_ObjType objType; 00066 00067 static Tcl_ObjType* objTypePtr() { return &objType; } 00068 00069 static Tcl_Obj* make(const Image<T>& img); 00070 00071 static void freeInternalRep(Tcl_Obj* objPtr); 00072 00073 static void dupInternalRep(Tcl_Obj* srcPtr, Tcl_Obj* dupPtr); 00074 00075 static void updateString(Tcl_Obj* objPtr); 00076 00077 static int setFromAny(Tcl_Interp* interp, Tcl_Obj* objPtr); 00078 }; 00079 00080 template <class T> 00081 Tcl_Obj* ImageObj<T>::make(const Image<T>& img) 00082 { 00083 Tcl_Obj* objPtr = Tcl_NewObj(); 00084 objPtr->typePtr = &ImageObj<T>::objType; 00085 objPtr->internalRep.otherValuePtr = new Image<T>(img); 00086 00087 LDEBUG("new Image: %p", objPtr->internalRep.otherValuePtr); 00088 00089 Tcl_InvalidateStringRep(objPtr); 00090 00091 return objPtr; 00092 } 00093 00094 template <class T> 00095 void ImageObj<T>::freeInternalRep(Tcl_Obj* objPtr) 00096 { 00097 Image<T>* iobj = 00098 static_cast<Image<T>*>(objPtr->internalRep.otherValuePtr); 00099 00100 LDEBUG("delete Image: %p", iobj); 00101 00102 delete iobj; 00103 00104 objPtr->internalRep.otherValuePtr = 0; 00105 } 00106 00107 template <class T> 00108 void ImageObj<T>::dupInternalRep(Tcl_Obj* srcPtr, Tcl_Obj* dupPtr) 00109 { 00110 if (dupPtr->typePtr != 0 && dupPtr->typePtr->freeIntRepProc != 0) 00111 { 00112 dupPtr->typePtr->freeIntRepProc(dupPtr); 00113 } 00114 00115 Image<T>* iobj = 00116 static_cast<Image<T>*>(srcPtr->internalRep.otherValuePtr); 00117 00118 LDEBUG("dup Image: %p (src)", iobj); 00119 00120 dupPtr->internalRep.otherValuePtr = 00121 static_cast<void*>(new Image<T>(*iobj)); 00122 00123 LDEBUG("dup Image: %p (dst)", dupPtr->internalRep.otherValuePtr); 00124 00125 dupPtr->typePtr = &ImageObj<T>::objType; 00126 } 00127 00128 template <class T> 00129 void ImageObj<T>::updateString(Tcl_Obj* objPtr) 00130 { 00131 Image<T>* iobj = 00132 static_cast<Image<T>*>(objPtr->internalRep.otherValuePtr); 00133 00134 ASSERT(iobj != 0); 00135 00136 ASSERT(objPtr->bytes == 0); 00137 00138 rutz::fstring s = 00139 rutz::sfmt("{{%s:%dx%d}", 00140 ImageObj<T>::objType.name, 00141 iobj->getWidth(), iobj->getHeight()); 00142 00143 LDEBUG("string Image: %p", iobj); 00144 00145 objPtr->bytes = Tcl_Alloc(s.length()+1);; 00146 strcpy(objPtr->bytes, s.c_str()); 00147 objPtr->length = s.length(); 00148 } 00149 00150 template <class T> 00151 int ImageObj<T>::setFromAny(Tcl_Interp* interp, Tcl_Obj* objPtr) 00152 { 00153 Tcl_AppendResult(interp, "can't convert to image type"); 00154 return TCL_ERROR; 00155 } 00156 00157 namespace 00158 { 00159 template <class T> 00160 tcl::obj image2tcl(Image<T> img) { return ImageObj<T>::make(img); } 00161 00162 template <class T> 00163 Image<T> tcl2image(Tcl_Obj* obj) 00164 { 00165 if (obj->typePtr == &ImageObj<T>::objType) 00166 { 00167 Image<T>* iobj = 00168 static_cast<Image<T>*>(obj->internalRep.otherValuePtr); 00169 return *iobj; 00170 } 00171 00172 throw rutz::error 00173 (rutz::sfmt 00174 ("wrong object type:\n" 00175 "\t got: %s\n" 00176 "\texpected: %s", 00177 obj->typePtr ? obj->typePtr->name : "(unknown)", 00178 ImageObj<T>::objType.name), 00179 SRC_POS); 00180 00181 /* can't happen */ return Image<T>(); 00182 } 00183 } 00184 00185 tcl::obj tcl::aux_convert_from(Dims d) 00186 { 00187 tcl::list result; 00188 result.append(d.w()); 00189 result.append(d.h()); 00190 return result.as_obj(); 00191 } 00192 00193 Dims tcl::aux_convert_to(Tcl_Obj* obj, Dims*) 00194 { 00195 tcl::list l(obj); 00196 return Dims(l.get<int>(0), l.get<int>(1)); 00197 } 00198 00199 #define INST_IMG_OBJ_TYPE(T) \ 00200 tcl::obj tcl::aux_convert_from(Image< T > img) \ 00201 { return image2tcl(img); } \ 00202 \ 00203 Image< T > tcl::aux_convert_to(Tcl_Obj* obj, Image<T>*) \ 00204 { return tcl2image< T >(obj); } \ 00205 \ 00206 template <> \ 00207 Tcl_ObjType ImageObj< T >::objType = \ 00208 { \ 00209 const_cast<char*>("Image<" #T ">"), \ 00210 &ImageObj< T >::freeInternalRep, \ 00211 &ImageObj< T >::dupInternalRep, \ 00212 &ImageObj< T >::updateString, \ 00213 &ImageObj< T >::setFromAny \ 00214 } 00215 00216 00217 INST_IMG_OBJ_TYPE(byte); 00218 INST_IMG_OBJ_TYPE(float); 00219 INST_IMG_OBJ_TYPE(PixRGB<byte>); 00220 INST_IMG_OBJ_TYPE(PixRGB<float>); 00221 00222 namespace 00223 { 00224 template <class T> 00225 Image<T> makeImage(unsigned int w, unsigned int h) 00226 { 00227 return Image<T>(w, h, ZEROS); 00228 } 00229 00230 template <class T> 00231 rutz::fstring describeImage(const Image<T>& img) 00232 { 00233 return rutz::sfmt("here it is: {%dx%d}", 00234 img.getWidth(), img.getHeight()); 00235 } 00236 00237 template <class T> 00238 bool imageInitialized(const Image<T>& img) 00239 { 00240 return img.initialized(); 00241 } 00242 00243 Image<byte> readGray(const char* fname) 00244 { return Raster::ReadGray(fname); } 00245 00246 Image<float> readFloat(const char* fname) 00247 { return Raster::ReadFloat(fname); } 00248 00249 Image<PixRGB<byte> > readRGB(const char* fname) 00250 { return Raster::ReadRGB(fname); } 00251 00252 00253 void writeGray(Image<byte> img, const char* fname) 00254 { Raster::WriteGray(img, fname); } 00255 00256 void writeFloat(Image<float> img, int flags, const char* fname) 00257 { Raster::WriteFloat(img, flags, fname); } 00258 00259 void writeRGB(Image<PixRGB<byte> > img, const char* fname) 00260 { Raster::WriteRGB(img, fname); } 00261 00262 template <class T> 00263 int imgInit(Tcl_Interp* interp, const char* pkgname) 00264 { 00265 GVX_PKG_CREATE(pkg, interp, pkgname, "4.$Revision: 1$"); 00266 00267 Tcl_RegisterObjType(&ImageObj<T>::objType); 00268 00269 pkg->def("make", "w h", &makeImage<T>, SRC_POS); 00270 pkg->def("describe", "img", &describeImage<T>, SRC_POS); 00271 pkg->def("initialized", "img", &imageInitialized<T>, SRC_POS); 00272 pkg->def("zoom", "img xzoom yzoom", &zoomXY<T>, SRC_POS); 00273 00274 GVX_PKG_RETURN(pkg); 00275 } 00276 } 00277 00278 extern "C" 00279 int Bimage_Init(Tcl_Interp* interp) 00280 { 00281 return imgInit<byte>(interp, "BImage"); 00282 } 00283 00284 extern "C" 00285 int Fimage_Init(Tcl_Interp* interp) 00286 { 00287 return imgInit<float>(interp, "FImage"); 00288 } 00289 00290 extern "C" 00291 int Cbimage_Init(Tcl_Interp* interp) 00292 { 00293 return imgInit<PixRGB<byte> >(interp, "CBImage"); 00294 } 00295 00296 extern "C" 00297 int Cfimage_Init(Tcl_Interp* interp) 00298 { 00299 return imgInit<PixRGB<float> >(interp, "CFImage"); 00300 } 00301 00302 extern "C" 00303 int Raster_Init(Tcl_Interp* interp) 00304 { 00305 GVX_PKG_CREATE(pkg, interp, "Raster", "4.$Revision: 1$"); 00306 00307 pkg->def("readGray", "fname", &readGray, SRC_POS); 00308 pkg->def("readFloat", "fname", &readFloat, SRC_POS); 00309 pkg->def("readRGB", "fname", &readRGB, SRC_POS); 00310 00311 pkg->def("writeGray", "img fname", &writeGray, SRC_POS); 00312 pkg->def("writeFloat", "img flags fname", &writeFloat, SRC_POS); 00313 pkg->def("writeRGB", "img fname", &writeRGB, SRC_POS); 00314 00315 GVX_PKG_RETURN(pkg); 00316 } 00317 00318 // ###################################################################### 00319 /* So things look consistent in everyone's emacs... */ 00320 /* Local Variables: */ 00321 /* indent-tabs-mode: nil */ 00322 /* End: */ 00323 00324 #endif // SCRIPT_IMAGESCRIPT_C_DEFINED