@@ -26,7 +26,7 @@ def float2fix(f):
2626
2727pixel_queue = queue .Queue ()
2828
29- def send_command (bytewidth , view , debug = False ):
29+ def send_command (bytewidth , view , iterations = 10000 , debug = False ):
3030 tstart = time .perf_counter ()
3131 command_bytes = struct .pack ("HHI" , view .width - 1 , view .height - 1 , view .max_iterations )
3232 command_bytes += view .corner_x .to_bytes (bytewidth , byteorder = 'little' , signed = True )
@@ -43,7 +43,7 @@ def send_command(bytewidth, view, debug=False):
4343 try :
4444 while True :
4545 if debug : print ("read" )
46- r = dev .read (0x81 , 256 , timeout = 10 )
46+ r = dev .read (0x81 , 256 , timeout = max ( 10 , iterations // 1000 ) )
4747 if debug : print ("Got: " + str (len (r )))
4848 if debug : print (str (r ))
4949 result += r
@@ -127,12 +127,14 @@ def to_string(self):
127127 if argv [1 ] == "gui" :
128128 import gi
129129 gi .require_version ("Gtk" , "3.0" )
130- from gi .repository import GLib , Gtk , Gdk
131- from gi .repository .Gtk import DrawingArea
130+ from gi .repository import GLib , Gtk , Gdk
131+ from gi .repository .Gtk import DrawingArea
132+ from gi .repository .GdkPixbuf import Pixbuf , Colorspace
133+ from gi .repository .GdkPixdata import Pixdata , PIXBUF_MAGIC_NUMBER , PIXDATA_HEADER_LENGTH , PixdataType
132134 import cairo
133135
134136 class GuiHandler :
135- surface = None
137+ pixbuf = None
136138 builder = None
137139 canvas = None
138140
@@ -144,6 +146,7 @@ class GuiHandler:
144146
145147 def __init__ (self , builder ) -> None :
146148 self .builder = builder
149+ self .pixels = None
147150 centerx_widget = builder .get_object ("center_x" )
148151 centery_widget = builder .get_object ("center_y" )
149152 radius_widget = builder .get_object ("radius" )
@@ -158,12 +161,13 @@ def __init__(self, builder) -> None:
158161 radius_widget .set_text (str (radius ))
159162 iterations_widget .set_text (str (iterations ))
160163
161- self .updateImageSurfaceIfNeeded ()
164+ self .updateImageBufferIfNeeded ()
162165
163166 def painter (self ):
164167 drawing_start = time .perf_counter ()
165168 try :
166- cr = cairo .Context (self .surface )
169+ channels = 3
170+ rowstride = self .width * channels
167171 pixel_count = 0
168172 while True :
169173 # get() will exit this thread if the
@@ -174,25 +178,24 @@ def painter(self):
174178 x = pixel [0 ]
175179 y = self .view .height - pixel [1 ]
176180
177- red , green , blue = colortable_float [pixel [2 ] & 0xf ]
181+ red , green , blue = colortable [pixel [2 ] & 0xf ]
178182 maxed = pixel [2 ] >> 7
179183
180- def draw_pixel ():
181- if not maxed :
182- cr .set_source_rgb (red , green , blue )
183- else :
184- cr .set_source_rgb (0 , 0 , 0 )
184+ pixel_index = y * rowstride + x * channels
185185
186- cr .rectangle (x , y , 1.5 , 1.5 )
187- cr .fill ()
188- if pixel_count % 1000 == 0 :
189- self .canvas .queue_draw ()
186+ if maxed :
187+ red = green = blue = 0
190188
191- return False
189+ if pixel_index + 2 < len (self .pixels ):
190+ self .pixels [pixel_index ] = red
191+ self .pixels [pixel_index + 1 ] = green
192+ self .pixels [pixel_index + 2 ] = blue
193+
194+ if pixel_count % (2 * self .width ) == 0 :
195+ Gdk .threads_enter ()
196+ self .canvas .queue_draw ()
197+ Gdk .threads_leave ()
192198
193- Gdk .threads_enter ()
194- draw_pixel ()
195- Gdk .threads_leave ()
196199 pixel_queue .task_done ()
197200
198201 finally :
@@ -202,12 +205,13 @@ def draw_pixel():
202205 def onDestroy (self , * args ):
203206 Gtk .main_quit ()
204207
205- def updateImageSurfaceIfNeeded (self ):
208+ def updateImageBufferIfNeeded (self ):
206209 self .canvas = canvas = builder .get_object ("canvas" )
207210 width = canvas .get_allocated_size ().allocation .width
208211 height = canvas .get_allocated_size ().allocation .height
209- if self .surface is None or self .width != width or self .height != height :
210- self .surface = cairo .ImageSurface (cairo .FORMAT_RGB24 , width , height )
212+ if (self .pixbuf is None or self .width != width or self .height != height ) and width > 0 and height > 0 :
213+ print (f"w { width } h { height } " )
214+ self .pixels = bytearray ((height + 1 ) * 3 * width )
211215 self .width , self .height = width , height
212216
213217 def getViewParameterWidgets (self ):
@@ -221,23 +225,22 @@ def getViewParameters(self):
221225 return map (getValue , self .getViewParameterWidgets ())
222226
223227 def onUpdateButtonPress (self , button ):
224- self .updateImageSurfaceIfNeeded ()
228+ self .updateImageBufferIfNeeded ()
225229
226230 center_x , center_y , radius = self .getViewParameters ()
227231 iterations = int (builder .get_object ("iterations" ).get_text ())
228232
229233 self .view .update (center_x = center_x , center_y = center_y , radius = radius , width = self .width , height = self .height , max_iterations = iterations )
230234 print (self .view .to_string ())
231235
232- cr = cairo .Context (self .surface )
233- cr .set_source_rgb (0 , 0 , 0 )
234- cr .rectangle (0 , 0 , self .width , self .height )
235- cr .fill ()
236+ # clear out image
237+ for i in range (len (self .pixels )):
238+ self .pixels [i ] = 0
236239
237240 view = self .view
238241 view .width = self .width
239242 view .height = self .height
240- usb_reader = lambda : send_command (9 , view , debug = False )
243+ usb_reader = lambda : send_command (9 , view , view . max_iterations , debug = False )
241244 usb_thread = threading .Thread (target = usb_reader , daemon = True )
242245 usb_thread .start ()
243246
@@ -262,8 +265,10 @@ def onCanvasMotion(self, canvas, event):
262265 canvas .queue_draw ()
263266
264267 def onDraw (self , canvas : DrawingArea , cr : cairo .Context ):
265- cr .set_source_surface (self .surface , 0 , 0 )
266- cr .paint ()
268+ if not self .pixels is None :
269+ pixbuf = Pixbuf .new_from_data (bytes (self .pixels ), Colorspace .RGB , False , 8 , self .width , self .height + 1 , self .width * 3 )
270+ Gdk .cairo_set_source_pixbuf (cr , pixbuf , 0 , 0 )
271+ cr .paint ()
267272 if not self .crosshairs is None :
268273 x , y = self .crosshairs [0 ]
269274 cr .set_source_rgb (1 , 1 , 1 )
0 commit comments