2 Commits
Author SHA1 Message Date
matze19999 ef03258e22 Release 0.13.3 2026-10-12 18:23:52 +02:00
matze19999 2f6efd9864 Release 0.13.2 2026-10-12 18:19:11 +02:00
15 changed files with 73 additions and 22 deletions

No files matched your search

+4 -4
View File
@@ -1,15 +1,15 @@
{ {
"id": "org.webosbrew.histogramhyperion", "id": "org.webosbrew.histogramhyperion",
"version": "0.13.1", "version": "0.13.3",
"type": "web", "type": "web",
"title": "HyperDRM", "title": "HyperDRM",
"appDescription": "Ambient lighting for webOS, Hyperion and HyperHDR", "appDescription": "Ambient lighting for webOS, Hyperion and HyperHDR",
"iconUri": "https://gitea.adnau.de/matze19999/HyperDRM/raw/branch/main/app/icon.png", "iconUri": "https://gitea.adnau.de/matze19999/HyperDRM/raw/branch/main/app/icon.png",
"sourceUrl": "https://gitea.adnau.de/matze19999/HyperDRM", "sourceUrl": "https://gitea.adnau.de/matze19999/HyperDRM",
"rootRequired": true, "rootRequired": true,
"ipkUrl": "https://gitea.adnau.de/matze19999/HyperDRM/raw/branch/main/HyperDRM_0.13.1_arm.ipk", "ipkUrl": "https://gitea.adnau.de/matze19999/HyperDRM/raw/branch/main/HyperDRM_0.13.3_arm.ipk",
"ipkHash": { "ipkHash": {
"sha256": "7ee27c6c8c0f7649690f1eb6e055b0add5ba2e57461cec58cbc8e144316af1d6" "sha256": "acb0978100796e8765e586a91183599ef4eb783631d8b68205d716621790e232"
}, },
"ipkSize": 1207854 "ipkSize": 1208120
} }
Binary file not shown.
+4 -2
View File
@@ -27,7 +27,7 @@ Only the own service is modified. Optional Auto PicCap can configure its receive
## Installation ## Installation
The current package is [HyperDRM_0.13.1_arm.ipk](HyperDRM_0.13.1_arm.ipk). Install it using the TV's webOS/Homebrew package installation workflow. The current package is [HyperDRM_0.13.3_arm.ipk](HyperDRM_0.13.3_arm.ipk). Install it using the TV's webOS/Homebrew package installation workflow.
Elevate the installed own service through Homebrew Channel: Elevate the installed own service through Homebrew Channel:
@@ -234,4 +234,6 @@ and briefly interrupts ambient lighting; it never runs automatically.
receiver-output and simulated service-lifecycle tests with ASan/UBSan. These host receiver-output and simulated service-lifecycle tests with ASan/UBSan. These host
tests do not replace real LG capture and remote-control validation on a TV. tests do not replace real LG capture and remote-control validation on a TV.
Histogram near-black handling suppresses colors with a maximum RGB channel of 12 or less, gradually restores brightness between 12 and 24, and preserves brighter colors. This applies only to histogram output; PicCap, receiver calibration and raw calibration samples are unchanged. Histogram near-black handling suppresses colors with a maximum RGB channel of 16 or less, gradually restores brightness between 16 and 32, and preserves brighter colors. This applies only to histogram output; PicCap, receiver calibration and raw calibration samples are unchanged.
Thin letterbox detection compares both edges against lit interior histogram samples and requires a consistently dark upper edge for at least two seconds. Histogram probes cannot determine the exact bar height or guarantee detection on every scene.
+1 -1
View File
@@ -1 +1 @@
0.13.1 0.13.3
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"id": "org.webosbrew.histogramhyperion", "id": "org.webosbrew.histogramhyperion",
"version": "0.13.1", "version": "0.13.3",
"vendor": "Local development", "vendor": "Local development",
"type": "web", "type": "web",
"main": "index.html", "main": "index.html",
+1 -1
View File
@@ -1,2 +1,2 @@
'use strict'; 'use strict';
var HYPERDRM_APP_VERSION = '0.13.1'; var HYPERDRM_APP_VERSION = '0.13.3';
+3
View File
@@ -0,0 +1,3 @@
# HyperDRM 0.13.2
Raise the histogram black cutoff to 16 and extend the proportional transition to 32. Live measurements showed raw [13,14,7] causing residual [1,1,0] to [2,2,1] at the bottom-right LEDs with the previous cutoff. Regression coverage now includes this sample. Brighter colors, PicCap and saved settings remain unchanged; very dark detail is suppressed more strongly.
+3
View File
@@ -0,0 +1,3 @@
# HyperDRM 0.13.3
Detect thinner horizontal black bars using edge-versus-interior contrast, distributed upper-edge support and lower-edge support. Preserve the existing dark-scene rejection, wide-bar rule and two-second stability gate. Regression tests include live G4 measurements, one-sided and isolated dark edges, dim frames and insufficient contrast. This is a histogram heuristic; it does not measure exact bar heights.
+25 -2
View File
@@ -4,14 +4,17 @@
* or dark frame so darkness alone cannot switch the active capture mode. */ * or dark frame so darkness alone cannot switch the active capture mode. */
static inline int letterbox_candidate(const unsigned black[16], const unsigned char color[16][3]) { static inline int letterbox_candidate(const unsigned black[16], const unsigned char color[16][3]) {
const unsigned interior[] = {2, 6, 10, 15}; const unsigned interior[] = {2, 6, 10, 15};
unsigned lit = 0; unsigned lit = 0, interior_black = 0, interior_peak = 0;
for (unsigned i = 0; i < 4; i++) { for (unsigned i = 0; i < 4; i++) {
unsigned r = interior[i], peak = color[r][0]; unsigned r = interior[i], peak = color[r][0];
for (unsigned c = 1; c < 3; c++) for (unsigned c = 1; c < 3; c++)
if (color[r][c] > peak) if (color[r][c] > peak)
peak = color[r][c]; peak = color[r][c];
if (black[r] < 20 && peak > 35) if (black[r] < 20 && peak > 35) {
lit++; lit++;
interior_black += black[r];
interior_peak += peak;
}
} }
if (lit < 2) if (lit < 2)
return -1; return -1;
@@ -19,6 +22,26 @@ static inline int letterbox_candidate(const unsigned black[16], const unsigned c
unsigned bottom = (black[1] + black[5] + black[9]) / 3; unsigned bottom = (black[1] + black[5] + black[9]) / 3;
if (top >= 55 && bottom >= 25) if (top >= 55 && bottom >= 25)
return 1; return 1;
/* Thin bars occupy only part of an edge probe. Require a broad upper
* dark edge, lower-edge support and contrast against lit interior probes.
* This remains a histogram heuristic, not a pixel-accurate crop. */
const unsigned top_regions[] = {3, 11, 12};
const unsigned bottom_regions[] = {1, 5, 9};
unsigned top_support = 0, bottom_support = 0, top_peak = 0;
for (unsigned i = 0; i < 3; i++) {
unsigned r = top_regions[i], peak = color[r][0];
for (unsigned c = 1; c < 3; c++)
if (color[r][c] > peak)
peak = color[r][c];
top_peak += peak;
top_support += black[r] >= 12;
bottom_support += black[bottom_regions[i]] >= 8;
}
unsigned baseline = interior_black / lit;
if (top_support == 3 && bottom_support >= 2 && top >= 12 && bottom >= 10 &&
top >= baseline + 8 && bottom >= baseline + 8 &&
(unsigned long)top_peak * lit * 100 <= (unsigned long)interior_peak * 3 * 60)
return 1;
if (top < 20 && bottom < 20) if (top < 20 && bottom < 20)
return 0; return 0;
return -1; return -1;
+3 -3
View File
@@ -7,10 +7,10 @@ static inline void dark_color_filter(unsigned char color[3]) {
for (unsigned c = 1; c < 3; c++) for (unsigned c = 1; c < 3; c++)
if (color[c] > peak) if (color[c] > peak)
peak = color[c]; peak = color[c];
if (peak >= 24) if (peak >= 32)
return; return;
unsigned gain = peak > 12 ? peak - 12 : 0; unsigned gain = peak > 16 ? peak - 16 : 0;
for (unsigned c = 0; c < 3; c++) for (unsigned c = 0; c < 3; c++)
color[c] = (unsigned char)((color[c] * gain + 6) / 12); color[c] = (unsigned char)((color[c] * gain + 8) / 16);
} }
#endif #endif
+18 -1
View File
@@ -11,5 +11,22 @@ int main(void){
for(unsigned i=0;i<16;i++)black[i]=100; for(unsigned i=0;i<16;i++)black[i]=100;
memset(color,0,sizeof(color));assert(letterbox_candidate(black,color)==-1); memset(color,0,sizeof(color));assert(letterbox_candidate(black,color)==-1);
memset(black,0,sizeof(black));assert(letterbox_candidate(black,color)==-1); memset(black,0,sizeof(black));assert(letterbox_candidate(black,color)==-1);
puts("PASS: full frame, measured letterbox, one edge only, black frame, dark frame"); unsigned thin_black[16]={12,23,1,21,9,6,6,16,18,12,26,23,23,22,37,8};
unsigned char thin_color[16][3]={{57,52,48},{97,94,92},{51,42,35},{25,24,21},
{71,65,60},{128,122,118},{84,74,67},{34,32,27},{47,41,36},{59,47,43},
{37,29,25},{19,18,15},{22,20,16},{22,19,15},{14,13,11},{78,75,72}};
assert(letterbox_candidate(thin_black,thin_color)==1);
thin_black[1]=thin_black[5]=thin_black[9]=0;
assert(letterbox_candidate(thin_black,thin_color)!=1);
thin_black[1]=23;thin_black[5]=6;thin_black[9]=12;
thin_black[11]=0;
assert(letterbox_candidate(thin_black,thin_color)!=1);
thin_black[11]=23;
memset(thin_color,10,sizeof(thin_color));
assert(letterbox_candidate(thin_black,thin_color)==-1);
memset(thin_color,100,sizeof(thin_color));
assert(letterbox_candidate(thin_black,thin_color)!=1);
memset(thin_black,15,sizeof(thin_black));
assert(letterbox_candidate(thin_black,thin_color)!=1);
puts("PASS: measured wide/thin bars, full frame, one-sided/isolated edges, dark frame and low contrast");
} }
+8 -5
View File
@@ -5,17 +5,20 @@ int main(void) {
for (unsigned v = 0; v <= 255; v++) { for (unsigned v = 0; v <= 255; v++) {
unsigned char gray[3] = {v, v, v}; unsigned char gray[3] = {v, v, v};
dark_color_filter(gray); dark_color_filter(gray);
unsigned expected = v <= 12 ? 0 : v >= 24 ? v : (v * (v - 12) + 6) / 12; unsigned expected = v <= 16 ? 0 : v >= 32 ? v : (v * (v - 16) + 8) / 16;
for (unsigned c = 0; c < 3; c++) assert(gray[c] == expected); for (unsigned c = 0; c < 3; c++) assert(gray[c] == expected);
} }
unsigned char residual[3] = {4, 8, 2}; unsigned char residual[3] = {4, 8, 2};
dark_color_filter(residual); dark_color_filter(residual);
assert(!residual[0] && !residual[1] && !residual[2]); assert(!residual[0] && !residual[1] && !residual[2]);
unsigned char transition[3] = {9, 18, 6}; unsigned char measured[3] = {13, 14, 7};
dark_color_filter(measured);
assert(!measured[0] && !measured[1] && !measured[2]);
unsigned char transition[3] = {12, 24, 8};
dark_color_filter(transition); dark_color_filter(transition);
assert(transition[0] == 5 && transition[1] == 9 && transition[2] == 3); assert(transition[0] == 6 && transition[1] == 12 && transition[2] == 4);
unsigned char saturated[3] = {0, 24, 0}; unsigned char saturated[3] = {0, 32, 0};
dark_color_filter(saturated); dark_color_filter(saturated);
assert(saturated[0] == 0 && saturated[1] == 24 && saturated[2] == 0); assert(saturated[0] == 0 && saturated[1] == 32 && saturated[2] == 0);
puts("PASS: near-black suppression, gradual transition, unchanged brighter colors"); puts("PASS: near-black suppression, gradual transition, unchanged brighter colors");
} }
+1 -1
View File
@@ -1,4 +1,4 @@
#ifndef HYPERDRM_VERSION_H #ifndef HYPERDRM_VERSION_H
#define HYPERDRM_VERSION_H #define HYPERDRM_VERSION_H
#define HYPERDRM_VERSION "0.13.1" #define HYPERDRM_VERSION "0.13.3"
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"id": "org.webosbrew.histogramhyperion", "id": "org.webosbrew.histogramhyperion",
"version": "0.13.1", "version": "0.13.3",
"vendor": "Local development", "vendor": "Local development",
"app": "org.webosbrew.histogramhyperion", "app": "org.webosbrew.histogramhyperion",
"services": [ "services": [
Binary file not shown.