1
+ package org .usfirst .frc .team2084 .smartdashboard .extensions .vision ;
2
+
3
+ import java .awt .Color ;
4
+ import java .awt .Dimension ;
5
+ import java .awt .Graphics ;
6
+ import java .awt .Graphics2D ;
7
+ import java .awt .geom .AffineTransform ;
8
+ import java .awt .image .BufferedImage ;
9
+ import java .io .ByteArrayInputStream ;
10
+ import java .net .DatagramPacket ;
11
+ import java .net .DatagramSocket ;
12
+ import java .net .InetAddress ;
13
+ import java .net .SocketException ;
14
+ import java .net .UnknownHostException ;
15
+
16
+ import javax .imageio .ImageIO ;
17
+
18
+ import org .usfirst .frc .team2084 .CMonster2016 .vision .UDPVideoServer ;
19
+ import org .usfirst .frc .team2084 .CMonster2016 .vision .VisionParameters ;
20
+
21
+ import edu .wpi .first .smartdashboard .gui .StaticWidget ;
22
+ import edu .wpi .first .smartdashboard .properties .IntegerProperty ;
23
+ import edu .wpi .first .smartdashboard .properties .Property ;
24
+
25
+ /**
26
+ *
27
+ * @author Ben Wolsieffer
28
+ */
29
+ @ SuppressWarnings ("serial" )
30
+ public class UDPStreamViewerExtension extends StaticWidget {
31
+
32
+ public static final String NAME = "UDP Stream Viewer" ;
33
+
34
+ private double rotateAngleRad = 0 ;
35
+ private long lastFPSCheck = 0 ;
36
+ private int lastFPS = 0 ;
37
+ private int fpsCounter = 0 ;
38
+
39
+ private DatagramSocket socket ;
40
+ private final byte [] buffer = new byte [100000 ];
41
+
42
+ public class BGThread extends Thread {
43
+
44
+ boolean destroyed = false ;
45
+
46
+ public BGThread () {
47
+ super ("Camera Viewer Background" );
48
+ }
49
+
50
+ long lastRepaint = 0 ;
51
+
52
+ @ Override
53
+ public void run () {
54
+ while (!destroyed ) {
55
+ try {
56
+ DatagramPacket packet = new DatagramPacket (buffer , buffer .length );
57
+ socket .receive (packet );
58
+
59
+ fpsCounter ++;
60
+ long currTime = System .currentTimeMillis ();
61
+ long elapsedTime = currTime - lastFPSCheck ;
62
+ if (elapsedTime > 500 ) {
63
+ if (elapsedTime > 2000 ) {
64
+ updateIP ();
65
+ }
66
+ lastFPSCheck = currTime ;
67
+ lastFPS = fpsCounter * 2 ;
68
+ fpsCounter = 0 ;
69
+ }
70
+
71
+ lastRepaint = System .currentTimeMillis ();
72
+ ByteArrayInputStream tmpStream = new ByteArrayInputStream (buffer , 0 , packet .getLength ());
73
+ imageToDraw = ImageIO .read (tmpStream );
74
+
75
+ imageUpdated (imageToDraw );
76
+
77
+ repaint ();
78
+
79
+ } catch (Exception e ) {
80
+ imageToDraw = null ;
81
+ repaint ();
82
+ e .printStackTrace ();
83
+ }
84
+ }
85
+
86
+ }
87
+
88
+ @ Override
89
+ public void destroy () {
90
+ destroyed = true ;
91
+ }
92
+ }
93
+
94
+ private BufferedImage imageToDraw ;
95
+ private BGThread bgThread = new BGThread ();
96
+ public final IntegerProperty rotateProperty = new IntegerProperty (this , "Degrees Rotation" , 0 );
97
+
98
+ /**
99
+ *
100
+ */
101
+ public UDPStreamViewerExtension () {
102
+ try {
103
+ socket = new DatagramSocket (UDPVideoServer .PORT );
104
+ } catch (SocketException e ) {
105
+ e .printStackTrace ();
106
+ }
107
+ }
108
+
109
+ private void updateIP () {
110
+ try {
111
+ VisionParameters .setStreamIP (InetAddress .getLocalHost ().getHostAddress ());
112
+ } catch (UnknownHostException e ) {
113
+ System .out .println (e );
114
+ }
115
+ }
116
+
117
+ @ Override
118
+ public void init () {
119
+ setPreferredSize (new Dimension (320 , 240 ));
120
+ propertyChanged (rotateProperty );
121
+ bgThread .start ();
122
+ updateIP ();
123
+ revalidate ();
124
+ repaint ();
125
+ }
126
+
127
+ @ Override
128
+ public void propertyChanged (Property property ) {
129
+ if (property == rotateProperty ) {
130
+ rotateAngleRad = Math .toRadians (rotateProperty .getValue ());
131
+ }
132
+
133
+ }
134
+
135
+ @ Override
136
+ public void disconnect () {
137
+ bgThread .destroy ();
138
+ super .disconnect ();
139
+ }
140
+
141
+ @ Override
142
+ protected void paintComponent (Graphics g ) {
143
+ BufferedImage drawnImage = imageToDraw ;
144
+
145
+ if (drawnImage != null ) {
146
+ // cast the Graphics context into a Graphics2D
147
+ Graphics2D g2d = (Graphics2D ) g ;
148
+
149
+ // get the existing Graphics transform and copy it so that we can
150
+ // perform scaling and rotation
151
+ AffineTransform origXform = g2d .getTransform ();
152
+ AffineTransform newXform = (AffineTransform ) (origXform .clone ());
153
+
154
+ // find the center of the original image
155
+ int origImageWidth = drawnImage .getWidth ();
156
+ int origImageHeight = drawnImage .getHeight ();
157
+ int imageCenterX = origImageWidth / 2 ;
158
+ int imageCenterY = origImageHeight / 2 ;
159
+
160
+ // perform the desired scaling
161
+ double panelWidth = getBounds ().width ;
162
+ double panelHeight = getBounds ().height ;
163
+ double panelCenterX = panelWidth / 2.0 ;
164
+ double panelCenterY = panelHeight / 2.0 ;
165
+ double rotatedImageWidth = origImageWidth * Math .abs (Math .cos (rotateAngleRad )) + origImageHeight * Math .abs (Math .sin (rotateAngleRad ));
166
+ double rotatedImageHeight = origImageWidth * Math .abs (Math .sin (rotateAngleRad )) + origImageHeight * Math .abs (Math .cos (rotateAngleRad ));
167
+
168
+ // compute scaling needed
169
+ double scale = Math .min (panelWidth / rotatedImageWidth , panelHeight / rotatedImageHeight );
170
+
171
+ // set the transform before drawing the image
172
+ // 1 - translate the origin to the center of the panel
173
+ // 2 - perform the desired rotation (rotation will be about origin)
174
+ // 3 - perform the desired scaling (will scale centered about
175
+ // origin)
176
+ newXform .translate (panelCenterX , panelCenterY );
177
+ newXform .rotate (rotateAngleRad );
178
+ newXform .scale (scale , scale );
179
+ g2d .setTransform (newXform );
180
+
181
+ // draw image so that the center of the image is at the "origin";
182
+ // the transform will take care of the rotation and scaling
183
+ g2d .drawImage (drawnImage , -imageCenterX , -imageCenterY , null );
184
+
185
+ // restore the original transform
186
+ g2d .setTransform (origXform );
187
+
188
+ g .setColor (Color .PINK );
189
+ g .drawString ("FPS: " + lastFPS , 10 , 10 );
190
+ } else {
191
+ g .setColor (Color .PINK );
192
+ g .fillRect (0 , 0 , getBounds ().width , getBounds ().height );
193
+ g .setColor (Color .BLACK );
194
+ g .drawString ("NO CONNECTION" , 10 , 10 );
195
+ }
196
+ }
197
+
198
+ public void imageUpdated (BufferedImage image ) {
199
+ }
200
+ }
0 commit comments