I realize this is an older question, but it comes up first in a Google search, and among the excellent answers provided, I didn't see anything fully comprehensive, so I did a little more digging and I ended up writing an enum class that not only allowed me to assign multiple custom values to the enum constants, I even added a method that allows me to assign values to them on the fly during code execution.
This enum class is for a "server" program that I run on a Raspberry Pi. The program receives commands from a client then it executes terminal commands that make adjustments to a webcam that is affixed to my 3D printer.
Using the Linux program 'v4l2-ctl' on the Pi, you can extract all of the possible adjustment commands for a given attached webcam, which also provides the setting datatype, the min and max values, the number of value steps in a given value range etc., so I took all of those and put them in an enum and created an enum interface that makes it easy to both set and get values for each command as well as a simple method to get the actual terminal command that is executed (using the Process and Runtime classes) in order to adjust the setting.
It is a rather large class and I apologize for that, but for me, it's always easier to learn something when I can see it working in full context, so I decided not to scale it down. However, even though it's large, it is definitely simple and it should be obvious what's happening in the class with minimal effort.
package constants;
import java.util.HashMap;
import java.util.Map;
public enum PICam {
BRIGHTNESS ("brightness", 0, "int", 0, 100, 1, 50),
CONTRAST ("contrast", 1, "int", 100, 100, 1, 0),
SATURATION ("saturation", 2, "int", 100, 100, 1, 0),
RED_BALANCE ("red_balance", 3, "intmenu", 1, 7999, 1, 1000),
BLUE_BALANCE ("blue_balance", 4, "int", 1, 7999, 1, 1000),
HORIZONTAL_FLIP ("horizontal_flip", 5, "bool", 0, 1, 1, 0),
VERTICAL_FLIP ("vertical_flip", 6, "bool", 0, 1, 1, 0),
POWER_LINE_FREQUENCY ("power_line_frequency", 7, "menu", 0, 3, 1, 1),
SHARPNESS ("sharpness", 8, "int", 100, 100, 1, 0),
COLOR_EFFECTS ("color_effects", 9, "menu", 0, 15, 1, 0),
ROTATE ("rotate", 10, "int", 0, 360, 90, 0),
COLOR_EFFECTS_CBCR ("color_effects_cbcr", 11, "int", 0, 65535, 1, 32896),
VIDEO_BITRATE_MODE ("video_bitrate_mode", 12, "menu", 0, 1, 1, 0),
VIDEO_BITRATE ("video_bitrate", 13, "int", 25000, 25000000, 25000, 10000000),
REPEAT_SEQUENCE_HEADER ("repeat_sequence_header", 14, "bool", 0, 1, 1, 0),
H264_I_FRAME_PERIOD ("h_264_i_frame_period", 15, "int", 0, 2147483647,1, 60),
H264_LEVEL ("h_264_level", 16, "menu", 0, 11, 1, 11),
H264_PROFILE ("h_264_profile", 17, "menu", 0, 4, 1, 4),
AUTO_EXPOSURE ("auto_exposure", 18, "menu", 0, 3, 1, 0),
EXPOSURE_TIME_ABSOLUTE ("exposure_time_absolute", 19, "int", 1, 10000, 1, 1000),
EXPOSURE_DYNAMIC_FRAMERATE ("exposure_dynamic_framerate", 20, "bool", 0, 1, 1, 0),
AUTO_EXPOSURE_BIAS ("auto_exposure_bias", 21, "intmenu", 0, 24, 1, 12),
WHITE_BALANCE_AUTO_PRESET ("white_balance_auto_preset", 22, "menu", 0, 9, 1, 1),
IMAGE_STABILIZATION ("image_stabilization", 23, "bool", 0, 1, 1, 0),
ISO_SENSITIVITY ("iso_sensitivity", 24, "intmenu", 0, 4, 1, 0),
ISO_SENSITIVITY_AUTO ("iso_sensitivity_auto", 25, "menu", 0, 1, 1, 1),
EXPOSURE_METERING_MODE ("exposure_metering_mode", 26, "menu", 0, 2, 1, 0),
SCENE_MODE ("scene_mode", 27, "menu", 0, 13, 1, 0),
COMPRESSION_QUALITY ("compression_quality", 28, "int", 1, 100, 1, 30);
private static final Map<String, PICam> LABEL_MAP = new HashMap<>();
private static final Map<Integer, PICam> INDEX_MAP = new HashMap<>();
private static final Map<String, PICam> TYPE_MAP = new HashMap<>();
private static final Map<Integer, PICam> MIN_MAP = new HashMap<>();
private static final Map<Integer, PICam> MAX_MAP = new HashMap<>();
private static final Map<Integer, PICam> STEP_MAP = new HashMap<>();
private static final Map<Integer, PICam> DEFAULT_MAP = new HashMap<>();
private static final Map<Integer, Integer> THIS_VALUE_MAP = new HashMap<>();
private static final String baseCommandLine = "/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=";
static {
for (PICam e: values()) {
LABEL_MAP.put(e.label, e);
INDEX_MAP.put(e.index, e);
TYPE_MAP.put(e.type, e);
MIN_MAP.put(e.min, e);
MAX_MAP.put(e.max, e);
STEP_MAP.put(e.step, e);
DEFAULT_MAP.put(e.defaultValue, e);
}
}
public final String label;
public final int index;
public final String type;
public final int min;
public final int max;
public final int step;
public final int defaultValue;
private PICam(String label, int index, String type, int min, int max, int step, int defaultValue) {
this.label = label;
this.index = index;
this.type = type;
this.min = min;
this.max = max;
this.step = step;
this.defaultValue = defaultValue;
}
public static void setValue(Integer index, Integer value) {
if (THIS_VALUE_MAP.containsKey(index)) THIS_VALUE_MAP.replace(index, value);
else THIS_VALUE_MAP.put(index, value);
}
public Integer getValue (Integer index) {
return THIS_VALUE_MAP.getOrDefault(index, null);
}
public static PICam getLabel(String label) {
return LABEL_MAP.get(label);
}
public static PICam getType(String type) {
return TYPE_MAP.get(type);
}
public static PICam getMin(int min) {
return MIN_MAP.get(min);
}
public static PICam getMax(int max) {
return MAX_MAP.get(max);
}
public static PICam getStep(int step) {
return STEP_MAP.get(step);
}
public static PICam getDefault(int defaultValue) {
return DEFAULT_MAP.get(defaultValue);
}
public static String getCommandFor(int index, int newValue) {
PICam picam = INDEX_MAP.get(index);
String commandValue = "";
if ("bool".equals(picam.type)) {
commandValue = (newValue == 0) ? "false" : "true";
}
else {
commandValue = String.valueOf(newValue);
}
return baseCommandLine + INDEX_MAP.get(index).label + "=" + commandValue;
}
public static String getCommandFor(PICam picam, Integer newValue) {
String commandValue = "";
if ("bool".equals(picam.type)) {
commandValue = (newValue == 0) ? "false" : "true";
}
else {
commandValue = String.valueOf(newValue);
}
return baseCommandLine + INDEX_MAP.get(picam.index).label + "=" + commandValue;
}
public static String getCommandFor(PICam piCam) {
int newValue = piCam.defaultValue;
String commandValue = "";
if ("bool".equals(piCam.type)) {
commandValue = (newValue == 0) ? "false" : "true";
}
else {
commandValue = String.valueOf(newValue);
}
return baseCommandLine + piCam.label + "=" + commandValue;
}
public static String getCommandFor(Integer index) {
PICam piCam = INDEX_MAP.get(index);
int newValue = piCam.defaultValue;
String commandValue = "";
if ("bool".equals(piCam.type)) {
commandValue = (newValue == 0) ? "false" : "true";
}
else {
commandValue = String.valueOf(newValue);
}
return baseCommandLine + piCam.label + "=" + commandValue;
}
}
Here are some ways that the class can be interacted with:
This code:
public static void test() {
PICam.setValue(0,127); //Set brightness to 125
PICam.setValue(PICam.SHARPNESS,143); //Set sharpness to 125
String command1 = PICam.getSetCommandStringFor(PICam.BRIGHTNESS); //Get command line string to include the brightness value that we previously set referencing it by enum constant.
String command2 = PICam.getSetCommandStringFor(0); //Get command line string to include the brightness value that we previously set referencing it by index number.
String command3 = PICam.getDefaultCamString(PICam.BRIGHTNESS); //Get command line string with the default value
String command4 = PICam.getSetCommandStringFor(PICam.SHARPNESS); //Get command line string with the sharpness value that we previously set.
String command5 = PICam.getDefaultCamString(PICam.SHARPNESS); //Get command line string with the default sharpness value.
System.out.println(command1);
System.out.println(command2);
System.out.println(command3);
System.out.println(command4);
System.out.println(command5);
}
Produces these results:
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=brightness=127
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=brightness=127
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=brightness=50
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=sharpness=143
/usr/bin/v4l2-ctl -d /dev/video0 --set-ctrl=sharpness=0