Skip to content

Commit d93e386

Browse files
committed
Add image rotation example
1 parent 36e1138 commit d93e386

File tree

4 files changed

+244
-15
lines changed

4 files changed

+244
-15
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ Below are the very pretty basic examples demonstrating of how Webcam Capture API
134134
* [How to display image from IP camera exposing MJPEG stream](https://github.com/sarxos/webcam-capture/blob/master/webcam-capture-drivers/driver-ipcam/src/examples/java/MjpegLignanoBeachExample.java)
135135
* [How to use composite driver to display both, build-in and IP camera images](https://github.com/sarxos/webcam-capture/blob/master/webcam-capture-drivers/driver-ipcam/src/examples/java/DualNativeAndMjpegWebcamExample.java)
136136
* [How to work with Raspberry Pi (camera module or UVC device)](https://github.com/sarxos/webcam-capture/wiki/How-To-Configure-Raspberry-Pi)
137+
* [How to rotate the image from camera with ```WebcamImageTransformer```](https://github.com/sarxos/webcam-capture/blob/master/webcam-capture/src/example/java/ImageTransformerRotationExample.java)
137138

138139
And here are some more advanced examples, few with quite fancy GUI.
139140

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import java.awt.Dimension;
2+
import java.awt.image.BufferedImage;
3+
import java.awt.image.BufferedImageOp;
4+
5+
import javax.swing.JFrame;
6+
7+
import com.github.sarxos.webcam.Webcam;
8+
import com.github.sarxos.webcam.WebcamImageTransformer;
9+
import com.github.sarxos.webcam.WebcamPanel;
10+
import com.github.sarxos.webcam.WebcamResolution;
11+
import com.github.sarxos.webcam.util.jh.JHFlipFilter;
12+
13+
14+
/**
15+
* This example demonstrates how to use {@link WebcamImageTransformer} to rotate the image from
16+
* camera by using {@link JHFlipFilter} from Jerry Huxtable filters package.
17+
*
18+
* @author Bartosz Firyn (sarxos)
19+
*/
20+
public class ImageTransformerRotationExample implements WebcamImageTransformer {
21+
22+
/**
23+
* This is filter from JH Labs which flips buffered image 90 degrees clockwise. For more details
24+
* please follow to the <a href="http://www.jhlabs.com/ip/filters/index.html">JH Labs Filters<a>
25+
* home page (filters source code can be found <a
26+
* href="https://github.com/axet/jhlabs">here</a>).
27+
*/
28+
private final BufferedImageOp filter = new JHFlipFilter(JHFlipFilter.FLIP_90CW);
29+
30+
public ImageTransformerRotationExample() {
31+
32+
// use VGA resolution
33+
34+
Dimension size = WebcamResolution.VGA.getSize();
35+
36+
// get default webcam and set image transformer to this (transformer will modify image after
37+
// it's received from webcam, in this case it will rotate it)
38+
39+
Webcam webcam = Webcam.getDefault();
40+
webcam.setViewSize(size);
41+
webcam.setImageTransformer(this);
42+
webcam.open();
43+
44+
// create window
45+
46+
JFrame window = new JFrame("Test Rotation");
47+
48+
// and webcam panel
49+
50+
WebcamPanel panel = new WebcamPanel(webcam);
51+
panel.setFPSDisplayed(true);
52+
panel.setFitArea(true);
53+
54+
// add panel to window
55+
56+
window.add(panel);
57+
window.pack();
58+
window.setVisible(true);
59+
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
60+
}
61+
62+
@Override
63+
public BufferedImage transform(BufferedImage image) {
64+
65+
// this will do rotation on image
66+
67+
return filter.filter(image, null);
68+
}
69+
70+
public static void main(String[] args) {
71+
new ImageTransformerRotationExample();
72+
}
73+
}

webcam-capture/src/main/java/com/github/sarxos/webcam/util/jh/JHFilter.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@
2626

2727

2828
/**
29-
* A convenience class which implements those methods of BufferedImageOp which
30-
* are rarely changed.
29+
* A convenience class which implements those methods of BufferedImageOp which are rarely changed.
3130
*/
3231
public abstract class JHFilter implements BufferedImageOp, Cloneable {
3332

3433
@Override
3534
public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
36-
if (dstCM == null)
35+
if (dstCM == null) {
3736
dstCM = src.getColorModel();
37+
}
3838
return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);
3939
}
4040

@@ -45,8 +45,9 @@ public Rectangle2D getBounds2D(BufferedImage src) {
4545

4646
@Override
4747
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
48-
if (dstPt == null)
48+
if (dstPt == null) {
4949
dstPt = new Point2D.Double();
50+
}
5051
dstPt.setLocation(srcPt.getX(), srcPt.getY());
5152
return dstPt;
5253
}
@@ -57,10 +58,9 @@ public RenderingHints getRenderingHints() {
5758
}
5859

5960
/**
60-
* A convenience method for getting ARGB pixels from an image. This tries to
61-
* avoid the performance penalty of BufferedImage.getRGB unmanaging the
62-
* image.
63-
*
61+
* A convenience method for getting ARGB pixels from an image. This tries to avoid the
62+
* performance penalty of BufferedImage.getRGB unmanaging the image.
63+
*
6464
* @param image a BufferedImage object
6565
* @param x the left edge of the pixel block
6666
* @param y the right edge of the pixel block
@@ -72,16 +72,16 @@ public RenderingHints getRenderingHints() {
7272
*/
7373
public int[] getRGB(BufferedImage image, int x, int y, int width, int height, int[] pixels) {
7474
int type = image.getType();
75-
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB)
75+
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
7676
return (int[]) image.getRaster().getDataElements(x, y, width, height, pixels);
77+
}
7778
return image.getRGB(x, y, width, height, pixels, 0, width);
7879
}
7980

8081
/**
81-
* A convenience method for setting ARGB pixels in an image. This tries to
82-
* avoid the performance penalty of BufferedImage.setRGB unmanaging the
83-
* image.
84-
*
82+
* A convenience method for setting ARGB pixels in an image. This tries to avoid the performance
83+
* penalty of BufferedImage.setRGB unmanaging the image.
84+
*
8585
* @param image a BufferedImage object
8686
* @param x the left edge of the pixel block
8787
* @param y the right edge of the pixel block
@@ -92,10 +92,11 @@ public int[] getRGB(BufferedImage image, int x, int y, int width, int height, in
9292
*/
9393
public void setRGB(BufferedImage image, int x, int y, int width, int height, int[] pixels) {
9494
int type = image.getType();
95-
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB)
95+
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
9696
image.getRaster().setDataElements(x, y, width, height, pixels);
97-
else
97+
} else {
9898
image.setRGB(x, y, width, height, pixels, 0, width);
99+
}
99100
}
100101

101102
@Override
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
Copyright 2006 Jerry Huxtable
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package com.github.sarxos.webcam.util.jh;
18+
19+
import java.awt.image.BufferedImage;
20+
import java.awt.image.ColorModel;
21+
22+
23+
/**
24+
* A filter which flips images or rotates by multiples of 90 degrees.
25+
*/
26+
public class JHFlipFilter extends JHFilter {
27+
28+
/**
29+
* Rotate the image 90 degrees clockwise.
30+
*/
31+
public static final int FLIP_90CW = 4;
32+
33+
/**
34+
* Rotate the image 90 degrees counter-clockwise.
35+
*/
36+
public static final int FLIP_90CCW = 5;
37+
38+
/**
39+
* Rotate the image 180 degrees.
40+
*/
41+
public static final int FLIP_180 = 6;
42+
43+
private int operation;
44+
45+
/**
46+
* Construct a FlipFilter which flips horizontally and vertically.
47+
*/
48+
public JHFlipFilter() {
49+
this(FLIP_90CW);
50+
}
51+
52+
/**
53+
* Construct a FlipFilter.
54+
*
55+
* @param operation the filter operation
56+
*/
57+
public JHFlipFilter(int operation) {
58+
this.operation = operation;
59+
}
60+
61+
/**
62+
* Set the filter operation.
63+
*
64+
* @param operation the filter operation
65+
* @see #getOperation
66+
*/
67+
public void setOperation(int operation) {
68+
this.operation = operation;
69+
}
70+
71+
/**
72+
* Get the filter operation.
73+
*
74+
* @return the filter operation
75+
* @see #setOperation
76+
*/
77+
public int getOperation() {
78+
return operation;
79+
}
80+
81+
@Override
82+
public BufferedImage filter(BufferedImage src, BufferedImage dst) {
83+
int width = src.getWidth();
84+
int height = src.getHeight();
85+
86+
int[] inPixels = getRGB(src, 0, 0, width, height, null);
87+
88+
int w = width;
89+
int h = height;
90+
91+
int newW = w;
92+
int newH = h;
93+
switch (operation) {
94+
case FLIP_90CW:
95+
newW = h;
96+
newH = w;
97+
break;
98+
case FLIP_90CCW:
99+
newW = h;
100+
newH = w;
101+
break;
102+
case FLIP_180:
103+
break;
104+
}
105+
106+
int[] newPixels = new int[newW * newH];
107+
108+
for (int row = 0; row < h; row++) {
109+
for (int col = 0; col < w; col++) {
110+
int index = row * width + col;
111+
int newRow = row;
112+
int newCol = col;
113+
switch (operation) {
114+
case FLIP_90CW:
115+
newRow = col;
116+
newCol = h - row - 1;
117+
;
118+
break;
119+
case FLIP_90CCW:
120+
newRow = w - col - 1;
121+
newCol = row;
122+
break;
123+
case FLIP_180:
124+
newRow = h - row - 1;
125+
newCol = w - col - 1;
126+
break;
127+
}
128+
int newIndex = newRow * newW + newCol;
129+
newPixels[newIndex] = inPixels[index];
130+
}
131+
}
132+
133+
if (dst == null) {
134+
ColorModel dstCM = src.getColorModel();
135+
dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(newW, newH), dstCM.isAlphaPremultiplied(), null);
136+
}
137+
setRGB(dst, 0, 0, newW, newH, newPixels);
138+
139+
return dst;
140+
}
141+
142+
@Override
143+
public String toString() {
144+
switch (operation) {
145+
case FLIP_90CW:
146+
return "Rotate 90";
147+
case FLIP_90CCW:
148+
return "Rotate -90";
149+
case FLIP_180:
150+
return "Rotate 180";
151+
}
152+
return "Flip";
153+
}
154+
}

0 commit comments

Comments
 (0)