@livedesk/client 0.1.105 → 0.1.107

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import readline from 'node:readline';
4
+ import { convertRgbaToRgb565 } from './livedesk-raw-capture-resampler.mjs';
4
5
 
5
6
  const screenshotModule = await import('node-screenshots');
6
7
  const Monitor = screenshotModule.Monitor || screenshotModule.default?.Monitor;
@@ -26,31 +27,6 @@ function pickMonitor(index) {
26
27
  return { monitor, selectedIndex, monitorCount: monitors.length };
27
28
  }
28
29
 
29
- function convertRgbaToRgb565(raw, sourceWidth, sourceHeight, maxWidth, maxHeight) {
30
- if (raw.length < sourceWidth * sourceHeight * 4) {
31
- throw new Error(`Raw capture is incomplete: ${raw.length} bytes for ${sourceWidth}x${sourceHeight}.`);
32
- }
33
- const scale = Math.min(1, maxWidth / sourceWidth, maxHeight / sourceHeight);
34
- const width = Math.max(1, Math.round(sourceWidth * scale));
35
- const height = Math.max(1, Math.round(sourceHeight * scale));
36
- const output = Buffer.allocUnsafe(width * height * 2);
37
- let target = 0;
38
- for (let y = 0; y < height; y += 1) {
39
- const sourceY = Math.min(sourceHeight - 1, Math.floor((y + 0.5) * sourceHeight / height));
40
- for (let x = 0; x < width; x += 1) {
41
- const sourceX = Math.min(sourceWidth - 1, Math.floor((x + 0.5) * sourceWidth / width));
42
- const source = (sourceY * sourceWidth + sourceX) * 4;
43
- const red = raw[source];
44
- const green = raw[source + 1];
45
- const blue = raw[source + 2];
46
- const pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
47
- output[target++] = pixel & 0xff;
48
- output[target++] = pixel >> 8;
49
- }
50
- }
51
- return { output, width, height };
52
- }
53
-
54
30
  function writeResponse(metadata, payload = Buffer.alloc(0)) {
55
31
  const header = Buffer.from(JSON.stringify(metadata), 'utf8');
56
32
  const prefix = Buffer.allocUnsafe(8);
@@ -90,7 +66,8 @@ for await (const line of input) {
90
66
  monitorIndex: selectedIndex,
91
67
  monitorCount,
92
68
  captureMs: Math.round(captureMs),
93
- convertMs: Math.round(convertMs)
69
+ convertMs: Math.round(convertMs),
70
+ resizeFilter: converted.filter
94
71
  }, converted.output);
95
72
  } catch (error) {
96
73
  writeResponse({
@@ -0,0 +1,72 @@
1
+ function clampInteger(value, min, max, fallback) {
2
+ const number = Number(value);
3
+ if (!Number.isFinite(number)) return fallback;
4
+ return Math.max(min, Math.min(max, Math.round(number)));
5
+ }
6
+
7
+ function writeRgb565(output, target, red, green, blue) {
8
+ const pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
9
+ output[target] = pixel & 0xff;
10
+ output[target + 1] = pixel >> 8;
11
+ }
12
+
13
+ export function convertRgbaToRgb565(raw, sourceWidthValue, sourceHeightValue, maxWidthValue, maxHeightValue) {
14
+ const sourceWidth = clampInteger(sourceWidthValue, 1, 32_768, 1);
15
+ const sourceHeight = clampInteger(sourceHeightValue, 1, 32_768, 1);
16
+ const maxWidth = clampInteger(maxWidthValue, 1, sourceWidth, sourceWidth);
17
+ const maxHeight = clampInteger(maxHeightValue, 1, sourceHeight, sourceHeight);
18
+ if (raw.length < sourceWidth * sourceHeight * 4) {
19
+ throw new Error(`Raw capture is incomplete: ${raw.length} bytes for ${sourceWidth}x${sourceHeight}.`);
20
+ }
21
+
22
+ const scale = Math.min(1, maxWidth / sourceWidth, maxHeight / sourceHeight);
23
+ const width = Math.max(1, Math.round(sourceWidth * scale));
24
+ const height = Math.max(1, Math.round(sourceHeight * scale));
25
+ const output = Buffer.allocUnsafe(width * height * 2);
26
+
27
+ if (width === sourceWidth && height === sourceHeight) {
28
+ for (let source = 0, target = 0; target < output.length; source += 4, target += 2) {
29
+ writeRgb565(output, target, raw[source], raw[source + 1], raw[source + 2]);
30
+ }
31
+ return { output, width, height, filter: 'none' };
32
+ }
33
+
34
+ const xStarts = new Int32Array(width);
35
+ const xEnds = new Int32Array(width);
36
+ for (let x = 0; x < width; x += 1) {
37
+ xStarts[x] = Math.min(sourceWidth - 1, Math.floor(x * sourceWidth / width));
38
+ xEnds[x] = Math.max(xStarts[x] + 1, Math.min(sourceWidth, Math.floor((x + 1) * sourceWidth / width)));
39
+ }
40
+
41
+ let target = 0;
42
+ for (let y = 0; y < height; y += 1) {
43
+ const sourceY0 = Math.min(sourceHeight - 1, Math.floor(y * sourceHeight / height));
44
+ const sourceY1 = Math.max(sourceY0 + 1, Math.min(sourceHeight, Math.floor((y + 1) * sourceHeight / height)));
45
+ for (let x = 0; x < width; x += 1) {
46
+ let red = 0;
47
+ let green = 0;
48
+ let blue = 0;
49
+ let samples = 0;
50
+ for (let sourceY = sourceY0; sourceY < sourceY1; sourceY += 1) {
51
+ let source = (sourceY * sourceWidth + xStarts[x]) * 4;
52
+ for (let sourceX = xStarts[x]; sourceX < xEnds[x]; sourceX += 1) {
53
+ red += raw[source];
54
+ green += raw[source + 1];
55
+ blue += raw[source + 2];
56
+ samples += 1;
57
+ source += 4;
58
+ }
59
+ }
60
+ writeRgb565(
61
+ output,
62
+ target,
63
+ Math.round(red / samples),
64
+ Math.round(green / samples),
65
+ Math.round(blue / samples)
66
+ );
67
+ target += 2;
68
+ }
69
+ }
70
+
71
+ return { output, width, height, filter: 'box' };
72
+ }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import readline from 'node:readline';
4
+ import { convertRgbaToRgb565 } from './livedesk-raw-capture-resampler.mjs';
4
5
 
5
6
  const screenshotModule = await import('node-screenshots');
6
7
  const Monitor = screenshotModule.Monitor || screenshotModule.default?.Monitor;
@@ -26,31 +27,6 @@ function pickMonitor(index) {
26
27
  return { monitor, selectedIndex, monitorCount: monitors.length };
27
28
  }
28
29
 
29
- function convertRgbaToRgb565(raw, sourceWidth, sourceHeight, maxWidth, maxHeight) {
30
- if (raw.length < sourceWidth * sourceHeight * 4) {
31
- throw new Error(`Raw capture is incomplete: ${raw.length} bytes for ${sourceWidth}x${sourceHeight}.`);
32
- }
33
- const scale = Math.min(1, maxWidth / sourceWidth, maxHeight / sourceHeight);
34
- const width = Math.max(1, Math.round(sourceWidth * scale));
35
- const height = Math.max(1, Math.round(sourceHeight * scale));
36
- const output = Buffer.allocUnsafe(width * height * 2);
37
- let target = 0;
38
- for (let y = 0; y < height; y += 1) {
39
- const sourceY = Math.min(sourceHeight - 1, Math.floor((y + 0.5) * sourceHeight / height));
40
- for (let x = 0; x < width; x += 1) {
41
- const sourceX = Math.min(sourceWidth - 1, Math.floor((x + 0.5) * sourceWidth / width));
42
- const source = (sourceY * sourceWidth + sourceX) * 4;
43
- const red = raw[source];
44
- const green = raw[source + 1];
45
- const blue = raw[source + 2];
46
- const pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
47
- output[target++] = pixel & 0xff;
48
- output[target++] = pixel >> 8;
49
- }
50
- }
51
- return { output, width, height };
52
- }
53
-
54
30
  function writeResponse(metadata, payload = Buffer.alloc(0)) {
55
31
  const header = Buffer.from(JSON.stringify(metadata), 'utf8');
56
32
  const prefix = Buffer.allocUnsafe(8);
@@ -90,7 +66,8 @@ for await (const line of input) {
90
66
  monitorIndex: selectedIndex,
91
67
  monitorCount,
92
68
  captureMs: Math.round(captureMs),
93
- convertMs: Math.round(convertMs)
69
+ convertMs: Math.round(convertMs),
70
+ resizeFilter: converted.filter
94
71
  }, converted.output);
95
72
  } catch (error) {
96
73
  writeResponse({
@@ -0,0 +1,72 @@
1
+ function clampInteger(value, min, max, fallback) {
2
+ const number = Number(value);
3
+ if (!Number.isFinite(number)) return fallback;
4
+ return Math.max(min, Math.min(max, Math.round(number)));
5
+ }
6
+
7
+ function writeRgb565(output, target, red, green, blue) {
8
+ const pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
9
+ output[target] = pixel & 0xff;
10
+ output[target + 1] = pixel >> 8;
11
+ }
12
+
13
+ export function convertRgbaToRgb565(raw, sourceWidthValue, sourceHeightValue, maxWidthValue, maxHeightValue) {
14
+ const sourceWidth = clampInteger(sourceWidthValue, 1, 32_768, 1);
15
+ const sourceHeight = clampInteger(sourceHeightValue, 1, 32_768, 1);
16
+ const maxWidth = clampInteger(maxWidthValue, 1, sourceWidth, sourceWidth);
17
+ const maxHeight = clampInteger(maxHeightValue, 1, sourceHeight, sourceHeight);
18
+ if (raw.length < sourceWidth * sourceHeight * 4) {
19
+ throw new Error(`Raw capture is incomplete: ${raw.length} bytes for ${sourceWidth}x${sourceHeight}.`);
20
+ }
21
+
22
+ const scale = Math.min(1, maxWidth / sourceWidth, maxHeight / sourceHeight);
23
+ const width = Math.max(1, Math.round(sourceWidth * scale));
24
+ const height = Math.max(1, Math.round(sourceHeight * scale));
25
+ const output = Buffer.allocUnsafe(width * height * 2);
26
+
27
+ if (width === sourceWidth && height === sourceHeight) {
28
+ for (let source = 0, target = 0; target < output.length; source += 4, target += 2) {
29
+ writeRgb565(output, target, raw[source], raw[source + 1], raw[source + 2]);
30
+ }
31
+ return { output, width, height, filter: 'none' };
32
+ }
33
+
34
+ const xStarts = new Int32Array(width);
35
+ const xEnds = new Int32Array(width);
36
+ for (let x = 0; x < width; x += 1) {
37
+ xStarts[x] = Math.min(sourceWidth - 1, Math.floor(x * sourceWidth / width));
38
+ xEnds[x] = Math.max(xStarts[x] + 1, Math.min(sourceWidth, Math.floor((x + 1) * sourceWidth / width)));
39
+ }
40
+
41
+ let target = 0;
42
+ for (let y = 0; y < height; y += 1) {
43
+ const sourceY0 = Math.min(sourceHeight - 1, Math.floor(y * sourceHeight / height));
44
+ const sourceY1 = Math.max(sourceY0 + 1, Math.min(sourceHeight, Math.floor((y + 1) * sourceHeight / height)));
45
+ for (let x = 0; x < width; x += 1) {
46
+ let red = 0;
47
+ let green = 0;
48
+ let blue = 0;
49
+ let samples = 0;
50
+ for (let sourceY = sourceY0; sourceY < sourceY1; sourceY += 1) {
51
+ let source = (sourceY * sourceWidth + xStarts[x]) * 4;
52
+ for (let sourceX = xStarts[x]; sourceX < xEnds[x]; sourceX += 1) {
53
+ red += raw[source];
54
+ green += raw[source + 1];
55
+ blue += raw[source + 2];
56
+ samples += 1;
57
+ source += 4;
58
+ }
59
+ }
60
+ writeRgb565(
61
+ output,
62
+ target,
63
+ Math.round(red / samples),
64
+ Math.round(green / samples),
65
+ Math.round(blue / samples)
66
+ );
67
+ target += 2;
68
+ }
69
+ }
70
+
71
+ return { output, width, height, filter: 'box' };
72
+ }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import readline from 'node:readline';
4
+ import { convertRgbaToRgb565 } from './livedesk-raw-capture-resampler.mjs';
4
5
 
5
6
  const screenshotModule = await import('node-screenshots');
6
7
  const Monitor = screenshotModule.Monitor || screenshotModule.default?.Monitor;
@@ -26,31 +27,6 @@ function pickMonitor(index) {
26
27
  return { monitor, selectedIndex, monitorCount: monitors.length };
27
28
  }
28
29
 
29
- function convertRgbaToRgb565(raw, sourceWidth, sourceHeight, maxWidth, maxHeight) {
30
- if (raw.length < sourceWidth * sourceHeight * 4) {
31
- throw new Error(`Raw capture is incomplete: ${raw.length} bytes for ${sourceWidth}x${sourceHeight}.`);
32
- }
33
- const scale = Math.min(1, maxWidth / sourceWidth, maxHeight / sourceHeight);
34
- const width = Math.max(1, Math.round(sourceWidth * scale));
35
- const height = Math.max(1, Math.round(sourceHeight * scale));
36
- const output = Buffer.allocUnsafe(width * height * 2);
37
- let target = 0;
38
- for (let y = 0; y < height; y += 1) {
39
- const sourceY = Math.min(sourceHeight - 1, Math.floor((y + 0.5) * sourceHeight / height));
40
- for (let x = 0; x < width; x += 1) {
41
- const sourceX = Math.min(sourceWidth - 1, Math.floor((x + 0.5) * sourceWidth / width));
42
- const source = (sourceY * sourceWidth + sourceX) * 4;
43
- const red = raw[source];
44
- const green = raw[source + 1];
45
- const blue = raw[source + 2];
46
- const pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
47
- output[target++] = pixel & 0xff;
48
- output[target++] = pixel >> 8;
49
- }
50
- }
51
- return { output, width, height };
52
- }
53
-
54
30
  function writeResponse(metadata, payload = Buffer.alloc(0)) {
55
31
  const header = Buffer.from(JSON.stringify(metadata), 'utf8');
56
32
  const prefix = Buffer.allocUnsafe(8);
@@ -90,7 +66,8 @@ for await (const line of input) {
90
66
  monitorIndex: selectedIndex,
91
67
  monitorCount,
92
68
  captureMs: Math.round(captureMs),
93
- convertMs: Math.round(convertMs)
69
+ convertMs: Math.round(convertMs),
70
+ resizeFilter: converted.filter
94
71
  }, converted.output);
95
72
  } catch (error) {
96
73
  writeResponse({
@@ -0,0 +1,72 @@
1
+ function clampInteger(value, min, max, fallback) {
2
+ const number = Number(value);
3
+ if (!Number.isFinite(number)) return fallback;
4
+ return Math.max(min, Math.min(max, Math.round(number)));
5
+ }
6
+
7
+ function writeRgb565(output, target, red, green, blue) {
8
+ const pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
9
+ output[target] = pixel & 0xff;
10
+ output[target + 1] = pixel >> 8;
11
+ }
12
+
13
+ export function convertRgbaToRgb565(raw, sourceWidthValue, sourceHeightValue, maxWidthValue, maxHeightValue) {
14
+ const sourceWidth = clampInteger(sourceWidthValue, 1, 32_768, 1);
15
+ const sourceHeight = clampInteger(sourceHeightValue, 1, 32_768, 1);
16
+ const maxWidth = clampInteger(maxWidthValue, 1, sourceWidth, sourceWidth);
17
+ const maxHeight = clampInteger(maxHeightValue, 1, sourceHeight, sourceHeight);
18
+ if (raw.length < sourceWidth * sourceHeight * 4) {
19
+ throw new Error(`Raw capture is incomplete: ${raw.length} bytes for ${sourceWidth}x${sourceHeight}.`);
20
+ }
21
+
22
+ const scale = Math.min(1, maxWidth / sourceWidth, maxHeight / sourceHeight);
23
+ const width = Math.max(1, Math.round(sourceWidth * scale));
24
+ const height = Math.max(1, Math.round(sourceHeight * scale));
25
+ const output = Buffer.allocUnsafe(width * height * 2);
26
+
27
+ if (width === sourceWidth && height === sourceHeight) {
28
+ for (let source = 0, target = 0; target < output.length; source += 4, target += 2) {
29
+ writeRgb565(output, target, raw[source], raw[source + 1], raw[source + 2]);
30
+ }
31
+ return { output, width, height, filter: 'none' };
32
+ }
33
+
34
+ const xStarts = new Int32Array(width);
35
+ const xEnds = new Int32Array(width);
36
+ for (let x = 0; x < width; x += 1) {
37
+ xStarts[x] = Math.min(sourceWidth - 1, Math.floor(x * sourceWidth / width));
38
+ xEnds[x] = Math.max(xStarts[x] + 1, Math.min(sourceWidth, Math.floor((x + 1) * sourceWidth / width)));
39
+ }
40
+
41
+ let target = 0;
42
+ for (let y = 0; y < height; y += 1) {
43
+ const sourceY0 = Math.min(sourceHeight - 1, Math.floor(y * sourceHeight / height));
44
+ const sourceY1 = Math.max(sourceY0 + 1, Math.min(sourceHeight, Math.floor((y + 1) * sourceHeight / height)));
45
+ for (let x = 0; x < width; x += 1) {
46
+ let red = 0;
47
+ let green = 0;
48
+ let blue = 0;
49
+ let samples = 0;
50
+ for (let sourceY = sourceY0; sourceY < sourceY1; sourceY += 1) {
51
+ let source = (sourceY * sourceWidth + xStarts[x]) * 4;
52
+ for (let sourceX = xStarts[x]; sourceX < xEnds[x]; sourceX += 1) {
53
+ red += raw[source];
54
+ green += raw[source + 1];
55
+ blue += raw[source + 2];
56
+ samples += 1;
57
+ source += 4;
58
+ }
59
+ }
60
+ writeRgb565(
61
+ output,
62
+ target,
63
+ Math.round(red / samples),
64
+ Math.round(green / samples),
65
+ Math.round(blue / samples)
66
+ );
67
+ target += 2;
68
+ }
69
+ }
70
+
71
+ return { output, width, height, filter: 'box' };
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/client",
3
- "version": "0.1.105",
3
+ "version": "0.1.107",
4
4
  "description": "LiveDesk local remote client",
5
5
  "type": "module",
6
6
  "bin": {