我正在尝试构建一个GUI,在这里我可以加载图像(并在画布上绘制(,并在按下按钮时用它的像素制作直方图(我也想在GUI上显示直方图,但为了简单起见,只针对"红色"像素(。
最初,我为图像画布设置了一个黑色背景,然后根据加载的图像更新画布(使用加载按钮(。同时,我还将像素保存到输入缓冲区中。
我找不到将绘图嵌入GUI的方法,所以现在我只在REPL中绘图。
我假设图像是256x256(但其他任何东西都可以,因为之后可以修改(。以下是我迄今为止尝试的代码:
#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)
为了绘制直方图,我必须显式调用(绘图按钮(,因为刷新按钮不会绘制它。无论如何,我试图将绘图放在界面内,而不是新窗口中,但我被卡住了。如果有什么不清楚的地方,请告诉我。
我对您的旧代码进行了一些更改,这似乎很有效:
(检查load-button
和get-red-pixels
,其余代码应相同(
#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)