위에 껄 한꺼번에 만들다 보니, 예상 외로 힘들어서 한 기능 씩 만들어 보기로 했습니다.
오늘은 이미지 표출에 대해서 만들어 보기로 합니다.
우선, 카메라 입력 때와 같은 UI 골격을 사용 하기로 결정 했습니다.
그리는 방식은 다음 두가지를 사용 할 것이구요.
- Canvas 클래스를 이용 한 표출
- JPanel 클래스를 이용 한 표출
Canvas 클래스를 사용 하는 경우 그리는 방식은
- 일반 paint 메서드 오버라이딩
- update 메서드를 시용한 더블 버퍼링
이 될 것입니다.
그래서 생각 해 보니,
- JPanel로 그릴 것인지 아니면 Canvas 로 그릴 지 지정하고
- DoubleBuffering 을 적용 할 지 여부를 지정 하는 게
필요 하지 않을까 해서 최초에 사용자에게 받아 보도록 콤보 박스를 만들어 보았어요
이렇게
최 상단 옵션은 앞으로 만들어질 동영상과 카메라 버전을 모두 확인 해 보기 위해서 만들어 봤습니다.
위의 옵션을 저장할 UsrSelectOptions 클래스 입니다.
static final class UsrSelectOptions
{
private final boolean isCanvas;
private final boolean isDoubleBuffering;
private final String themeType;
UsrSelectOptions(final String themeType,final boolean isCanvas,final boolean isDoubleBuffering)
{
this.themeType = themeType;
this.isCanvas = isCanvas;
this.isDoubleBuffering = isDoubleBuffering;
}
public boolean isCanvas() {
return isCanvas;
}
public boolean isDoubleBuffering() {
return isDoubleBuffering;
}
public String getThemeType() {
return themeType;
}
}
사용자 화면 만들기 전에 만들 도록 했습니다.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// try {
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
// } catch (Exception useDefault) {
// }
selectUsrOptionGui();
JFrame f = new JFrame("OpenCV Java Works");
... 생략
final CVTestPane cvmainPane = new CVTestPane(f, mUsrOptions);
});
}
selectUsrOptionGui 메서드 내에서 다음과 같이 선언하여 저장 하였습니다.
private static void selectUsrOptionGui() {
final String themeOptions[]={"Image","Movie", "Camera"};
final String containerOptions[]={"Canvas","Panel"};
final String drawOptions[]={"None","Dbuffering"};
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3, 0));
panel.setBackground(new Color(0, 0, 0));
panel.setSize(new Dimension(250, 100));
panel.setPreferredSize(new Dimension(250, 100));
JComboBox<String> cmbCntOptions = new JComboBox<String>(containerOptions);
cmbCntOptions.setActionCommand("ContainerOpts");
JComboBox<String> cmbDrwOptions = new JComboBox<String>(drawOptions);
cmbDrwOptions.setActionCommand("DrawOpts");
JComboBox<String> cmbThemeOptions = new JComboBox<String>(themeOptions);
cmbThemeOptions.setActionCommand("ThemeOpts");
// Add controls to set up horizontal and vertical gaps
panel.add(cmbThemeOptions);
panel.add(cmbCntOptions);
panel.add(cmbDrwOptions);
UIManager.put("OptionPane.minimumSize", new Dimension(270, 120));
int result = JOptionPane.showConfirmDialog(null, panel, "Select User Option",
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
final String themeType = (String)cmbThemeOptions.getSelectedItem();
boolean isCanvas = false, isDoubleBuffering = false;
String strSelectedOpt = (String)cmbCntOptions.getSelectedItem();
if(strSelectedOpt.equals("Panel"))
isCanvas = false;
else isCanvas = true;
strSelectedOpt = (String)cmbDrwOptions.getSelectedItem();
if(strSelectedOpt.equals("None"))
isDoubleBuffering = false;
else isDoubleBuffering = true;
mUsrOptions = new UsrSelectOptions(themeType,isCanvas,isDoubleBuffering);
} else {
System.out.println("Closed");
//cvmainPane.stopMovie(isCanvas);
System.exit(0);
}
}
이 중에 아래 코드는
final String themeOptions[]={"Image","Movie", "Camera"};
우리가 처리 해야 할 이미지, 동영상 그리고 카메라 입력에 대한 내용을 다루는 것입니다.
UsrSelectOptions 클래스 인스턴스는 전역 옵션 처럼 사용 하면 어떨까 하네요.
그렇게 하면 다음 처럼 모든 리스너에게 전달 하도록 합니다.
class MainButtonClickListener implements ActionListener {
final UsrSelectOptions usrOptions;
public MainButtonClickListener(final UsrSelectOptions usrOptions) {
this.usrOptions = usrOptions;
}
@Override
public void actionPerformed(ActionEvent e) {
boolean isStop = false;
if (e.getSource() instanceof JButton) {
JButton currentBtn = (JButton) e.getSource();
if(usrOptions.isCanvas)
imageCanvas.setThemeButton(currentBtn);
else
imagePanel.setThemeButton(currentBtn);
if (currentBtn.getText().startsWith("Stop")) {
isStop = true;
}
}
if (e.getActionCommand().equals("goImageCanvas")) {
if(!isStop) mSelectedFile = selectFileGui("Image");
imageCanvas.loadImage(mSelectedFile, isStop);
}else if (e.getActionCommand().equals("goImagePanel")) {
if(!isStop) mSelectedFile = selectFileGui("Image");
imagePanel.loadImage(mSelectedFile, isStop);
}
}
}
그리고 캔버스의 경우에는 두 개의 클래스를 방식에 따라서 사용하기 때문에 다음 추상 클래스로 ImageCanvas 를 하나 만들고 하위 클래스에서 사용 받도록 했습니다.
(ImageCanvasDoubleBuffer, ImageCanvasNoDoubleBuffer)
abstract class ImageCanvas extends Canvas
{
abstract void setThemeButton(JButton currentBtn);
abstract void stopTimer();
abstract void loadImage(String imagePath, boolean isStop);
abstract void loadImage(int drawingStyle);
abstract void loadImage(int drawingStyle, CannyOption cannyOption);
}
loadImage 메서드는 세개가 있는 데, 최초 버튼을 눌렀을 때 진행 하는 메서드는 아래 메서드 형태 입니다.
abstract void loadImage(String imagePath, boolean isStop);
아래 두개의 메서드는 왼쪽 프로세싱 버튼을 눌렀을 때, 이미 만들어진 버퍼 이미지를 조작 하기 위해서 사용 되는 메서드 입니다.
abstract void loadImage(int drawingStyle);
abstract void loadImage(int drawingStyle, CannyOption cannyOption);
그럼 코드 상으로는 이렇게 되겠죠?
private ImageCanvas imageCanvas;
...
private void initImagePanel(final UsrSelectOptions usrOptions) {
setLayout(new BorderLayout());
btnListener = new MainButtonClickListener(usrOptions);
JPanel btnFuncPane = new FuncButtonPanel();
JPanel btnCtrlPane = new JPanel();
btnCtrlPane.add(goImage);
if(usrOptions.isCanvas)
{
if(usrOptions.isDoubleBuffering)
imageCanvas = new ImageCanvasDoubleBuffer();
else
imageCanvas = new ImageCanvasNoDoubleBuffer();
goImage.setActionCommand("goImageCanvas");
add(imageCanvas, BorderLayout.CENTER);
}
else
{
imagePanel = new ImagePanel();
goImage.setActionCommand("goImagePanel");
add(imagePanel, BorderLayout.CENTER);
}
add(btnCtrlPane, BorderLayout.SOUTH);
add(btnFuncPane, BorderLayout.WEST);
goImage.addActionListener(btnListener);
}
이렇게 선택 하면
제대로 나오네요~
이제 그럼 왼쪽의 버튼 액션을 만들어 볼 차례 입니다.
계속...
'프로그래밍 > [Java] OpenCV' 카테고리의 다른 글
OpenCV와 자바 - 4.2. 동영상 조작 (0) | 2022.09.16 |
---|---|
OpenCV와 자바 - 4.1. 이미지 조작 - 2 (0) | 2022.09.15 |
OpenCV와 자바 - 4. 동영상과 이미지 UI-1 (1) | 2022.09.13 |
OpenCV와 자바 - 3. 프로세싱-2 (0) | 2022.09.12 |
OpenCV와 자바 - 3. 프로세싱 (2) | 2022.09.11 |