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("BRACKET");
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         statusDrawer.setEnabledOperation(false, true);  // 画面のタッチ操作を禁止
242         for (int index = 0; index < bracketCount; index++)
243         {
244             // 撮影条件を更新する
245             updateBracketingStatus(index, startIndex);
246             startIndex++;
247
248             try
249             {
250                 // AFポイントを設定する
251                 if (afPoint != null)
252                 {
253                     camera.setAutoFocusPoint(afPoint);
254                 }
255             }
256             catch (Exception e)
257             {
258                 e.printStackTrace();
259             }
260
261             if (bracketCount == 1)
262             {
263                 // 1枚しか撮影しない時は、撮影前にウェイトをかける
264                 waitSeconds(waitSeconds);
265             }
266
267             try
268             {
269                 // 写真を撮影する
270                 camera.takePicture(new HashMap<String, Object>(), this);
271                 isShootingWait = true;
272                 while (isShootingWait)
273                 {
274                     // ここで撮影状態が整うまで少し待つ
275                     Thread.sleep(BRACKETING_INTERVAL_MILLISECOND);
276                     updateShootingWaitStatus();
277                 }
278             }
279             catch (Exception e)
280             {
281                 e.printStackTrace();
282             }
283
284             // 撮影したことをバイブレータで知らせる
285             statusDrawer.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT);
286
287             // 指定された時間待機、ただし、最後の撮影が終わったあとには待たないようにする。
288             if ((index + 1) < bracketCount)
289             {
290                 waitSeconds(waitSeconds);
291             }
292         }
293         try
294         {
295             // 変更したプロパティ値を元の値に戻す...ちょっと待ってから
296             Thread.sleep(BRACKETING_INTERVAL_MILLISECOND);
297             if (originalProperty != null)
298             {
299                 camera.setCameraPropertyValue(targetPropertyName, originalProperty);
300             }
301
302             // とにかくAF枠を消す。
303             camera.clearAutoFocusPoint();
304             autoFocusFrame.hideFocusFrame();
305
306             indicator.onAfLockUpdate(false);
307
308             // 撮影終了をバイブレータで知らせる
309             statusDrawer.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE);
310         }
311         catch (Exception e)
312         {
313             e.printStackTrace();
314         }
315         statusDrawer.setEnabledOperation(true, false);  // 画面のタッチ操作を有効化する
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 + "sec.");
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("BRACKET " + (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 }