Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added some missing options #44

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ stats.json
# dev environments
.vscode/*
**/.DS_Store
test_images/*.jpeg
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
src/
test_images/
yarn.lock

tsconfig.json
Expand Down
106 changes: 105 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ Note that this example produces a raw H264 video. Wrapping it in a video contain
- [`SensorMode`](#sensormode)
- [`ExposureMode`](#exposuremode)
- [`AwbMode`](#awbmode)
- [`DynamicRange`](#dynamicRange)
- [`ImageEffect`](#imageEffect)

## `StillCamera`

Expand Down Expand Up @@ -261,8 +263,21 @@ const stillCamera = new StillCamera({
- `exposureCompensation: number` - _Range: `-10`-`10`; Default: `0`_
- [`exposureMode: ExposureMode`](#exposuremode) - _Default: `ExposureMode.Auto`_
- [`awbMode: AwbMode`](#awbmode) - _Default: `AwbMode.Auto`_
- `awbGains: [number, number]` - _Default: `null`_
- `analogGain: number` - _Default: `0`_
- `digitalGain: number` - _Default: `0`_
- `quality: number` - _Default: `100`_
- `colorEffect: [number, number]` - _Default: `[0,0]`_
- [`imageEffect: ImageEffectMode`](#imageeffect) - _Default: `ImageEffectMode.None`_
- [`dynamicRange: DynamicRange`](#dynamicrange) - _Default: `DynamicRange.Off`_
- `videoStabilization: boolean` - _Default: `false`_
- `raw: boolean` - _Default: `false`_
- [`meteringMode`](#meteringMode) - _Default: `MeteringMode.Off`_
- `thumbnail: [number, number, number] | 'none'` - _Default: `[64, 48, 35]`_
- [`flickerMode`](#flickerMode) - _Default: `null`_
- `burst: boolean` - _Default: `false`_
- `roi: [number, number, number, number]` - _Default: `null`_
- `statistics: boolean` - _Default: `false`_

### `StillCamera.takeImage(): Promise<Buffer>`

Expand Down Expand Up @@ -307,8 +322,17 @@ const streamCamera = new StreamCamera({
- `exposureCompensation: number` - _Range: `-10`-`10`; Default: `0`_
- [`exposureMode: ExposureMode`](#exposuremode) - _Default: `ExposureMode.Auto`_
- [`awbMode: AwbMode`](#awbmode) - _Default: `AwbMode.Auto`_
- `awbGains: [number, number]` - _Default: `null`_
- `analogGain: number` - _Default: `0`_
- `digitalGain: number` - _Default: `0`_
- `colorEffect: [number, number]` - _Default: `[0,0]`_
- [`imageEffect: ImageEffectMode`](#imageeffect) - _Default: `ImageEffectMode.None`_
- [`dynamicRange: DynamicRange`](#dynamicrange) - _Default: `DynamicRange.Off`_
- `videoStabilization: boolean` - _Default: `false`_
- [`meteringMode`](#meteringMode) - _Default: `MeteringMode.Off`_
- [`flickerMode`](#flickerMode) - _Default: `FlickerMode.Off`_
- `roi: [number, number, number, number]` - _Default: Full sensor_
- `statistics: boolean` - _Default: `false`_

### `startCapture(): Promise<void>`

Expand Down Expand Up @@ -446,7 +470,19 @@ These are slightly different depending on the version of Raspberry Pi camera you
| 4 | 1640x1232 | 4:3 | 0.1-40fps | Full | 2x2 |
| 5 | 1640x922 | 16:9 | 0.1-40fps | Full | 2x2 |
| 6 | 1280x720 | 16:9 | 40-90fps | Partial | 2x2 |
| 7 | 640x480 | 4:3 | 40-90fps | Partial | 2x2 |
| 7 | 640x480 | 4:3 | 40-200fps* | Partial | 2x2 |

*For frame rates over 120fps, it is necessary to turn off automatic exposure and gain control using -ex off. Doing so should achieve the higher frame rates, but exposure time and gains will need to be set to fixed values supplied by the user.

#### HQ Camera (IMX477):

| Mode | Size | Aspect Ratio | Frame rates | FOV | Binning |
|------|---------------------|--------------|-------------|---------|-------------|
| 0 | automatic selection | | | | |
| 1 | 2028x1080 | 169:90 | 0.1-50fps | Partial | 2x2 binned |
| 2 | 2028x1520 | 4:3 | 0.1-50fps | Full | 2x2 binned |
| 3 | 4056x3040 | 4:3 | 0.005-10fps | Full | None |
| 4 | 1332x990 | 74:55 | 50.1-120fps | Partial | 2x2 binned |

## `ExposureMode`

Expand Down Expand Up @@ -489,3 +525,71 @@ White balance mode options.
```javascript
import { AwbMode } from 'pi-camera-connect';
```

## `ImageEffect`

Image Effect options.

- `ImageEffectMode.None`
- `ImageEffectMode.Negative`
- `ImageEffectMode.Solarise`
- `ImageEffectMode.Sketch`
- `ImageEffectMode.Denoise`
- `ImageEffectMode.Emboss`
- `ImageEffectMode.OilPaint`
- `ImageEffectMode.Hatch`
- `ImageEffectMode.GPen`
- `ImageEffectMode.Pastel`
- `ImageEffectMode.Watercolour`
- `ImageEffectMode.Film`
- `ImageEffectMode.Blur`
- `ImageEffectMode.Saturation`
- `ImageEffectMode.ColourSwap`
- `ImageEffectMode.WashedOut`
- `ImageEffectMode.Posterise`
- `ImageEffectMode.ColourPoint`
- `ImageEffectMode.ColourBalance`
- `ImageEffectMode.Cartoon`

```javascript
import { ImageEffectMode } from 'pi-camera-connect';
```

## `DynamicRange`

Dynamic Range options.

- `DynamicRange.Off`
- `DynamicRange.Low`
- `DynamicRange.Medium`
- `DynamicRange.High`

```javascript
import { DynamicRange } from 'pi-camera-connect';
```

## `MeteringMode`

Dynamic Range options.

- `MeteringMode.Average`
- `MeteringMode.Spot`
- `MeteringMode.Backlit`
- `MeteringMode.Matrix`

```javascript
import { MeteringMode } from 'pi-camera-connect';
```

## `FlickerMode`

Dynamic Range options.

- `FlickerMode.Off`
- `FlickerMode.Auto`
- `FlickerMode.Frq50hz`
- `FlickerMode.Frq60hz`

```javascript
import { FlickerMode } from 'pi-camera-connect';
```
44 changes: 44 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,47 @@ export enum AwbMode {
Horizon = 'horizon',
GreyWorld = 'greyworld',
}

export enum ImageEffectMode {
None = 'none',
Negative = 'negative',
Solarise = 'solarise',
Sketch = 'sketch',
Denoise = 'denoise',
Emboss = 'emboss',
OilPaint = 'oilpaint',
Hatch = 'hatch',
GPen = 'gpen',
Pastel = 'pastel',
Watercolour = 'watercolour',
Film = 'film',
Blur = 'blur',
Saturation = 'saturation',
ColourSwap = 'colourswap',
WashedOut = 'washedout',
Posterise = 'posterise',
ColourPoint = 'colourpoint',
ColourBalance = 'colourbalance',
Cartoon = 'cartoon',
}

export enum DynamicRange {
Off = 'off',
Low = 'low',
Medium = 'medium',
High = 'high',
}

export enum MeteringMode {
Average = 'average',
Spot = 'spot',
Backlit = 'backlit',
Matrix = 'matrix',
}

export enum FlickerMode {
Off = 'off',
Auto = 'auto',
'Frq50hz' = '50hz',
'Frq60Hz' = '60hz',
}
75 changes: 73 additions & 2 deletions src/lib/shared-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ export function getSharedArgs(options: StillOptions | StreamOptions): string[] {
...(options.saturation ? ['--saturation', options.saturation.toString()] : []),

/**
* ISO
* ISO (100 to 800)
*/
...(options.iso ? ['--ISO', options.iso.toString()] : []),

/**
* EV Compensation
* EV Compensation (-10 to 10; default 0)
*/
...(options.exposureCompensation ? ['--ev', options.exposureCompensation.toString()] : []),

Expand All @@ -85,14 +85,85 @@ export function getSharedArgs(options: StillOptions | StreamOptions): string[] {
*/
...(options.awbMode ? ['--awb', options.awbMode.toString()] : []),

/**
* Sets the blue and red channel gains if awbMode is Off
*/
...(options.awbGains ? ['--awbgains', options.awbGains.toString()] : []),

/**
* Analog Gain
* Sets the analog gain value directly on the sensor (floating point value from
* 1.0 to 8.0 for the OV5647 sensor on Camera Module V1, and 1.0 to 12.0 for the
* IMX219 sensor on Camera Module V2 and the IMX447 on the HQ Camera).
*/
...(options.analogGain ? ['--analoggain', options.analogGain.toString()] : []),

/**
* Digital Gain
* Sets the digital gain value applied by the ISP
* (floating point value from 1.0 to 64.0,
* but values over about 4.0 willproduce overexposed images)
*/
...(options.digitalGain ? ['--digitalgain', options.digitalGain.toString()] : []),

/**
* Image Effect
*/
...(options.imageEffect ? ['--imxfx', options.imageEffect.toString()] : []),

/**
* Dynamic Range Control
*/
...(options.dynamicRange ? ['--drc', options.dynamicRange] : []),

/**
* Color Effects
* The supplied U and V parameters (range 0 to 255) are applied to
* the U and Y channels of the image. For example, --colfx 128:128
* should result in a monochrome image.
*/
...(options.colorEffect ? ['--colfx', options.colorEffect.join(':')] : []),

/**
* Metering
* Specify the metering mode used for the preview and capture.
*/
...(options.meteringMode ? ['--metering', options.meteringMode] : []),

/**
* Flicker Avoid Mode
* Set a mode to compensate for lights flickering at the mains frequency,
* which can be seen as a dark horizontal band across an image.
* Flicker avoidance locks the exposure time to a multiple of the mains
* flicker frequency (8.33ms for 60Hz, or 10ms for 50Hz).
* This means that images can be noisier as the control algorithm has to
* increase the gain instead of exposure time should it wish for an
* intermediate exposure value. auto can be confused by external factors,
* therefore it is preferable to leave this setting off unless actually required.
*/
...(options.flickerMode ? ['--flicker', options.flickerMode] : []),

/**
* Video Stabilisation
gregnr marked this conversation as resolved.
Show resolved Hide resolved
* In video mode only, turn on video stabilization.
*/
...(options.videoStabilization ? ['--vstab'] : []),

/**
* Statistics
* Force recomputation of statistics on stills capture pass. Digital gain and AWB are
* recomputed based on the actual capture frame statistics,
* rather than the preceding preview frame.
*/
...(options.statistics ? ['--stats'] : []),

/**
* Sensor region of interest
* Allows the specification of the area of the sensor to be used as
* the source for the preview and capture. This is defined as x,y for
* the top left corner, and a width and height, all values in
* normalised coordinates (0.0-1.0).
*/
...(options.roi ? ['--roi', options.roi.toString()] : []),
];
}
15 changes: 15 additions & 0 deletions src/lib/still-camera.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import * as fs from 'fs';
import { performance } from 'perf_hooks';

import StillCamera from './still-camera';

const TEST_IMAGES_DIR = 'test_images';

if (!fs.existsSync(TEST_IMAGES_DIR)) {
fs.mkdirSync(TEST_IMAGES_DIR);
}

test('takeImage() returns JPEG', async () => {
const t0 = performance.now();

const stillCamera = new StillCamera();

const jpegImage = await stillCamera.takeImage();
const t1 = performance.now();

const time = ((t1 - t0) / 1000).toFixed(2);
await fs.promises.writeFile(`test_images/stillCapture_(${time}-secs).jpeg`, jpegImage, 'binary');

expect(jpegImage.indexOf(StillCamera.jpegSignature)).toBe(0);
});
Loading