스윙 기반 돋보기

11490 단어 swingnullimage
개요
본 코드는 JDK6u20 버전에서 디버깅을 통과하여 픽셀에 대한 캡처 처리와 TexturePaint를 이용하여 BufferedImage 대상에 대한 지원
모든 JComponent 구성 요소에 대한 확대경 효과를 제공합니다.
2. 사전 준비 작업
1. 전송된 JComponent 대상을 BufferedImage 대상으로 원본 이미지로 변환하고 아래 코드가 완성됩니다. 관건적인 단계는 BufferedImage 대상에서 자신의 도형 장치 대상을 만드는 것입니다.
orginalImage = new BufferedImage(this.srcComponent.getSize().width,
this.srcComponent.getSize().height, BufferedImage.TYPE_INT_ARGB);
Graphics g = orginalImage.createGraphics();
this.srcComponent.paintAll(g);
2. 소스 BufferedImage 객체에서 모든 픽셀 데이터를 읽습니다. 이것은 다음에 사용됩니다.코드는 다음과 같다.
originalPixels = new int[orginalImage.getWidth()*orginalImage.getHeight()];
orginalImage.getRaster().getDataElements(0,0, orginalImage.getWidth(),
orginalImage.getHeight(), originalPixels)
3. 돋보기 구성 요소를 만들고 사용자 정의 JFrame 대상을 사용하여 테두리를 제거하고 모양을 원형으로 만들어 코드는 다음과 같다.
zoomFrame = new JFrame("MagnifyGlass");
zoomFrame.setUndecorated(true);
Shape shape = new Ellipse2D.Double(0, 0,180, 180); AWTUtilitiesWrapper.
setWindowShape(
zoomFrame,shape);
3: 주요 사고방식과 핵심 코드
1. 원본 이미지에서 마우스의 위치를 포획합니다. 이것은 MouseMotionListener 인터페이스를 완성해야 합니다. 위치를 포획하는 코드는 다음과 같습니다.
double x = e.getPoint().getX();
double y = e.getPoint().getY();
2. 원본 이미지에서 마우스의 위치에 따라 원본 이미지의 픽셀을 캡처합니다. 픽셀의 범위는 축소된 비율에 따라 결정됩니다.
//get garb area rectangle
int grabCols = (int)((double)mySize.width/zoomFactor);
int grabRows = (int)((double)mySize.height/zoomFactor);
3. 소스 이미지 객체의 1차원 픽셀 배열에서 확대할 3D 픽셀 배열을 가져옵니다. 이 구현의 키 중 하나는 다음과 같습니다.
3D 픽셀 배열 객체를 먼저 정의합니다.
int[][][] data = newint[grabRows][grabCols][4];
3D ARGB의 픽셀 배열로 변환하기
//Alpha data
data[row][col][0] = (aRow[col] >> 24) & 0xFF;
//Red data
data[row][col][1] = (aRow[col] >> 16) & 0xFF;
//Green data
data[row][col][2] = (aRow[col] >> 8) & 0xFF;
//Blue data
data[row][col][3]= (aRow[col]) & 0xFF;
4. 호출 방법convertToOneDim()은 캡처된 픽셀을 1차원 배열로 변환하여 작성된 BufferedImage 객체에 배치합니다. 구현 코드는 다음과 같습니다.
grabImage.getRaster().setDataElements( 0, 0,grabWidth, grabHeight, oneDimPixelData );
5. TexturePaint를 이용하여grabImage 대상을 사용하여 돋보기 구성 요소를 채웁니다
TexturePaint tp = new TexturePaint((BufferedImage)grabImage,rect);
g2.setPaint(tp); g2.fill(circle1);
6.screen 좌표를 획득하여 확대경이 마우스를 따라다니는 효과를 실현한다
마우스의 화면 좌표 가져오기
//get screen point
Point offsetPoint = srcComponent.getLocationOnScreen();
e.translatePoint(offsetPoint.x, offsetPoint.y);
screenPoint = e.getPoint();
확대경이 마우스를 따라 움직이는 효과를 실현하려면:
zoomFrame.setLocation(screenPoint);
zoomFrame.setAlwaysOnTop(true);
7. 가장자리 픽셀 확대 문제를 처리하고 빈 부분은 흰색으로 채운다
data[row][col][0] = 0xFF;//alpha
data[row][col][1] = 0xFF;//red
data[row][col][2] = 0xFF;//green
data[row][col][3] = 0xFF;//blue
8. 최종 효과는 다음과 같습니다.
모든 소스 코드와 테스트 프로그램은 다음과 같습니다.
import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Paint; import java.awt.Point; import java.awt.RadialGradientPaint; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.TexturePaint; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel;  import javax.swing.JComponent; import javax.swing.JFrame;  public class PixelMagnifyGlass extends JComponent implements MouseMotionListener { 	 	/** 	 * magnify the image based on pixel data. 	 */ 	 	private static final long serialVersionUID = -1632282149543956832L; 	private double zoomFactor; 	private JComponent srcComponent; 	private Point imgPoint; 	private Point screenPoint; 	private JFrame zoomFrame; 	private Dimension mySize; 	private BufferedImage orginalImage; 	private int[] originalPixels; 	 	public PixelMagnifyGlass(JComponent comp, Dimension size, double zoom) { 		 this.srcComponent = comp; 		 screenPoint = new Point(-1, -1); 		 comp.addMouseMotionListener(this); 		 this.mySize = size; 		 this.zoomFactor = zoom; 		  		 // convert the JComponent to image 		 orginalImage = new BufferedImage(this.srcComponent.getSize().width,  				 		this.srcComponent.getSize().height, BufferedImage.TYPE_INT_ARGB); 		 Graphics g = orginalImage.createGraphics(); 		 this.srcComponent.paintAll(g); 		 g.dispose(); 		  		 // get all pixel arrays 		 originalPixels = new int[orginalImage.getWidth()*orginalImage.getHeight()]; 		 orginalImage.getRaster().getDataElements( 0, 0, orginalImage.getWidth(), orginalImage.getHeight(), originalPixels);  		  		 // start the glass component 		zoomFrame = new JFrame("MagnifyGlass"); 		zoomFrame.setUndecorated(true); 		Shape shape = new Ellipse2D.Double(0, 0,mySize.getWidth(), mySize.getHeight()); 		AWTUtilitiesWrapper.setWindowShape(zoomFrame, shape); 		  	} 	 	public void paint(Graphics g) { 		if(imgPoint.x == -1) { 			g.setColor(Color.BLUE); 			g.fillRect(0,0, mySize.width, mySize.height); 			return; 		} 		 		// draw zoom in/out image here 		Graphics2D g2 = (Graphics2D) g; 		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 		int grabWidth = (int)((double)mySize.width / zoomFactor); 		int grabHeight = (int)((double)mySize.height / zoomFactor); 		int[][][] threeDimPixelData = clipImageToThreeDim(originalPixels, (int)imgPoint.getX(), (int)imgPoint.getY()); 		int[] oneDimPixelData = convertToOneDim(threeDimPixelData, grabWidth, grabHeight); 		ColorModel cMD = orginalImage.getColorModel(); 		BufferedImage grabImage = new BufferedImage(orginalImage.getColorModel(), cMD.createCompatibleWritableRaster(grabWidth, grabHeight), cMD.isAlphaPremultiplied(), null); 		grabImage.getRaster().setDataElements( 0, 0, grabWidth, grabHeight, oneDimPixelData ); 		 		Image scaleImg = grabImage.getScaledInstance(mySize.width, mySize.height, Image.SCALE_FAST); 		// g2.drawImage(scaleImg, 0,0,null); 		 		// add glass edge with black 		Shape innerCircle = new Ellipse2D.Float(15.5f, 15.5f, mySize.width - 30, mySize.height - 30); 		Ellipse2D outterCircle = new Ellipse2D.Float(0, 0, mySize.width, mySize.height); 		Paint gp = new RadialGradientPaint((float)outterCircle.getCenterX(), (float)outterCircle.getCenterY(), 				 							(mySize.width)/2, 											new float[]{0f,0.8f,1f},new Color[]{Color.WHITE,Color.GRAY,Color.BLACK}); 		g2.setPaint(gp); 		g2.fill(outterCircle); 		Rectangle rect = new Rectangle(0,0,scaleImg.getWidth(null), scaleImg.getHeight(null)); 		TexturePaint tp = new TexturePaint((BufferedImage)grabImage, rect); 		g2.setPaint(tp); 		g2.fill(innerCircle); 	} 	 	public Dimension getPreferredSize() { 		return mySize; 	} 	 	public Dimension getMinimumSize() { 		return mySize; 	} 	 	public Dimension getMaximumSize() { 		return mySize; 	} 	 	 	@Override 	public void mouseDragged(MouseEvent e) { 		mouseMoved(e); 		 	} 	 	public int[][][] clipImageToThreeDim(int[] oneDPix, int startCols, int startRows) { 		 		// get garb area rectangle 		int grabCols = (int)((double)mySize.width / zoomFactor); 		int grabRows = (int)((double)mySize.height / zoomFactor); 		int[][][] data = new int[grabRows][grabCols][4]; 		 		for (int row = 0; row < grabRows; row++) { 			int[] aRow = new int[grabCols]; 			for (int col = 0; col < grabCols; col++) { 				int element = (row + startRows) * orginalImage.getWidth() + (startCols + col); 				 				// image edge detection and assign it as white color. 				if(element >= oneDPix.length || (startCols + col) >= orginalImage.getWidth()) { 					aRow[col] = 0; 				} else { 					aRow[col] = oneDPix[element]; 				} 			} 			 			for (int col = 0; col < grabCols; col++) { 				if(aRow[col] == 0) { 					// Alpha data 					data[row][col][0] = 0xFF; 					// Red data 					data[row][col][1] = 0xFF; 					// Green data 					data[row][col][2] = 0xFF; 					// Blue data 					data[row][col][3] = 0xFF; 				} else { 					// Alpha data 					data[row][col][0] = (aRow[col] >> 24) & 0xFF; 					// Red data 					data[row][col][1] = (aRow[col] >> 16) & 0xFF; 					// Green data 					data[row][col][2] = (aRow[col] >> 8) & 0xFF; 					// Blue data 					data[row][col][3] = (aRow[col]) & 0xFF; 				} 			} // end for loop on column  		} 		return data; 	} 	 	/* 

The purpose of this method is to convert the data in the 3D array of ints back into

*

the 1d array of type int.

* */ public int[] convertToOneDim(int[][][] data, int imgCols, int imgRows) { // Create the 1D array of type int to be populated with pixel data int[] oneDPix = new int[imgCols * imgRows * 4]; // Move the data into the 1D array. Note the // use of the bitwise OR operator and the // bitwise left-shift operators to put the // four 8-bit bytes into each int. for (int row = 0, cnt = 0; row < imgRows; row++) { for (int col = 0; col < imgCols; col++) { oneDPix[cnt] = ((data[row][col][0] << 24) & 0xFF000000) | ((data[row][col][1] << 16) & 0x00FF0000) | ((data[row][col][2] << 8) & 0x0000FF00) | ((data[row][col][3]) & 0x000000FF); cnt++; }// end for loop on col }// end for loop on row return oneDPix; }// end convertToOneDim @Override public void mouseMoved(MouseEvent e) { double x = e.getPoint().getX(); double y = e.getPoint().getY(); // we did not need to handle edge pixel like this again. // if((x + mySize.getWidth()) > this.orginalImage.getWidth()) { // x = x - ((x + mySize.getWidth()) - this.orginalImage.getWidth()); // } // if((y + mySize.getHeight()) > this.orginalImage.getHeight()) { // y = y - ((y + mySize.getHeight()) - this.orginalImage.getHeight()); // } // end comment by gloomy fish on 15-October-2011 imgPoint = new Point((int)x, (int)y); // get screen point Point offsetPoint = srcComponent.getLocationOnScreen(); e.translatePoint(offsetPoint.x, offsetPoint.y); screenPoint = e.getPoint(); repaint(); invokeGlass(); } /** * */ public void invokeGlass() { if(imgPoint.x == -1) { return; } if(zoomFrame.isVisible()) { zoomFrame.getContentPane().remove(this); zoomFrame.getContentPane().add(this); zoomFrame.setLocation(screenPoint); } else { zoomFrame.getContentPane().remove(this); zoomFrame.getContentPane().add(this); zoomFrame.pack(); zoomFrame.setLocation(screenPoint); zoomFrame.setVisible(true); zoomFrame.setAlwaysOnTop(true); } } }

테스트 프로그램:
import java.awt.Dimension; import java.io.File;  import javax.swing.ImageIcon; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel;  public class TestDetachedMagnifyingGlass { 	 	public TestDetachedMagnifyingGlass(File f) { 		ImageIcon i = new ImageIcon(f.getPath()); 		JLabel label = new JLabel(i); 		JFrame imageFrame = new JFrame("IMage"); 		imageFrame.getContentPane().add(label); 		imageFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 		imageFrame.pack(); 		imageFrame.setVisible(true); 		 		new PixelMagnifyGlass(label, new Dimension(180,180),2.0); 		// mag.invokeGlass(); 	} 	 	public static void main(String[] args) { 		JFileChooser chooser = new JFileChooser(); 		chooser.showOpenDialog(null); 		File f = chooser.getSelectedFile(); 		new TestDetachedMagnifyingGlass(f); 	}  } 

좋은 웹페이지 즐겨찾기