Merge branch 'multi_colortransform'

Conflicts:
	CMakeLists.txt
	config/hyperion.config.json

Former-commit-id: 43d42e4fed479f60333b35bc092f9a55cd2ad8e8
This commit is contained in:
T. van der Zwan 2013-12-05 15:58:53 +00:00
commit f65f546c61
31 changed files with 1890 additions and 403 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/*.user /*.user
/build /build
/build-x86

View File

@ -35,6 +35,7 @@ include_directories(${CMAKE_SOURCE_DIR}/include)
# Prefer static linking over dynamic # Prefer static linking over dynamic
#set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") #set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so")
#set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_BUILD_TYPE "Release") set(CMAKE_BUILD_TYPE "Release")
# enable C++11 # enable C++11
@ -43,14 +44,20 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall")
# Configure the use of QT4 # Configure the use of QT4
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED QUIET) find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED QUIET)
#SET(QT_DONT_USE_QTGUI TRUE) # add protocol buffers
#SET(QT_USE_QTCONSOLE TRUE) find_package(Protobuf REQUIRED)
#add libusb and pthreads
find_package(libusb-1.0 REQUIRED)
find_package(Threads REQUIRED)
include(${QT_USE_FILE}) include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS}) add_definitions(${QT_DEFINITIONS})
link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf) link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(bin/install_hyperion.sh ${LIBRARY_OUTPUT_PATH} @ONLY)
configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY) configure_file(config/hyperion.config.json ${LIBRARY_OUTPUT_PATH} @ONLY)
configure_file(config/hyperion_x86.config.json ${LIBRARY_OUTPUT_PATH} @ONLY)
# Add the source/lib directories # Add the source/lib directories
add_subdirectory(dependencies) add_subdirectory(dependencies)

View File

@ -0,0 +1,409 @@
// Automatically generated configuration file for 'Hyperion daemon'
// Generated by: HyperCon (The Hyperion deamon configuration file builder
{
/// Device configuration contains the following fields:
/// * 'name' : The user friendly name of the device (only used for display purposes)
/// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806',
/// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none')
/// * 'output' : The output specification depends on selected device. This can for example be the
/// device specifier, device serial number, or the output file name
/// * 'rate' : The baudrate of the output to the device
/// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.).
"device" :
{
"name" : "MyPi",
"type" : "ws2801",
"output" : "/dev/spidev0.0",
"rate" : 500000,
"colorOrder" : "rgb"
},
/// Color manipulation configuration used to tune the output colors to specific surroundings. Contains the following fields:
/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following tuning parameters:
/// - 'saturationGain' The gain adjustement of the saturation
/// - 'valueGain' The gain adjustement of the value
/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the following tuning parameters for each channel:
/// - 'threshold' The minimum required input value for the channel to be on (else zero)
/// - 'gamma' The gamma-curve correction factor
/// - 'blacklevel' The lowest possible value (when the channel is black)
/// - 'whitelevel' The highest possible value (when the channel is white)
/// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning parameters:
/// - 'type' The type of smoothing algorithm ('linear' or 'none')
/// - 'time_ms' The time constant for smoothing algorithm in milliseconds
/// - 'updateFrequency' The update frequency of the leds in Hz
"color" :
{
"transform" :
[
{
"id" : "MyPi device",
"leds" : "0-49",
"hsv" :
{
"saturationGain" : 1.0000,
"valueGain" : 1.5000
},
"red" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 0.8000
},
"green" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 1.0000
},
"blue" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 1.0000
}
}
],
"smoothing" :
{
"type" : "linear",
"time_ms" : 200,
"updateFrequency" : 20.0000
}
},
/// The configuration for each individual led. This contains the specification of the area
/// averaged of an input image for each led to determine its color. Each item in the list
/// contains the following fields:
/// * index: The index of the led. This determines its location in the string of leds; zero
/// being the first led.
/// * hscan: The fractional part of the image along the horizontal used for the averaging
/// (minimum and maximum inclusive)
/// * vscan: The fractional part of the image along the vertical used for the averaging
/// (minimum and maximum inclusive)
"leds" :
[
{
"index" : 0,
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 1,
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 2,
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 3,
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 4,
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 5,
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 6,
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 7,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 8,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 9,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
},
{
"index" : 10,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
},
{
"index" : 11,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
},
{
"index" : 12,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
},
{
"index" : 13,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
},
{
"index" : 14,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
},
{
"index" : 15,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
},
{
"index" : 16,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 17,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 18,
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 19,
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 20,
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 21,
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 22,
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 23,
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 24,
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 25,
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 26,
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 27,
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 28,
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 29,
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 30,
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 31,
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 32,
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 33,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 34,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
},
{
"index" : 35,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
},
{
"index" : 36,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
},
{
"index" : 37,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
},
{
"index" : 38,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
},
{
"index" : 39,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
},
{
"index" : 40,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
},
{
"index" : 41,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 42,
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 43,
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 44,
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 45,
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 46,
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 47,
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 48,
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 49,
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
}
],
/// The black border configuration, contains the following items:
/// * enable : true if the detector should be activated
"blackborderdetector" :
{
"enable" : true
},
/// The boot-sequence configuration, contains the following items:
/// * type : The type of the boot-sequence ('rainbow', 'knightrider', 'none')
/// The boot-sequence configuration, contains the following items:
/// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none')
/// * duration_ms : The length of the boot-sequence [ms]
"bootsequence" :
{
"type" : "Rainbow",
"duration_ms" : 3000
},
/// The configuration for the frame-grabber, contains the following items:
/// * width : The width of the grabbed frames [pixels]
/// * height : The height of the grabbed frames [pixels]
/// * frequency_Hz : The frequency of the frame grab [Hz]
"framegrabber" :
{
"width" : 64,
"height" : 64,
"frequency_Hz" : 10.0
},
/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields:
/// * xbmcAddress : The IP address of the XBMC-host
/// * xbmcTcpPort : The TCP-port of the XBMC-server
/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback
/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show
/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback
/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu
"xbmcVideoChecker" :
{
"xbmcAddress" : "127.0.0.1",
"xbmcTcpPort" : 9090,
"grabVideo" : true,
"grabPictures" : true,
"grabAudio" : true,
"grabMenu" : false
},
/// The configuration of the Json server which enables the json remote interface
/// * port : Port at which the json server is started
"jsonServer" :
{
"port" : 19444
},
/// The configuration of the Proto server which enables the protobuffer remote interface
/// * port : Port at which the protobuffer server is started
"protoServer" :
{
"port" : 19445
},
/// The configuration of the boblight server which enables the boblight remote interface
/// * port : Port at which the boblight server is started
// "boblightServer" :
// {
// "port" : 19333
// },
"end-of-json" : "end-of-json"
}

View File

@ -0,0 +1,438 @@
// Automatically generated configuration file for 'Hyperion daemon'
// Generated by: HyperCon (The Hyperion deamon configuration file builder
{
/// Device configuration contains the following fields:
/// * 'name' : The user friendly name of the device (only used for display purposes)
/// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806',
/// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'test' and 'none')
/// * 'output' : The output specification depends on selected device. This can for example be the
/// device specifier, device serial number, or the output file name
/// * 'rate' : The baudrate of the output to the device
/// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.).
"device" :
{
"name" : "MyPi",
"type" : "test",
"output" : "./hyperiond.test.out",
"rate" : 500000,
"colorOrder" : "rgb"
},
/// Color manipulation configuration used to tune the output colors to specific surroundings. Contains the following fields:
/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following tuning parameters:
/// - 'saturationGain' The gain adjustement of the saturation
/// - 'valueGain' The gain adjustement of the value
/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the following tuning parameters for each channel:
/// - 'threshold' The minimum required input value for the channel to be on (else zero)
/// - 'gamma' The gamma-curve correction factor
/// - 'blacklevel' The lowest possible value (when the channel is black)
/// - 'whitelevel' The highest possible value (when the channel is white)
/// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning parameters:
/// - 'type' The type of smoothing algorithm ('linear' or 'none')
/// - 'time_ms' The time constant for smoothing algorithm in milliseconds
/// - 'updateFrequency' The update frequency of the leds in Hz
"color" :
{
"transform" :
[
{
"id" : "device_1",
"leds" : "0,1,2,3-10, 12-32, 33, 34, 35-49",
"hsv" :
{
"saturationGain" : 1.0000,
"valueGain" : 1.5000
},
"red" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 0.8000
},
"green" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 1.0000
},
"blue" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 1.0000
}
},
{
"id" : "device_2",
"leds" : "11",
"hsv" :
{
"saturationGain" : 1.0000,
"valueGain" : 1.5000
},
"red" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 0.8000
},
"green" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 1.0000
},
"blue" :
{
"threshold" : 0.1000,
"gamma" : 2.0000,
"blacklevel" : 0.0000,
"whitelevel" : 1.0000
}
}
],
"smoothing" :
{
"type" : "none",
"time_ms" : 200,
"updateFrequency" : 20.0000
}
},
/// The configuration for each individual led. This contains the specification of the area
/// averaged of an input image for each led to determine its color. Each item in the list
/// contains the following fields:
/// * index: The index of the led. This determines its location in the string of leds; zero
/// being the first led.
/// * hscan: The fractional part of the image along the horizontal used for the averaging
/// (minimum and maximum inclusive)
/// * vscan: The fractional part of the image along the vertical used for the averaging
/// (minimum and maximum inclusive)
"leds" :
[
{
"index" : 0,
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 1,
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 2,
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 3,
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 4,
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 5,
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 6,
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 7,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 8,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 9,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
},
{
"index" : 10,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
},
{
"index" : 11,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
},
{
"index" : 12,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
},
{
"index" : 13,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
},
{
"index" : 14,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
},
{
"index" : 15,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
},
{
"index" : 16,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 17,
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 18,
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 19,
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 20,
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 21,
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 22,
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 23,
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 24,
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 25,
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 26,
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 27,
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 28,
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 29,
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 30,
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 31,
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 32,
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 33,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
},
{
"index" : 34,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
},
{
"index" : 35,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
},
{
"index" : 36,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
},
{
"index" : 37,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
},
{
"index" : 38,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
},
{
"index" : 39,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
},
{
"index" : 40,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
},
{
"index" : 41,
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 42,
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 43,
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 44,
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 45,
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 46,
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 47,
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 48,
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
},
{
"index" : 49,
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
}
],
/// The black border configuration, contains the following items:
/// * enable : true if the detector should be activated
"blackborderdetector" :
{
"enable" : true
},
/// The boot-sequence configuration, contains the following items:
/// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none')
/// * duration_ms : The length of the boot-sequence [ms]
"bootsequence" :
{
"type" : "Rainbow",
"duration_ms" : 3000
},
/// The configuration for the frame-grabber, contains the following items:
/// * width : The width of the grabbed frames [pixels]
/// * height : The height of the grabbed frames [pixels]
/// * frequency_Hz : The frequency of the frame grab [Hz]
"framegrabber" :
{
"width" : 64,
"height" : 64,
"frequency_Hz" : 10.0
},
/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields:
/// * xbmcAddress : The IP address of the XBMC-host
/// * xbmcTcpPort : The TCP-port of the XBMC-server
/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback
/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show
/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback
/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu
// "xbmcVideoChecker" :
// {
// "xbmcAddress" : "127.0.0.1",
// "xbmcTcpPort" : 9090,
// "grabVideo" : true,
// "grabPictures" : true,
// "grabAudio" : true,
// "grabMenu" : false
// },
/// The configuration of the Json server which enables the json remote interface
/// * port : Port at which the json server is started
"jsonServer" :
{
"port" : 19444
},
/// The configuration of the Proto server which enables the protobuffer remote interface
/// * port : Port at which the protobuffer server is started
"protoServer" :
{
"port" : 19445
},
/// The configuration of the boblight server which enables the boblight remote interface
/// * port : Port at which the boblight server is started
// "boblightServer" :
// {
// "port" : 19333
// },
"end-of-json" : "end-of-json"
}

View File

@ -0,0 +1,26 @@
#pragma once
// STL includes
#include <string>
// Utils includes
#include <utils/RgbChannelTransform.h>
#include <utils/HsvTransform.h>
class ColorTransform
{
public:
/// Unique identifier for this color transform
std::string _id;
/// The RED-Channel (RGB) transform
RgbChannelTransform _rgbRedTransform;
/// The GREEN-Channel (RGB) transform
RgbChannelTransform _rgbGreenTransform;
/// The BLUE-Channel (RGB) transform
RgbChannelTransform _rgbBlueTransform;
/// The HSV Transform for applying Saturation and Value transforms
HsvTransform _hsvTransform;
};

View File

@ -16,8 +16,10 @@
#include <hyperion/PriorityMuxer.h> #include <hyperion/PriorityMuxer.h>
// Forward class declaration // Forward class declaration
class HsvTransform;
class ColorTransform; class ColorTransform;
class HsvTransform;
class RgbChannelTransform;
class MultiColorTransform;
/// ///
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
@ -33,7 +35,7 @@ public:
/// ///
/// RGB-Color channel enumeration /// RGB-Color channel enumeration
/// ///
enum Color enum RgbChannel
{ {
RED, GREEN, BLUE, INVALID RED, GREEN, BLUE, INVALID
}; };
@ -88,15 +90,19 @@ public:
void setColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms); void setColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms);
/// ///
/// Sets/Updates a part of the color transformation. /// Returns the list with unique transform identifiers
/// @return The list with transform identifiers
/// ///
/// @param[in] transform The type of transform to configure const std::vector<std::string> & getTransformIds() const;
/// @param[in] color The color channel to which the transform applies (only applicable for
/// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL,
/// Transform::WHITELEVEL)
/// @param[in] value The new value for the given transform
/// ///
void setTransform(Transform transform, Color color, double value); /// Returns the ColorTransform with the given identifier
/// @return The transform with the given identifier (or nullptr if the identifier does not exist)
///
ColorTransform * getTransform(const std::string& id);
/// Tell Hyperion that the transforms have changed and the leds need to be updated
void transformsUpdated();
/// ///
/// Clears the given priority channel. This will switch the led-colors to the colors of the next /// Clears the given priority channel. This will switch the led-colors to the colors of the next
@ -111,18 +117,6 @@ public:
/// ///
void clearall(); void clearall();
///
/// Returns the value of a specific color transform
///
/// @param[in] transform The type of transform
/// @param[in] color The color channel to which the transform applies (only applicable for
/// Transform::THRESHOLD, Transform::GAMMA, Transform::BLACKLEVEL,
/// Transform::WHITELEVEL)
///
/// @return The value of the specified color transform
///
double getTransform(Transform transform, Color color) const;
/// ///
/// Returns a list of active priorities /// Returns a list of active priorities
/// ///
@ -144,8 +138,12 @@ public:
static LedDevice * createDevice(const Json::Value & deviceConfig); static LedDevice * createDevice(const Json::Value & deviceConfig);
static ColorOrder createColorOrder(const Json::Value & deviceConfig); static ColorOrder createColorOrder(const Json::Value & deviceConfig);
static LedString createLedString(const Json::Value & ledsConfig); static LedString createLedString(const Json::Value & ledsConfig);
static MultiColorTransform * createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorTransformConfig);
static ColorTransform * createColorTransform(const Json::Value & transformConfig);
static HsvTransform * createHsvTransform(const Json::Value & hsvConfig); static HsvTransform * createHsvTransform(const Json::Value & hsvConfig);
static ColorTransform * createColorTransform(const Json::Value & colorConfig); static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig);
static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice);
private slots: private slots:
@ -156,28 +154,14 @@ private slots:
void update(); void update();
private: private:
///
/// Applies all color transmforms to the given list of colors. The transformation is performed
/// in place.
///
/// @param colors The colors to be transformed
///
void applyTransform(std::vector<ColorRgb>& colors) const;
/// The specifiation of the led frame construction and picture integration /// The specifiation of the led frame construction and picture integration
LedString _ledString; LedString _ledString;
/// The priority muxer /// The priority muxer
PriorityMuxer _muxer; PriorityMuxer _muxer;
/// The HSV Transform for applying Saturation and Value transforms /// The transformation from raw colors to led colors
HsvTransform * _hsvTransform; MultiColorTransform * _raw2ledTransform;
/// The RED-Channel (RGB) transform
ColorTransform * _redTransform;
/// The GREEN-Channel (RGB) transform
ColorTransform * _greenTransform;
/// The BLUE-Channel (RGB) transform
ColorTransform * _blueTransform;
/// Value with the desired color byte order /// Value with the desired color byte order
ColorOrder _colorOrder; ColorOrder _colorOrder;

View File

@ -12,21 +12,21 @@
/// 4) finally, in case of a weird choice of parameters, the output is clamped between [0:1] /// 4) finally, in case of a weird choice of parameters, the output is clamped between [0:1]
/// ///
/// All configuration values are doubles and assume the color value to be between 0 and 1 /// All configuration values are doubles and assume the color value to be between 0 and 1
class ColorTransform class RgbChannelTransform
{ {
public: public:
/// Default constructor /// Default constructor
ColorTransform(); RgbChannelTransform();
/// Constructor /// Constructor
/// @param threshold /// @param threshold The minimum threshold
/// @param gamma /// @param gamma The gamma of the gamma-curve correction
/// @param blacklevel /// @param blacklevel The minimum value for the RGB-Channel
/// @param whitelevel /// @param whitelevel The maximum value for the RGB-Channel
ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel); RgbChannelTransform(double threshold, double gamma, double blacklevel, double whitelevel);
/// Destructor /// Destructor
~ColorTransform(); ~RgbChannelTransform();
/// @return The current threshold value /// @return The current threshold value
double getThreshold() const; double getThreshold() const;

View File

@ -39,6 +39,8 @@ SET(Hyperion_HEADERS
${CURRENT_HEADER_DIR}/BlackBorderDetector.h ${CURRENT_HEADER_DIR}/BlackBorderDetector.h
${CURRENT_HEADER_DIR}/BlackBorderProcessor.h ${CURRENT_HEADER_DIR}/BlackBorderProcessor.h
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
${CURRENT_SOURCE_DIR}/device/LedSpiDevice.h ${CURRENT_SOURCE_DIR}/device/LedSpiDevice.h
${CURRENT_SOURCE_DIR}/device/LedRs232Device.h ${CURRENT_SOURCE_DIR}/device/LedRs232Device.h
${CURRENT_SOURCE_DIR}/device/LedDeviceTest.h ${CURRENT_SOURCE_DIR}/device/LedDeviceTest.h
@ -60,6 +62,7 @@ SET(Hyperion_SOURCES
${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp ${CURRENT_SOURCE_DIR}/BlackBorderDetector.cpp
${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp ${CURRENT_SOURCE_DIR}/BlackBorderProcessor.cpp
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
${CURRENT_SOURCE_DIR}/device/LedSpiDevice.cpp ${CURRENT_SOURCE_DIR}/device/LedSpiDevice.cpp

View File

@ -4,6 +4,9 @@
// QT includes // QT includes
#include <QDateTime> #include <QDateTime>
#include <QRegExp>
#include <QString>
#include <QStringList>
// JsonSchema include // JsonSchema include
#include <utils/jsonschema/JsonFactory.h> #include <utils/jsonschema/JsonFactory.h>
@ -22,11 +25,9 @@
#include "device/LedDeviceLightpack.h" #include "device/LedDeviceLightpack.h"
#include "device/LedDeviceMultiLightpack.h" #include "device/LedDeviceMultiLightpack.h"
#include "MultiColorTransform.h"
#include "LinearColorSmoothing.h" #include "LinearColorSmoothing.h"
#include <utils/ColorTransform.h>
#include <utils/HsvTransform.h>
LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig)
{ {
std::cout << "Device configuration: " << deviceConfig << std::endl; std::cout << "Device configuration: " << deviceConfig << std::endl;
@ -155,6 +156,98 @@ Hyperion::ColorOrder Hyperion::createColorOrder(const Json::Value &deviceConfig)
return ORDER_RGB; return ORDER_RGB;
} }
ColorTransform * Hyperion::createColorTransform(const Json::Value & transformConfig)
{
const std::string id = transformConfig.get("id", "default").asString();
RgbChannelTransform * redTransform = createRgbChannelTransform(transformConfig["red"]);
RgbChannelTransform * greenTransform = createRgbChannelTransform(transformConfig["green"]);
RgbChannelTransform * blueTransform = createRgbChannelTransform(transformConfig["blue"]);
HsvTransform * hsvTransform = createHsvTransform(transformConfig["hsv"]);
ColorTransform * transform = new ColorTransform();
transform->_id = id;
transform->_rgbRedTransform = *redTransform;
transform->_rgbGreenTransform = *greenTransform;
transform->_rgbBlueTransform = *blueTransform;
transform->_hsvTransform = *hsvTransform;
// Cleanup the allocated individual transforms
delete redTransform;
delete greenTransform;
delete blueTransform;
delete hsvTransform;
return transform;
}
MultiColorTransform * Hyperion::createLedColorsTransform(const unsigned ledCnt, const Json::Value & colorConfig)
{
// Create the result, the transforms are added to this
MultiColorTransform * transform = new MultiColorTransform(ledCnt);
const Json::Value transformConfig = colorConfig.get("transform", Json::nullValue);
if (transformConfig.isNull())
{
// Old style color transformation config (just one for all leds)
ColorTransform * colorTransform = createColorTransform(colorConfig);
transform->addTransform(colorTransform);
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
}
else if (!transformConfig.isArray())
{
ColorTransform * colorTransform = createColorTransform(transformConfig);
transform->addTransform(colorTransform);
transform->setTransformForLed(colorTransform->_id, 0, ledCnt-1);
}
else
{
const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*");
for (Json::UInt i = 0; i < transformConfig.size(); ++i)
{
const Json::Value & config = transformConfig[i];
ColorTransform * colorTransform = createColorTransform(config);
transform->addTransform(colorTransform);
const QString ledIndicesStr = config.get("leds", "").asCString();
if (!overallExp.exactMatch(ledIndicesStr))
{
std::cerr << "Given led indices " << i << " not correct format: " << ledIndicesStr.toStdString() << std::endl;
continue;
}
std::cout << "ColorTransform '" << colorTransform->_id << "' => [";
const QStringList ledIndexList = ledIndicesStr.split(",");
for (int i=0; i<ledIndexList.size(); ++i) {
if (i > 0)
{
std::cout << ", ";
}
if (ledIndexList[i].contains("-"))
{
QStringList ledIndices = ledIndexList[i].split("-");
int startInd = ledIndices[0].toInt();
int endInd = ledIndices[1].toInt();
transform->setTransformForLed(colorTransform->_id, startInd, endInd);
std::cout << startInd << "-" << endInd;
}
else
{
int index = ledIndexList[i].toInt();
transform->setTransformForLed(colorTransform->_id, index, index);
std::cout << index;
}
}
std::cout << "]" << std::endl;
}
}
return transform;
}
HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig) HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig)
{ {
const double saturationGain = hsvConfig.get("saturationGain", 1.0).asDouble(); const double saturationGain = hsvConfig.get("saturationGain", 1.0).asDouble();
@ -163,14 +256,14 @@ HsvTransform * Hyperion::createHsvTransform(const Json::Value & hsvConfig)
return new HsvTransform(saturationGain, valueGain); return new HsvTransform(saturationGain, valueGain);
} }
ColorTransform* Hyperion::createColorTransform(const Json::Value& colorConfig) RgbChannelTransform* Hyperion::createRgbChannelTransform(const Json::Value& colorConfig)
{ {
const double threshold = colorConfig.get("threshold", 0.0).asDouble(); const double threshold = colorConfig.get("threshold", 0.0).asDouble();
const double gamma = colorConfig.get("gamma", 1.0).asDouble(); const double gamma = colorConfig.get("gamma", 1.0).asDouble();
const double blacklevel = colorConfig.get("blacklevel", 0.0).asDouble(); const double blacklevel = colorConfig.get("blacklevel", 0.0).asDouble();
const double whitelevel = colorConfig.get("whitelevel", 1.0).asDouble(); const double whitelevel = colorConfig.get("whitelevel", 1.0).asDouble();
ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel); RgbChannelTransform* transform = new RgbChannelTransform(threshold, gamma, blacklevel, whitelevel);
return transform; return transform;
} }
@ -246,14 +339,15 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig,
Hyperion::Hyperion(const Json::Value &jsonConfig) : Hyperion::Hyperion(const Json::Value &jsonConfig) :
_ledString(createLedString(jsonConfig["leds"])), _ledString(createLedString(jsonConfig["leds"])),
_muxer(_ledString.leds().size()), _muxer(_ledString.leds().size()),
_hsvTransform(createHsvTransform(jsonConfig["color"]["hsv"])), _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])),
_redTransform(createColorTransform(jsonConfig["color"]["red"])),
_greenTransform(createColorTransform(jsonConfig["color"]["green"])),
_blueTransform(createColorTransform(jsonConfig["color"]["blue"])),
_colorOrder(createColorOrder(jsonConfig["device"])), _colorOrder(createColorOrder(jsonConfig["device"])),
_device(createDevice(jsonConfig["device"])), _device(createDevice(jsonConfig["device"])),
_timer() _timer()
{ {
if (!_raw2ledTransform->verifyTransforms())
{
throw std::runtime_error("Color transformation incorrectly set");
}
// initialize the image processor factory // initialize the image processor factory
ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool()); ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool());
@ -278,13 +372,8 @@ Hyperion::~Hyperion()
// Delete the Led-String // Delete the Led-String
delete _device; delete _device;
// delete he hsv transform // delete the color transform
delete _hsvTransform; delete _raw2ledTransform;
// Delete the color-transform
delete _blueTransform;
delete _greenTransform;
delete _redTransform;
} }
unsigned Hyperion::getLedCount() const unsigned Hyperion::getLedCount() const
@ -319,55 +408,18 @@ void Hyperion::setColors(int priority, const std::vector<ColorRgb>& ledColors, c
} }
} }
void Hyperion::setTransform(Hyperion::Transform transform, Hyperion::Color color, double value) const std::vector<std::string> & Hyperion::getTransformIds() const
{ {
// select the transform of the requested color return _raw2ledTransform->getTransformIds();
ColorTransform * t = nullptr; }
switch (color)
{
case RED:
t = _redTransform;
break;
case GREEN:
t = _greenTransform;
break;
case BLUE:
t = _blueTransform;
break;
default:
break;
}
// set transform value ColorTransform * Hyperion::getTransform(const std::string& id)
switch (transform) {
{ return _raw2ledTransform->getTransform(id);
case SATURATION_GAIN: }
_hsvTransform->setSaturationGain(value);
break;
case VALUE_GAIN:
_hsvTransform->setValueGain(value);
break;
case THRESHOLD:
assert (t != nullptr);
t->setThreshold(value);
break;
case GAMMA:
assert (t != nullptr);
t->setGamma(value);
break;
case BLACKLEVEL:
assert (t != nullptr);
t->setBlacklevel(value);
break;
case WHITELEVEL:
assert (t != nullptr);
t->setWhitelevel(value);
break;
default:
assert(false);
}
// update the led output void Hyperion::transformsUpdated()
{
update(); update();
} }
@ -393,51 +445,6 @@ void Hyperion::clearall()
update(); update();
} }
double Hyperion::getTransform(Hyperion::Transform transform, Hyperion::Color color) const
{
// select the transform of the requested color
ColorTransform * t = nullptr;
switch (color)
{
case RED:
t = _redTransform;
break;
case GREEN:
t = _greenTransform;
break;
case BLUE:
t = _blueTransform;
break;
default:
break;
}
// set transform value
switch (transform)
{
case SATURATION_GAIN:
return _hsvTransform->getSaturationGain();
case VALUE_GAIN:
return _hsvTransform->getValueGain();
case THRESHOLD:
assert (t != nullptr);
return t->getThreshold();
case GAMMA:
assert (t != nullptr);
return t->getGamma();
case BLACKLEVEL:
assert (t != nullptr);
return t->getBlacklevel();
case WHITELEVEL:
assert (t != nullptr);
return t->getWhitelevel();
default:
assert(false);
}
return 999.0;
}
QList<int> Hyperion::getActivePriorities() const QList<int> Hyperion::getActivePriorities() const
{ {
return _muxer.getPriorities(); return _muxer.getPriorities();
@ -458,14 +465,9 @@ void Hyperion::update()
const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority); const PriorityMuxer::InputInfo & priorityInfo = _muxer.getInputInfo(priority);
// Apply the transform to each led and color-channel // Apply the transform to each led and color-channel
std::vector<ColorRgb> ledColors(priorityInfo.ledColors); std::vector<ColorRgb> ledColors = _raw2ledTransform->applyTransform(priorityInfo.ledColors);
for (ColorRgb& color : ledColors) for (ColorRgb& color : ledColors)
{ {
_hsvTransform->transform(color.red, color.green, color.blue);
color.red = _redTransform->transform(color.red);
color.green = _greenTransform->transform(color.green);
color.blue = _blueTransform->transform(color.blue);
// correct the color byte order // correct the color byte order
switch (_colorOrder) switch (_colorOrder)
{ {

View File

@ -4,8 +4,6 @@
#include <hyperion/ImageToLedsMap.h> #include <hyperion/ImageToLedsMap.h>
#include <hyperion/BlackBorderProcessor.h> #include <hyperion/BlackBorderProcessor.h>
#include <utils/ColorTransform.h>
using namespace hyperion; using namespace hyperion;
ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector) : ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector) :

View File

@ -0,0 +1,97 @@
// STL includes
#include <cassert>
// Hyperion includes
#include "MultiColorTransform.h"
MultiColorTransform::MultiColorTransform(const unsigned ledCnt) :
_ledTransforms(ledCnt, nullptr)
{
}
MultiColorTransform::~MultiColorTransform()
{
// Clean up all the transforms
for (ColorTransform * transform : _transform)
{
delete transform;
}
}
void MultiColorTransform::addTransform(ColorTransform * transform)
{
_transformIds.push_back(transform->_id);
_transform.push_back(transform);
}
void MultiColorTransform::setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed)
{
assert(startLed <= endLed);
assert(endLed < _ledTransforms.size());
// Get the identified transform (don't care if is nullptr)
ColorTransform * transform = getTransform(id);
for (unsigned iLed=startLed; iLed<=endLed; ++iLed)
{
_ledTransforms[iLed] = transform;
}
}
bool MultiColorTransform::verifyTransforms() const
{
bool allLedsSet = true;
for (unsigned iLed=0; iLed<_ledTransforms.size(); ++iLed)
{
if (_ledTransforms[iLed] == nullptr)
{
std::cerr << "No transform set for " << iLed << std::endl;
allLedsSet = false;
}
}
return allLedsSet;
}
const std::vector<std::string> & MultiColorTransform::getTransformIds()
{
return _transformIds;
}
ColorTransform* MultiColorTransform::getTransform(const std::string& id)
{
// Iterate through the unique transforms until we find the one with the given id
for (ColorTransform* transform : _transform)
{
if (transform->_id == id)
{
return transform;
}
}
// The ColorTransform was not found
return nullptr;
}
std::vector<ColorRgb> MultiColorTransform::applyTransform(const std::vector<ColorRgb>& rawColors)
{
// Create a copy, as we will do the rest of the transformation in place
std::vector<ColorRgb> ledColors(rawColors);
const size_t itCnt = std::min(_ledTransforms.size(), rawColors.size());
for (size_t i=0; i<itCnt; ++i)
{
ColorTransform* transform = _ledTransforms[i];
if (transform == nullptr)
{
// No transform set for this led (do nothing)
continue;
}
ColorRgb& color = ledColors[i];
transform->_hsvTransform.transform(color.red, color.green, color.blue);
color.red = transform->_rgbRedTransform.transform(color.red);
color.green = transform->_rgbGreenTransform.transform(color.green);
color.blue = transform->_rgbBlueTransform.transform(color.blue);
}
return ledColors;
}

View File

@ -0,0 +1,66 @@
#pragma once
// STL includes
#include <vector>
// Utils includes
#include <utils/ColorRgb.h>
// Hyperion includes
#include <hyperion/ColorTransform.h>
///
/// The LedColorTransform is responsible for performing color transformation from 'raw' colors
/// received as input to colors mapped to match the color-properties of the leds.
///
class MultiColorTransform
{
public:
MultiColorTransform(const unsigned ledCnt);
~MultiColorTransform();
/**
* Adds a new ColorTransform to this MultiColorTransform
*
* @param transform The new ColorTransform (ownership is transfered)
*/
void addTransform(ColorTransform * transform);
void setTransformForLed(const std::string& id, const unsigned startLed, const unsigned endLed);
bool verifyTransforms() const;
///
/// Returns the identifier of all the unique ColorTransform
///
/// @return The list with unique id's of the ColorTransforms
const std::vector<std::string> & getTransformIds();
///
/// Returns the pointer to the ColorTransform with the given id
///
/// @param id The identifier of the ColorTransform
///
/// @return The ColorTransform with the given id (or nullptr if it does not exist)
///
ColorTransform* getTransform(const std::string& id);
///
/// Performs the color transoformation from raw-color to led-color
///
/// @param rawColors The list with raw colors
///
/// @return The list with led-colors
///
std::vector<ColorRgb> applyTransform(const std::vector<ColorRgb>& rawColors);
private:
/// List with transform ids
std::vector<std::string> _transformIds;
/// List with unique ColorTransforms
std::vector<ColorTransform*> _transform;
/// List with a pointer to the ColorTransform for each individual led
std::vector<ColorTransform*> _ledTransforms;
};

View File

@ -12,9 +12,10 @@
#include <QDateTime> #include <QDateTime>
// hyperion util includes // hyperion util includes
#include "hyperion/ImageProcessorFactory.h" #include <hyperion/ImageProcessorFactory.h>
#include "hyperion/ImageProcessor.h" #include <hyperion/ImageProcessor.h>
#include "utils/ColorRgb.h" #include <hyperion/ColorTransform.h>
#include <utils/ColorRgb.h>
// project includes // project includes
#include "JsonClientConnection.h" #include "JsonClientConnection.h"
@ -173,25 +174,39 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &message)
} }
// collect transform information // collect transform information
Json::Value & transform = info["transform"]; Json::Value & transformArray = info["transform"];
transform["saturationGain"] = _hyperion->getTransform(Hyperion::SATURATION_GAIN, Hyperion::INVALID); for (const std::string& transformId : _hyperion->getTransformIds())
transform["valueGain"] = _hyperion->getTransform(Hyperion::VALUE_GAIN, Hyperion::INVALID); {
Json::Value & threshold = transform["threshold"]; const ColorTransform * colorTransform = _hyperion->getTransform(transformId);
threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::RED)); if (colorTransform == nullptr)
threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::GREEN)); {
threshold.append(_hyperion->getTransform(Hyperion::THRESHOLD, Hyperion::BLUE)); std::cerr << "Incorrect color transform id: " << transformId << std::endl;
Json::Value & gamma = transform["gamma"]; continue;
gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::RED)); }
gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::GREEN));
gamma.append(_hyperion->getTransform(Hyperion::GAMMA, Hyperion::BLUE)); Json::Value & transform = transformArray.append(Json::Value());
Json::Value & blacklevel = transform["blacklevel"]; transform["id"] = transformId;
blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::RED));
blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::GREEN)); transform["saturationGain"] = colorTransform->_hsvTransform.getSaturationGain();
blacklevel.append(_hyperion->getTransform(Hyperion::BLACKLEVEL, Hyperion::BLUE)); transform["valueGain"] = colorTransform->_hsvTransform.getValueGain();
Json::Value & whitelevel = transform["whitelevel"];
whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::RED)); Json::Value & threshold = transform["threshold"];
whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::GREEN)); threshold.append(colorTransform->_rgbRedTransform.getThreshold());
whitelevel.append(_hyperion->getTransform(Hyperion::WHITELEVEL, Hyperion::BLUE)); threshold.append(colorTransform->_rgbGreenTransform.getThreshold());
threshold.append(colorTransform->_rgbBlueTransform.getThreshold());
Json::Value & gamma = transform["gamma"];
gamma.append(colorTransform->_rgbRedTransform.getGamma());
gamma.append(colorTransform->_rgbGreenTransform.getGamma());
gamma.append(colorTransform->_rgbBlueTransform.getGamma());
Json::Value & blacklevel = transform["blacklevel"];
blacklevel.append(colorTransform->_rgbRedTransform.getBlacklevel());
blacklevel.append(colorTransform->_rgbGreenTransform.getBlacklevel());
blacklevel.append(colorTransform->_rgbBlueTransform.getBlacklevel());
Json::Value & whitelevel = transform["whitelevel"];
whitelevel.append(colorTransform->_rgbRedTransform.getWhitelevel());
whitelevel.append(colorTransform->_rgbGreenTransform.getWhitelevel());
whitelevel.append(colorTransform->_rgbBlueTransform.getWhitelevel());
}
// send the result // send the result
sendMessage(result); sendMessage(result);
@ -222,48 +237,59 @@ void JsonClientConnection::handleTransformCommand(const Json::Value &message)
{ {
const Json::Value & transform = message["transform"]; const Json::Value & transform = message["transform"];
const std::string transformId = transform.get("id", _hyperion->getTransformIds().front()).asString();
ColorTransform * colorTransform = _hyperion->getTransform(transformId);
if (colorTransform == nullptr)
{
//sendErrorReply(std::string("Incorrect transform identifier: ") + transformId);
return;
}
if (transform.isMember("saturationGain")) if (transform.isMember("saturationGain"))
{ {
_hyperion->setTransform(Hyperion::SATURATION_GAIN, Hyperion::INVALID, transform["saturationGain"].asDouble()); colorTransform->_hsvTransform.setSaturationGain(transform["saturationGain"].asDouble());
} }
if (transform.isMember("valueGain")) if (transform.isMember("valueGain"))
{ {
_hyperion->setTransform(Hyperion::VALUE_GAIN, Hyperion::INVALID, transform["valueGain"].asDouble()); colorTransform->_hsvTransform.setValueGain(transform["valueGain"].asDouble());
} }
if (transform.isMember("threshold")) if (transform.isMember("threshold"))
{ {
const Json::Value & threshold = transform["threshold"]; const Json::Value & values = transform["threshold"];
_hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::RED, threshold[0u].asDouble()); colorTransform->_rgbRedTransform .setThreshold(values[0u].asDouble());
_hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::GREEN, threshold[1u].asDouble()); colorTransform->_rgbGreenTransform.setThreshold(values[1u].asDouble());
_hyperion->setTransform(Hyperion::THRESHOLD, Hyperion::BLUE, threshold[2u].asDouble()); colorTransform->_rgbBlueTransform .setThreshold(values[2u].asDouble());
} }
if (transform.isMember("gamma")) if (transform.isMember("gamma"))
{ {
const Json::Value & threshold = transform["gamma"]; const Json::Value & values = transform["gamma"];
_hyperion->setTransform(Hyperion::GAMMA, Hyperion::RED, threshold[0u].asDouble()); colorTransform->_rgbRedTransform .setGamma(values[0u].asDouble());
_hyperion->setTransform(Hyperion::GAMMA, Hyperion::GREEN, threshold[1u].asDouble()); colorTransform->_rgbGreenTransform.setGamma(values[1u].asDouble());
_hyperion->setTransform(Hyperion::GAMMA, Hyperion::BLUE, threshold[2u].asDouble()); colorTransform->_rgbBlueTransform .setGamma(values[2u].asDouble());
} }
if (transform.isMember("blacklevel")) if (transform.isMember("blacklevel"))
{ {
const Json::Value & threshold = transform["blacklevel"]; const Json::Value & values = transform["blacklevel"];
_hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::RED, threshold[0u].asDouble()); colorTransform->_rgbRedTransform .setBlacklevel(values[0u].asDouble());
_hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::GREEN, threshold[1u].asDouble()); colorTransform->_rgbGreenTransform.setBlacklevel(values[1u].asDouble());
_hyperion->setTransform(Hyperion::BLACKLEVEL, Hyperion::BLUE, threshold[2u].asDouble()); colorTransform->_rgbBlueTransform .setBlacklevel(values[2u].asDouble());
} }
if (transform.isMember("whitelevel")) if (transform.isMember("whitelevel"))
{ {
const Json::Value & threshold = transform["whitelevel"]; const Json::Value & values = transform["whitelevel"];
_hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::RED, threshold[0u].asDouble()); colorTransform->_rgbRedTransform .setWhitelevel(values[0u].asDouble());
_hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::GREEN, threshold[1u].asDouble()); colorTransform->_rgbGreenTransform.setWhitelevel(values[1u].asDouble());
_hyperion->setTransform(Hyperion::WHITELEVEL, Hyperion::BLUE, threshold[2u].asDouble()); colorTransform->_rgbBlueTransform .setWhitelevel(values[2u].asDouble());
} }
// commit the changes
_hyperion->transformsUpdated();
sendSuccessReply(); sendSuccessReply();
} }

View File

@ -1,68 +1,72 @@
{ {
"type":"object", "type":"object",
"required":true, "required":true,
"properties":{ "properties":{
"command": { "command": {
"type" : "string", "type" : "string",
"required" : true, "required" : true,
"enum" : ["transform"] "enum" : ["transform"]
}, },
"transform": { "transform": {
"type": "object", "type": "object",
"required": true, "required": true,
"properties": { "properties": {
"saturationGain" : { "id" : {
"type" : "double", "type" : "string",
"required" : false, "required" : false
"minimum" : 0.0 },
}, "saturationGain" : {
"valueGain" : { "type" : "double",
"type" : "double", "required" : false,
"required" : false, "minimum" : 0.0
"minimum" : 0.0 },
}, "valueGain" : {
"threshold": { "type" : "double",
"type": "array", "required" : false,
"required": false, "minimum" : 0.0
"items" : { },
"type": "double", "threshold": {
"minimum": 0.0, "type": "array",
"maximum": 1.0 "required": false,
}, "items" : {
"minItems": 3, "type": "double",
"maxItems": 3 "minimum": 0.0,
}, "maximum": 1.0
"gamma": { },
"type": "array", "minItems": 3,
"required": false, "maxItems": 3
"items" : { },
"type": "double", "gamma": {
"minimum": 0.0 "type": "array",
}, "required": false,
"minItems": 3, "items" : {
"maxItems": 3 "type": "double",
}, "minimum": 0.0
"blacklevel": { },
"type": "array", "minItems": 3,
"required": false, "maxItems": 3
"items" : { },
"type": "double" "blacklevel": {
}, "type": "array",
"minItems": 3, "required": false,
"maxItems": 3 "items" : {
}, "type": "double"
"whitelevel": { },
"type": "array", "minItems": 3,
"required": false, "maxItems": 3
"items" : { },
"type": "double" "whitelevel": {
}, "type": "array",
"minItems": 3, "required": false,
"maxItems": 3 "items" : {
} "type": "double"
}, },
"additionalProperties": false "minItems": 3,
} "maxItems": 3
}, }
"additionalProperties": false },
"additionalProperties": false
}
},
"additionalProperties": false
} }

View File

@ -11,11 +11,11 @@ add_library(hyperion-utils
${CURRENT_HEADER_DIR}/ColorRgba.h ${CURRENT_HEADER_DIR}/ColorRgba.h
${CURRENT_SOURCE_DIR}/ColorRgba.cpp ${CURRENT_SOURCE_DIR}/ColorRgba.cpp
${CURRENT_HEADER_DIR}/Image.h ${CURRENT_HEADER_DIR}/Image.h
${CURRENT_HEADER_DIR}/ColorTransform.h
${CURRENT_HEADER_DIR}/HsvTransform.h
${CURRENT_SOURCE_DIR}/ColorTransform.cpp ${CURRENT_HEADER_DIR}/HsvTransform.h
${CURRENT_SOURCE_DIR}/HsvTransform.cpp ${CURRENT_SOURCE_DIR}/HsvTransform.cpp
${CURRENT_HEADER_DIR}/RgbChannelTransform.h
${CURRENT_SOURCE_DIR}/RgbChannelTransform.cpp
${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h ${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h
${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h ${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h

View File

@ -1,9 +1,10 @@
// STL includes // STL includes
#include <cmath> #include <cmath>
#include <utils/ColorTransform.h> // Utils includes
#include <utils/RgbChannelTransform.h>
ColorTransform::ColorTransform() : RgbChannelTransform::RgbChannelTransform() :
_threshold(0), _threshold(0),
_gamma(1.0), _gamma(1.0),
_blacklevel(0.0), _blacklevel(0.0),
@ -12,7 +13,7 @@ ColorTransform::ColorTransform() :
initializeMapping(); initializeMapping();
} }
ColorTransform::ColorTransform(double threshold, double gamma, double blacklevel, double whitelevel) : RgbChannelTransform::RgbChannelTransform(double threshold, double gamma, double blacklevel, double whitelevel) :
_threshold(threshold), _threshold(threshold),
_gamma(gamma), _gamma(gamma),
_blacklevel(blacklevel), _blacklevel(blacklevel),
@ -21,55 +22,55 @@ ColorTransform::ColorTransform(double threshold, double gamma, double blacklevel
initializeMapping(); initializeMapping();
} }
ColorTransform::~ColorTransform() RgbChannelTransform::~RgbChannelTransform()
{ {
} }
double ColorTransform::getThreshold() const double RgbChannelTransform::getThreshold() const
{ {
return _threshold; return _threshold;
} }
void ColorTransform::setThreshold(double threshold) void RgbChannelTransform::setThreshold(double threshold)
{ {
_threshold = threshold; _threshold = threshold;
initializeMapping(); initializeMapping();
} }
double ColorTransform::getGamma() const double RgbChannelTransform::getGamma() const
{ {
return _gamma; return _gamma;
} }
void ColorTransform::setGamma(double gamma) void RgbChannelTransform::setGamma(double gamma)
{ {
_gamma = gamma; _gamma = gamma;
initializeMapping(); initializeMapping();
} }
double ColorTransform::getBlacklevel() const double RgbChannelTransform::getBlacklevel() const
{ {
return _blacklevel; return _blacklevel;
} }
void ColorTransform::setBlacklevel(double blacklevel) void RgbChannelTransform::setBlacklevel(double blacklevel)
{ {
_blacklevel = blacklevel; _blacklevel = blacklevel;
initializeMapping(); initializeMapping();
} }
double ColorTransform::getWhitelevel() const double RgbChannelTransform::getWhitelevel() const
{ {
return _whitelevel; return _whitelevel;
} }
void ColorTransform::setWhitelevel(double whitelevel) void RgbChannelTransform::setWhitelevel(double whitelevel)
{ {
_whitelevel = whitelevel; _whitelevel = whitelevel;
initializeMapping(); initializeMapping();
} }
void ColorTransform::initializeMapping() void RgbChannelTransform::initializeMapping()
{ {
// initialize the mapping as a linear array // initialize the mapping as a linear array
for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)

View File

@ -154,6 +154,8 @@ void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value &
wrongType = !value.isNumeric(); wrongType = !value.isNumeric();
else if (type == "integer") else if (type == "integer")
wrongType = !value.isIntegral(); wrongType = !value.isIntegral();
else if (type == "double")
wrongType = !value.isDouble();
else if (type == "boolean") else if (type == "boolean")
wrongType = !value.isBool(); wrongType = !value.isBool();
else if (type == "object") else if (type == "object")
@ -162,6 +164,8 @@ void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value &
wrongType = !value.isArray(); wrongType = !value.isArray();
else if (type == "null") else if (type == "null")
wrongType = !value.isNull(); wrongType = !value.isNull();
else if (type == "enum")
wrongType = !value.isString();
else if (type == "any") else if (type == "any")
wrongType = false; wrongType = false;
else else

View File

@ -8,19 +8,19 @@ import java.io.OutputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.Properties; import java.util.Properties;
import java.util.zip.GZIPInputStream; import java.util.Vector;
import java.util.zip.GZIPOutputStream;
public class ConfigurationFile { public class ConfigurationFile {
private final Properties pProps = new Properties(); private final Properties mProps = new Properties();
public void load(String pFilename) { public void load(String pFilename) {
pProps.clear(); mProps.clear();
// try (InputStream in = new InflaterInputStream(new FileInputStream(pFilename))){ // try (InputStream in = new InflaterInputStream(new FileInputStream(pFilename))){
try (InputStream in = new GZIPInputStream(new FileInputStream(pFilename))){ // try (InputStream in = new GZIPInputStream(new FileInputStream(pFilename))){
// try (InputStream in = new FileInputStream(pFilename)) { try (InputStream in = new FileInputStream(pFilename)) {
pProps.load(in); mProps.load(in);
} catch (Throwable t) { } catch (Throwable t) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
t.printStackTrace(); t.printStackTrace();
@ -29,15 +29,18 @@ public class ConfigurationFile {
public void save(String pFilename) { public void save(String pFilename) {
// try (OutputStream out = new DeflaterOutputStream(new FileOutputStream(pFilename))) { // try (OutputStream out = new DeflaterOutputStream(new FileOutputStream(pFilename))) {
try (OutputStream out = new GZIPOutputStream(new FileOutputStream(pFilename))) { // try (OutputStream out = new GZIPOutputStream(new FileOutputStream(pFilename))) {
// try (OutputStream out = (new FileOutputStream(pFilename))) { try (OutputStream out = (new FileOutputStream(pFilename))) {
pProps.store(out, "Pesistent settings file for HyperCon"); mProps.store(out, "Pesistent settings file for HyperCon");
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public void store(Object pObj) { public void store(Object pObj) {
store(pObj, pObj.getClass().getSimpleName(), "");
}
public void store(Object pObj, String preamble, String postamble) {
String className = pObj.getClass().getSimpleName(); String className = pObj.getClass().getSimpleName();
// Retrieve the member variables // Retrieve the member variables
Field[] fields = pObj.getClass().getDeclaredFields(); Field[] fields = pObj.getClass().getDeclaredFields();
@ -48,27 +51,99 @@ public class ConfigurationFile {
continue; continue;
} }
String key = className + "." + field.getName(); String key = preamble + "." + field.getName() + postamble;
try { try {
Object value = field.get(pObj); Object value = field.get(pObj);
if (value.getClass().isEnum()) { if (value.getClass().isEnum()) {
pProps.setProperty(key, ((Enum<?>)value).name()); mProps.setProperty(key, ((Enum<?>)value).name());
} else if (value.getClass().isAssignableFrom(Vector.class)) {
@SuppressWarnings("unchecked")
Vector<Object> v = (Vector<Object>) value;
for (int i=0; i<v.size(); ++i) {
store(v.get(i), key + "[" + i + "]", "");
}
} else { } else {
pProps.setProperty(key, value.toString()); mProps.setProperty(key, value.toString());
} }
} catch (Throwable t) {} } catch (Throwable t) {}
} }
} }
public void restore(Object pObj) { public void restore(Object pObj) {
restore(pObj, mProps);
}
public void restore(Object pObj, Properties pProps) {
String className = pObj.getClass().getSimpleName(); String className = pObj.getClass().getSimpleName();
restore(pObj, pProps, className + ".");
}
@SuppressWarnings("unchecked")
public void restore(Object pObj, Properties pProps, String pPreamble) {
// Retrieve the member variables // Retrieve the member variables
Field[] fields = pObj.getClass().getDeclaredFields(); Field[] fields = pObj.getClass().getDeclaredFields();
// Iterate each variable // Iterate each variable
for (Field field : fields) { for (Field field : fields) {
String key = className + "." + field.getName(); if (field.getType().isAssignableFrom(Vector.class)) {
// Obtain the Vector
Vector<Object> vector;
try {
vector = (Vector<Object>)field.get(pObj);
} catch (Throwable t) {
t.printStackTrace();
break;
}
// Clear existing elements from the vector
vector.clear();
// Iterate through the properties to find the indices of the vector
int i=0;
while (true) {
String curIndexKey = pPreamble + field.getName() + "[" + i + "]";
Properties elemProps = new Properties();
// Find all the elements for the current vector index
for (Object keyObj : pProps.keySet()) {
String keyStr = (String)keyObj;
if (keyStr.startsWith(curIndexKey)) {
// Remove the name and dot
elemProps.put(keyStr.substring(curIndexKey.length()+1), pProps.get(keyStr));
}
}
if (elemProps.isEmpty()) {
// Found no more elements for the vector
break;
}
// Construct new instance of vectors generic type
ParameterizedType vectorElementType = (ParameterizedType) field.getGenericType();
Class<?> vectorElementClass = (Class<?>) vectorElementType.getActualTypeArguments()[0];
// Find the constructor with no arguments and create a new instance
Object newElement = null;
try {
newElement = vectorElementClass.getConstructor().newInstance();
} catch (Throwable t) {
System.err.println("Failed to find empty default constructor for " + vectorElementClass.getName());
break;
}
if (newElement == null) {
System.err.println("Failed to construct instance for " + vectorElementClass.getName());
break;
}
// Restore the instance members from the collected properties
restore(newElement, elemProps, "");
// Add the instance to the vector
vector.addElement(newElement);
++i;
}
continue;
}
String key = pPreamble + field.getName();
String value = pProps.getProperty(key); String value = pProps.getProperty(key);
if (value == null) { if (value == null) {
System.out.println("Persistent settings does not contain value for " + key); System.out.println("Persistent settings does not contain value for " + key);
@ -97,6 +172,6 @@ public class ConfigurationFile {
@Override @Override
public String toString() { public String toString() {
return pProps.toString(); return mProps.toString();
} }
} }

View File

@ -1,5 +1,6 @@
package org.hyperion.hypercon.gui; package org.hyperion.hypercon.gui;
import java.awt.BorderLayout;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.GridLayout; import java.awt.GridLayout;
import java.beans.Transient; import java.beans.Transient;
@ -11,20 +12,27 @@ import javax.swing.GroupLayout;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JSpinner; import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel; import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.hyperion.hypercon.spec.ColorConfig; import org.hyperion.hypercon.spec.TransformConfig;
/** /**
* Configuration panel for the ColorConfig. * Configuration panel for the ColorConfig.
* *
* NB This has not been integrated in the GUI jet! * NB This has not been integrated in the GUI jet!
*/ */
public class ColorPanel extends JPanel { public class ColorTransformPanel extends JPanel {
private final ColorConfig mColorConfig; private final TransformConfig mColorConfig;
private JPanel mIndexPanel;
private JLabel mIndexLabel;
private JTextField mIndexField;
private JPanel mRgbTransformPanel; private JPanel mRgbTransformPanel;
private JLabel mThresholdLabel; private JLabel mThresholdLabel;
@ -53,10 +61,10 @@ public class ColorPanel extends JPanel {
private JLabel mValueAdjustLabel; private JLabel mValueAdjustLabel;
private JSpinner mValueAdjustSpinner; private JSpinner mValueAdjustSpinner;
public ColorPanel(ColorConfig pColorConfig) { public ColorTransformPanel(TransformConfig pTransformConfig) {
super(); super();
mColorConfig = pColorConfig; mColorConfig = pTransformConfig;
initialise(); initialise();
} }
@ -70,12 +78,32 @@ public class ColorPanel extends JPanel {
} }
private void initialise() { private void initialise() {
setBorder(BorderFactory.createTitledBorder("Color transform")); setBorder(BorderFactory.createTitledBorder("Transform [" + mColorConfig.mId + "]"));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(getIndexPanel());
add(Box.createVerticalStrut(10));
add(getRgbPanel()); add(getRgbPanel());
add(Box.createVerticalStrut(10)); add(Box.createVerticalStrut(10));
add(getHsvPanel()); add(getHsvPanel());
add(Box.createVerticalGlue());
}
private JPanel getIndexPanel() {
if (mIndexPanel == null) {
mIndexPanel = new JPanel();
mIndexPanel.setMaximumSize(new Dimension(1024, 25));
mIndexPanel.setLayout(new BorderLayout(10,10));
mIndexLabel = new JLabel("Indices:");
mIndexPanel.add(mIndexLabel, BorderLayout.WEST);
mIndexField = new JTextField(mColorConfig.mLedIndexString);
mIndexField.setToolTipText("Comma seperated indices or index ranges (eg '1-10, 13, 14, 17-19')");
mIndexField.getDocument().addDocumentListener(mDocumentListener);
mIndexPanel.add(mIndexField, BorderLayout.CENTER);
}
return mIndexPanel;
} }
private JPanel getRgbPanel() { private JPanel getRgbPanel() {
@ -216,4 +244,18 @@ public class ColorPanel extends JPanel {
mColorConfig.mValueGain = (Double)mValueAdjustSpinner.getValue(); mColorConfig.mValueGain = (Double)mValueAdjustSpinner.getValue();
} }
}; };
private final DocumentListener mDocumentListener = new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
mColorConfig.mLedIndexString = mIndexField.getText();
}
@Override
public void insertUpdate(DocumentEvent e) {
mColorConfig.mLedIndexString = mIndexField.getText();
}
@Override
public void changedUpdate(DocumentEvent e) {
mColorConfig.mLedIndexString = mIndexField.getText();
}
};
} }

View File

@ -0,0 +1,130 @@
package org.hyperion.hypercon.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.hyperion.hypercon.spec.ColorConfig;
import org.hyperion.hypercon.spec.TransformConfig;
public class ColorsPanel extends JPanel {
private final ColorConfig mColorConfig;
private final DefaultComboBoxModel<TransformConfig> mTransformsModel;
private JPanel mControlPanel;
private JComboBox<TransformConfig> mTransformCombo;
private JButton mAddTransformButton;
private JButton mDelTransformButton;
private JPanel mTransformPanel;
private final Map<TransformConfig, ColorTransformPanel> mTransformPanels = new HashMap<>();
public ColorsPanel(ColorConfig pColorConfig) {
super();
mColorConfig = pColorConfig;
mTransformsModel = new DefaultComboBoxModel<TransformConfig>(mColorConfig.mTransforms);
initialise();
}
private void initialise() {
setLayout(new BorderLayout(10,10));
setBorder(BorderFactory.createTitledBorder("Colors"));
add(getControlPanel(), BorderLayout.NORTH);
mTransformPanel = new JPanel();
mTransformPanel.setLayout(new BorderLayout());
add(mTransformPanel, BorderLayout.CENTER);
for (TransformConfig config : mColorConfig.mTransforms) {
mTransformPanels.put(config, new ColorTransformPanel(config));
}
ColorTransformPanel currentPanel = mTransformPanels.get(mColorConfig.mTransforms.get(0));
mTransformPanel.add(currentPanel, BorderLayout.CENTER);
}
private JPanel getControlPanel() {
if (mControlPanel == null) {
mControlPanel = new JPanel();
mControlPanel.setLayout(new BoxLayout(mControlPanel, BoxLayout.LINE_AXIS));
mTransformCombo = new JComboBox<>(mTransformsModel);
mTransformCombo.addActionListener(mComboListener);
mControlPanel.add(mTransformCombo);
mAddTransformButton = new JButton(mAddAction);
mControlPanel.add(mAddTransformButton);
mDelTransformButton = new JButton(mDelAction);
mDelTransformButton.setEnabled(mTransformCombo.getItemCount() > 1);
mControlPanel.add(mDelTransformButton);
}
return mControlPanel;
}
private final Action mAddAction = new AbstractAction("Add") {
@Override
public void actionPerformed(ActionEvent e) {
String newId = JOptionPane.showInputDialog("Give an identifier for the new color-transform:");
if (newId == null || newId.isEmpty()) {
// No proper value given
return;
}
TransformConfig config = new TransformConfig();
config.mId = newId;
ColorTransformPanel panel = new ColorTransformPanel(config);
mTransformPanels.put(config, panel);
mTransformsModel.addElement(config);
mTransformsModel.setSelectedItem(config);
mDelTransformButton.setEnabled(true);
}
};
private final Action mDelAction = new AbstractAction("Del") {
@Override
public void actionPerformed(ActionEvent e) {
TransformConfig config = (TransformConfig) mTransformCombo.getSelectedItem();
mTransformPanels.remove(config);
mTransformsModel.removeElement(config);
mDelTransformButton.setEnabled(mTransformCombo.getItemCount() > 1);
}
};
private final ActionListener mComboListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TransformConfig selConfig = (TransformConfig) mTransformsModel.getSelectedItem();
if (selConfig == null) {
// Something went wrong here, there should always be a selection!
return;
}
ColorTransformPanel panel = mTransformPanels.get(selConfig);
mTransformPanel.removeAll();
mTransformPanel.add(panel, BorderLayout.CENTER);
mTransformPanel.revalidate();
mTransformPanel.repaint();
}
};
}

View File

@ -174,7 +174,7 @@ public class ConfigPanel extends JPanel {
mProcessPanel.add(new BootSequencePanel(ledString.mMiscConfig)); mProcessPanel.add(new BootSequencePanel(ledString.mMiscConfig));
mProcessPanel.add(new FrameGrabberPanel(ledString.mMiscConfig)); mProcessPanel.add(new FrameGrabberPanel(ledString.mMiscConfig));
mProcessPanel.add(new ColorSmoothingPanel(ledString.mColorConfig)); mProcessPanel.add(new ColorSmoothingPanel(ledString.mColorConfig));
mProcessPanel.add(new ColorPanel(ledString.mColorConfig)); mProcessPanel.add(new ColorsPanel(ledString.mColorConfig));
mProcessPanel.add(Box.createVerticalGlue()); mProcessPanel.add(Box.createVerticalGlue());
} }
return mProcessPanel; return mProcessPanel;

View File

@ -0,0 +1,48 @@
package org.hyperion.hypercon.gui;
import java.awt.GridLayout;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class LedDivideDialog extends JFrame {
private final int mLedCount;
private final int mTransformCount;
private JPanel mContentPanel;
public LedDivideDialog(int pLedCnt, int pTransformCnt) {
super();
mLedCount = pLedCnt;
mTransformCount = pTransformCnt;
initialise();
}
private void initialise() {
mContentPanel = new JPanel();
mContentPanel.setLayout(new GridLayout(mLedCount, mTransformCount, 5, 5));
for (int iLed=0; iLed<mLedCount; ++iLed) {
ButtonGroup ledGroup = new ButtonGroup();
for (int iTransform=0; iTransform<mTransformCount; ++iTransform) {
JRadioButton ledTransformButton = new JRadioButton();
ledGroup.add(ledTransformButton);
mContentPanel.add(ledTransformButton);
}
}
setContentPane(mContentPanel);
}
public static void main(String[] pArgs) {
LedDivideDialog dialog = new LedDivideDialog(50, 3);
dialog.setSize(600, 800);
dialog.setVisible(true);
}
}

View File

@ -1,42 +1,18 @@
package org.hyperion.hypercon.spec; package org.hyperion.hypercon.spec;
import java.util.Locale; import java.util.Locale;
import java.util.Vector;
/** /**
* The color tuning parameters of the different color channels (both in RGB space as in HSV space) * The color tuning parameters of the different color channels (both in RGB space as in HSV space)
*/ */
public class ColorConfig { public class ColorConfig {
/** The saturation gain (in HSV space) */
public double mSaturationGain = 1.0;
/** The value gain (in HSV space) */
public double mValueGain = 1.5;
/** The minimum required RED-value (in RGB space) */ /** List with color transformations */
public double mRedThreshold = 0.1; public Vector<TransformConfig> mTransforms = new Vector<>();
/** The gamma-curve correct for the RED-value (in RGB space) */ {
public double mRedGamma = 2.0; mTransforms.add(new TransformConfig());
/** The black-level of the RED-value (in RGB space) */ }
public double mRedBlacklevel = 0.0;
/** The white-level of the RED-value (in RGB space) */
public double mRedWhitelevel = 0.8;
/** The minimum required GREEN-value (in RGB space) */
public double mGreenThreshold = 0.1;
/** The gamma-curve correct for the GREEN-value (in RGB space) */
public double mGreenGamma = 2.0;
/** The black-level of the GREEN-value (in RGB space) */
public double mGreenBlacklevel = 0.0;
/** The white-level of the GREEN-value (in RGB space) */
public double mGreenWhitelevel = 1.0;
/** The minimum required BLUE-value (in RGB space) */
public double mBlueThreshold = 0.1;
/** The gamma-curve correct for the BLUE-value (in RGB space) */
public double mBlueGamma = 2.0;
/** The black-level of the BLUE-value (in RGB space) */
public double mBlueBlacklevel = 0.0;
/** The white-level of the BLUE-value (in RGB space) */
public double mBlueWhitelevel = 1.0;
public boolean mSmoothingEnabled = false; public boolean mSmoothingEnabled = false;
/** The type of smoothing algorithm */ /** The type of smoothing algorithm */
@ -54,81 +30,53 @@ public class ColorConfig {
public String toJsonString() { public String toJsonString() {
StringBuffer strBuf = new StringBuffer(); StringBuffer strBuf = new StringBuffer();
strBuf.append("\t/// Color manipulation configuration used to tune the output colors to specific surroundings. Contains the following fields:\n"); strBuf.append("\t/// Color manipulation configuration used to tune the output colors to specific surroundings. \n");
strBuf.append("\t/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following tuning parameters:\n"); strBuf.append("\t/// The configuration contains a list of color-transforms. Each transform contains the \n");
strBuf.append("\t/// following fields:\n");
strBuf.append("\t/// * 'id' : The unique identifier of the color transformation (eg 'device_1')");
strBuf.append("\t/// * 'leds' : The indices (or index ranges) of the leds to which this color transform applies\n");
strBuf.append("\t/// (eg '0-5, 9, 11, 12-17'). The indices are zero based.");
strBuf.append("\t/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following \n");
strBuf.append("\t/// tuning parameters:\n");
strBuf.append("\t/// - 'saturationGain' The gain adjustement of the saturation\n"); strBuf.append("\t/// - 'saturationGain' The gain adjustement of the saturation\n");
strBuf.append("\t/// - 'valueGain' The gain adjustement of the value\n"); strBuf.append("\t/// - 'valueGain' The gain adjustement of the value\n");
strBuf.append("\t/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the following tuning parameters for each channel:\n"); strBuf.append("\t/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the \n");
strBuf.append("\t/// - 'threshold' The minimum required input value for the channel to be on (else zero)\n"); strBuf.append("\t/// following tuning parameters for each channel:\n");
strBuf.append("\t/// - 'threshold' The minimum required input value for the channel to be on \n");
strBuf.append("\t/// (else zero)\n");
strBuf.append("\t/// - 'gamma' The gamma-curve correction factor\n"); strBuf.append("\t/// - 'gamma' The gamma-curve correction factor\n");
strBuf.append("\t/// - 'blacklevel' The lowest possible value (when the channel is black)\n"); strBuf.append("\t/// - 'blacklevel' The lowest possible value (when the channel is black)\n");
strBuf.append("\t/// - 'whitelevel' The highest possible value (when the channel is white)\n"); strBuf.append("\t/// - 'whitelevel' The highest possible value (when the channel is white)\n");
strBuf.append("\t/// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning parameters:\n"); strBuf.append("\t///");
strBuf.append("\t/// Next to the list with color transforms there is also a smoothing option.");
strBuf.append("\t/// * 'smoothing' : Smoothing of the colors in the time-domain with the following tuning \n");
strBuf.append("\t/// parameters:\n");
strBuf.append("\t/// - 'type' The type of smoothing algorithm ('linear' or 'none')\n"); strBuf.append("\t/// - 'type' The type of smoothing algorithm ('linear' or 'none')\n");
strBuf.append("\t/// - 'time_ms' The time constant for smoothing algorithm in milliseconds\n"); strBuf.append("\t/// - 'time_ms' The time constant for smoothing algorithm in milliseconds\n");
strBuf.append("\t/// - 'updateFrequency' The update frequency of the leds in Hz\n"); strBuf.append("\t/// - 'updateFrequency' The update frequency of the leds in Hz\n");
strBuf.append("\t\"color\" :\n"); strBuf.append("\t\"color\" :\n");
strBuf.append("\t{\n"); strBuf.append("\t{\n");
strBuf.append(hsvToJsonString() + ",\n");
strBuf.append(rgbToJsonString() + ",\n"); strBuf.append("\t\t\"transform\" :\n");
strBuf.append("\t\t[\n");
for (int i=0; i<mTransforms.size(); ++i) {
TransformConfig transform = mTransforms.get(i);
strBuf.append(transform.toJsonString());
if (i == mTransforms.size()-1) {
strBuf.append("\n");
} else {
strBuf.append(",\n");
}
}
strBuf.append("\t\t],\n");
strBuf.append(smoothingToString() + "\n"); strBuf.append(smoothingToString() + "\n");
strBuf.append("\t}"); strBuf.append("\t}");
return strBuf.toString(); return strBuf.toString();
} }
/**
* Creates the JSON string of the HSV-subconfiguration as used in the Hyperion deamon configfile
*
* @return The JSON string of the HSV-config
*/
private String hsvToJsonString() {
StringBuffer strBuf = new StringBuffer();
strBuf.append("\t\t\"hsv\" :\n");
strBuf.append("\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"saturationGain\" : %.4f,\n", mSaturationGain));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"valueGain\" : %.4f\n", mValueGain));
strBuf.append("\t\t}");
return strBuf.toString();
}
/**
* Creates the JSON string of the RGB-subconfiguration as used in the Hyperion deamon configfile
*
* @return The JSON string of the RGB-config
*/
private String rgbToJsonString() {
StringBuffer strBuf = new StringBuffer();
strBuf.append("\t\t\"red\" :\n");
strBuf.append("\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mRedThreshold));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mRedGamma));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mRedBlacklevel));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mRedWhitelevel));
strBuf.append("\t\t},\n");
strBuf.append("\t\t\"green\" :\n");
strBuf.append("\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mGreenThreshold));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mGreenGamma));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mGreenBlacklevel));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mGreenWhitelevel));
strBuf.append("\t\t},\n");
strBuf.append("\t\t\"blue\" :\n");
strBuf.append("\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mBlueThreshold));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mBlueGamma));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mBlueBlacklevel));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mBlueWhitelevel));
strBuf.append("\t\t}");
return strBuf.toString();
}
/** /**
* Creates the JSON string of the smoothing subconfiguration as used in the Hyperion deamon configfile * Creates the JSON string of the smoothing subconfiguration as used in the Hyperion deamon configfile
* *

View File

@ -0,0 +1,111 @@
package org.hyperion.hypercon.spec;
import java.util.Locale;
public class TransformConfig {
/** The identifier of this ColorTransform configuration */
public String mId = "default";
/** The indices to which this transform applies */
public String mLedIndexString = "0-49";
/** The saturation gain (in HSV space) */
public double mSaturationGain = 1.0;
/** The value gain (in HSV space) */
public double mValueGain = 1.5;
/** The minimum required RED-value (in RGB space) */
public double mRedThreshold = 0.1;
/** The gamma-curve correct for the RED-value (in RGB space) */
public double mRedGamma = 2.0;
/** The black-level of the RED-value (in RGB space) */
public double mRedBlacklevel = 0.0;
/** The white-level of the RED-value (in RGB space) */
public double mRedWhitelevel = 0.8;
/** The minimum required GREEN-value (in RGB space) */
public double mGreenThreshold = 0.1;
/** The gamma-curve correct for the GREEN-value (in RGB space) */
public double mGreenGamma = 2.0;
/** The black-level of the GREEN-value (in RGB space) */
public double mGreenBlacklevel = 0.0;
/** The white-level of the GREEN-value (in RGB space) */
public double mGreenWhitelevel = 1.0;
/** The minimum required BLUE-value (in RGB space) */
public double mBlueThreshold = 0.1;
/** The gamma-curve correct for the BLUE-value (in RGB space) */
public double mBlueGamma = 2.0;
/** The black-level of the BLUE-value (in RGB space) */
public double mBlueBlacklevel = 0.0;
/** The white-level of the BLUE-value (in RGB space) */
public double mBlueWhitelevel = 1.0;
public String toJsonString() {
StringBuffer strBuf = new StringBuffer();
strBuf.append("\t\t\t{\n");
strBuf.append("\t\t\t\t\"id\" : \"" + mId + "\",\n");
strBuf.append("\t\t\t\t\"leds\" : \"" + mLedIndexString + "\",\n");
strBuf.append(hsvToJsonString() + ",\n");
strBuf.append(rgbToJsonString() + "\n");
strBuf.append("\t\t\t}");
return strBuf.toString();
}
/**
* Creates the JSON string of the HSV-subconfiguration as used in the Hyperion deamon configfile
*
* @return The JSON string of the HSV-config
*/
private String hsvToJsonString() {
StringBuffer strBuf = new StringBuffer();
strBuf.append("\t\t\t\t\"hsv\" :\n");
strBuf.append("\t\t\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"saturationGain\" : %.4f,\n", mSaturationGain));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"valueGain\" : %.4f\n", mValueGain));
strBuf.append("\t\t\t\t}");
return strBuf.toString();
}
/**
* Creates the JSON string of the RGB-subconfiguration as used in the Hyperion deamon configfile
*
* @return The JSON string of the RGB-config
*/
private String rgbToJsonString() {
StringBuffer strBuf = new StringBuffer();
strBuf.append("\t\t\t\t\"red\" :\n");
strBuf.append("\t\t\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"threshold\" : %.4f,\n", mRedThreshold));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"gamma\" : %.4f,\n", mRedGamma));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"blacklevel\" : %.4f,\n", mRedBlacklevel));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"whitelevel\" : %.4f\n", mRedWhitelevel));
strBuf.append("\t\t\t\t},\n");
strBuf.append("\t\t\t\t\"green\" :\n");
strBuf.append("\t\t\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"threshold\" : %.4f,\n", mGreenThreshold));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"gamma\" : %.4f,\n", mGreenGamma));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"blacklevel\" : %.4f,\n", mGreenBlacklevel));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"whitelevel\" : %.4f\n", mGreenWhitelevel));
strBuf.append("\t\t\t\t},\n");
strBuf.append("\t\t\t\t\"blue\" :\n");
strBuf.append("\t\t\t\t{\n");
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"threshold\" : %.4f,\n", mBlueThreshold));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"gamma\" : %.4f,\n", mBlueGamma));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"blacklevel\" : %.4f,\n", mBlueBlacklevel));
strBuf.append(String.format(Locale.ROOT, "\t\t\t\t\t\"whitelevel\" : %.4f\n", mBlueWhitelevel));
strBuf.append("\t\t\t\t}");
return strBuf.toString();
}
@Override
public String toString() {
return mId;
}
}

View File

@ -160,7 +160,7 @@ void JsonConnection::clearAll()
parseReply(reply); parseReply(reply);
} }
void JsonConnection::setTransform(double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel) void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel)
{ {
std::cout << "Set color transforms" << std::endl; std::cout << "Set color transforms" << std::endl;
@ -169,6 +169,11 @@ void JsonConnection::setTransform(double * saturation, double * value, ColorTran
command["command"] = "transform"; command["command"] = "transform";
Json::Value & transform = command["transform"]; Json::Value & transform = command["transform"];
if (transformId != nullptr)
{
transform["id"] = *transformId;
}
if (saturation != nullptr) if (saturation != nullptr)
{ {
transform["saturationGain"] = *saturation; transform["saturationGain"] = *saturation;

View File

@ -76,6 +76,7 @@ public:
/// ///
/// @note Note that providing a NULL will leave the settings on the server unchanged /// @note Note that providing a NULL will leave the settings on the server unchanged
/// ///
/// @param transformId The identifier of the transform to set
/// @param saturation The HSV saturation gain /// @param saturation The HSV saturation gain
/// @param value The HSV value gain /// @param value The HSV value gain
/// @param threshold The threshold /// @param threshold The threshold
@ -84,6 +85,7 @@ public:
/// @param whitelevel The whitelevel /// @param whitelevel The whitelevel
/// ///
void setTransform( void setTransform(
std::string * transformId,
double * saturation, double * saturation,
double * value, double * value,
ColorTransformValues * threshold, ColorTransformValues * threshold,

View File

@ -45,6 +45,7 @@ int main(int argc, char * argv[])
SwitchParameter<> & argServerInfo = parameters.add<SwitchParameter<> >('l', "list" , "List server info"); SwitchParameter<> & argServerInfo = parameters.add<SwitchParameter<> >('l', "list" , "List server info");
SwitchParameter<> & argClear = parameters.add<SwitchParameter<> >('x', "clear" , "Clear data for the priority channel provided by the -p option"); SwitchParameter<> & argClear = parameters.add<SwitchParameter<> >('x', "clear" , "Clear data for the priority channel provided by the -p option");
SwitchParameter<> & argClearAll = parameters.add<SwitchParameter<> >(0x0, "clearall" , "Clear data for all active priority channels"); SwitchParameter<> & argClearAll = parameters.add<SwitchParameter<> >(0x0, "clearall" , "Clear data for all active priority channels");
StringParameter & argId = parameters.add<StringParameter> ('q', "qualifier" , "Identifier(qualifier) of the transform to set");
DoubleParameter & argSaturation = parameters.add<DoubleParameter> ('s', "saturation", "Set the HSV saturation gain of the leds"); DoubleParameter & argSaturation = parameters.add<DoubleParameter> ('s', "saturation", "Set the HSV saturation gain of the leds");
DoubleParameter & argValue = parameters.add<DoubleParameter> ('v', "value" , "Set the HSV value gain of the leds"); DoubleParameter & argValue = parameters.add<DoubleParameter> ('v', "value" , "Set the HSV value gain of the leds");
TransformParameter & argGamma = parameters.add<TransformParameter>('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated values)"); TransformParameter & argGamma = parameters.add<TransformParameter>('g', "gamma" , "Set the gamma of the leds (requires 3 space seperated values)");
@ -83,6 +84,7 @@ int main(int argc, char * argv[])
std::cerr << " " << argClear.usageLine() << std::endl; std::cerr << " " << argClear.usageLine() << std::endl;
std::cerr << " " << argClearAll.usageLine() << std::endl; std::cerr << " " << argClearAll.usageLine() << std::endl;
std::cerr << "or one or more of the available color transformations:" << std::endl; std::cerr << "or one or more of the available color transformations:" << std::endl;
std::cerr << " " << argId.usageLine() << std::endl;
std::cerr << " " << argSaturation.usageLine() << std::endl; std::cerr << " " << argSaturation.usageLine() << std::endl;
std::cerr << " " << argValue.usageLine() << std::endl; std::cerr << " " << argValue.usageLine() << std::endl;
std::cerr << " " << argThreshold.usageLine() << std::endl; std::cerr << " " << argThreshold.usageLine() << std::endl;
@ -119,9 +121,11 @@ int main(int argc, char * argv[])
} }
else if (colorTransform) else if (colorTransform)
{ {
std::string transId;
double saturation, value; double saturation, value;
ColorTransformValues threshold, gamma, blacklevel, whitelevel; ColorTransformValues threshold, gamma, blacklevel, whitelevel;
if (argId.isSet()) transId = argId.getValue();
if (argSaturation.isSet()) saturation = argSaturation.getValue(); if (argSaturation.isSet()) saturation = argSaturation.getValue();
if (argValue.isSet()) value = argValue.getValue(); if (argValue.isSet()) value = argValue.getValue();
if (argThreshold.isSet()) threshold = argThreshold.getValue(); if (argThreshold.isSet()) threshold = argThreshold.getValue();
@ -130,6 +134,7 @@ int main(int argc, char * argv[])
if (argWhitelevel.isSet()) whitelevel = argWhitelevel.getValue(); if (argWhitelevel.isSet()) whitelevel = argWhitelevel.getValue();
connection.setTransform( connection.setTransform(
argId.isSet() ? &transId : nullptr,
argSaturation.isSet() ? &saturation : nullptr, argSaturation.isSet() ? &saturation : nullptr,
argValue.isSet() ? &value : nullptr, argValue.isSet() ? &value : nullptr,
argThreshold.isSet() ? &threshold : nullptr, argThreshold.isSet() ? &threshold : nullptr,

View File

@ -41,5 +41,9 @@ add_executable(test_blackborderprocessor
target_link_libraries(test_blackborderprocessor target_link_libraries(test_blackborderprocessor
hyperion) hyperion)
add_executable(test_qregexp TestQRegExp.cpp)
target_link_libraries(test_qregexp
${QT_LIBRARIES})
add_executable(spidev_test spidev_test.c) add_executable(spidev_test spidev_test.c)
add_executable(gpio2spi switchPinCtrl.c) add_executable(gpio2spi switchPinCtrl.c)

View File

@ -148,7 +148,7 @@ int main()
// Switch back (in one shot) to no border // Switch back (in one shot) to no border
assert(processor.process(noBorderImage)); assert(processor.process(noBorderImage));
assert(processor.getCurrentBorder().type == BlackBorder::none); assert(processor.getCurrentBorder().verticalSize == 0 && processor.getCurrentBorder().horizontalSize == 0);
return 0; return 0;
} }

View File

@ -2,13 +2,14 @@
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
#include <utils/ColorTransform.h> // Utils includes
#include <utils/RgbChannelTransform.h>
int main() int main()
{ {
{ {
std::cout << "Testing linear transform" << std::endl; std::cout << "Testing linear transform" << std::endl;
ColorTransform t; RgbChannelTransform t;
for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
uint8_t input = i; uint8_t input = i;
@ -29,7 +30,7 @@ int main()
{ {
std::cout << "Testing threshold" << std::endl; std::cout << "Testing threshold" << std::endl;
ColorTransform t(.10, 1.0, 0.0, 1.0); RgbChannelTransform t(.10, 1.0, 0.0, 1.0);
for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
uint8_t input = i; uint8_t input = i;
@ -50,7 +51,7 @@ int main()
{ {
std::cout << "Testing blacklevel and whitelevel" << std::endl; std::cout << "Testing blacklevel and whitelevel" << std::endl;
ColorTransform t(0, 1.0, 0.2, 0.8); RgbChannelTransform t(0, 1.0, 0.2, 0.8);
for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
uint8_t input = i; uint8_t input = i;
@ -71,7 +72,7 @@ int main()
{ {
std::cout << "Testing gamma" << std::endl; std::cout << "Testing gamma" << std::endl;
ColorTransform t(0, 2.0, 0.0, 1.0); RgbChannelTransform t(0, 2.0, 0.0, 1.0);
for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
uint8_t input = i; uint8_t input = i;

50
test/TestQRegExp.cpp Normal file
View File

@ -0,0 +1,50 @@
// STL includes
#include <iostream>
// QT includes
#include <QRegExp>
#include <QString>
#include <QStringList>
int main()
{
QString testString = "1-9, 11, 12,13,16-17";
QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*");
{
std::cout << "[1] Match found: " << (overallExp.exactMatch("5")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("4-")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("-4")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("3-9")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90,100")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90, 100")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90, 100-200")?"true":"false") << std::endl;
std::cout << "[1] Match found: " << (overallExp.exactMatch("1-90, 100-200, 100")?"true":"false") << std::endl;
}
{
if (!overallExp.exactMatch(testString)) {
std::cout << "No correct match" << std::endl;
return -1;
}
QStringList splitString = testString.split(QChar(','));
for (int i=0; i<splitString.size(); ++i) {
if (splitString[i].contains("-"))
{
QStringList str = splitString[i].split("-");
int startInd = str[0].toInt();
int endInd = str[1].toInt();
std::cout << "==> " << startInd << "-" << endInd << std::endl;
}
else
{
int index = splitString[i].toInt();
std::cout << "==> " << index << std::endl;
}
}
}
return 0;
}