react-native-vision-camera
Version:
A powerful, high-performance React Native Camera library.
160 lines (147 loc) • 7.67 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCameraFormat = getCameraFormat;
var _CameraError = require("../CameraError");
function filtersToFilterMap(filters) {
return filters.reduce((map, curr, index) => {
for (const key in curr) {
// @ts-expect-error keys are untyped
map[key] = {
// @ts-expect-error keys are untyped
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
target: curr[key],
priority: filters.length - index
};
}
return map;
}, {});
}
/**
* Get the best matching Camera format for the given device that satisfies your requirements using a sorting filter. By default, formats are sorted by highest to lowest resolution.
*
* The {@linkcode filters | filters} are ranked by priority, from highest to lowest.
* This means the first item you pass will have a higher priority than the second, and so on.
*
* @param device The Camera Device you're currently using
* @param filters The filters you want to use. The format that matches your filter the closest will be returned
* @returns The format that matches your filter the closest.
*
* @example
* ```ts
* const format = getCameraFormat(device, [
* { videoResolution: { width: 3048, height: 2160 } },
* { fps: 60 }
* ])
* ```
*/
function getCameraFormat(device, filters) {
// Combine filters into a single filter map for constant-time lookup
const filter = filtersToFilterMap(filters);
let bestFormat = device.formats[0];
if (bestFormat == null) throw new _CameraError.CameraRuntimeError('device/invalid-device', `The given Camera Device (${device.id}) does not have any formats!`);
// Compare each format using a point scoring system
for (const format of device.formats) {
let leftPoints = 0;
let rightPoints = 0;
// Video Resolution
if (filter.videoResolution != null) {
const leftVideoResolution = bestFormat.videoWidth * bestFormat.videoHeight;
const rightVideoResolution = format.videoWidth * format.videoHeight;
if (filter.videoResolution.target === 'max') {
// We just want the maximum resolution
if (leftVideoResolution > rightVideoResolution) leftPoints += filter.videoResolution.priority;
if (rightVideoResolution > leftVideoResolution) rightPoints += filter.videoResolution.priority;
} else {
// Find video resolution closest to the filter (ignoring orientation)
const targetResolution = filter.videoResolution.target.width * filter.videoResolution.target.height;
const leftDiff = Math.abs(leftVideoResolution - targetResolution);
const rightDiff = Math.abs(rightVideoResolution - targetResolution);
if (leftDiff < rightDiff) leftPoints += filter.videoResolution.priority;
if (rightDiff < leftDiff) rightPoints += filter.videoResolution.priority;
}
}
// Photo Resolution
if (filter.photoResolution != null) {
const leftPhotoResolution = bestFormat.photoWidth * bestFormat.photoHeight;
const rightPhotoResolution = format.photoWidth * format.photoHeight;
if (filter.photoResolution.target === 'max') {
// We just want the maximum resolution
if (leftPhotoResolution > rightPhotoResolution) leftPoints += filter.photoResolution.priority;
if (rightPhotoResolution > leftPhotoResolution) rightPoints += filter.photoResolution.priority;
} else {
// Find closest photo resolution to the filter (ignoring orientation)
const targetResolution = filter.photoResolution.target.width * filter.photoResolution.target.height;
const leftDiff = Math.abs(leftPhotoResolution - targetResolution);
const rightDiff = Math.abs(rightPhotoResolution - targetResolution);
if (leftDiff < rightDiff) leftPoints += filter.photoResolution.priority;
if (rightDiff < leftDiff) rightPoints += filter.photoResolution.priority;
}
}
// Find closest aspect ratio (video)
if (filter.videoAspectRatio != null) {
const leftAspect = bestFormat.videoWidth / bestFormat.videoHeight;
const rightAspect = format.videoWidth / format.videoHeight;
const leftDiff = Math.abs(leftAspect - filter.videoAspectRatio.target);
const rightDiff = Math.abs(rightAspect - filter.videoAspectRatio.target);
if (leftDiff < rightDiff) leftPoints += filter.videoAspectRatio.priority;
if (rightDiff < leftDiff) rightPoints += filter.videoAspectRatio.priority;
}
// Find closest aspect ratio (photo)
if (filter.photoAspectRatio != null) {
const leftAspect = bestFormat.photoWidth / bestFormat.photoHeight;
const rightAspect = format.photoWidth / format.photoHeight;
const leftDiff = Math.abs(leftAspect - filter.photoAspectRatio.target);
const rightDiff = Math.abs(rightAspect - filter.photoAspectRatio.target);
if (leftDiff < rightDiff) leftPoints += filter.photoAspectRatio.priority;
if (rightDiff < leftDiff) rightPoints += filter.photoAspectRatio.priority;
}
// Find closest max FPS
if (filter.fps != null) {
if (filter.fps.target === 'max') {
if (bestFormat.maxFps > format.maxFps) leftPoints += filter.fps.priority;
if (format.maxFps > bestFormat.maxFps) rightPoints += filter.fps.priority;
} else {
if (bestFormat.maxFps >= filter.fps.target) leftPoints += filter.fps.priority;
if (format.maxFps >= filter.fps.target) rightPoints += filter.fps.priority;
}
}
// Find closest ISO
if (filter.iso != null) {
if (filter.iso.target === 'max') {
if (bestFormat.maxISO > format.maxISO) leftPoints += filter.iso.priority;
if (format.maxISO > bestFormat.maxISO) rightPoints += filter.iso.priority;
} else if (filter.iso.target === 'min') {
if (bestFormat.minISO < format.minISO) leftPoints += filter.iso.priority;
if (format.minISO < bestFormat.minISO) rightPoints += filter.iso.priority;
} else {
if (filter.iso.target >= bestFormat.minISO && filter.iso.target <= bestFormat.maxISO) leftPoints += filter.iso.priority;
if (filter.iso.target >= format.minISO && filter.iso.target <= format.maxISO) rightPoints += filter.iso.priority;
}
}
// Find video stabilization mode
if (filter.videoStabilizationMode != null) {
if (bestFormat.videoStabilizationModes.includes(filter.videoStabilizationMode.target)) leftPoints += filter.videoStabilizationMode.priority;
if (format.videoStabilizationModes.includes(filter.videoStabilizationMode.target)) rightPoints += filter.videoStabilizationMode.priority;
}
// Find Photo HDR formats
if (filter.photoHdr != null) {
if (bestFormat.supportsPhotoHdr === filter.photoHdr.target) leftPoints += filter.photoHdr.priority;
if (format.supportsPhotoHdr === filter.photoHdr.target) rightPoints += filter.photoHdr.priority;
}
// Find Video HDR formats
if (filter.videoHdr != null) {
if (bestFormat.supportsVideoHdr === filter.videoHdr.target) leftPoints += filter.videoHdr.priority;
if (format.supportsVideoHdr === filter.videoHdr.target) rightPoints += filter.videoHdr.priority;
}
// Find matching AF system
if (filter.autoFocusSystem != null) {
if (bestFormat.autoFocusSystem === filter.autoFocusSystem.target) leftPoints += filter.autoFocusSystem.priority;
if (format.autoFocusSystem === filter.autoFocusSystem.target) rightPoints += filter.autoFocusSystem.priority;
}
if (rightPoints > leftPoints) bestFormat = format;
}
return bestFormat;
}
//# sourceMappingURL=getCameraFormat.js.map
;