OPC(Olympus Air)用撮影アプリ。
Révision | e37d74205e8f3378fb31fe667a2a2e1b2d8e8f72 (tree) |
---|---|
l'heure | 2017-07-20 00:08:52 |
Auteur | MRSa <mrsa@myad...> |
Commiter | MRSa |
インターバル&ブラケッティング撮影のエンジンを組み込む。
@@ -37,7 +37,7 @@ | ||
37 | 37 | <ConfirmationsSetting value="0" id="Add" /> |
38 | 38 | <ConfirmationsSetting value="0" id="Remove" /> |
39 | 39 | </component> |
40 | - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | |
40 | + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | |
41 | 41 | <output url="file://$PROJECT_DIR$/build/classes" /> |
42 | 42 | </component> |
43 | 43 | <component name="ProjectType"> |
@@ -32,6 +32,9 @@ public interface IOlyCameraCoordinator | ||
32 | 32 | /** ムービー撮影機能の実行(開始・終了) **/ |
33 | 33 | void movieControl(); |
34 | 34 | |
35 | + /** インターバル&ブラケッティング撮影の実行 **/ | |
36 | + void bracketingShot(int bracketingStyle, int bracketingCount, int durationSeconds); | |
37 | + | |
35 | 38 | /** 撮影確認画像の設定 **/ |
36 | 39 | void setRecViewMode(boolean isRecViewMode); |
37 | 40 |
@@ -25,6 +25,7 @@ import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraPropertyProvider | ||
25 | 25 | import jp.sfjp.gokigen.a01c.olycamerawrapper.property.LoadSaveCameraProperties; |
26 | 26 | import jp.sfjp.gokigen.a01c.olycamerawrapper.property.OlyCameraPropertyProxy; |
27 | 27 | import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.AutoFocusControl; |
28 | +import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.BracketingShotControl; | |
28 | 29 | import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.MovieRecordingControl; |
29 | 30 | import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.SingleShotControl; |
30 | 31 | import jp.sfjp.gokigen.a01c.preference.ICameraPropertyAccessor; |
@@ -52,6 +53,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo | ||
52 | 53 | private final AutoFocusControl autoFocus; |
53 | 54 | private final SingleShotControl singleShot; |
54 | 55 | private final MovieRecordingControl movieControl; |
56 | + private final BracketingShotControl bracketingShot; | |
55 | 57 | private final OlyCameraPropertyProxy propertyProxy; |
56 | 58 | private final LoadSaveCameraProperties loadSaveCameraProperties; |
57 | 59 | private final OlyCameraConnection cameraConnection; |
@@ -60,7 +62,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo | ||
60 | 62 | |
61 | 63 | private boolean isManualFocus = false; |
62 | 64 | private boolean isAutoFocusLocked = false; |
63 | - private boolean isExposureLocked = false; | |
65 | + //private boolean isExposureLocked = false; | |
64 | 66 | |
65 | 67 | /** |
66 | 68 | * コンストラクタ |
@@ -81,6 +83,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo | ||
81 | 83 | autoFocus = new AutoFocusControl(camera, focusFrameDisplay, this); // AF制御 |
82 | 84 | singleShot = new SingleShotControl(camera, focusFrameDisplay, this, showInformation); // 1枚撮影 |
83 | 85 | movieControl = new MovieRecordingControl(context, camera, showInformation); // ムービー撮影 |
86 | + bracketingShot = new BracketingShotControl(camera, focusFrameDisplay, this, showInformation); // ブラケッティング&インターバル撮影 | |
84 | 87 | propertyProxy = new OlyCameraPropertyProxy(camera); // カメラプロパティ |
85 | 88 | cameraStatusDisplay = new CameraStatusDisplay(propertyProxy, showInformation); // 画面表示 |
86 | 89 | this.levelMeter = new LevelMeterHolder(showInformation, android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(context).getBoolean(ICameraPropertyAccessor.SHOW_LEVEL_GAUGE_STATUS, false)); // デジタル水準器 |
@@ -216,6 +219,20 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo | ||
216 | 219 | } |
217 | 220 | |
218 | 221 | /** |
222 | + * インターバル&ブラケッティング撮影の実行 | |
223 | + * | |
224 | + * @param bracketingStyle : ブラケッティングスタイル | |
225 | + * @param bracketingCount : 撮影枚数 | |
226 | + * @param durationSeconds : 撮影間隔(単位:秒) | |
227 | + * | |
228 | + */ | |
229 | + @Override | |
230 | + public void bracketingShot(int bracketingStyle, int bracketingCount, int durationSeconds) | |
231 | + { | |
232 | + bracketingShot.startShootBracketing(bracketingStyle, bracketingCount, durationSeconds); | |
233 | + } | |
234 | + | |
235 | + /** | |
219 | 236 | * 撮影確認画像を生成するか設定する |
220 | 237 | * |
221 | 238 | */ |
@@ -331,8 +348,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo | ||
331 | 348 | @Override |
332 | 349 | public boolean isAELock() |
333 | 350 | { |
334 | - isExposureLocked = propertyProxy.isExposureLocked(); | |
335 | - return (isExposureLocked); | |
351 | + return (propertyProxy.isExposureLocked()); | |
336 | 352 | } |
337 | 353 | |
338 | 354 | @Override |
@@ -0,0 +1,434 @@ | ||
1 | +package jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture; | |
2 | + | |
3 | +import android.graphics.Color; | |
4 | +import android.graphics.PointF; | |
5 | +import android.util.Log; | |
6 | + | |
7 | +import java.util.HashMap; | |
8 | +import java.util.List; | |
9 | +import java.util.concurrent.ExecutorService; | |
10 | +import java.util.concurrent.Executors; | |
11 | + | |
12 | +import jp.co.olympus.camerakit.OLYCamera; | |
13 | +import jp.co.olympus.camerakit.OLYCameraAutoFocusResult; | |
14 | +import jp.sfjp.gokigen.a01c.IShowInformation; | |
15 | +import jp.sfjp.gokigen.a01c.liveview.IAutoFocusFrameDisplay; | |
16 | +import jp.sfjp.gokigen.a01c.olycamerawrapper.IIndicatorControl; | |
17 | +import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraProperty; | |
18 | + | |
19 | +/** | |
20 | + * インターバル撮影&ブラケッティング撮影 実行クラス | |
21 | + * | |
22 | + * | |
23 | + * Created by MRSa on 2017/07/19. | |
24 | + */ | |
25 | +public class BracketingShotControl implements OLYCamera.TakePictureCallback | |
26 | +{ | |
27 | + private final String TAG = toString(); | |
28 | + | |
29 | + private static final int BRACKETING_INTERVAL_MILLISECOND = 300; // 撮影待ち時間(ms) | |
30 | + private static final int BRACKETING_PROPERTY_VALUE_SET_RETRY = 10; | |
31 | + | |
32 | + private static final int BRACKET_NONE = 0; // 通常のショット | |
33 | + private static final int BRACKET_EXPREV = 1; // 露出補正 | |
34 | + private static final int BRACKET_APERTURE = 2; // 絞り | |
35 | + private static final int BRACKET_ISO = 3; // ISO | |
36 | + private static final int BRACKET_SHUTTER = 4; // シャッター | |
37 | + private static final int BRACKET_WB = 5; // ホワイトバランス | |
38 | + private static final int BRACKET_COLOR_TONE = 6; // カラートーン | |
39 | + | |
40 | + private final OLYCamera camera; | |
41 | + private final IAutoFocusFrameDisplay autoFocusFrame; | |
42 | + private final IShowInformation statusDrawer; | |
43 | + private final IIndicatorControl indicator; | |
44 | + private boolean isShootingWait = false; | |
45 | + private boolean isBracketingAction = false; | |
46 | + private int retryUpdateBracketingStatus = 0; | |
47 | + private int waitSeconds = 0; // 撮影待ち時間 | |
48 | + | |
49 | + private int bracketCount = 0; | |
50 | + private String targetPropertyName = null; | |
51 | + private String originalProperty = null; | |
52 | + private int originalPropertyIndex = -1; | |
53 | + private List<String> propertyValueList = null; | |
54 | + | |
55 | + /** | |
56 | + * コンストラクタ | |
57 | + * | |
58 | + */ | |
59 | + public BracketingShotControl(OLYCamera camera, IAutoFocusFrameDisplay focusFrameDrawer, IIndicatorControl indicator, IShowInformation statusDrawer) | |
60 | + { | |
61 | + this.camera = camera; | |
62 | + this.autoFocusFrame = focusFrameDrawer; | |
63 | + this.indicator = indicator; | |
64 | + this.statusDrawer = statusDrawer; | |
65 | + } | |
66 | + | |
67 | + /** | |
68 | + * ブラケッティング対象のプロパティの現在設定値と、その選択肢を記憶する | |
69 | + * | |
70 | + * @param name ブラケッティング対象の名前 | |
71 | + * @return ブラケッティングの現在設定値 | |
72 | + */ | |
73 | + private int prepareBracketProperty(String name) | |
74 | + { | |
75 | + try | |
76 | + { | |
77 | + targetPropertyName = name; | |
78 | + if (name.length() > 0) | |
79 | + { | |
80 | + originalProperty = camera.getCameraPropertyValue(name); | |
81 | + propertyValueList = camera.getCameraPropertyValueList(name); | |
82 | + if (bracketCount < 0) | |
83 | + { | |
84 | + bracketCount = propertyValueList.size(); | |
85 | + } | |
86 | + return (propertyValueList.indexOf(originalProperty)); | |
87 | + } | |
88 | + else | |
89 | + { | |
90 | + originalProperty = null; | |
91 | + propertyValueList = null; | |
92 | + } | |
93 | + } | |
94 | + catch (Exception e) | |
95 | + { | |
96 | + originalProperty = null; | |
97 | + propertyValueList = null; | |
98 | + e.printStackTrace(); | |
99 | + System.gc(); | |
100 | + } | |
101 | + return (-1); | |
102 | + } | |
103 | + | |
104 | + | |
105 | + /** | |
106 | + * ブラケッティング対象のプロパティを特定する | |
107 | + * | |
108 | + * @param isBracketing プロパティ | |
109 | + * @return true : 対象の特定完了 / false : 対象の特定失敗 | |
110 | + */ | |
111 | + private boolean decideBracketProperty(int isBracketing) | |
112 | + { | |
113 | + switch (isBracketing) | |
114 | + { | |
115 | + case BRACKET_EXPREV: | |
116 | + // 露出ブラケット | |
117 | + targetPropertyName = IOlyCameraProperty.EXPOSURE_COMPENSATION; | |
118 | + break; | |
119 | + | |
120 | + case BRACKET_APERTURE: | |
121 | + // 絞り値設定 | |
122 | + targetPropertyName = IOlyCameraProperty.APERTURE; | |
123 | + break; | |
124 | + | |
125 | + case BRACKET_ISO: | |
126 | + // ISO | |
127 | + targetPropertyName = IOlyCameraProperty.ISO_SENSITIVITY; | |
128 | + break; | |
129 | + | |
130 | + case BRACKET_SHUTTER: | |
131 | + // シャッターブラケット | |
132 | + targetPropertyName = IOlyCameraProperty.SHUTTER_SPEED; | |
133 | + break; | |
134 | + | |
135 | + case BRACKET_WB: | |
136 | + // ホワイトバランスブラケット | |
137 | + targetPropertyName = IOlyCameraProperty.WB_MODE; | |
138 | + bracketCount = -1; | |
139 | + break; | |
140 | + | |
141 | + case BRACKET_COLOR_TONE: | |
142 | + // ピクチャーモードブラケット | |
143 | + targetPropertyName = IOlyCameraProperty.COLOR_TONE; | |
144 | + bracketCount = -1; | |
145 | + break; | |
146 | + | |
147 | + case BRACKET_NONE: | |
148 | + // パラメータは変更しないパターン... | |
149 | + targetPropertyName = ""; | |
150 | + break; | |
151 | + | |
152 | + default: | |
153 | + // 何もしない | |
154 | + return (false); | |
155 | + } | |
156 | + originalPropertyIndex = prepareBracketProperty(targetPropertyName); | |
157 | + return (true); | |
158 | + } | |
159 | + | |
160 | + | |
161 | + /** | |
162 | + * 写真撮影(ブラケッティング撮影)を開始する | |
163 | + * bracketingStyle : ブラケッティングスタイル | |
164 | + * bracketingCount : 撮影枚数 | |
165 | + * durationSeconds : 撮影間隔(単位:秒) | |
166 | + */ | |
167 | + public void startShootBracketing(int bracketingStyle, int bracketingCount, int durationSeconds) | |
168 | + { | |
169 | + if ((camera.isTakingPicture())||(camera.isRecordingVideo())||(isBracketingAction)) | |
170 | + { | |
171 | + // スチル or ムービー撮影中、ブラケッティング撮影中なら、何もしない | |
172 | + return; | |
173 | + } | |
174 | + | |
175 | + // ブラケッティング撮影の準備 | |
176 | + bracketCount = bracketingCount; | |
177 | + if (!decideBracketProperty(bracketingStyle)) | |
178 | + { | |
179 | + // ブラケッティング指定ではないので、何もせずに終了する | |
180 | + return; | |
181 | + } | |
182 | + | |
183 | + // 撮影間隔 (単位:秒) | |
184 | + waitSeconds = durationSeconds; | |
185 | + | |
186 | + // ブラケッティング撮影開始! (別スレッドでブラケッティング撮影を開始する) | |
187 | + ExecutorService executor = Executors.newSingleThreadExecutor(); | |
188 | + executor.submit(new Runnable() | |
189 | + { | |
190 | + @Override | |
191 | + public void run() | |
192 | + { | |
193 | + isBracketingAction = true; | |
194 | + updateMessage("INT"); | |
195 | + try | |
196 | + { | |
197 | + startBracket(); | |
198 | + } | |
199 | + catch (Exception e) | |
200 | + { | |
201 | + e.printStackTrace(); | |
202 | + } | |
203 | + isBracketingAction = false; | |
204 | + updateMessage(""); | |
205 | + } | |
206 | + }); | |
207 | + } | |
208 | + | |
209 | + /** | |
210 | + * 画面にメッセージを表示する | |
211 | + * | |
212 | + * @param msg 表示するメッセージ | |
213 | + */ | |
214 | + private void updateMessage(String msg) | |
215 | + { | |
216 | + statusDrawer.setMessage(IShowInformation.AREA_C, Color.CYAN, msg); | |
217 | + } | |
218 | + | |
219 | + /** | |
220 | + * ブラケッティング撮影を開始する | |
221 | + * (これは別スレッドで処理する) | |
222 | + * | |
223 | + * 一番小さい選択肢(インデックス)から設定された撮影枚数分、 | |
224 | + * 徐々に選択肢をずらして撮影する。 | |
225 | + * | |
226 | + */ | |
227 | + private void startBracket() | |
228 | + { | |
229 | + int startIndex = originalPropertyIndex - (bracketCount / 2); | |
230 | + if (propertyValueList != null) | |
231 | + { | |
232 | + if ((startIndex + bracketCount) > propertyValueList.size()) | |
233 | + { | |
234 | + startIndex = propertyValueList.size() - bracketCount; | |
235 | + } | |
236 | + } | |
237 | + if (startIndex < 0) | |
238 | + { | |
239 | + startIndex = 0; | |
240 | + } | |
241 | + | |
242 | + PointF afPoint = camera.getActualAutoFocusPoint(); | |
243 | + for (int index = 0; index < bracketCount; index++) | |
244 | + { | |
245 | + // 撮影条件を更新する | |
246 | + updateBracketingStatus(index, startIndex); | |
247 | + startIndex++; | |
248 | + | |
249 | + try | |
250 | + { | |
251 | + // AFポイントを設定する | |
252 | + if (afPoint != null) | |
253 | + { | |
254 | + camera.setAutoFocusPoint(afPoint); | |
255 | + } | |
256 | + } | |
257 | + catch (Exception e) | |
258 | + { | |
259 | + e.printStackTrace(); | |
260 | + } | |
261 | + | |
262 | + if (bracketCount == 1) | |
263 | + { | |
264 | + // 1枚しか撮影しない時は、撮影前にウェイトをかける | |
265 | + waitSeconds(waitSeconds); | |
266 | + } | |
267 | + | |
268 | + try | |
269 | + { | |
270 | + // 写真を撮影する | |
271 | + camera.takePicture(new HashMap<String, Object>(), this); | |
272 | + isShootingWait = true; | |
273 | + while (isShootingWait) | |
274 | + { | |
275 | + // ここで撮影状態が整うまで少し待つ | |
276 | + Thread.sleep(BRACKETING_INTERVAL_MILLISECOND); | |
277 | + updateShootingWaitStatus(); | |
278 | + } | |
279 | + } | |
280 | + catch (Exception e) | |
281 | + { | |
282 | + e.printStackTrace(); | |
283 | + } | |
284 | + | |
285 | + // 撮影したことをバイブレータで知らせる | |
286 | + statusDrawer.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT); | |
287 | + | |
288 | + // 指定された時間待機、ただし、最後の撮影が終わったあとには待たないようにする。 | |
289 | + if ((index + 1) < bracketCount) | |
290 | + { | |
291 | + waitSeconds(waitSeconds); | |
292 | + } | |
293 | + } | |
294 | + try | |
295 | + { | |
296 | + // 変更したプロパティ値を元の値に戻す...ちょっと待ってから | |
297 | + Thread.sleep(BRACKETING_INTERVAL_MILLISECOND); | |
298 | + if (originalProperty != null) | |
299 | + { | |
300 | + camera.setCameraPropertyValue(targetPropertyName, originalProperty); | |
301 | + } | |
302 | + | |
303 | + // とにかくAF枠を消す。 | |
304 | + camera.clearAutoFocusPoint(); | |
305 | + autoFocusFrame.hideFocusFrame(); | |
306 | + | |
307 | + indicator.onAfLockUpdate(false); | |
308 | + | |
309 | + // 撮影終了をバイブレータで知らせる | |
310 | + statusDrawer.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE); | |
311 | + } | |
312 | + catch (Exception e) | |
313 | + { | |
314 | + e.printStackTrace(); | |
315 | + } | |
316 | + } | |
317 | + | |
318 | + /** | |
319 | + * 指定された時間待機する | |
320 | + * | |
321 | + * @param seconds 待機秒数 | |
322 | + */ | |
323 | + private void waitSeconds(int seconds) | |
324 | + { | |
325 | + for (int count = seconds; count > 0; count--) | |
326 | + { | |
327 | + // 待ち時間(単位:秒) | |
328 | + try | |
329 | + { | |
330 | + // BKT表示(撮影枚数表示と待ち時間)を変える | |
331 | + updateMessage("WAIT " + count + "s."); | |
332 | + Thread.sleep(1000); | |
333 | + } | |
334 | + catch (Exception e) | |
335 | + { | |
336 | + e.printStackTrace(); | |
337 | + } | |
338 | + } | |
339 | + updateMessage(""); | |
340 | + } | |
341 | + | |
342 | + /** | |
343 | + * ブラケッティング撮影の状態を更新する | |
344 | + * | |
345 | + * @param index 撮影が終了したカウント(0始まり) | |
346 | + */ | |
347 | + private void updateBracketingStatus(int index, int currentIndex) | |
348 | + { | |
349 | + Log.v(TAG, "updateBracketingStatus() : " + index + "(" + currentIndex + ")"); | |
350 | + | |
351 | + // カメラのプロパティ設定を変える | |
352 | + try | |
353 | + { | |
354 | + if (propertyValueList != null) | |
355 | + { | |
356 | + Thread.sleep(BRACKETING_INTERVAL_MILLISECOND); | |
357 | + camera.setCameraPropertyValue(targetPropertyName, propertyValueList.get(currentIndex)); | |
358 | + } | |
359 | + } | |
360 | + catch (Exception e) | |
361 | + { | |
362 | + e.printStackTrace(); | |
363 | + | |
364 | + // 頭に来たので、再度呼ぶ (リトライオーバーするまで) | |
365 | + if (retryUpdateBracketingStatus < BRACKETING_PROPERTY_VALUE_SET_RETRY) | |
366 | + { | |
367 | + retryUpdateBracketingStatus++; | |
368 | + updateBracketingStatus(index, currentIndex); | |
369 | + } | |
370 | + } | |
371 | + retryUpdateBracketingStatus = 0; | |
372 | + | |
373 | + // 撮影枚数表示を変える | |
374 | + updateMessage("INT " + (index + 1) + "/" + bracketCount); | |
375 | + } | |
376 | + | |
377 | + /** | |
378 | + * カメラの状態を取得し、撮影可能か確認する。 | |
379 | + * (trueならまだ撮影処理中、falseなら撮影可能) | |
380 | + */ | |
381 | + private void updateShootingWaitStatus() | |
382 | + { | |
383 | + boolean isBusy = false; | |
384 | + try | |
385 | + { | |
386 | + isBusy = ((camera.isTakingPicture())||(camera.isMediaBusy())||(camera.isRecordingVideo())); | |
387 | + | |
388 | + // ちょっと待ち時間をとりたい... | |
389 | + String messageToShow = "getShootingBusyStatus() : " + String.valueOf(isBusy); | |
390 | + Log.v(TAG, messageToShow); | |
391 | + } | |
392 | + catch (Exception e) | |
393 | + { | |
394 | + e.printStackTrace(); | |
395 | + } | |
396 | + isShootingWait = isBusy; | |
397 | + } | |
398 | + | |
399 | + /** | |
400 | + * OLYCamera.TakePictureCallback の実装 | |
401 | + * | |
402 | + * | |
403 | + */ | |
404 | + @Override | |
405 | + public void onProgress(OLYCamera olyCamera, OLYCamera.TakingProgress takingProgress, OLYCameraAutoFocusResult olyCameraAutoFocusResult) | |
406 | + { | |
407 | + // 特に何もしないでおこう | |
408 | + } | |
409 | + | |
410 | + /** | |
411 | + * OLYCamera.TakePictureCallback の実装 | |
412 | + * | |
413 | + */ | |
414 | + @Override | |
415 | + public void onCompleted() | |
416 | + { | |
417 | + // 撮影待ち状態の更新 | |
418 | + updateShootingWaitStatus(); | |
419 | + } | |
420 | + | |
421 | + /** | |
422 | + * OLYCamera.TakePictureCallback の実装 | |
423 | + * | |
424 | + * @param e 例外情報 | |
425 | + */ | |
426 | + @Override | |
427 | + public void onErrorOccurred(Exception e) | |
428 | + { | |
429 | + e.printStackTrace(); | |
430 | + | |
431 | + // 撮影待ち状態の更新 | |
432 | + updateShootingWaitStatus(); | |
433 | + } | |
434 | +} |