Camera exposure logic is in place. Will take a photo with the device camera and use the exif data to determine the correct exposure for the bolex.

- Determines # of stops between fstop of phone and set fstop of bolex
- Determines # of stops between iso of phone and set iso of bolex
- Compensates for the 0.8 prism constant
This commit is contained in:
mmcwilliams 2018-02-03 16:49:37 -05:00
parent 7a392aba0e
commit 4b72c9eeed
1 changed files with 178 additions and 60 deletions

View File

@ -1,3 +1,7 @@
/* jshint esversion:6, strict:true, browser:true*/
/* global console, alert */
'use strict'; 'use strict';
var mobile = {}; var mobile = {};
@ -29,7 +33,7 @@ mobile.ble.scan = function () {
alert('No INTVAL devices found.'); alert('No INTVAL devices found.');
settingsPage(); settingsPage();
} }
}, 5000) }, 5000);
}; };
mobile.ble.onDiscover = function (device) { mobile.ble.onDiscover = function (device) {
@ -43,18 +47,18 @@ mobile.ble.onDiscover = function (device) {
} else { } else {
//console.log(`BLE - Discovered Other ${device.id}`); //console.log(`BLE - Discovered Other ${device.id}`);
} }
} };
mobile.ble.connect = function (device) { mobile.ble.connect = function (device) {
console.log(`BLE - Connecting to ${device.id}`) console.log(`BLE - Connecting to ${device.id}`);
ble.connect(device.id, (peripheral) => { ble.connect(device.id, (peripheral) => {
mobile.ble.onConnect(peripheral, device); mobile.ble.onConnect(peripheral, device);
}, mobile.ble.onError); }, mobile.ble.onError);
}; };
mobile.ble.onConnect = function (peripheral, device) { mobile.ble.onConnect = function (peripheral, device) {
const elem = document.getElementById('bluetooth') const elem = document.getElementById('bluetooth');
const option = document.createElement('option') const option = document.createElement('option');
const disconnect = document.getElementById('disconnect'); const disconnect = document.getElementById('disconnect');
const scan = document.getElementById('scan'); const scan = document.getElementById('scan');
@ -85,11 +89,11 @@ mobile.ble.disconnect = function () {
const scan = document.getElementById('scan'); const scan = document.getElementById('scan');
let device; let device;
if (!mobile.ble.connected) { if (!mobile.ble.connected) {
console.warn('Not connected to any device') console.warn('Not connected to any device');
return false return false;
} }
device = mobile.ble.device device = mobile.ble.device;
console.log(`BLE - Disconnecting from ${device.id}`) console.log(`BLE - Disconnecting from ${device.id}`);
ble.disconnect(device.id, mobile.ble.onDisconnect, mobile.ble.onDisconnect); ble.disconnect(device.id, mobile.ble.onDisconnect, mobile.ble.onDisconnect);
elem.innerHTML = ''; elem.innerHTML = '';
@ -112,6 +116,9 @@ mobile.ble.onError = function (err) {
mobile.init = function () { mobile.init = function () {
const bleInputs = document.querySelectorAll('.ble'); const bleInputs = document.querySelectorAll('.ble');
const bolIso = document.querySelector('.iso');
const bolF = document.querySelector('.fstop');
document.querySelector('body').classList.add('mobile'); document.querySelector('body').classList.add('mobile');
window.frame = mobile.frame; window.frame = mobile.frame;
@ -128,13 +135,13 @@ mobile.init = function () {
} }
spinnerInit(); spinnerInit();
mobile.ble.scan(); mobile.ble.scan();
mobile.cameraValues() mobile.cameraValues();
}; };
mobile.getState = function () { mobile.getState = function () {
if (!mobile.ble.connected) { if (!mobile.ble.connected) {
// //returning here will prevent error alert
} }
ble.read(mobile.ble.device.id, ble.read(mobile.ble.device.id,
mobile.ble.SERVICE_ID, mobile.ble.SERVICE_ID,
@ -145,7 +152,7 @@ mobile.getState = function () {
mobile.stateSuccess = function (data) { mobile.stateSuccess = function (data) {
let str = bytesToString(data); let str = bytesToString(data);
let res = JSON.parse(str); let res = JSON.parse(str);
setState(res) setState(res);
}; };
mobile.frame = function () { mobile.frame = function () {
@ -229,7 +236,7 @@ mobile.exposureSuccess = function () {
mobile.setDelay = function () { mobile.setDelay = function () {
const delay = document.getElementById('delay').value; const delay = document.getElementById('delay').value;
const scaledDelay = scaleTime(delay, STATE.delayScale) const scaledDelay = scaleTime(delay, STATE.delayScale);
let opts = { let opts = {
type : 'delay', type : 'delay',
delay : scaledDelay delay : scaledDelay
@ -243,7 +250,7 @@ mobile.setDelay = function () {
} }
mobile.delaySuccess = function () { mobile.delaySuccess = function () {
console.log('Set delay') console.log('Set delay');
mobile.getState(); mobile.getState();
}; };
@ -417,6 +424,7 @@ mobile.setWifiSuccess = function () {
console.log('Set new wifi credentials'); console.log('Set new wifi credentials');
setTimeout(mobile.getWifi, 100); setTimeout(mobile.getWifi, 100);
}; };
mobile.exif = {}
mobile.getCamera = function () { mobile.getCamera = function () {
const opts = { const opts = {
@ -430,62 +438,171 @@ mobile.cameraSuccess = function (result) {
const thisResult = JSON.parse(result); const thisResult = JSON.parse(result);
const metadata = JSON.parse(thisResult.json_metadata); const metadata = JSON.parse(thisResult.json_metadata);
mobile.cameraExposure(fstop, metadata); mobile.cameraExposure(metadata.Exif);
} };
mobile.cameraError = function (err) { mobile.cameraError = function (err) {
console.error(err); console.error(err);
alert(err); alert(err);
}; };
mobile.cameraExposure = function (exif) { mobile.cameraExposure = function (exif) {
const cam_exp = document.getElementById('cam_exp');
const cam_f = document.getElementById('cam_f');
const cam_iso = document.getElementById('cam_iso');
const bol_exp = document.getElementById('bol_exp');
const bol_f = document.getElementById('bol_f');
const bol_iso = document.getElementById('bol_iso');
const bol_f_diff = document.getElementById('bol_f_diff');
const bol_iso_diff = document.getElementById('bol_iso_diff');
const bol_exp_diff = document.getElementById('bol_exp_diff');
const fstop = BOLEX.fstop || 5.6; const fstop = BOLEX.fstop || 5.6;
const iso = BOLEX.iso || 100; const iso = BOLEX.iso || 100;
const prism = BOLEX.prism || 0.8;
const cFstop = exif.AperatureValue || exif.FNumber; const cFstop = exif.ApertureValue || exif.FNumber;
const cExposure = exif.ShutterSpeedValue ? (1 / exif.ShutterSpeedValue) * 1000 : exif.ExposureTime * 1000; const cExposure = exif.ExposureTime * 1000;
const cISO = exif.ISOSpeedRatings[0]; const cIso = exif.ISOSpeedRatings[0];
//convert fstop to "fnumber", an absolute scale where stops are scaled to 1.0
const f = mobile.fnumber(cFstop);
const target = mobile.fnumber(fstop); //bolex
let exposure = cExposure;
let isoStops = 0;
let fStops = 0;
let scale_elem;
let exposure_elem;
let proceed;
let e1;
let e2;
mobile.exif = exif;
console.dir(exif);
console.log(`fstop : ${fstop}`);
console.log(`iso : ${iso}`);
bol_f.value = fstop;
bol_iso.value = iso;
console.log(`cExposure : ${cExposure}`);
console.log(`cFstop : ${cFstop}`);
console.log(`cIso : ${cIso}`);
cam_exp.value = cExposure;
cam_f.value = cFstop;
cam_iso.value = cIso;
console.log(`f : ${f}`);
console.log(`target : ${target}`);
//Determine if fstop of phone camera "f"
if (target !== f) {
fStops = f - target;
exposure = exposure / Math.pow(2, fStops);
}
bol_f_diff.innerHTML = Math.round(parseFloat(-fStops) * 10) / 10;
console.log(`fstops : ${fStops}`);
console.log(`exposure => ${exposure}`);
if (cIso != iso) {
isoStops = (Math.log(cIso) / Math.log(2)) - (Math.log(iso) / Math.log(2));
}
bol_iso_diff.innerHTML = Math.round(parseFloat(isoStops) * 10) / 10;
console.log(`isoStops : ${isoStops}`)
//Double or halve exposure based on the differences in ISO stops
exposure = exposure * Math.pow(2, isoStops);
console.log(`exposure => ${exposure}`);
console.log(`prism : ${prism}`);
//Compensate for Bolex prism
exposure = exposure * Math.pow(2, prism);
console.log(`exposure => ${prism}`);
exposure = Math.round(exposure) //round to nearest millisecond
bol_exp.value = exposure;
bol_exp_diff.value = 0;
if (exposure > 500) {
proceed = confirm(`Set camera exposure to ${exposure}ms to match photo.`);
}
if (proceed && exposure > 500) {
e1 = new Event('change');
e2 = new Event('change');
scale_elem = document.getElementById('scale');
exposure_elem = document.getElementById('exposure');
scale_elem.value = 'ms';
scale_elem.dispatchEvent(e1);
exposure_elem.value = exposure;
exposure_elem.dispatchEvent(e2);
}
alert(`${fstop} ${iso} ${cFstop} ${cISO} ${cExposure}`);
/* /*
ApertureValue: 1.6959938131099002 {
BrightnessValue: -0.3966568568788107 "Exif": {
ColorSpace: 65535 "DateTimeOriginal": "2018:02:02 16:59:13",
DateTimeDigitized: "2018:01:08 23:06:13" "ExposureBiasValue": 0,
DateTimeOriginal: "2018:01:08 23:06:13" "SensingMethod": 2,
ExposureBiasValue: 0 "BrightnessValue": -0.9969016228800144,
ExposureMode: 0 "LensMake": "Apple",
ExposureProgram: 2 "FNumber": 1.8,
ExposureTime: 0.2 "FocalLength": 3.99,
FNumber: 1.8 "ShutterSpeedValue": 2.049355412374274,
Flash: 24 "SceneType": 1,
FocalLenIn35mmFilm: 28 "ApertureValue": 1.6959938131099002,
FocalLength: 3.99 "SubjectArea": [
ISOSpeedRatings: [100] (1) 2015,
LensMake: "Apple" 1511,
LensModel: "iPhone 8 back camera 3.99mm f/1.8" 2217,
LensSpecification: [3.99, 3.99, 1.8, 1.8] (4) 1330
MeteringMode: 5 ],
PixelXDimension: 4032 "ColorSpace": 65535,
PixelYDimension: 3024 "LensSpecification": [
SceneType: 1 3.99,
SensingMethod: 2 3.99,
ShutterSpeedValue: 2.38401125849867 1.8,
SubjectArea: [2015, 1511, 2217, 1330] (4) 1.8
SubsecTimeDigitized: "567" ],
SubsecTimeOriginal: "567" "PixelYDimension": 3024,
WhiteBalance: 0 "WhiteBalance": 0,
"DateTimeDigitized": "2018:02:02 16:59:13",
"ExposureMode": 0,
"ISOSpeedRatings": [
100
],
"PixelXDimension": 4032,
"LensModel": "iPhone 8 back camera 3.99mm f/1.8",
"ExposureTime": 0.25,
"Flash": 24,
"SubsecTimeDigitized": "209",
"SubsecTimeOriginal": "209",
"ExposureProgram": 2,
"FocalLenIn35mmFilm": 28,
"MeteringMode": 5
}
}
*/ */
}; };
mobile.cameraValues = function () {
document.querySelectorAll('.iso').forEach(input => { mobile.refreshExposure = function () {
input.onchange = function () { if (typeof mobile.exif.ExposureTime !== 'undefined') {
var val = this.value; mobile.cameraExposure(mobile.exif);
document.querySelectorAll('.iso').forEach(e => {
e.value = val;
})
} }
}) };
}
mobile.fnumber = function (fstop) {
return Math.log(fstop) / Math.log(Math.sqrt(2));
};
mobile.EV = function (fstop, shutter) {
const sec = shutter / 1000; //shutter in ms => seconds
const square = Math.pow(fstop, 2);
return Math.log(square / sec);
};
/** /**
* Mobile helper functions * Mobile helper functions
@ -493,11 +610,12 @@ mobile.cameraValues = function () {
function bytesToString (buffer) { function bytesToString (buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer)); return String.fromCharCode.apply(null, new Uint8Array(buffer));
}; }
function stringToBytes(string) { function stringToBytes(string) {
var array = new Uint8Array(string.length); var array = new Uint8Array(string.length);
for (var i = 0, l = string.length; i < l; i++) { for (var i = 0, l = string.length; i < l; i++) {
array[i] = string.charCodeAt(i); array[i] = string.charCodeAt(i);
} }
return array.buffer; return array.buffer;
}; }