Reputation:
I'm trying to build a GUI where I have the possibility to load an image (and draw it on a canvas) and to make a histogram out of it's pixels when I press a button (I want to display the histogram on the GUI too, but only for the "red" pixels for simplicity).
Initially I put a black background for the image canvas and afterwards the canvas is updated based on what image is loaded (using the load-button). In the same time I also save the pixels into input-buffer.
I couldn't find a way to embedded the plot onto the GUI, so for now I only plot it in the REPL.
I assume that the images are 256x256 (but anything else is fine as it can be modified afterwards). Here's the code of what I've tried so far:
#lang racket/gui
(require plot)
(define SIZE 256)
(define frame
(new frame%
[label "BMP"]
[x 0] [y 0]
[width 1000] [height 500]))
(define main-panel
(new horizontal-panel%
[parent frame]))
;---------------FOR THE IMAGE---------------------
(define input-panel
(new vertical-panel%
[parent main-panel]))
;in order to put a black fundal for the bitmap initially
(define input-bitmap (make-bitmap SIZE SIZE))
(define input-dc (send input-bitmap make-dc))
(send input-dc set-background (make-color 0 0 0))
(send input-dc clear)
(define input-canvas
(new canvas%
[parent input-panel]
[paint-callback
(λ (canvas dc)
(send dc draw-bitmap input-bitmap 0 0))]))
;update canvas with the new loaded image
;also save the pixels in the input-buffer
(define input-buffer (make-bytes (* SIZE SIZE 4)))
(define load-button
(new button%
[parent input-panel]
[label "Load file"]
[callback
(λ (button event)
(define path (get-file))
(when path
(set! input-bitmap (read-bitmap path))
(send input-canvas on-paint)
(send input-bitmap get-argb-pixels 0 0 SIZE SIZE input-buffer)))]))
;---------------FOR THE HISTOGRAM---------------------
;builds a list of SIZE elements holding the frequency of each pixels
;e.g.: '((0 100) (1 50) ... (255 75)) ->this is given to the histogram
(define (get-red-pixels buffer)
(define red-pixels
(for/list ([i (in-range 1 (* SIZE SIZE 4) 4)])
(bytes-ref buffer i)))
(map list (build-list SIZE values)
(for/list ([i SIZE])
(length (filter (λ(x) (= i x)) red-pixels)))))
(define (plot-histogram)
(plot (discrete-histogram (get-red-pixels input-buffer)
#:y-max 100
#:color 1 #:line-color 1)))
(define histogram-panel
(new vertical-panel%
[parent main-panel]))
(define refresh-button
(new button%
[parent histogram-panel]
[label "Refresh"]
[callback
(λ (button event)
;not plotting when pressed..
;also I want the plot to be on the interface
(plot-histogram))]))
(send frame show #t)
In order for the histogram to be plotted I must explicit call (plot-button) as the refresh-button doesn't plot it. Anyway I am trying to put the plot inside the interface not in a new window, however I'm stuck. Please let me know if anything is unclear.
Upvotes: 0
Views: 157
Reputation: 7576
I made some changes in your old code and this seems to work:
(check load-button
and get-red-pixels
, rest of code should be the same)
#lang racket/gui
(require plot)
(define SIZE 256)
(define frame
(new frame%
[label "BMP"]
[x 0] [y 0]
[width 1000] [height 500]))
(define main-panel
(new horizontal-panel%
[parent frame]))
;---------------FOR THE IMAGE---------------------
(define input-panel
(new vertical-panel%
[parent main-panel]))
;in order to put a black fundal for the bitmap initially
(define input-bitmap (make-bitmap SIZE SIZE))
(define input-dc (send input-bitmap make-dc))
(send input-dc set-background (make-color 0 0 0))
(send input-dc clear)
(define input-canvas
(new canvas%
[parent input-panel]
[paint-callback
(λ (canvas dc)
(send dc draw-bitmap input-bitmap 0 0))]))
;update canvas with the new loaded image
;also save the pixels in the input-buffer
(define input-buffer (make-bytes (* SIZE SIZE 4)))
(define load-button
(new button%
[parent input-panel]
[label "Load file"]
[callback
(λ (button event)
(let ((path (get-file)))
(when path
(set! input-bitmap (make-object bitmap% path))
(send input-canvas on-paint)
(send input-bitmap get-argb-pixels 0 0 SIZE SIZE input-buffer)
(plot/dc (discrete-histogram (get-red-pixels input-buffer)
#:y-max SIZE
#:color 1
#:line-color 1)
(send histogram-canvas get-dc)
0 0
SIZE SIZE))))]))
;---------------FOR THE HISTOGRAM---------------------
;builds a list of SIZE elements holding the frequency of each pixels
;e.g.: '((0 100) (1 50) ... (255 75)) ->this is given to the histogram
(define (get-red-pixels buffer)
(let ((red-pixels
(for/list ([i (in-range 1 (* SIZE SIZE 4) 4)])
(bytes-ref buffer i))))
(map list
(build-list SIZE values)
(for/list ([i SIZE])
(count (λ(x) (= i x)) red-pixels)))))
(define histogram-panel
(new vertical-panel%
[parent main-panel]))
(define histogram-canvas
(new canvas%
[parent histogram-panel]))
(send frame show #t)
Upvotes: 0