OSDN Git Service

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