Revision: 75599
          http://sourceforge.net/p/brlcad/code/75599
Author:   starseeker
Date:     2020-04-24 21:00:13 +0000 (Fri, 24 Apr 2020)
Log Message:
-----------
Checkpoint an experiment with Tk_PhotoImage - after studying the C api and some 
discussions with the tcl IRC channel, it should be possible to leverage 
Tk_Photo for image data display from C.  This program generates patterns of 
data in an image and uses Tk_PhotoPutBlock to both update the image data itself 
and let Tk know it needs to redraw.  In theory this should be no different than 
getting RGBA values from a rasterizer or raytracer.  Not doing any event 
handling yet, however.

Modified Paths:
--------------
    brlcad/trunk/src/libdm/CMakeLists.txt

Added Paths:
-----------
    brlcad/trunk/src/libdm/tcl_img.cpp

Modified: brlcad/trunk/src/libdm/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libdm/CMakeLists.txt       2020-04-23 23:35:43 UTC (rev 
75598)
+++ brlcad/trunk/src/libdm/CMakeLists.txt       2020-04-24 21:00:13 UTC (rev 
75599)
@@ -129,6 +129,10 @@
 if(BRLCAD_ENABLE_OSG)
   add_dependencies(libdm profont_ProFont_ttf_cp)
 endif(BRLCAD_ENABLE_OSG)
+
+#add_executable(tcl_img tcl_img.cpp)
+#target_link_libraries(tcl_img ${TCL_LIBRARY} ${TK_LIBRARY})
+
 set(libdm_ignore_files
   CMakeLists.txt
   README
@@ -157,6 +161,7 @@
   fontstash/stb_truetype.h
   osg-test.cpp
   osg_bob.cpp
+  tcl_img.cpp
   )
 CMAKEFILES(${libdm_ignore_files})
 CMAKEFILES(dm_private.h)

Added: brlcad/trunk/src/libdm/tcl_img.cpp
===================================================================
--- brlcad/trunk/src/libdm/tcl_img.cpp                          (rev 0)
+++ brlcad/trunk/src/libdm/tcl_img.cpp  2020-04-24 21:00:13 UTC (rev 75599)
@@ -0,0 +1,149 @@
+/*                     T C L _ I M G . C P P
+ * BRL-CAD
+ *
+ * Published in 2020 by the United States Government.
+ * This work is in the public domain.
+ *
+ */
+/** @file tcl_img.cpp
+ *
+ * Self contained example of working with image data
+ * in Tcl/Tk in C/C++
+ *
+ * Eventually this should probably turn into a Togl-esque
+ * widget that we properly include, so we ensure that our
+ * window is behaving the way Tk expects it to for things
+ * like refresh.  Our current behavior in that regard is
+ * a bit iffy - ogl works but I'm not convinced that's
+ * because we're doing the Tcl/Tk bits right, and X is
+ * doing low level blitting and other X calls (which
+ * isn't great for maintainability/portability and
+ * can be a headache for debugging.)
+ *
+ */
+
+#include "common.h"
+
+#include <random>
+#include <vector>
+#include <iostream>
+#include <chrono>
+#include <thread>
+
+#include "tcl.h"
+#include "tk.h"
+
+const char *DM_PHOTO = ".dm0.photo";
+const char *DM_LABEL = ".dm0";
+
+void
+update_data(Tcl_Interp *interp, int r, int g, int b)
+{
+    Tk_PhotoImageBlock dm_data;
+    Tk_PhotoHandle dm_img = Tk_FindPhoto(interp, DM_PHOTO);
+    Tk_PhotoGetImage(dm_img, &dm_data);
+
+    std::default_random_engine gen;
+    std::uniform_int_distribution<int> vals(0,255);
+    for (int i = 0; i < (dm_data.width * dm_data.height * 4); i+=4) {
+       dm_data.pixelPtr[i] = (r) ? vals(gen) : 0;
+       dm_data.pixelPtr[i+1] = (g) ? vals(gen) : 0;
+       dm_data.pixelPtr[i+2] = (b) ? vals(gen) : 0;
+       // Alpha stays at 255
+    }
+
+    Tk_PhotoPutBlock(interp, dm_img, &dm_data, 0, 0, dm_data.width, 
dm_data.height, TK_PHOTO_COMPOSITE_SET);
+
+    // Pause a second after updating
+    std::this_thread::sleep_for (std::chrono::seconds(1));
+}
+
+
+int
+main()
+{
+    std::default_random_engine gen;
+    std::uniform_int_distribution<int> vals(0,255);
+    std::vector<int> rgb;
+    int wsize = 512;
+
+    for (int i = 0; i < wsize; i++) {
+       for (int j = 0; j < wsize; j++) {
+           rgb.push_back(0);
+           rgb.push_back(vals(gen));
+           rgb.push_back(0);
+           rgb.push_back(255);
+       }
+    }
+
+    Tcl_Interp *interp = Tcl_CreateInterp();
+    Tk_Init(interp);
+    Tk_Window tkwin = Tk_MainWindow(interp);
+    Tk_GeometryRequest(tkwin, wsize, wsize);
+    Tk_MakeWindowExist(tkwin);
+    Tk_MapWindow(tkwin);
+
+    /* Note: confirmed with Tcl/Tk community that (at least as of Tcl/Tk 8.6)
+     * Tcl_Eval is the ONLY way to create an image object.  The C API just
+     * doesn't expose that ability, although it does support manipulation of
+     * the created object. */
+    std::string img_cmd = std::string("image create photo ") + 
std::string(DM_PHOTO);
+    Tcl_Eval(interp, img_cmd.c_str());
+    Tk_PhotoHandle dm_img = Tk_FindPhoto(interp, DM_PHOTO);
+    Tk_PhotoBlank(dm_img);
+    Tk_PhotoSetSize(interp, dm_img, wsize, wsize);
+
+    Tk_PhotoImageBlock dm_data;
+    dm_data.width = wsize;
+    dm_data.height = wsize;
+    dm_data.pixelSize = 4;
+    dm_data.pitch = wsize * 4;
+    dm_data.offset[0] = 0;
+    dm_data.offset[1] = 1;
+    dm_data.offset[2] = 2;
+    dm_data.offset[3] = 3;
+    dm_data.pixelPtr = (unsigned char *)Tcl_AttemptAlloc(dm_data.width * 
dm_data.height * 4);
+    if (!dm_data.pixelPtr) {
+       std::cerr << "Tcl/Tk photo memory allocation failed!\n";
+       exit(1);
+    }
+    for (int i = 0; i < (dm_data.width * dm_data.height * 4); i++) {
+       // Initialize the buffer with random values (simulates on-the-fly
+       // buffer generation from a rasterization or raytrace)
+       dm_data.pixelPtr[i] = rgb[i];
+    }
+
+    Tk_PhotoPutBlock(interp, dm_img, &dm_data, 0, 0, wsize, wsize, 
TK_PHOTO_COMPOSITE_SET);
+
+    // TODO - examples use a label to pack and display an image - is this the
+    // right way for us to do it in MGED/Archer?
+    std::string label_cmd = std::string("label ") + std::string(DM_LABEL) + 
std::string(" -image ") + std::string(DM_PHOTO);
+    Tcl_Eval(interp, label_cmd.c_str());
+    std::string pack_cmd = std::string("pack ") + std::string(DM_LABEL);
+    Tcl_Eval(interp, pack_cmd.c_str());
+
+    std::uniform_int_distribution<int> colors(0,1);
+    while (1) {
+       int handled = 0;
+       while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT)) {
+            handled++;
+        }
+       if (!Tk_GetNumMainWindows()) {
+           // If we've closed the window, we're done
+           exit(0);
+       }
+
+       // Generate a new random pattern on the same image
+       update_data(interp, colors(gen), colors(gen), colors(gen));
+    }
+
+}
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8


Property changes on: brlcad/trunk/src/libdm/tcl_img.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to