OSDN Git Service

インターバル&ブラケッティング撮影のエンジンを組み込む。
authorMRSa <mrsa@myad.jp>
Wed, 19 Jul 2017 15:08:52 +0000 (00:08 +0900)
committerMRSa <mrsa@myad.jp>
Wed, 19 Jul 2017 15:08:52 +0000 (00:08 +0900)
.idea/misc.xml
wear/src/main/java/jp/sfjp/gokigen/a01c/olycamerawrapper/IOlyCameraCoordinator.java
wear/src/main/java/jp/sfjp/gokigen/a01c/olycamerawrapper/OlyCameraCoordinator.java
wear/src/main/java/jp/sfjp/gokigen/a01c/olycamerawrapper/takepicture/BracketingShotControl.java [new file with mode: 0644]

index fbb6828..5d19981 100644 (file)
@@ -37,7 +37,7 @@
     <ConfirmationsSetting value="0" id="Add" />
     <ConfirmationsSetting value="0" id="Remove" />
   </component>
-  <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">
+  <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">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
   <component name="ProjectType">
index 371334a..8f6c792 100644 (file)
@@ -32,6 +32,9 @@ public interface IOlyCameraCoordinator
     /** ムービー撮影機能の実行(開始・終了) **/
     void movieControl();
 
+    /** インターバル&ブラケッティング撮影の実行 **/
+    void bracketingShot(int bracketingStyle, int bracketingCount, int durationSeconds);
+
     /** 撮影確認画像の設定 **/
     void setRecViewMode(boolean isRecViewMode);
 
index db79943..805b2e6 100644 (file)
@@ -25,6 +25,7 @@ import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraPropertyProvider
 import jp.sfjp.gokigen.a01c.olycamerawrapper.property.LoadSaveCameraProperties;
 import jp.sfjp.gokigen.a01c.olycamerawrapper.property.OlyCameraPropertyProxy;
 import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.AutoFocusControl;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.BracketingShotControl;
 import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.MovieRecordingControl;
 import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.SingleShotControl;
 import jp.sfjp.gokigen.a01c.preference.ICameraPropertyAccessor;
@@ -52,6 +53,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo
     private final AutoFocusControl autoFocus;
     private final SingleShotControl singleShot;
     private final MovieRecordingControl movieControl;
+    private final BracketingShotControl bracketingShot;
     private final OlyCameraPropertyProxy propertyProxy;
     private final LoadSaveCameraProperties loadSaveCameraProperties;
     private final OlyCameraConnection cameraConnection;
@@ -60,7 +62,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo
 
     private boolean isManualFocus = false;
     private boolean isAutoFocusLocked = false;
-    private boolean isExposureLocked = false;
+    //private boolean isExposureLocked = false;
 
     /**
      * コンストラクタ
@@ -81,6 +83,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo
         autoFocus = new AutoFocusControl(camera, focusFrameDisplay, this); // AF制御
         singleShot = new SingleShotControl(camera, focusFrameDisplay, this, showInformation);  // 1枚撮影
         movieControl = new MovieRecordingControl(context, camera, showInformation); // ムービー撮影
+        bracketingShot = new BracketingShotControl(camera, focusFrameDisplay, this, showInformation);  // ブラケッティング&インターバル撮影
         propertyProxy = new OlyCameraPropertyProxy(camera); // カメラプロパティ
         cameraStatusDisplay = new CameraStatusDisplay(propertyProxy, showInformation);  // 画面表示
         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
     }
 
     /**
+     *   インターバル&ブラケッティング撮影の実行
+     *
+     *     @param bracketingStyle : ブラケッティングスタイル
+     *     @param bracketingCount : 撮影枚数
+     *     @param durationSeconds : 撮影間隔(単位:秒)
+     *
+     */
+    @Override
+    public void bracketingShot(int bracketingStyle, int bracketingCount, int durationSeconds)
+    {
+        bracketingShot.startShootBracketing(bracketingStyle, bracketingCount, durationSeconds);
+    }
+
+    /**
      *   撮影確認画像を生成するか設定する
      *
      */
@@ -331,8 +348,7 @@ public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorCo
     @Override
     public boolean isAELock()
     {
-        isExposureLocked = propertyProxy.isExposureLocked();
-        return (isExposureLocked);
+        return (propertyProxy.isExposureLocked());
     }
 
     @Override
diff --git a/wear/src/main/java/jp/sfjp/gokigen/a01c/olycamerawrapper/takepicture/BracketingShotControl.java b/wear/src/main/java/jp/sfjp/gokigen/a01c/olycamerawrapper/takepicture/BracketingShotControl.java
new file mode 100644 (file)
index 0000000..08f313d
--- /dev/null
@@ -0,0 +1,434 @@
+package jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture;
+
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraAutoFocusResult;
+import jp.sfjp.gokigen.a01c.IShowInformation;
+import jp.sfjp.gokigen.a01c.liveview.IAutoFocusFrameDisplay;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.IIndicatorControl;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraProperty;
+
+/**
+ *   インターバル撮影&ブラケッティング撮影 実行クラス
+ *
+ *
+ * Created by MRSa on 2017/07/19.
+ */
+public class BracketingShotControl implements OLYCamera.TakePictureCallback
+{
+    private final String TAG = toString();
+
+    private static final int BRACKETING_INTERVAL_MILLISECOND = 300; // 撮影待ち時間(ms)
+    private static final int BRACKETING_PROPERTY_VALUE_SET_RETRY = 10;
+
+    private static final int BRACKET_NONE = 0;       // 通常のショット
+    private static final int BRACKET_EXPREV = 1;     // 露出補正
+    private static final int BRACKET_APERTURE = 2;   // 絞り
+    private static final int BRACKET_ISO = 3;         // ISO
+    private static final int BRACKET_SHUTTER = 4;    // シャッター
+    private static final int BRACKET_WB = 5;          // ホワイトバランス
+    private static final int BRACKET_COLOR_TONE = 6; // カラートーン
+
+    private final OLYCamera camera;
+    private final IAutoFocusFrameDisplay autoFocusFrame;
+    private final IShowInformation statusDrawer;
+    private final IIndicatorControl indicator;
+    private boolean isShootingWait = false;
+    private boolean isBracketingAction = false;
+    private int retryUpdateBracketingStatus = 0;
+    private int waitSeconds = 0;  // 撮影待ち時間
+
+    private int bracketCount = 0;
+    private String targetPropertyName = null;
+    private String originalProperty = null;
+    private int  originalPropertyIndex = -1;
+    private List<String> propertyValueList = null;
+
+    /**
+     *  コンストラクタ
+     *
+     */
+    public BracketingShotControl(OLYCamera camera, IAutoFocusFrameDisplay focusFrameDrawer, IIndicatorControl indicator, IShowInformation statusDrawer)
+    {
+        this.camera = camera;
+        this.autoFocusFrame = focusFrameDrawer;
+        this.indicator = indicator;
+        this.statusDrawer = statusDrawer;
+    }
+
+    /**
+     *  ブラケッティング対象のプロパティの現在設定値と、その選択肢を記憶する
+     *
+     * @param name ブラケッティング対象の名前
+     * @return  ブラケッティングの現在設定値
+     */
+    private int prepareBracketProperty(String name)
+    {
+        try
+        {
+            targetPropertyName = name;
+            if (name.length() > 0)
+            {
+                originalProperty = camera.getCameraPropertyValue(name);
+                propertyValueList = camera.getCameraPropertyValueList(name);
+                if (bracketCount < 0)
+                {
+                    bracketCount = propertyValueList.size();
+                }
+                return (propertyValueList.indexOf(originalProperty));
+            }
+            else
+            {
+                originalProperty = null;
+                propertyValueList = null;
+            }
+        }
+        catch (Exception e)
+        {
+            originalProperty = null;
+            propertyValueList = null;
+            e.printStackTrace();
+            System.gc();
+        }
+        return (-1);
+    }
+
+
+    /**
+     *   ブラケッティング対象のプロパティを特定する
+     *
+     * @param isBracketing プロパティ
+     * @return true : 対象の特定完了 / false : 対象の特定失敗
+     */
+    private boolean decideBracketProperty(int isBracketing)
+    {
+        switch (isBracketing)
+        {
+            case BRACKET_EXPREV:
+                // 露出ブラケット
+                targetPropertyName = IOlyCameraProperty.EXPOSURE_COMPENSATION;
+                break;
+
+            case BRACKET_APERTURE:
+                // 絞り値設定
+                targetPropertyName = IOlyCameraProperty.APERTURE;
+                break;
+
+            case BRACKET_ISO:
+                // ISO
+                targetPropertyName = IOlyCameraProperty.ISO_SENSITIVITY;
+                break;
+
+            case BRACKET_SHUTTER:
+                // シャッターブラケット
+                targetPropertyName = IOlyCameraProperty.SHUTTER_SPEED;
+                break;
+
+            case BRACKET_WB:
+                // ホワイトバランスブラケット
+                targetPropertyName = IOlyCameraProperty.WB_MODE;
+                bracketCount = -1;
+                break;
+
+            case BRACKET_COLOR_TONE:
+                // ピクチャーモードブラケット
+                targetPropertyName = IOlyCameraProperty.COLOR_TONE;
+                bracketCount = -1;
+                break;
+
+            case BRACKET_NONE:
+                // パラメータは変更しないパターン...
+                targetPropertyName = "";
+                break;
+
+            default:
+                // 何もしない
+                return (false);
+        }
+        originalPropertyIndex = prepareBracketProperty(targetPropertyName);
+        return (true);
+    }
+
+
+    /**
+     *  写真撮影(ブラケッティング撮影)を開始する
+     *    bracketingStyle : ブラケッティングスタイル
+     *    bracketingCount : 撮影枚数
+     *    durationSeconds : 撮影間隔(単位:秒)
+     */
+    public void startShootBracketing(int bracketingStyle, int bracketingCount, int durationSeconds)
+    {
+        if ((camera.isTakingPicture())||(camera.isRecordingVideo())||(isBracketingAction))
+        {
+            // スチル or ムービー撮影中、ブラケッティング撮影中なら、何もしない
+            return;
+        }
+
+        // ブラケッティング撮影の準備
+        bracketCount = bracketingCount;
+        if (!decideBracketProperty(bracketingStyle))
+        {
+            // ブラケッティング指定ではないので、何もせずに終了する
+            return;
+        }
+
+        // 撮影間隔 (単位:秒)
+        waitSeconds = durationSeconds;
+
+        // ブラケッティング撮影開始! (別スレッドでブラケッティング撮影を開始する)
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        executor.submit(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                isBracketingAction = true;
+                updateMessage("INT");
+                try
+                {
+                    startBracket();
+                }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                }
+                isBracketingAction = false;
+                updateMessage("");
+            }
+        });
+    }
+
+    /**
+     *   画面にメッセージを表示する
+     *
+     * @param msg  表示するメッセージ
+     */
+    private void updateMessage(String msg)
+    {
+        statusDrawer.setMessage(IShowInformation.AREA_C, Color.CYAN, msg);
+    }
+
+    /**
+     *   ブラケッティング撮影を開始する
+     *   (これは別スレッドで処理する)
+     *
+     *      一番小さい選択肢(インデックス)から設定された撮影枚数分、
+     *      徐々に選択肢をずらして撮影する。
+     *
+     */
+    private void startBracket()
+    {
+        int startIndex = originalPropertyIndex - (bracketCount / 2);
+        if (propertyValueList != null)
+        {
+            if ((startIndex + bracketCount) > propertyValueList.size())
+            {
+                startIndex = propertyValueList.size() - bracketCount;
+            }
+        }
+        if (startIndex < 0)
+        {
+            startIndex = 0;
+        }
+
+        PointF afPoint = camera.getActualAutoFocusPoint();
+        for (int index = 0; index < bracketCount; index++)
+        {
+            // 撮影条件を更新する
+            updateBracketingStatus(index, startIndex);
+            startIndex++;
+
+            try
+            {
+                // AFポイントを設定する
+                if (afPoint != null)
+                {
+                    camera.setAutoFocusPoint(afPoint);
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+
+            if (bracketCount == 1)
+            {
+                // 1枚しか撮影しない時は、撮影前にウェイトをかける
+                waitSeconds(waitSeconds);
+            }
+
+            try
+            {
+                // 写真を撮影する
+                camera.takePicture(new HashMap<String, Object>(), this);
+                isShootingWait = true;
+                while (isShootingWait)
+                {
+                    // ここで撮影状態が整うまで少し待つ
+                    Thread.sleep(BRACKETING_INTERVAL_MILLISECOND);
+                    updateShootingWaitStatus();
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+
+            // 撮影したことをバイブレータで知らせる
+            statusDrawer.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT);
+
+            // 指定された時間待機、ただし、最後の撮影が終わったあとには待たないようにする。
+            if ((index + 1) < bracketCount)
+            {
+                waitSeconds(waitSeconds);
+            }
+        }
+        try
+        {
+            // 変更したプロパティ値を元の値に戻す...ちょっと待ってから
+            Thread.sleep(BRACKETING_INTERVAL_MILLISECOND);
+            if (originalProperty != null)
+            {
+                camera.setCameraPropertyValue(targetPropertyName, originalProperty);
+            }
+
+            // とにかくAF枠を消す。
+            camera.clearAutoFocusPoint();
+            autoFocusFrame.hideFocusFrame();
+
+            indicator.onAfLockUpdate(false);
+
+            // 撮影終了をバイブレータで知らせる
+            statusDrawer.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *   指定された時間待機する
+     *
+     * @param seconds  待機秒数
+     */
+    private void waitSeconds(int seconds)
+    {
+        for (int count = seconds; count > 0; count--)
+        {
+            // 待ち時間(単位:秒)
+            try
+            {
+                // BKT表示(撮影枚数表示と待ち時間)を変える
+                updateMessage("WAIT " + count + "s.");
+                Thread.sleep(1000);
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+        }
+        updateMessage("");
+    }
+
+    /**
+     *   ブラケッティング撮影の状態を更新する
+     *
+     * @param index  撮影が終了したカウント(0始まり)
+     */
+    private void updateBracketingStatus(int index, int currentIndex)
+    {
+        Log.v(TAG, "updateBracketingStatus() : " + index + "(" + currentIndex + ")");
+
+        // カメラのプロパティ設定を変える
+        try
+        {
+            if (propertyValueList != null)
+            {
+                Thread.sleep(BRACKETING_INTERVAL_MILLISECOND);
+                camera.setCameraPropertyValue(targetPropertyName, propertyValueList.get(currentIndex));
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+
+            // 頭に来たので、再度呼ぶ (リトライオーバーするまで)
+            if (retryUpdateBracketingStatus < BRACKETING_PROPERTY_VALUE_SET_RETRY)
+            {
+                retryUpdateBracketingStatus++;
+                updateBracketingStatus(index, currentIndex);
+            }
+        }
+        retryUpdateBracketingStatus = 0;
+
+        // 撮影枚数表示を変える
+        updateMessage("INT " + (index + 1) + "/" + bracketCount);
+    }
+
+    /**
+     *   カメラの状態を取得し、撮影可能か確認する。
+     *   (trueならまだ撮影処理中、falseなら撮影可能)
+     */
+    private void updateShootingWaitStatus()
+    {
+        boolean isBusy = false;
+        try
+        {
+            isBusy = ((camera.isTakingPicture())||(camera.isMediaBusy())||(camera.isRecordingVideo()));
+
+            // ちょっと待ち時間をとりたい...
+            String messageToShow = "getShootingBusyStatus() : " + String.valueOf(isBusy);
+            Log.v(TAG, messageToShow);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        isShootingWait = isBusy;
+    }
+
+    /**
+     *   OLYCamera.TakePictureCallback の実装
+     *
+     *
+     */
+    @Override
+    public void onProgress(OLYCamera olyCamera, OLYCamera.TakingProgress takingProgress, OLYCameraAutoFocusResult olyCameraAutoFocusResult)
+    {
+        // 特に何もしないでおこう
+    }
+
+    /**
+     *   OLYCamera.TakePictureCallback の実装
+     *
+     */
+    @Override
+    public void onCompleted()
+    {
+        // 撮影待ち状態の更新
+        updateShootingWaitStatus();
+    }
+
+    /**
+     *   OLYCamera.TakePictureCallback の実装
+     *
+     * @param e 例外情報
+     */
+    @Override
+    public void onErrorOccurred(Exception e)
+    {
+         e.printStackTrace();
+
+         // 撮影待ち状態の更新
+         updateShootingWaitStatus();
+    }
+}