m3_lightmeter/lib/screens/metering/metering_bloc.dart

94 lines
2.8 KiB
Dart
Raw Normal View History

2022-10-29 18:02:45 +00:00
import 'dart:math';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/models/exposure_pair.dart';
import 'package:lightmeter/models/photography_value.dart';
import 'metering_event.dart';
import 'metering_state.dart';
class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
2022-10-30 18:06:51 +00:00
final StopType stopType;
2022-10-29 18:02:45 +00:00
late final _apertureValues = apertureValues.whereStopType(stopType);
late final _shutterSpeedValues = shutterSpeedValues.whereStopType(stopType);
late final _isoValues = isoValues.whereStopType(stopType);
final _random = Random();
MeteringBloc(this.stopType)
: super(
const MeteringState(
iso: 100,
ev: 21.3,
evCompensation: 0.0,
nd: 0.0,
exposurePairs: [],
),
) {
on<MeasureEvent>(_onMeasure);
add(const MeasureEvent());
}
2022-10-29 18:14:49 +00:00
/// https://www.scantips.com/lights/exposurecalc.html
2022-10-29 18:02:45 +00:00
void _onMeasure(_, Emitter emit) {
double log2(double x) => log(x) / log(2);
final aperture = _apertureValues[_random.nextInt(_apertureValues.length)];
final shutterSpeed = _shutterSpeedValues[_random.nextInt(_shutterSpeedValues.thirdStops().length)];
final iso = _isoValues[_random.nextInt(_isoValues.thirdStops().length)];
final evAtSystemIso = log2(pow(aperture.value, 2).toDouble()) - log2(shutterSpeed.value);
final ev = evAtSystemIso - log2(iso.value / state.iso);
final exposurePairs = _buildExposureValues(ev);
emit(MeteringState(
iso: state.iso,
ev: ev,
evCompensation: state.evCompensation,
nd: state.nd,
exposurePairs: exposurePairs,
));
}
List<ExposurePair> _buildExposureValues(double ev) {
late final int evSteps;
switch (stopType) {
2022-10-30 18:06:51 +00:00
case StopType.full:
2022-10-29 18:02:45 +00:00
evSteps = ev.floor();
break;
2022-10-30 18:06:51 +00:00
case StopType.half:
2022-10-29 18:02:45 +00:00
evSteps = (ev / 0.5).floor();
break;
2022-10-30 18:06:51 +00:00
case StopType.third:
2022-10-29 18:02:45 +00:00
evSteps = (ev / 0.3).floor();
break;
}
2022-10-30 18:06:51 +00:00
final evOffset = _shutterSpeedValues.indexOf(const ShutterSpeedValue(1, false, StopType.full)) - evSteps;
2022-10-29 18:02:45 +00:00
late final int apertureOffset;
late final int shutterSpeedOffset;
if (evOffset >= 0) {
apertureOffset = 0;
shutterSpeedOffset = evOffset;
} else {
apertureOffset = -evOffset;
shutterSpeedOffset = 0;
}
int itemsCount = min(_apertureValues.length + shutterSpeedOffset, _shutterSpeedValues.length + apertureOffset) -
max(apertureOffset, shutterSpeedOffset);
2022-10-29 18:04:06 +00:00
if (itemsCount < 0) {
return List.empty(growable: false);
}
2022-10-29 18:02:45 +00:00
return List.generate(
itemsCount,
(index) => ExposurePair(
_apertureValues[index + apertureOffset],
_shutterSpeedValues[index + shutterSpeedOffset],
),
growable: false,
);
}
}