From 6cf1af5eb7491f31dcab0979a8f3a0c6f79f9cd4 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 29 Oct 2019 22:43:41 +0000 Subject: [PATCH 001/243] Various tweaks for reporting bugs. --- _docs/help.html | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 13804dbad..f1e5e37d2 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -1378,14 +1378,7 @@ settings to the defaults (under Settings/Settings manager/"Reset settings").

If there's still a problem, please check other third party camera applications to see if they have the same problem or not. (It's not enough to try your device's "stock" camera - in some cases, devices may have bugs for - third party camera applications that don't affect the stock camera.) If the issue is specific to Camera2 API, then - please check third party camera applications also using Camera2, e.g.:

- + third party camera applications that don't affect the stock camera.)

If you find a bug, please report it here (please check for existing tickets first). @@ -1394,15 +1387,14 @@ can paste the information into your web browser, email or whatever.

For more general questions or things like feature suggestions, please use the forums. -For some enquiries (e.g., requests for specific projects you are working on), you may prefer to use email. +For some enquiries you may prefer to use email. Please contact me at mark.harman.apps@gmail.com. Please note that I get a lot of emails for Open Camera these days - I try to reply as many as I can, but this is not always feasible. I do however read every email and forum post.

Note that whilst I welcome reviews/ratings, they are not a good way for reporting bugs (I may -miss it, there's only limited number of characters for me to reply, and I don't get notified of -further replies).

+miss it, there's only limited number of characters for me to reply).


Open Camera Privacy Policy.

-- GitLab From 998807587a80d762052ce1c4a8cfa9a885de3eb5 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 3 Nov 2019 14:15:14 +0000 Subject: [PATCH 002/243] Move info to new info.html . --- _docs/index.html | 8 ++-- _docs/info.html | 118 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 _docs/info.html diff --git a/_docs/index.html b/_docs/index.html index bbab5e5d9..e30e2b5a2 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -126,10 +126,11 @@ browsers -->

Download on Google Play.

-
-

Open Camera is completely free, however if you wish you can show your appreciation and support future development by purchasing -my donation app on Google Play. +

Also see alternative download sites.

+
+

Open Camera is completely free, however if you wish you can show your appreciation by supporting me.

+

Open Camera Blog ~ @@ -141,6 +142,7 @@ browsers -->

@@ -165,7 +165,7 @@ browsers -->
-

Requirements

+

Requirements

Open Camera requires Android 4.0.3 or better. Some features may only be available on some devices (it may depend on Android version, or require specific support from the camera/device).

@@ -178,17 +178,17 @@ your wedding etc :)

Instructions

-

Credits

+

Credits

Open Camera is written by Mark Harman with additional contributors, see credits for details.

-

Privacy policy

+

Privacy policy

See my privacy policy for details.

-

Licence

+

Licence

-- GitLab From 5c311b101676901025b3d1b6d9d8a0cda84f5791 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 8 Nov 2019 00:21:22 +0000 Subject: [PATCH 006/243] Minor changes. --- _docs/help.html | 8 +------- _docs/index.html | 5 +++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index f1e5e37d2..716dc6c44 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -56,11 +56,6 @@ -

More of my Free software: -Vibrance HDR ~ - -

- Open Camera icon

Open Camera Help

@@ -212,8 +207,7 @@ will be available which instead work by making the screen light up (note, front
  • Expo {} - Enables Auto Exposure Bracketing (AEB) mode. Takes multiple images at different exposure levels. See Settings/"Photo settings" for options to control the number of images and stops. These images can be processed in other applications to create HDR images. For Android, you can try my own - Vibrance HDR. For - PC platforms, try Luminance HDR.
  • + Vibrance HDR.
  • Focus {} - Enables Focus Bracketing mode. (Only available on some devices, and if Camera2 API is used.) This mode takes a series of photos each with a different focus distance. Two sliders appear, allowing you diff --git a/_docs/index.html b/_docs/index.html index cd1bec446..77226b252 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -145,7 +145,7 @@ browsers -->
  • Support me!
  • Credits
  • Privacy policy
  • -
  • Licence
  • +
  • Licence and Terms of Service
  • History
  • @@ -188,9 +188,10 @@ your wedding etc :)

    See my privacy policy for details.

    -

    Licence

    +

    Licence and Terms of Service

    +

    Open Camera is released under the GPL v3 or later. The source code is available from -- GitLab From eacd440f52c7cc47f0e9fa119787e479e5e7267c Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 10 Nov 2019 17:55:45 +0000 Subject: [PATCH 007/243] Reword. --- _docs/info.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/_docs/info.html b/_docs/info.html index 9bb7fac11..9336d9539 100644 --- a/_docs/info.html +++ b/_docs/info.html @@ -58,7 +58,11 @@

    Support me!

    -

    Open Camera is completely free, however if you wish you can show your appreciation and support me by making an optional payment. Please note that this is not required (and that I also receive income via website ads), and that doing so will not provide any additional features (or remove ads). However for those who wish to make a contribution to me, this is greatly appreciated!

    + + +

    Open Camera is completely free, however if you wish you can show your appreciation to me by making an optional payment. + Please note that this is not required, and that doing so will not provide any additional features (or remove the ads I have on the + website). However for those who wish to make a contribution to me, this is greatly appreciated!

    You can contribute through PayPal, simply click the "Buy Now" button, and enter the amount you wish to give me:

    -- GitLab From fbb1969af2219e2a287c0130efe23548f22508de Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 10 Nov 2019 18:12:38 +0000 Subject: [PATCH 008/243] Corrections, and "Select remote device" wasn't in strings. --- app/src/main/res/values/strings.xml | 4 +++- app/src/main/res/xml/preferences.xml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e2dbef4d9..55f1f0b75 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -886,7 +886,7 @@ Select the file format used for saving photos. This affects \"standard\" (not RAW) photos. Note that PNG format is not truly lossless, instead it is converted from a JPEG at 100%% quality.\n%s Camera API - Select Camera2 API to enables extra feature such as manual modes for exposure, focus, white balance, along with RAW (if supported by the device), but may not work properly on all devices. Changing the API will cause a restart.\n%s + Select Camera2 API to enable extra features such as manual modes for exposure, focus, white balance, along with RAW (if supported by the device). Changing the API will cause a restart.\n%s Original camera API Camera2 API @@ -908,6 +908,8 @@ For more help, click \"Online help\" from Settings. + Select remote device + Privacy policy diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 64457526b..20d3c230d 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -202,8 +202,10 @@ + android:title="@string/preference_select_remote"> + + Date: Sun, 10 Nov 2019 18:12:45 +0000 Subject: [PATCH 009/243] Update. --- app/src/main/res/values-de/strings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c4a14399f..489a01db1 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -812,4 +812,15 @@ Schattierter Text Normaler Text + Suchfeld zur Änderung der Belichtungskorrektur + + Wähle das Dateiformat zum Speichern der Fotos. Das wirkt sich nur auf \"Standard-\" (nicht RAW-) Fotos aus. Merke: Das PNG-Format ist nicht verlustlos, es wird aus einem JPEG mit 100%%iger Qualität konvertiert.\n%s + + Camera-API + Wähle das Camera2-API um extra Features wie manuelle Modi für Belichtung, Fokus, Weißabgleich sowie RAW-Format (falls vom Gerät unterstützt) zu nutzen. Die Änderung des API verursacht einen Neustart der App.\n%s + Original Camera-API + Camera2-API + + Wähle eine Fernsteuerung + -- GitLab From 7f60300d4fec80b447636957300c9ced6e1f3685 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 16 Nov 2019 16:06:26 +0000 Subject: [PATCH 010/243] Fix case typo. --- app/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d141c4056..3f2978880 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -858,7 +858,7 @@ Обычный текст Текст с тенью фона - СОхранение изображений… + Сохранение изображений… Закончить панораму Отменить панораму -- GitLab From e795c3ca622f6c827b23b1ecef0f5162504310b1 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Dec 2019 12:57:42 +0000 Subject: [PATCH 011/243] Force a BLE scan upcon BLE connection attempt --- .../remotecontrol/BluetoothLeService.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java index f2c6d5338..fd8f0b3e6 100644 --- a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java +++ b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java @@ -38,6 +38,7 @@ public class BluetoothLeService extends Service { private String device_address; private BluetoothGatt bluetoothGatt; private String remote_device_type; + private final Handler bluetoothHandler = new Handler(); private final HashMap subscribed_characteristics = new HashMap<>(); private final List charsToSubscribe = new ArrayList<>(); @@ -73,6 +74,21 @@ public class BluetoothLeService extends Service { public final static int COMMAND_UP = 64; public final static int COMMAND_DOWN = 80; + /* This forces a gratuitous BLE scan to help the device + * connect to the remote faster. This is due to limitations of the + * Android BLE stack and API (just knowing the MAC is not enough on + * many phones).*/ + private void triggerScan() { + // Stops scanning after a pre-defined scan period. + bluetoothHandler.postDelayed(new Runnable() { + @Override + public void run() { + bluetoothAdapter.stopLeScan(null); + } + }, 10000); + bluetoothAdapter.startLeScan(null); + } + public void setRemoteDeviceType(String remote_device_type) { if( MyDebug.LOG ) Log.d(TAG, "Setting remote type: " + remote_device_type); @@ -346,7 +362,13 @@ public class BluetoothLeService extends Service { return false; } - bluetoothGatt = device.connectGatt(this, false, mGattCallback); + // It looks like Android won't connect to BLE devices properly without scanning + // for them first, even when connecting by explicit MAC address. Since we're using + // BLE for underwater housings and we want rock solid connectivity, we trigger + // a scan for 10 seconds + triggerScan(); + + bluetoothGatt = device.connectGatt(this, true, mGattCallback); device_address = address; return true; } -- GitLab From fc4ce004d5c6b32b26a9351ee53fe95042541403 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Dec 2019 21:43:53 +0000 Subject: [PATCH 012/243] Add gyro sensors support to about debug info. --- .../main/java/net/sourceforge/opencamera/MainActivity.java | 1 + .../net/sourceforge/opencamera/MyPreferenceFragment.java | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 9850b80d8..2c93ca282 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1672,6 +1672,7 @@ public class MainActivity extends Activity { bundle.putBoolean("supports_hdr", this.supportsHDR()); bundle.putBoolean("supports_nr", this.supportsNoiseReduction()); bundle.putBoolean("supports_panorama", this.supportsPanorama()); + bundle.putBoolean("has_gyro_sensors", applicationInterface.getGyroSensor().hasSensors()); bundle.putBoolean("supports_expo_bracketing", this.supportsExpoBracketing()); bundle.putBoolean("supports_preview_bitmaps", this.supportsPreviewBitmaps()); bundle.putInt("max_expo_bracketing_n_images", this.maxExpoBracketingNImages()); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index b533801cc..295180e86 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -383,6 +383,10 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared pg.removePreference(pref); } + final boolean has_gyro_sensors = bundle.getBoolean("has_gyro_sensors"); + if( MyDebug.LOG ) + Log.d(TAG, "has_gyro_sensors: " + has_gyro_sensors); + final boolean supports_expo_bracketing = bundle.getBoolean("supports_expo_bracketing"); if( MyDebug.LOG ) Log.d(TAG, "supports_expo_bracketing: " + supports_expo_bracketing); @@ -1186,6 +1190,8 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared about_string.append(getString(supports_hdr ? R.string.about_available : R.string.about_not_available)); about_string.append("\nPanorama?: "); about_string.append(getString(supports_panorama ? R.string.about_available : R.string.about_not_available)); + about_string.append("\nGyro sensors?: "); + about_string.append(getString(has_gyro_sensors ? R.string.about_available : R.string.about_not_available)); about_string.append("\nExpo?: "); about_string.append(getString(supports_expo_bracketing ? R.string.about_available : R.string.about_not_available)); about_string.append("\nExpo compensation?: "); -- GitLab From 008d9bce3c1fb5f5b1037c8055454bf8f46cef29 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Dec 2019 21:44:02 +0000 Subject: [PATCH 013/243] Fix typo in comment. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 2c93ca282..7958ab7a1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -3415,7 +3415,7 @@ public class MainActivity extends Activity { if( preview.getCameraController() == null ) return false; if( preview.isVideoHighSpeed() ) { - // manuai ISO/exposure not supported for high speed video mode + // manual ISO/exposure not supported for high speed video mode // it's safer not to allow opening the panel at all (otherwise the user could open it, and switch to manual) return false; } -- GitLab From 27e10196d91af3910cf69488ddcf7e0aec5909f6 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Dec 2019 21:44:15 +0000 Subject: [PATCH 014/243] Fix typo in comment. --- .../main/java/net/sourceforge/opencamera/preview/Preview.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 219942f59..bb729714d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -3082,7 +3082,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } } else if( capture_rate_factor > 1.0 ) { - // resultant framerate remains the same, instead adjst the capture rate + // resultant framerate remains the same, instead adjust the capture rate video_profile.videoCaptureRate = video_profile.videoCaptureRate / (double)capture_rate_factor; if( MyDebug.LOG ) Log.d(TAG, "scaled capture rate to: " + video_profile.videoCaptureRate); -- GitLab From 0f8882a96c927c18a6c650b1da25d347f3364ee5 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Dec 2019 21:44:31 +0000 Subject: [PATCH 015/243] Update licence text string. --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 55f1f0b75..bedfa3055 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -937,7 +937,7 @@ Open Source licences Open Camera - Open Camera is © 2013–2019 Mark Harman, released under the GPL v3 or later. Tap here for full licence text. + Open Camera is © 2013–2019 Mark Harman, released under the GPL v3 or later. Tap here for full licence text and terms of service. Google\'s Material Design icons Open Camera uses icons from Google\'s Material Design icons (https://developer.android.com/design/downloads/index.html , -- GitLab From 2d86dceec8b8a177c04a6659cd707738336839ff Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Dec 2019 22:23:50 +0000 Subject: [PATCH 016/243] Simplify some strings, make some translations consistent. --- app/src/main/res/values-az/strings.xml | 4 ++-- app/src/main/res/values-be/strings.xml | 6 +++--- app/src/main/res/values-cs/strings.xml | 6 +++--- app/src/main/res/values-de/strings.xml | 4 ++-- app/src/main/res/values-el/strings.xml | 4 ++-- app/src/main/res/values-es/strings.xml | 4 ++-- app/src/main/res/values-fr/strings.xml | 6 +++--- app/src/main/res/values-hu/strings.xml | 4 ++-- app/src/main/res/values-it/strings.xml | 6 +++--- app/src/main/res/values-ja/strings.xml | 6 +++--- app/src/main/res/values-nb/strings.xml | 4 ++-- app/src/main/res/values-pl/strings.xml | 4 ++-- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt-rPT/strings.xml | 4 ++-- app/src/main/res/values-ru/strings.xml | 6 +++--- app/src/main/res/values-sl/strings.xml | 4 ++-- app/src/main/res/values-tr/strings.xml | 6 +++--- app/src/main/res/values-uk/strings.xml | 6 +++--- app/src/main/res/values-vi/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 6 +++--- app/src/main/res/values-zh-rTW/strings.xml | 6 +++--- app/src/main/res/values/strings.xml | 2 +- 22 files changed, 51 insertions(+), 51 deletions(-) diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index db80beadc..248066342 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -91,7 +91,7 @@ Çəkilişdən sonra fasilə Şəkil çəkildikdən sonra paylaşma və ya silinmə imkanları yaradan fasilə Çəkiliş səsi - Şəkil çəkilən zaman eşidilən səs (bağlanması üçün Android 4.2+ tələb olunur) + Şəkil çəkilən zaman eşidilən səs Səs səviyyəsi düyməsi Saxlanma yeri Şəkil və videonun saxlanması üçün qovluq adı @@ -182,7 +182,7 @@ Dəstək üçün İanə Əgər bu proqram xoşunuza gəlirsə, lütfən ianə vermək haqqında düşünün. Siz bunu Proqram üçün ianə - toxunaraq almaqla edə bilərsiniz, bu funksiya proqrama ianə vermək üçün səhifəni açacaq. Təşəkkürlər! Camera2 API istifadəsi - Android 5 Camera2 API işə salınması - əlavə funksiyalar təqdim edir, amma hazırda bu ekperimentaldır (yenidənbaşlamalara səbəb ola bilər) + Camera2 API işə salınması - əlavə funksiyalar təqdim edir, amma hazırda bu ekperimentaldır (yenidənbaşlamalara səbəb ola bilər) Haqqında Proqram məlumatları Parametrləri sıfırla diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 47c68e2c5..057339b09 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -103,12 +103,12 @@ Паўза пасля фатаграфавання Паўза пасля фатаграфавання, падчас якой магчыма падзяліцца або выдаліць фота Гук засаўкі - Прайграванне гуку пры фатаграфаванні (патрабуецца Android 4.2 або вышэй, каб адключыць) + Прайграванне гуку пры фатаграфаванні Клавішы рэгулявання гучнасці Захаваць месца Тэчка для захавання фота / відэа файлаў Выкарыстоўваць сховішча Access Framework - Ці варта выкарыстоўваць сховішча Android 5 Access Framework для захавання фотаздымкаў і відэазапісаў + Ці варта выкарыстоўваць сховішча Access Framework для захавання фотаздымкаў і відэазапісаў Захаваць фотапрэфікс Выкарыстоўваць прэфікс для захавання фотаздымкаў Захаваць відэапрэфікс @@ -210,7 +210,7 @@ Ахвяруйце на распрацоўку Калі вам падабаецца гэты дадатак, калі ласка, падтрымайце распрацоўку . Вы можаце зрабіць гэта, купіўшы мой дадатак .Абярыце гэты параметр і адкрыецца старонка для ахвяравання . Дзякую! Выкарыстоўваць Camera2 API - Дазваляе выкарыстоўваць Camera2 API Android 5 + Дазваляе выкарыстоўваць Camera2 API Інфармацыя Інфармацыя Скід налад diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 839818b47..dd0d3c086 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -103,13 +103,13 @@ Pauza po pořízení fotografie Zobrazit fotografii po pořízení s možností sdílení nebo vymazání fotografie Zvuk závěrky - Přehrát zvuk při pořizování fotografie (vyžaduje Android 4.2 a vyšší pro vypnutí) + Přehrát zvuk při pořizování fotografie Tlačítka hlasitosti Uložit polohu Složka pro uložení fotek/videa Použít Storage Access Framework - Zdali použít Android 5\'s Storage Access Framework pro uložení fotek a videí + Zdali použít Storage Access Framework pro uložení fotek a videí Uložit předponu pro fotografie Předpona používaná při ukládání fotografií Uložit předponu pro videa @@ -214,7 +214,7 @@ Přispět na podporu vývoje Pokud se Vám tato aplikace líbí, prosím zvažte přispění koupí mé "darovací aplikace" - tato volba otevře stránku mé darovací aplikace. Díky! Použít Camera2 API - Zapne Camera2 API Androidu 5 - nabízí možnosti navíc, ale je v současné době experimentální (způsobí restart aplikace) + Zapne Camera2 API - nabízí možnosti navíc, ale je v současné době experimentální (způsobí restart aplikace) O programu Informace aplikace a ladění Obnovit nastavení diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 489a01db1..b8c0d70be 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -104,7 +104,7 @@ Pause nach der Fotoaufnahme Nach der Aufnahme pausieren mit der Möglichkeit, das Foto zu teilen oder zu löschen Auslöseton - Abspielen eines Tones bei der Aufnahme (benötigt Android 4.2 oder höher zum Deaktivieren) + Abspielen eines Tones bei der Aufnahme Lautstärketasten Audio Steuerungsoptionen Audio Steuerung Empfindlichkeit @@ -229,7 +229,7 @@ Spende Wenn Ihnen diese App gefällt, würde ich mich über eine Spende freuen, indem Sie meine Spenden-App kaufen. Dazu brauchen Sie nur diese Option anzuklicken. Danke! Camera2-API verwenden - Aktiviert die Android-5-Camera2-API mit Zusatzfunktionen (experimentell, Neustart erforderlich) + Aktiviert die Camera2-API mit Zusatzfunktionen (experimentell, Neustart erforderlich) Über Anwendungs- und Debug-Informationen Einstellungen zurücksetzen diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index b95b6cf8d..5416e4cab 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -111,7 +111,7 @@ Χώρος αποθήκευσης Φάκελος για αποθήκευση φωτογραφίας/βίντεο Χρήση αποθήκευσης πρόσβασης πλαισίου - Αν θέλετε χρησιμοποιήστε την Android 5\'s Πρόσβαση αποθήκευσης πλαισίου για την αποθήκευση φωτογραφιών και βίντεο + Αν θέλετε χρησιμοποιήστε την Πρόσβαση αποθήκευσης πλαισίου για την αποθήκευση φωτογραφιών και βίντεο Αποθήκευση προθέματος φωτογραφιών Πρόθεμα για την αποθήκευση αρχείων φωτογραφιών Αποθήκευση βίντεο προθέματος @@ -227,7 +227,7 @@ Δωρεά για υποστήριξη της ανάπτυξης Αν σας αρέσει αυτή η εφαρμογή, παρακαλούμε κάντε μια δωρεά για υποστήριξη της ανάπτυξης. Μπορείτε να το κάνετε αυτό μέσω της επιλογής "Δωρεά" - κάντε αυτή την επιλογή για να ανοίξει η σελίδα δωρεών. Ευχαριστούμε! Χρήση τού Camera2 API - Ενεργοποίηση του Camera2 API σε συσκεύες Android 5 - προσφέρει επιπλέον χαρακτηριστικά, αλλά ενδέχεται να μην λειτουργούν σωστά σε όλες τις συσκευές (θα προκαλέσει μια επανεκκίνηση) + Ενεργοποίηση του Camera2 API - προσφέρει επιπλέον χαρακτηριστικά, αλλά ενδέχεται να μην λειτουργούν σωστά σε όλες τις συσκευές (θα προκαλέσει μια επανεκκίνηση) Σχετικά με Εφαρμογή και πληροφορίες εντοπισμού σφαλμάτων Ρυθμίσεις επαναφοράς diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3d73d06e4..354b9966f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -112,7 +112,7 @@ Carpeta de almacenamiento Carpeta para guardar los archivos de foto/video Utilizar el Framework de Acceso del Almacenamiento - Utilice el Framework de Acceso del Almacenamiento de Android 5 para guardar fotos y videos + Utilice el Framework de Acceso del Almacenamiento para guardar fotos y videos Prefijo de foto Prefijo utilizado para el nombre de las fotos Prefijo de video @@ -228,7 +228,7 @@ Done para apoyar el proyecto Si te gusta esta aplicación, por favor considera hacer una donación para apoyar el proyecto. Puedes hacerlo comprando mi "aplicación de donación" - haz clic en esta opción para abrir la página de mi aplicación de donación. ¡Gracias! Utiliza Camera2 API - Utiliza la Camara2 de Android 5 - ofrece funcionalidades extra, pero esta en fase experimental (causara un reseteo de la aplicación) + Utiliza la Camara2 - ofrece funcionalidades extra, pero esta en fase experimental (causara un reseteo de la aplicación) Acerca de Información de aplicación y depuración Restablecer ajustes diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2ae73e666..61d56343d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -103,7 +103,7 @@ Mettre en pause après la prise de photo Mettre en pause l\'écran après avoir pris une photo, avec la possibilité de partager ou supprimer la photo Son de l\'obturateur - Jouer un son lorsque vous prenez une photo (nécessite Android 4.2 ou supérieur pour désactiver) + Jouer un son lorsque vous prenez une photo Touches de volumes Option contrôle audio Sensibilité contrôle audio @@ -111,7 +111,7 @@ Dossier de stockage Dossier où sont stockés les fichiers photo/vidéo Utilisation «\u00A0Storage Access Framework\u00A0» - Utilise le Storage Access Framework d\'Android 5 pour enregistrer les photos et vidéos + Utilise le Storage Access Framework pour enregistrer les photos et vidéos Préfixe du nom de photo Le préfixe est utilisé pour le nom de fichier des photos Préfixe du nom de la vidéo @@ -224,7 +224,7 @@ Faire un don pour soutenir le développement Si vous aimez ce logiciel, n\'hésitez pas à faire un don. Vous pouvez le faire via l\'achat de mon «\u00A0application de don\u00A0» - Cliquer sur cette option va ouvrir la page de l\'application de don. Merci\u00A0! Utiliser l\'API Camera2 - Active l\'API Camera2 d\'Android 5 - permet d\'utiliser des fonctionnalités supplémentaires, mais reste encore expérimental (peut provoquer un redémarrage) + Active l\'API Camera2 - permet d\'utiliser des fonctionnalités supplémentaires, mais reste encore expérimental (peut provoquer un redémarrage) À propos Informations de l\'application et de debug Réinitialiser les paramètres diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 67c57ebef..fd2c10055 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -112,7 +112,7 @@ Mentés helye Fotók, videofájlok mentésének könyvtára Storage Access Framework használata - Használja-e az Android 5 Storage Access Frameworkjét a fotók és videók mentéséhez + Használja-e az Storage Access Frameworkjét a fotók és videók mentéséhez Fotó fájlnév előtag A fényképek mentésekor használt fájlnév előtag Videó fájlnév előtag @@ -228,7 +228,7 @@ Támogasd a fejlesztést adománnyal A tetszik az alkalmazás, fontold meg adomány küldését a fejlesztés támogatására. Ezt a „támogatói alkalmazás” megvásárlásával teheted meg – kattints ide, hogy megnyisd a támogató alkalmazás oldalát. Köszönjük! Camera2 API használata - Lehetővé teszi az Android 5-ös Camera2 API használatát - extra funkciókat kínál, de nem minden eszközön működik megfelelően (újraindulást eredményez) + Lehetővé teszi az Camera2 API használatát - extra funkciókat kínál, de nem minden eszközön működik megfelelően (újraindulást eredményez) Névjegy App és hibakeresési információk Beállítások visszaállítása diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index f94aea7f7..5378761f3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -103,7 +103,7 @@ Pausa dopo aver scattato la foto Mette in pausa lo schermo dopo aver scattato la foto, permettendo inoltre di condividere o cancellare la foto Suono otturatore - Emette un suono quando scatta una foto (richiede Android 4.2 o versioni superiori per disabilitarlo) + Emette un suono quando scatta una foto Tasti volume Opzioni controllo Audio Sensibilità controllo Audio @@ -111,7 +111,7 @@ Posizione di salvataggio Cartella in cui salvare foto e video Usa Storage Access Framework - Quando utilizzare Storage Access Framework di Android 5 per il salvataggio di foto e video + Quando utilizzare Storage Access Framework per il salvataggio di foto e video Salva prefisso per foto Prefisso da usare per il filename di salvataggio delle foto Salva prefisso per video @@ -223,7 +223,7 @@ Dona per supportare lo sviluppo Se questa applicazione ti piace, puoi sempre pensare di fare una donazione. Puoi farlo premendo sul relativo bottone - cliccando su quel tasto aprirai la pagina per la donazione. Grazie mille! Usa le API Camera2 - Abilita API Camera2 di Android 5 - offre caratteristiche extra, ma potrebbe non funzionare correttamente su tutti i modelli (potrebbe causare un riavvio) + Abilita API Camera2 - offre caratteristiche extra, ma potrebbe non funzionare correttamente su tutti i modelli (potrebbe causare un riavvio) Informazioni App e informazioni di debug Reset settings diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 3ef71b1e5..1dd4281d5 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -103,13 +103,13 @@ 撮影の後に一時停止する 一時停止した画面上で写真の共有もしくは削除ができます シャッター音 - 撮影時に音を再生する (無効にする場合はAndroid 4.2以上が必要です) + 撮影時に音を再生する 音量キー 保存場所 写真/ビデオを保存するフォルダを決めます ストレージへのフレームワークを使用する - 写真やビデオを保存する際にAndroid 5.0以降のフレームワークを使用するかどうかを選択します + 写真やビデオを保存する際にStorage Accessフレームワークを使用するかどうかを選択します 保存する写真の命名ルール 保存する写真のファイル名の手前につける内容を設定します 保存するビデオの命名ルール @@ -214,7 +214,7 @@ サポートのために寄付をする このアプリが気に入りましたら寄付をお願いします。この項目を押すと寄付への窓口が開きます。寄付権を購入する事で寄付ができます。寄付してくれたらありがとう! Camera2 APIを使う - 有効にするとAndroid 5.0以降に搭載のCamera2 APIを使用します。この設定は試験的に提供しています (再起動が必要です) + 有効にするとCamera2 APIを使用します。この設定は試験的に提供しています (再起動が必要です) このアプリについて アプリとデバッグの情報を表示します 設定をリセットする diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 7ed0295b1..c9aadae57 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -112,7 +112,7 @@ Lagringsplasseringen Mappen som bildene/videoen skal lagres i. Bruk lagringstilgangsrammeverket - Hvorvidt Android 5.x sin lagringstilgangsrammeverk skal brukes til å lagre bilder og videoer. + Hvorvidt lagringstilgangsrammeverk skal brukes til å lagre bilder og videoer. Forstavelsen til fotolagring Forstavelsen som skal brukes til lagringsfilnavnene til bildene. Forstavelsen til videolagring @@ -228,7 +228,7 @@ Doner for å støtte utviklingen. Hvis du liker denne appen, så tenk gjerne på om du vil gi meg en donasjon for å støtte utviklingen. Du kan gjøre dette ved å kjøpe min "donasjonsapp" — Klikk på denne innstillingen for å gå til siden for min donasjonsapp. Takk! Bruk Camera2-APIen - Aktiverer Android 5.x sin Camera2-API - Den tilbyr ekstra egenskaper, men kan kanskje ikke virke riktig på alle enheter (Vil føre til en omstart). + Aktiverer Camera2-API - Den tilbyr ekstra egenskaper, men kan kanskje ikke virke riktig på alle enheter (Vil føre til en omstart). Om Open Camera App- og avlusings-informasjon Tilbakestill innstillinger diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 7cf003bf3..88036b933 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -111,7 +111,7 @@ Lokalizacja zapisu Folder, do którego będą zapisywane pliki Używaj SAF (systemowa obsługa dostępu do pamięci) - Używa Storage Access Framework Androida 5 do zapisu plików zdjęć i filmów + Używa Storage Access Framework do zapisu plików zdjęć i filmów Przedrostek nazw zdjęć Przedrostek używany w nazwach plików zdjęć Przedrostek nazw filmów @@ -227,7 +227,7 @@ Przekaż darowiznę Jeśli spodobała Ci się ta aplikacja rozważ przekazanie darowizny, która wesprze rozwój aplikacji. Możesz to zrobić poprzez zakup specjalnej aplikacji - dotknij tutaj aby otworzyć stronę. Dzięki! Używaj Camera2 API - Włącza Camera2 API Androida 5, które oferuje wiele dodatkowych funkcji, ale może działać niepoprawnie na niektórych urządzeniach (może spowodować restart) + Włącza Camera2 API, które oferuje wiele dodatkowych funkcji, ale może działać niepoprawnie na niektórych urządzeniach (może spowodować restart) O aplikacji Informacje o aplikacji i debugowanie Reset ustawień diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 33fdc4dc3..8b62133df 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -99,7 +99,7 @@ Pausar depois de tirar foto Pausar a tela depois de tirar uma foto, com a opção para compartilhar ou deletar foto Som de captura - Toca um som quando tira uma foto (requer Android 4.2+ para desabilitar) + Toca um som quando tira uma foto Teclas de volume Local de armazenamento Escolha a pasta para salvar os arquivos de foto/vídeo diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 2a9b9a7e7..84cbc11ab 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -112,7 +112,7 @@ Local de armazenamento Pasta para guardar os ficheiros das fotografias/vídeos Usar Storage Access Framework - Optar por usar o Storage Access Framework do Android 5 para guardar fotografias e vídeos + Optar por usar o Storage Access Framework para guardar fotografias e vídeos Prefixo das fotografias guardadas O prefixo usado para guardar o nome dos ficheiros das fotografias Prefixo dos vídeos guardados @@ -228,7 +228,7 @@ Doar para apoiar o desenvolvimento Se gosta desta aplicação, por favor concidere fazer um donativo para apoiar o desenvolvimento. Pode fazê-lo ao comprar a minha "aplicação de donativo" - clique nesta opção para abrir a página da minha aplicação de donativo. Obrigado! Usar API Camera2 - Ativa a API Camera2 do Android 5 - oferece funcionalidades extra, mas é atualmente experimental (causará reinício) + Ativa a API Camera2 - oferece funcionalidades extra, mas é atualmente experimental (causará reinício) Sobre Informações da aplicação e de depuração Repor definições diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3f2978880..0f7e97a3e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -104,7 +104,7 @@ Пауза после съёмки Пауза после снятия фото, с возможностью поделиться или удалить фотографию Звук затвора - Воспроизведение звука при съемке фотографии (требуется Android 4.2+ для отключения) + Воспроизведение звука при съемке фотографии Клавиши громкости Настройки управления звуком Чувствительность управления звуком @@ -112,7 +112,7 @@ Папка сохранения Имя папки для сохранения фото и видео (также может быть полный путь) Использовать Storage Access Framework - Для Android 5 использовать Storage Access Framework для сохранения фото и видео + Использовать Storage Access Framework для сохранения фото и видео Префикс для фото Префикс имен файлов для сохраняемых фото Префикс для видео @@ -228,7 +228,7 @@ Пожертвовать Если вам нравится это приложение, киньте мне копейку. Вы можете сделать это, купив мое приложение. Спасибо! Использовать Camera2 API - Разрешает использование Camera2 API для Android 5 - дополнительные, но экспериментальные возможности (требуется перезапуск) + Разрешает использование Camera2 API - дополнительные, но экспериментальные возможности (требуется перезапуск) О программе Информация Сброс настроек diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 83f93c01c..1c0b0cd8e 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -112,7 +112,7 @@ Mesto za shranjevanje Mapa za shranjevanje datotek fotografij/videoposnetkov Uporabi ogrodje za dostop do pomnilniške naprave - Ali naj se uporabi ogrodje za dostop do pomnilniške naprave Androida 5 za shranjevanje fotografij in videoposnetkov + Ali naj se uporabi ogrodje za dostop do pomnilniške naprave za shranjevanje fotografij in videoposnetkov Predpona shranjenih fotografij Predpona imena datotek fotografij Predpona shranjenih videoposnetkov @@ -228,7 +228,7 @@ Daruj za podporo razvoju Če vam je ta program všeč, razmislite o darovanju, da podprete razvoj. To lahko naredite z nakupom mojega "programa za darovanje" - kliknite na to možnost za odpiranje strani z mojim programom. Hvala! Uporabi API Camera2 - Omogoči API Camera2 Androida 5 - ponuja dodatne značilnosti, vendar morda ne bo pravilno deloval na vseh napravah (lahko povzroči ponovni zagon) + Omogoči API Camera2 - ponuja dodatne značilnosti, vendar morda ne bo pravilno deloval na vseh napravah (lahko povzroči ponovni zagon) O programu Program in podatki za razhroščevanje Ponastavi nastavitve diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 6faf399f0..011a4fbad 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -103,13 +103,13 @@ Fotoğraf çektikten sonra beklet Fotoğraf çektikten sonra fotoğrafı paylaşma ya da silme seçeneği için ekranı duraklat Fotoğraf çekme sesi - Fotoğraf çekerken ses çal(kapatmak için Android 4.2 ya da daha üstü gereklidir) + Fotoğraf çekerken ses çal Ses seviyesi tuşları Kaydetme yeri Fotoğraf/vidyo dosyaları için kayıt klasörü Storage Access Framework kullan - Android 5\'s fotoğraf ve vidyoları kaydetmek için Storage Access Framework kullan + Fotoğraf ve vidyoları kaydetmek için Storage Access Framework kullan Fotoğraf adlandırma öneki kaydet Fotoğraflarda dosya adlarını kaydetmede kullanılacak önek vidyo adlandırma öneki kaydet @@ -213,7 +213,7 @@ Geliştirmeyi desteklemek için bağışta bulunun Uygulamayı beğendiyseniz, bağış yapmayı düşünebilirsiniz. "donation app" satın alarak bunu yapabilirsiniz - bu seçeneğe tıkladığınızda bağış uygulaması için sayfam açılacaktır. Teşekkürler! Camera2 API sini kullan - Etkinleştirir Android 5\'s Camera2 API - ekstra özellikler sunar fakat şuan deneyseldir(yeniden başlatacaktır) + Etkinleştirir Camera2 API - ekstra özellikler sunar fakat şuan deneyseldir(yeniden başlatacaktır) Hakkında Uygulama ve eksiklik bilgisi Ayarları temizle diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 0f220824d..dc81774a0 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -104,7 +104,7 @@ Пауза після знімку Пауза після зняття фото, з можливістю поділитися чи видалити фотографію Звук затвору - Відтворення звуку під час знімку фотографії (потрібно версія Android 4.2+ аби вимкнути) + Відтворення звуку під час знімку фотографії Кнопки гучності Налаштування керування звуком @@ -113,7 +113,7 @@ Тека збереження "Ім'я теки для збереження фото та відео (також може бути повний шлях)" Використовувати Storage Access Framework - Для Android 5 використовувати Storage Access Framework для збереження фото та відео + Використовувати Storage Access Framework для збереження фото та відео Префікс для фото Префікс імен файлів для знімків Префікс для відео @@ -229,7 +229,7 @@ Подякувати Якщо вам сподобався цей додаток, киньте монетку. Ви можете зробити це, придбавши мій додаток. Дякую! Використовувати Camera2 API - Дозволяє використання Camera2 API для Android 5 - додаткові, але експериментальні можливості (потрібно перезавантажити) + Дозволяє використання Camera2 API - додаткові, але експериментальні можливості (потрібно перезавантажити) Про додаток Інформація Скидання налаштувань diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 416df69cb..91457294a 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -112,7 +112,7 @@ Vị trí lưu Thư mục lưu tệp tin ảnh/video Sử dụng Khung Truy cập Lưu trữ - Sử dụng Khung Truy cập Lưu trữ để lưu ảnh và video. Nên kích hoạt (từ Android 5 trở lên) để có thể lưu vào thẻ nhớ ngoài. + Sử dụng Khung Truy cập Lưu trữ để lưu ảnh và video. Nên kích hoạt để có thể lưu vào thẻ nhớ ngoài. Tiền tố ảnh Đặt tiền tố trong tên tệp khi lưu ảnh Tiền tố video diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 292e86201..e3b25a280 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -103,7 +103,7 @@ 拍照后暂停 拍照后暂停屏幕,带有选项分享或删除照片 快门声音 - 拍照时播放声音(需要 Android 4.2 或更高才能禁用) + 拍照时播放声音 音量键功能 语音识别 麦克风灵敏度 @@ -111,7 +111,7 @@ 保存位置 用来保存照片/视频文件的文件夹 使用存储访问架构 - 是否使用 Android 5 的存储访问架构保存照片和视频 + 是否使用存储访问架构保存照片和视频 保存照片前缀 用于保存照片文件名的前缀 保存视频前缀 @@ -220,7 +220,7 @@ 捐赠以支持开发 如果您喜欢这个程序,可以通过购买我的“捐助 app”向我捐助。点击此选项将打开我的“捐助 app”页面。谢谢! 使用 Camera2 API - 启用 Android 5 的 Camera2 API - 提供附加功能,但当前处于实验阶段 (会引起重启) + 启用 Camera2 API - 提供附加功能,但当前处于实验阶段 (会引起重启) 关于 应用程序和调试信息 复位设置 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index e43886665..03e47cbba 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -102,12 +102,12 @@ 拍照後暫停 拍照後暫停螢幕,顯示分享或刪除照片選項 快門聲音 - 拍照時播放聲音(需要 Android 4.2 或更高才能停用) + 拍照時播放聲音 音量鍵 儲存位置 用來儲存照片/影片檔的資料夾 使用 Storage Access Framework - 是否使用 Android 5 的 Storage Access Framework 來儲存照片和影片 + 是否使用 Storage Access Framework 來儲存照片和影片 照片檔名前綴 用於儲存照片檔名的前置字串 影片檔名前綴 @@ -210,7 +210,7 @@ 捐贈以支援開發 如果您喜歡這個程式,請考慮捐助。您可以透過購買我的“捐助 app”來進行捐助 - 點擊此選項將打開我的捐助 app 頁面。謝謝! 使用 Camera2 API - 啟用 Android 5 的 Camera2 API - 提供更多功能,但仍在實驗中 (會造成重新啟動) + 啟用 Camera2 API - 提供更多功能,但仍在實驗中 (會造成重新啟動) 關於 應用程式和除錯資訊 復原設定 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bedfa3055..c8d1515e3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -113,7 +113,7 @@ Save location Folder to save the photo/video files in Use Storage Access Framework - Whether to use Storage Access Framework for saving photos and videos. This should be enabled (on Android 5+) to allow saving to external SD cards. + Whether to use Storage Access Framework for saving photos and videos. This should be enabled to allow saving to external SD cards. Save photo prefix The prefix to use for the save filenames for photos Save video prefix -- GitLab From daa6e59a63fe75057a8921b45d7e8f11ff783458 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Dec 2019 22:34:43 +0000 Subject: [PATCH 017/243] Clarify digital video stabilization. --- _docs/help.html | 5 +++-- app/src/main/res/values/strings.xml | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 716dc6c44..9f3bb327b 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -905,8 +905,9 @@ be left set to true for faster operation, but it's an option just in case.

    --

    Video resolution - Select the resolution of videos taken by the camera.

    -

    Enable video stabilization - Video stabilization reduces the shaking due to the motion of the camera in -both the preview and in recorded videos.

    +

    Enable digital video stabilization - Video stabilization reduces the shaking due to the motion of the camera in +both the preview and in recorded videos. This enables a digital method in the camera driver, and may be unnecessary if +your device supports optical image stabilization (OIS).

    Video format - Allows choice of various video file formats and codecs. Please test before using, as some may not work properly on all devices! Also note:

      diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c8d1515e3..9cadf61c3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -200,8 +200,8 @@ Video resolution Force 4K UHD video (only works on some devices) Enable 3840x2160 resolution for video recording on back camera - this option is a hack that may allow 4K devices on 4K cameras that don\'t expose the option to 3rd party camera apps. This isn\'t guaranteed to work, please test before working. - Enable video stabilization - Video stabilization reduces the shaking due to the motion of the camera in both the preview and in recorded videos + Enable digital video stabilization + Video stabilization reduces the shaking due to the motion of the camera in both the preview and in recorded videos. This may be unnecessary if your device supports optical image stabilization (OIS). Video bitrate (approx) Set the approximate bitrate of videos (higher means better quality, but takes up more disk space; may cause video recording to fail if bitrate not supported)\n%s Video frame rate (approx) -- GitLab From 0289a7a77a8699858f7cae6240d9d8236c2af5c4 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 9 Dec 2019 00:00:06 +0000 Subject: [PATCH 018/243] When using "Pause after taking photo", touching to unpause no longer triggers auto focus, or taking another photo for "Touch to capture". --- _docs/history.html | 5 +++++ .../sourceforge/opencamera/preview/Preview.java | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 4f73769f2..7aeaa290b 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -48,6 +48,11 @@

      < Main Page.

      +Version 1.48 (Work in progress)
      +
      +FIXED   When using "Pause after taking photo", touching to unpause no longer
      +        triggers auto focus, or taking another photo for "Touch to capture".
      +
       Version 1.47.3 (2019/10/20)
       
       FIXED   Grids were being drawing too faintly.
      diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      index bb729714d..00450a79e 100644
      --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      @@ -549,6 +549,11 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
           public boolean touchEvent(MotionEvent event) {
               if( MyDebug.LOG )
                   Log.d(TAG, "touch event at : " + event.getX() + " , " + event.getY() + " at time " + event.getEventTime());
      +
      +        boolean was_paused = !this.is_preview_started;
      +        if( MyDebug.LOG )
      +            Log.d(TAG, "was_paused: " + was_paused);
      +
               if( gestureDetector.onTouchEvent(event) ) {
                   if( MyDebug.LOG )
                       Log.d(TAG, "touch event handled by gestureDetector");
      @@ -619,7 +624,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
               }
               cancelAutoFocus();
       
      -        if( camera_controller != null && !this.using_face_detection ) {
      +        // don't set focus areas on touch if the user is touching to unpause!
      +        if( camera_controller != null && !this.using_face_detection && !was_paused ) {
                   this.has_focus_area = false;
                   ArrayList areas = getAreas(event.getX(), event.getY());
                   if( camera_controller.setFocusAndMeteringArea(areas) ) {
      @@ -636,7 +642,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
                   }
               }
       
      -        if( !this.is_video && applicationInterface.getTouchCapturePref() ) {
      +        // don't take a photo on touch if the user is touching to unpause!
      +        if( !this.is_video && !was_paused && applicationInterface.getTouchCapturePref() ) {
                   if( MyDebug.LOG )
                       Log.d(TAG, "touch to capture");
                   // interpret as if user had clicked take photo/video button, except that we set the focus/metering areas
      @@ -644,7 +651,10 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
                   return true;
               }
       
      -        tryAutoFocus(false, true);
      +        // don't auto focus on touch if the user is touching to unpause!
      +        if( !was_paused ) {
      +            tryAutoFocus(false, true);
      +        }
               return true;
           }
       
      -- 
      GitLab
      
      
      From 753c1633d9a9f7b0cad5a3db675e4c1ae495b85a Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Tue, 10 Dec 2019 23:22:18 +0000
      Subject: [PATCH 019/243] Update testTakePhotoFrontCamera() to check all
       non-default cameras.
      
      ---
       .../opencamera/test/MainActivityTest.java     | 96 +++++++++++--------
       1 file changed, 57 insertions(+), 39 deletions(-)
      
      diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java
      index 4d6cfdd13..79e808470 100644
      --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java
      +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java
      @@ -4032,7 +4032,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2
      Date: Tue, 10 Dec 2019 23:46:39 +0000
      Subject: [PATCH 020/243] Update comment for getNRModePref().
      
      ---
       .../sourceforge/opencamera/preview/ApplicationInterface.java    | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java
      index d4becefb8..b08d34a18 100644
      --- a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java
      +++ b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java
      @@ -110,7 +110,7 @@ public interface ApplicationInterface {
               NRMODE_NORMAL,
               NRMODE_LOW_LIGHT
           }
      -    NRModePref getNRModePref(); // only relevant if getBurstForNoiseReduction() returns true
      +    NRModePref getNRModePref(); // only relevant if getBurstForNoiseReduction() returns true; if this changes without reopening the preview's camera, call Preview.setupBurstMode()
           boolean getOptimiseAEForDROPref(); // see CameraController doc for setOptimiseAEForDRO().
           enum RawPref {
               RAWPREF_JPEG_ONLY, // JPEG only
      -- 
      GitLab
      
      
      From a3721dc3f638246d6910053a5384efc71affe0ed Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Tue, 10 Dec 2019 23:58:50 +0000
      Subject: [PATCH 021/243] Test low light mode in testTakePhotoNR.
      
      ---
       .../opencamera/test/MainActivityTest.java      | 18 ++++++++++++++++++
       .../cameracontroller/CameraController.java     |  1 +
       .../cameracontroller/CameraController2.java    |  2 +-
       3 files changed, 20 insertions(+), 1 deletion(-)
      
      diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java
      index 79e808470..2afc0573c 100644
      --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java
      +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java
      @@ -3434,6 +3434,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= CameraController.ISO_FOR_DARK )
      +            assertEquals(CameraController.N_IMAGES_NR_DARK_LOW_LIGHT, mActivity.getPreview().getCameraController().getBurstTotal());
      +        // reset
      +        mActivity.getApplicationInterface().setNRMode("preference_nr_mode_normal");
      +        mActivity.getPreview().setupBurstMode();
      +
               // then try front camera
       
               if( mPreview.getCameraControllerManager().getNumberOfCameras() <= 1 ) {
      @@ -10420,6 +10437,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= 1100 ) {
      +                        if( capture_result_iso >= ISO_FOR_DARK ) {
                                   if( MyDebug.LOG )
                                       Log.d(TAG, "optimise for dark scene");
                                   n_burst = noise_reduction_low_light ? N_IMAGES_NR_DARK_LOW_LIGHT : N_IMAGES_NR_DARK;
      -- 
      GitLab
      
      
      From 1a01f7b8bd6fb10e34846964b9056b725233ecd7 Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Thu, 12 Dec 2019 00:39:00 +0000
      Subject: [PATCH 022/243] Updates to FAQ.
      
      ---
       _docs/help.html                               | 37 ++++++++++++-------
       .../sourceforge/opencamera/MainActivity.java  |  1 +
       2 files changed, 24 insertions(+), 14 deletions(-)
      
      diff --git a/_docs/help.html b/_docs/help.html
      index 9f3bb327b..88ea00c51 100644
      --- a/_docs/help.html
      +++ b/_docs/help.html
      @@ -1165,6 +1165,19 @@ the Storage Access Framework method as with Android 5 (or the Android/dat
       with Android 4.4).
       
    +

    Can you implement disabling shutter sound for my phone? - + If Open Camera shows the option Settings/"Camera API", then changing to "Camera2 API" means you'll be able to disable + shutter sounds under "Settings/More camera controls...". + When not using Camera2 API, if the option "Shutter sound" under "More camera controls..." isn't shown, + then it's not available. There + are possible workarounds for some of these devices (which is why some third party camera applications + may be able to silence the shutter), though the issue is these don't work on all devices, and tend + to use methods that Google now discourage. The fault is with the device for not supporting + standard method for cameras to disable the shutter sound on Android. In particular, if under Settings/About + you see that "Can disable shutter sound?" says No, it means the device's camera API is telling 3rd + party camera apps that shutter sound can't be disabled (so either it can't do it, or the API is lying + - either way, this should be reported to your manufacturer).

    +

    Photos or videos fail to save! - Firstly, if you're trying to save to an external SD card, see "How can I save to my external SD card?" above. Otherwise:

    Frequently Asked Questions

    @@ -1168,28 +1168,28 @@ with Android 4.4).

    Can you implement disabling shutter sound for my phone? - - If Open Camera shows the option Settings/"Camera API", then changing to "Camera2 API" means you'll be able to disable - shutter sounds under "Settings/More camera controls...". - When not using Camera2 API, if the option "Shutter sound" under "More camera controls..." isn't shown, - then it's not available. There - are possible workarounds for some of these devices (which is why some third party camera applications - may be able to silence the shutter), though the issue is these don't work on all devices, and tend - to use methods that Google now discourage. The fault is with the device for not supporting - standard method for cameras to disable the shutter sound on Android. In particular, if under Settings/About - you see that "Can disable shutter sound?" says No, it means the device's camera API is telling 3rd - party camera apps that shutter sound can't be disabled (so either it can't do it, or the API is lying - - either way, this should be reported to your manufacturer).

    + If Open Camera shows the option Settings/"Camera API", then changing to "Camera2 API" means you'll be able to disable + shutter sounds under "Settings/More camera controls...". + When not using Camera2 API, if the option "Shutter sound" under "More camera controls..." isn't shown, + then it's not available. There + are possible workarounds for some of these devices (which is why some third party camera applications + may be able to silence the shutter), though the issue is these don't work on all devices, and tend + to use methods that Google now discourage. The fault is with the device for not supporting + standard method for cameras to disable the shutter sound on Android. In particular, if under Settings/About + you see that "Can disable shutter sound?" says No, it means the device's camera API is telling 3rd + party camera apps that shutter sound can't be disabled (so either it can't do it, or the API is lying + - either way, this should be reported to your manufacturer).

    Photos or videos fail to save! - Firstly, if you're trying to save to an external SD card, see "How can I save to my external SD card?" above. Otherwise:

      -
    • If Settings/More camera controls/"Use Storage Access Framework" is enabled, - in some cases the permission may be lost, try rechoosing the save location (from - Settings/More camera controls/"Save location".
    • -
    • If not using Storage Access Framework, but you have changed the save location, - it may be you've chosen somewhere where applications don't have permission to save - files.
    • -
    • Or sometimes simply restarting the devices fixes such problems.
    • +
    • If Settings/More camera controls/"Use Storage Access Framework" is enabled, + in some cases the permission may be lost, try rechoosing the save location (from + Settings/More camera controls/"Save location".
    • +
    • If not using Storage Access Framework, but you have changed the save location, + it may be you've chosen somewhere where applications don't have permission to save + files.
    • +
    • Or sometimes simply restarting the devices fixes such problems.

    My pictures are being rotated/cropped! - This likely means the auto-level @@ -1219,8 +1219,8 @@ camera, and there is no guarantee that they will be met. For best chance of succ the standard Android camera API. Some devices do now support high speed frame rates when Camera2 API is enabled.

    Why doesn't Open Camera show 23MP resolution on my Sony Xperia, only 8MP? - This was a problem on older devices - and/or with the old Camera API because of Sony not making this available to third party camera applications. On newer Sony - devices, this should become available if you set Settings/"Camera API" to "Camera2 API".

    + and/or with the old Camera API because of Sony not making this available to third party camera applications. On newer Sony + devices, this should become available if you set Settings/"Camera API" to "Camera2 API".

    Why does the resolution of my photos not match the specified camera resolution? - This happens if auto-level is enabled. The image is rotated to be level, which means the @@ -1232,11 +1232,11 @@ standard Android API for 3rd party camera apps to use.

    Why doesn't touch to focus work? - Touching the screen should allow you to choose a particular region to focus on. If this doesn't work:

      -
    • Check the focus mode (under the popup menu), for best results you usually want - Continuous focus iconContinuous or - Continuous focus iconAuto focus modes.
    • -
    • Check that Settings/"Face detection" is disabled (focus regions aren't possible in face detection mode).
    • -
    • Some devices or cameras (especially front cameras) don't support touch to focus.
    • +
    • Check the focus mode (under the popup menu), for best results you usually want + Continuous focus iconContinuous or + Continuous focus iconAuto focus modes.
    • +
    • Check that Settings/"Face detection" is disabled (focus regions aren't possible in face detection mode).
    • +
    • Some devices or cameras (especially front cameras) don't support touch to focus.

    I get "FAILED TO OPEN CAMERA" - In some cases this is fixed by restarting @@ -1383,8 +1383,8 @@ no longer seems to work properly, try a reboot of your device, or if that fails settings to the defaults (under Settings/Settings manager/"Reset settings").

    If there's still a problem, please check other third party camera applications to see if they have the same - problem or not. (It's not enough to try your device's "stock" camera - in some cases, devices may have bugs for - third party camera applications that don't affect the stock camera.)

    + problem or not. (It's not enough to try your device's "stock" camera - in some cases, devices may have bugs for + third party camera applications that don't affect the stock camera.)

    If you find a bug, please report it here (please check for existing tickets first). diff --git a/_docs/info.html b/_docs/info.html index 3030a33d9..e54b35cb7 100644 --- a/_docs/info.html +++ b/_docs/info.html @@ -61,8 +61,8 @@

    Open Camera is completely free, however if you wish you can show your appreciation to me by making an optional payment. - Please note that this is not required, and that doing so will not provide any additional features (or remove the ads I have on the - website). However for those who wish to make a contribution to me, this is greatly appreciated!

    + Please note that this is not required, and that doing so will not provide any additional features (or remove the ads I have on the + website). However for those who wish to make a contribution to me, this is greatly appreciated!

    You can contribute through PayPal, simply click the "Buy Now" button, and enter the amount you wish to give me:

    @@ -82,9 +82,9 @@ the same amount! Unfortunately PayPal doesn't seem to allow offering the same de
    -- GitLab From 1aa9b2b8048e39083a1ba37dfdc5da7feb1bc7b3 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 30 Dec 2019 19:49:19 +0000 Subject: [PATCH 050/243] Move video bitrate and frame rate options to debugging section. --- _docs/help.html | 42 ++++++++++++++-------------- _docs/history.html | 1 + app/src/main/res/xml/preferences.xml | 32 ++++++++++----------- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 0d9d74a2c..7deb36183 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -918,27 +918,6 @@ not work properly on all devices! Also note:

    • If using 3GPP, then restarting video when hitting maximum filesize will not be seamless (even on Android 8).
    -

    Video bitrate (approx) - If set to a value other than "default", the default video bitrate is overridden. Higher values mean better -quality video, but the files take up more disk space. Note that some values may be unsupported by your device, and may -cause the recording to fail - in some cases, this can cause problems with the camera that require a reboot to fix. So -please test before using. Also note that the bitrate setting is approximate - the resultant video file will typically be slightly different -to that requested.

    - -

    Video frame rate (approx) - If set to a value other than "default", the camera will try to match this frame -rate.

    -
      -
    • This is very approximate, as frame rate depends on many factors such as your device and lighting - conditions, and this is only a "recommendation" to the camera driver, so there is no guarantee that the - resultant video's frame rate will match with the requested value.
    • -
    • Some frame rate values may be unsupported by your device, and cause the recording to fail, so please test before - using.
    • -
    • Even if video recording is successful, if achieving a specific FPS is desired, please check the resultant video's - frame rate rather than assuming that it was achieved.
    • -
    • For best results (especially for 120fps or higher), please set Settings/"Camera API" to "Camera2 API".
    • -
    • This setting is ignored in slow motion mode, where instead Open Camera will choose an appropriate high speed frame - rate.
    • -
    -

    Video flat (log) profile - Enables a "flat" or "log" color profile for recording video. Only available if Camera2 API is used. This is intended to create videos for further editing in post production. Note that it may be necessary to increase the video bitrate when shooting with a log profile. This feature is currently experimental, @@ -996,6 +975,27 @@ SRT files, and use them to display the information as subtitles. The subtitles w known). Similarly for "Store compass direction". Note that you can control the formatting style for date, time and location using the options under the "Photo settings" menu (Datestamp format, Timestamp format, GPS stamp format, Distance unit).

    +

    Video bitrate (approx) - If set to a value other than "default", the default video bitrate is overridden. Higher values mean better + quality video, but the files take up more disk space. Note that some values may be unsupported by your device, and may + cause the recording to fail - in some cases, this can cause problems with the camera that require a reboot to fix. So + please test before using. Also note that the bitrate setting is approximate - the resultant video file will typically be slightly different + to that requested.

    + +

    Video frame rate (approx) - If set to a value other than "default", the camera will try to match this frame + rate.

    +
      +
    • This is very approximate, as frame rate depends on many factors such as your device and lighting + conditions, and this is only a "recommendation" to the camera driver, so there is no guarantee that the + resultant video's frame rate will match with the requested value.
    • +
    • Some frame rate values may be unsupported by your device, and cause the recording to fail, so please test before + using.
    • +
    • Even if video recording is successful, if achieving a specific FPS is desired, please check the resultant video's + frame rate rather than assuming that it was achieved.
    • +
    • For best results (especially for 120fps or higher), please set Settings/"Camera API" to "Camera2 API".
    • +
    • This setting is ignored in slow motion mode, where instead Open Camera will choose an appropriate high speed frame + rate.
    • +
    +

    Force 4K UHD video (may not work on all devices) - Enable recording in 4K UHD (3840x2160) on the back camera (if ticked, this overrides the setting in "Video resolution"). This is provided for some phones that don't properly expose their 4K video resolution to 3rd party camera apps (and so 4K resolution doesn't show in the Video resolution option above). diff --git a/_docs/history.html b/_docs/history.html index 1ad18b3be..10722dd29 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -60,6 +60,7 @@ FIXED Seamless video restart on maximum filesize (for Android 8+) wasn't broad FIXED Recording video on Android 8+ could leave zero-size files if size approached the maximum filesize, but a restart did not occur. UPDATED Don't set video digital stabilization when in photo mode. +UPDATED Moved video bitrate and frame rate options to debugging section. Version 1.47.3 (2019/10/20) diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 20d3c230d..229afb91e 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1004,22 +1004,6 @@ android:defaultValue="preference_video_output_format_default" /> - - - - + + + + Date: Mon, 30 Dec 2019 19:54:07 +0000 Subject: [PATCH 051/243] More details on audio source option. --- _docs/help.html | 3 ++- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 7deb36183..e549d968c 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -955,7 +955,8 @@ or later, the resume should be seamless (unless using 3GPP video file format).Audio source - Select the audio source for recording video. The effect of this depends on your device - if it supports an external microphone, you may be able to use this by selecting "External mic". The other options may provide different settings affecting the resultant audio (e.g., automatic gain control), though this behaviour is -device specific.

    +device specific. These options are just controls for the Android MediaRecorder API, and so the exact behaviour is +up to the device.

    Audio channels - If recording audio with video, this option allows you to specify mono or stereo recording. Note that most devices do not support stereo recording. Even for devices that do support this, you may need to modify diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 387522f25..5efe5caee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -217,7 +217,7 @@ Record audio Record audio when recording video Audio source - Microphone to use for recording audio\n%s + Microphone to use for recording audio. Note that the exact behaviour of the options depends on how the option is implemented on your device.\n%s Audio channels Specify mono or stereo for recording audio (stereo only supported on some devices) Flash while recording video -- GitLab From 0666694a9c0b4232807462f98084f6604ee357f2 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 2 Jan 2020 23:24:08 +0000 Subject: [PATCH 052/243] manual merge: manual seekbar values for exposure times up to 1200s --- .../opencamera/ui/ManualSeekbars.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/ManualSeekbars.java b/app/src/main/java/net/sourceforge/opencamera/ui/ManualSeekbars.java index 7af0f53ee..148a296d3 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/ManualSeekbars.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/ManualSeekbars.java @@ -218,7 +218,30 @@ public class ManualSeekbars { } // 20 to 60, per 5s - for(int i=20;i<=60;i+=5) { + for(int i=20;i<60;i+=5) { + long exposure = 1000000000L*i; + if( exposure > min_exposure_time && exposure < max_exposure_time ) + seekbar_values.add(exposure); + } + + // n.b., very long exposure times are not widely supported, but requested at https://sourceforge.net/p/opencamera/code/merge-requests/49/ + + // 60 to 180, per 15s + for(int i=60;i<180;i+=15) { + long exposure = 1000000000L*i; + if( exposure > min_exposure_time && exposure < max_exposure_time ) + seekbar_values.add(exposure); + } + + // 180 to 600, per 60s + for(int i=180;i<600;i+=60) { + long exposure = 1000000000L*i; + if( exposure > min_exposure_time && exposure < max_exposure_time ) + seekbar_values.add(exposure); + } + + // 600 to 1200, per 120s + for(int i=600;i<=1200;i+=120) { long exposure = 1000000000L*i; if( exposure > min_exposure_time && exposure < max_exposure_time ) seekbar_values.add(exposure); -- GitLab From 719ec033c5a749da67ee5f3bb69fdac139b736e4 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 4 Jan 2020 01:01:51 +0000 Subject: [PATCH 053/243] Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. --- _docs/history.html | 2 + .../sourceforge/opencamera/MainActivity.java | 52 ++++++++++++++++--- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 10722dd29..623f13d95 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -59,6 +59,8 @@ FIXED Seamless video restart on maximum filesize (for Android 8+) wasn't broad except the last one, meaning they were taking longer to show up in mediastore gallery. FIXED Recording video on Android 8+ could leave zero-size files if size approached the maximum filesize, but a restart did not occur. +UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or + back facing. UPDATED Don't set video digital stabilization when in photo mode. UPDATED Moved video bitrate and frame rate options to debugging section. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 327adbd17..7b4f21b93 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1,6 +1,7 @@ package net.sourceforge.opencamera; import net.sourceforge.opencamera.cameracontroller.CameraController; +import net.sourceforge.opencamera.cameracontroller.CameraControllerManager; import net.sourceforge.opencamera.cameracontroller.CameraControllerManager2; import net.sourceforge.opencamera.preview.Preview; import net.sourceforge.opencamera.preview.VideoProfile; @@ -1033,6 +1034,36 @@ public class MainActivity extends Activity { preview.onResume(); + { + // show a toast for the camera if it's not the first for front of back facing (otherwise on multi-front/back camera + // devices, it's easy to forget if set to a different camera) + // but we only show this when resuming, not every time the camera opens + int cameraId = applicationInterface.getCameraIdPref(); + if( cameraId > 0 ) { + CameraControllerManager camera_controller_manager = preview.getCameraControllerManager(); + boolean front_facing = camera_controller_manager.isFrontFacing(cameraId); + if( MyDebug.LOG ) + Log.d(TAG, "front_facing: " + front_facing); + if( camera_controller_manager.getNumberOfCameras() > 2 ) { + boolean camera_is_default = true; + for(int i=0;i 2 ) { + // telling the user which camera is pointless for only two cameras, but on devices that now + // expose many cameras it can be confusing, so show a toast to at least display the id + String toast_string = getResources().getString( + preview.getCameraControllerManager().isFrontFacing(cameraId) ? R.string.front_camera : R.string.back_camera ) + + " : " + getResources().getString(R.string.camera_id) + " " + cameraId; + preview.showToast(null, toast_string); + } + } + /** * Selects the next camera on the phone - in practice, switches between * front and back cameras @@ -1423,14 +1465,8 @@ public class MainActivity extends Activity { this.closePopup(); if( this.preview.canSwitchCamera() ) { int cameraId = getNextCameraId(); - if( preview.getCameraControllerManager().getNumberOfCameras() > 2 ) { - // telling the user which camera is pointless for only two cameras, but on devices that now - // expose many cameras it can be confusing, so show a toast to at least display the id - String toast_string = getResources().getString( - preview.getCameraControllerManager().isFrontFacing(cameraId) ? R.string.front_camera : R.string.back_camera ) + - " : " + getResources().getString(R.string.camera_id) + " " + cameraId; - preview.showToast(null, toast_string); - } + + showCameraIdToast(cameraId); View switchCameraButton = findViewById(R.id.switch_camera); switchCameraButton.setEnabled(false); // prevent slowdown if user repeatedly clicks -- GitLab From 5a667221875e8e0fb784209eb1e867f8102c0791 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 10 Jan 2020 00:03:11 +0000 Subject: [PATCH 054/243] Add logging. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 7b4f21b93..1396db994 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -2611,6 +2611,8 @@ public class MainActivity extends Activity { } } if( thumbnail != null ) { + if( MyDebug.LOG ) + Log.d(TAG, "thumbnail orientation is " + media.orientation); if( media.orientation != 0 ) { if( MyDebug.LOG ) Log.d(TAG, "thumbnail size is " + thumbnail.getWidth() + " x " + thumbnail.getHeight()); -- GitLab From 277357ca08e5551779da186007a5a9116cf12298 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 11 Jan 2020 01:16:00 +0000 Subject: [PATCH 055/243] Fix problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. --- _docs/history.html | 2 ++ .../opencamera/ui/DrawPreview.java | 21 ++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 623f13d95..34f64dce5 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -59,6 +59,8 @@ FIXED Seamless video restart on maximum filesize (for Android 8+) wasn't broad except the last one, meaning they were taking longer to show up in mediastore gallery. FIXED Recording video on Android 8+ could leave zero-size files if size approached the maximum filesize, but a restart did not occur. +FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen + preview aspect ratio. UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. UPDATED Don't set video digital stabilization when in photo mode. diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 3ee57b198..ac272cc82 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -1550,8 +1550,11 @@ public class DrawPreview { text_base_y = canvas.getHeight() - (int)(2.5*gap_y); // leave room for GUI icons } else if( ui_rotation == 90 || ui_rotation == 270 ) { + // ui_rotation 90 is upside down portrait + // 270 is portrait + //text_base_y = canvas.getHeight() + (int)(0.5*gap_y); - /*ImageButton view = (ImageButton)main_activity.findViewById(R.id.take_photo); + View view = main_activity.findViewById(R.id.take_photo); // align with "top" of the take_photo button, but remember to take the rotation into account! view.getLocationOnScreen(gui_location); int view_left = gui_location[0]; @@ -1559,19 +1562,27 @@ public class DrawPreview { int this_left = gui_location[0]; // diff_x is the difference from the centre of the canvas to the position we want int diff_x = view_left - ( this_left + canvas.getWidth()/2 ); - */ + /*if( MyDebug.LOG ) { Log.d(TAG, "view left: " + view_left); Log.d(TAG, "this left: " + this_left); Log.d(TAG, "canvas is " + canvas.getWidth() + " x " + canvas.getHeight()); + Log.d(TAG, "compare offset_x: " + (preview.getView().getRootView().getRight()/2 - diff_x)/scale); }*/ + // diff_x is the difference from the centre of the canvas to the position we want // assumes canvas is centered // avoids calling getLocationOnScreen for performance - int diff_x = preview.getView().getRootView().getRight()/2 - (int) (100 * scale + 0.5f); // convert dps to pixels + /*int offset_x = (int) (124 * scale + 0.5f); // convert dps to pixels + // offset_x should be enough such that on-screen level angle (this is the lowest display on-screen text) does not + // interfere with take photo icon when using at least a 16:9 preview aspect ratio + // should correspond to the logged "compare offset_x" above + int diff_x = preview.getView().getRootView().getRight()/2 - offset_x; + */ + int max_x = canvas.getWidth(); if( ui_rotation == 90 ) { - // so we don't interfere with the top bar info (datetime, free memory, ISO) + // so we don't interfere with the top bar info (datetime, free memory, ISO) when upside down max_x -= (int)(2.5*gap_y); } /*if( MyDebug.LOG ) { @@ -1581,7 +1592,7 @@ public class DrawPreview { Log.d(TAG, "max_x: " + max_x); }*/ if( canvas.getWidth()/2 + diff_x > max_x ) { - // in case goes off the size of the canvas, for "black bar" cases (when preview aspect ratio != screen aspect ratio) + // in case goes off the size of the canvas, for "black bar" cases (when preview aspect ratio < screen aspect ratio) diff_x = max_x - canvas.getWidth()/2; } text_base_y = canvas.getHeight()/2 + diff_x - (int)(0.5*gap_y); -- GitLab From d9e4fef97b9590c51cf3cbc9391acb1f0d5a70ad Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 11 Jan 2020 16:15:26 +0000 Subject: [PATCH 056/243] Refactor log profile to allow more custom tonemaps, add JTLog. --- _docs/credits.html | 1 + .../sourceforge/opencamera/MainActivity.java | 25 ++- .../opencamera/MyApplicationInterface.java | 16 +- .../cameracontroller/CameraController.java | 14 +- .../cameracontroller/CameraController1.java | 6 +- .../cameracontroller/CameraController2.java | 168 +++++++++++------- .../preview/ApplicationInterface.java | 5 +- .../preview/BasicApplicationInterface.java | 4 +- .../opencamera/preview/Preview.java | 12 +- app/src/main/res/values/arrays.xml | 2 + app/src/main/res/values/strings.xml | 18 +- 11 files changed, 176 insertions(+), 95 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index 87bef5dad..896850bac 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -51,6 +51,7 @@

    • App icon by Adam Lapinski.
    • Improvements/help for video frame rates (including high speed) by George Joseph.
    • +
    • Support for the video picture profiles implementation and custom Log profile JTLog design by JT Haapala.
    • Smart Housing Bluetooth LE support by Edouard Lafargue
    • Improved selfie stick button support by Lau Keat Hwa.
    • Option for filenames to be based on UTC (Zulu) time by David Pletcher ( lpm_sourceforge AT cathedralcanyon DOT net , https://www.cathedralcanyon.net ).
    • diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 1396db994..4c719f7f1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4027,9 +4027,28 @@ public class MainActivity extends Activity { simple = false; } - if( applicationInterface.useVideoLogProfile() && preview.supportsTonemapCurve() ) { - simple = false; - toast_string += "\n" + getResources().getString(R.string.video_log); + { + CameraController.TonemapProfile tonemap_profile = applicationInterface.getVideoTonemapProfile(); + if( tonemap_profile != CameraController.TonemapProfile.TONEMAPPROFILE_OFF && preview.supportsTonemapCurve() ) { + if( applicationInterface.getVideoTonemapProfile() != CameraController.TonemapProfile.TONEMAPPROFILE_OFF && preview.supportsTonemapCurve() ) { + int string_id = 0; + switch( tonemap_profile ) { + case TONEMAPPROFILE_LOG: + string_id = R.string.video_log; + break; + case TONEMAPPROFILE_JTLOG: + string_id = R.string.preference_video_jtlog; + break; + } + if( string_id != 0 ) { + simple = false; + toast_string += "\n" + getResources().getString(string_id); + } + else { + Log.e(TAG, "unknown tonemap_profile: " + tonemap_profile); + } + } + } } boolean record_audio = applicationInterface.getRecordAudioPref(); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 067c9c6dd..4d8f46a76 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -721,26 +721,28 @@ public class MyApplicationInterface extends BasicApplicationInterface { } @Override - public boolean useVideoLogProfile() { + public CameraController.TonemapProfile getVideoTonemapProfile() { String video_log = sharedPreferences.getString(PreferenceKeys.VideoLogPreferenceKey, "off"); - // only return true for values recognised by getVideoLogProfileStrength() + // only return TONEMAPPROFILE_LOG for values recognised by getVideoLogProfileStrength() switch( video_log ) { case "off": - return false; + return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; case "fine": case "low": case "medium": case "strong": case "extra_strong": - return true; + return CameraController.TonemapProfile.TONEMAPPROFILE_LOG; + case "jtlog": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOG; } - return false; + return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; } @Override public float getVideoLogProfileStrength() { String video_log = sharedPreferences.getString(PreferenceKeys.VideoLogPreferenceKey, "off"); - // remember to update useVideoLogProfile() if adding/changing modes + // remember to update getVideoTonemapProfile() if adding/changing modes switch( video_log ) { case "off": return 0.0f; @@ -754,6 +756,8 @@ public class MyApplicationInterface extends BasicApplicationInterface { return 100.0f; case "extra_strong": return 500.0f; + case "jtlog": + return 0.0f; } return 0.0f; } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index fca4f0ef9..1a03cca4b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -448,8 +448,18 @@ public abstract class CameraController { */ public abstract void setVideoStabilization(boolean enabled); public abstract boolean getVideoStabilization(); - public abstract void setLogProfile(boolean use_log_profile, float log_profile_strength); - public abstract boolean isLogProfile(); + public enum TonemapProfile { + TONEMAPPROFILE_OFF, + TONEMAPPROFILE_LOG, + TONEMAPPROFILE_JTLOG + } + + /** Sets a tonemap profile. + * @param tonemap_profile The type of the tonemap profile. + * @param log_profile_strength Only relevant if tonemap_profile set to TONEMAPPROFILE_LOG. + */ + public abstract void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength); + //public abstract boolean isLogProfile(); public abstract int getJpegQuality(); public abstract void setJpegQuality(int quality); public abstract int getZoom(); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 5b3d29b24..132a5fda0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -890,15 +890,15 @@ public class CameraController1 extends CameraController { } @Override - public void setLogProfile(boolean use_log_profile, float log_profile_strength) { + public void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength) { // not supported for CameraController1! } - @Override + /*@Override public boolean isLogProfile() { // not supported for CameraController1! return false; - } + }*/ public int getJpegQuality() { Camera.Parameters parameters = this.getParameters(); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 793c0814e..d1dc330b1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -77,7 +77,18 @@ public class CameraController2 extends CameraController { private boolean supports_face_detect_mode_full; private boolean supports_optical_stabilization; private boolean supports_photo_video_recording; - private final static int tonemap_max_curve_points_c = 64; + + private final static int tonemap_log_max_curve_points_c = 64; + private final static float [] jtlog_values = new float[] { + 0.0000f, 0.0000f, 0.0230f, 0.2295f, 0.0280f, 0.2783f, 0.0319f, 0.3049f, 0.0369f, 0.3321f, 0.0430f, 0.3589f, + 0.0500f, 0.3844f, 0.0583f, 0.4098f, 0.0680f, 0.4351f, 0.0800f, 0.4619f, 0.0930f, 0.4870f, 0.1051f, 0.5076f, + 0.1180f, 0.5275f, 0.1430f, 0.5612f, 0.1680f, 0.5904f, 0.1930f, 0.6162f, 0.2180f, 0.6395f, 0.2430f, 0.6608f, + 0.2680f, 0.6804f, 0.2930f, 0.6986f, 0.3180f, 0.7157f, 0.3430f, 0.7318f, 0.3680f, 0.7471f, 0.3930f, 0.7615f, + 0.4180f, 0.7753f, 0.4430f, 0.7885f, 0.4680f, 0.8011f, 0.4930f, 0.8132f, 0.5180f, 0.8249f, 0.5430f, 0.8361f, + 0.5680f, 0.8470f, 0.5930f, 0.8575f, 0.6180f, 0.8677f, 0.6430f, 0.8776f, 0.6680f, 0.8872f, 0.6930f, 0.8966f, + 0.7180f, 0.9057f, 0.7430f, 0.9145f, 1.0000f, 1.0000f + }; + private final ErrorCallback preview_error_cb; private final ErrorCallback camera_error_cb; private CameraCaptureSession captureSession; @@ -265,7 +276,7 @@ public class CameraController2 extends CameraController { private int face_detect_mode = CaptureRequest.STATISTICS_FACE_DETECT_MODE_OFF; private Integer default_optical_stabilization; private boolean video_stabilization; - private boolean use_log_profile; + private TonemapProfile tonemap_profile = TonemapProfile.TONEMAPPROFILE_OFF; private float log_profile_strength; private Integer default_tonemap_mode; // since we don't know what a device's tonemap mode is, we save it so we can switch back to it private Range ae_target_fps_range; @@ -328,7 +339,7 @@ public class CameraController2 extends CameraController { setFaceDetectMode(builder); setRawMode(builder); setStabilization(builder); - setLogProfile(builder); + setTonemapProfile(builder); if( is_still ) { if( location != null ) { @@ -782,60 +793,78 @@ public class CameraController2 extends CameraController { return out; } - private void setLogProfile(CaptureRequest.Builder builder) { + private void setTonemapProfile(CaptureRequest.Builder builder) { if( MyDebug.LOG ) { - Log.d(TAG, "setLogProfile"); - Log.d(TAG, "use_log_profile: " + use_log_profile); + Log.d(TAG, "setTonemapProfile"); + Log.d(TAG, "tonemap_profile: " + tonemap_profile); Log.d(TAG, "log_profile_strength: " + log_profile_strength); Log.d(TAG, "default_tonemap_mode: " + default_tonemap_mode); } - if( use_log_profile && log_profile_strength > 0.0f ) { + boolean have_tonemap_profile = tonemap_profile != TonemapProfile.TONEMAPPROFILE_OFF; + if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_LOG && log_profile_strength == 0.0f ) + have_tonemap_profile = false; + + if( have_tonemap_profile ) { if( default_tonemap_mode == null ) { // save the default tonemap_mode default_tonemap_mode = builder.get(CaptureRequest.TONEMAP_MODE); if( MyDebug.LOG ) Log.d(TAG, "default_tonemap_mode: " + default_tonemap_mode); } - // if changing this, make sure we don't exceed tonemap_max_curve_points_c - // we want: - // 0-15: step 1 (16 values) - // 16-47: step 2 (16 values) - // 48-111: step 4 (16 values) - // 112-231 : step 8 (15 values) - // 232-255: step 24 (1 value) - int step = 1, c = 0; - float [] values = new float[2*tonemap_max_curve_points_c]; - for(int i=0;i<232;i+=step) { - float in = ((float)i) / 255.0f; - float out = getLogProfile(in); - values[c++] = in; - values[c++] = out; - if( (c/2) % 16 == 0 ) { - step *= 2; - } - } - values[c++] = 1.0f; - values[c++] = getLogProfile(1.0f); - /*{ - int n_values = 257; - float [] values = new float [2*n_values]; - for(int i=0;i= tonemap_max_curve_points_c; + // for now we only expose supporting of custom tonemap curves if there are enough curve points for all the + // profiles we support + camera_features.supports_tonemap_curve = + tonemap_max_curve_points >= tonemap_log_max_curve_points_c && + tonemap_max_curve_points >= jtlog_values.length; } else { if( MyDebug.LOG ) @@ -3678,19 +3716,19 @@ public class CameraController2 extends CameraController { } @Override - public void setLogProfile(boolean use_log_profile, float log_profile_strength) { + public void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength) { if( MyDebug.LOG ) { - Log.d(TAG, "setLogProfile: " + use_log_profile); + Log.d(TAG, "setTonemapProfile: " + tonemap_profile); Log.d(TAG, "log_profile_strength: " + log_profile_strength); } - if( camera_settings.use_log_profile == use_log_profile && camera_settings.log_profile_strength == log_profile_strength ) + if( camera_settings.tonemap_profile == tonemap_profile && camera_settings.log_profile_strength == log_profile_strength ) return; // no change - camera_settings.use_log_profile = use_log_profile; - if( use_log_profile ) + camera_settings.tonemap_profile = tonemap_profile; + if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_LOG ) camera_settings.log_profile_strength = log_profile_strength; else camera_settings.log_profile_strength = 0.0f; - camera_settings.setLogProfile(previewBuilder); + camera_settings.setTonemapProfile(previewBuilder); try { setRepeatingRequest(); } @@ -3704,10 +3742,10 @@ public class CameraController2 extends CameraController { } } - @Override + /*@Override public boolean isLogProfile() { return camera_settings.use_log_profile; - } + }*/ /** For testing. */ @@ -7134,15 +7172,15 @@ public class CameraController2 extends CameraController { private void handleContinuousFocusMove(CaptureResult result) { Integer af_state = result.get(CaptureResult.CONTROL_AF_STATE); if( af_state != null && af_state == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN && af_state != last_af_state ) { - if( MyDebug.LOG ) - Log.d(TAG, "continuous focusing started"); + /*if( MyDebug.LOG ) + Log.d(TAG, "continuous focusing started");*/ if( continuous_focus_move_callback != null ) { continuous_focus_move_callback.onContinuousFocusMove(true); } } else if( af_state != null && last_af_state == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN && af_state != last_af_state ) { - if( MyDebug.LOG ) - Log.d(TAG, "continuous focusing stopped"); + /*if( MyDebug.LOG ) + Log.d(TAG, "continuous focusing stopped");*/ if( continuous_focus_move_callback != null ) { continuous_focus_move_callback.onContinuousFocusMove(false); } @@ -7173,8 +7211,8 @@ public class CameraController2 extends CameraController { Integer af_state = result.get(CaptureResult.CONTROL_AF_STATE); if( af_state != null && af_state != last_af_state ) { - if( MyDebug.LOG ) - Log.d(TAG, "CONTROL_AF_STATE changed from " + last_af_state + " to " + af_state); + /*if( MyDebug.LOG ) + Log.d(TAG, "CONTROL_AF_STATE changed from " + last_af_state + " to " + af_state);*/ last_af_state = af_state; } diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java index 3f888d676..8983154ce 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java @@ -12,6 +12,7 @@ import android.net.Uri; import android.util.Pair; import android.view.MotionEvent; +import net.sourceforge.opencamera.cameracontroller.CameraController; import net.sourceforge.opencamera.cameracontroller.RawImage; /** Provides communication between the Preview and the rest of the application @@ -66,8 +67,8 @@ public interface ApplicationInterface { String getVideoBitratePref(); // return "default" to let Preview choose String getVideoFPSPref(); // return "default" to let Preview choose; if getVideoCaptureRateFactor() returns a value other than 1.0, this is the capture fps; the resultant video's fps will be getVideoFPSPref()*getVideoCaptureRateFactor() float getVideoCaptureRateFactor(); // return 1.0f for standard operation, less than 1.0 for slow motion, more than 1.0 for timelapse; consider using a higher fps for slow motion, see getVideoFPSPref() - boolean useVideoLogProfile(); // whether to use a log profile for video mode - float getVideoLogProfileStrength(); // strength of the log profile for video mode, if useVideoLogProfile() returns true + CameraController.TonemapProfile getVideoTonemapProfile(); // tonemap profile to use for video mode + float getVideoLogProfileStrength(); // strength of the log profile for video mode, if getVideoTonemapProfile() returns TONEMAPPROFILE_LOG long getVideoMaxDurationPref(); // time in ms after which to automatically stop video recording (return 0 for off) int getVideoRestartTimesPref(); // number of times to restart video recording after hitting max duration (return 0 for never auto-restarting) VideoMaxFileSize getVideoMaxFileSizePref() throws NoFreeStorageException; // see VideoMaxFileSize class for details diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java index 1071d1323..9233fcdb4 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java @@ -141,8 +141,8 @@ public abstract class BasicApplicationInterface implements ApplicationInterface } @Override - public boolean useVideoLogProfile() { - return false; + public CameraController.TonemapProfile getVideoTonemapProfile() { + return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; } @Override diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 708665484..ef6542dfb 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -1775,13 +1775,17 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( MyDebug.LOG ) Log.d(TAG, "is_video?: " + is_video); if( this.is_video ) { - boolean use_video_log_profile = supports_tonemap_curve && applicationInterface.useVideoLogProfile(); - float video_log_profile_strength = use_video_log_profile ? applicationInterface.getVideoLogProfileStrength() : 0.0f; + CameraController.TonemapProfile tonemap_profile = CameraController.TonemapProfile.TONEMAPPROFILE_OFF; + if( supports_tonemap_curve ) { + tonemap_profile = applicationInterface.getVideoTonemapProfile(); + + } + float video_log_profile_strength = (tonemap_profile == CameraController.TonemapProfile.TONEMAPPROFILE_LOG) ? applicationInterface.getVideoLogProfileStrength() : 0.0f; if( MyDebug.LOG ) { - Log.d(TAG, "use_video_log_profile: " + use_video_log_profile); + Log.d(TAG, "tonemap_profile: " + tonemap_profile); Log.d(TAG, "video_log_profile_strength: " + video_log_profile_strength); } - camera_controller.setLogProfile(use_video_log_profile, video_log_profile_strength); + camera_controller.setTonemapProfile(tonemap_profile, video_log_profile_strength); } // in theory it shouldn't matter if we call setVideoHighSpeed(true) if is_video==false, as it should only have an effect diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 9d36156f3..3ae52c5ba 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -564,6 +564,7 @@ @string/preference_video_log_medium @string/preference_video_log_strong @string/preference_video_log_extra_strong + @string/preference_video_jtlog off @@ -572,6 +573,7 @@ medium strong extra_strong + jtlog @string/preference_record_audio_src_camcorder diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5efe5caee..236d83524 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -539,14 +539,14 @@ Allow photos whilst recording video Allows taking photos whilst recording videos. Disable this if there are problems with video recording with Camera2 API enabled on your device. - Video flat (log) profile - Enable a flat (log) profile for video mode\n%s - Off - Fine - Low - Medium - Strong - Extra strong + Video picture profiles + Set standard or flat picture profile for video mode\n%s + Default + Log (Fine) + Log (Low) + Log (Medium) + Log (Strong) + Log (Extra strong) Log profile Camcorder @@ -910,6 +910,8 @@ Select remote device + JTLog + Privacy policy -- GitLab From e5f6269e938b7a1160c5d44e1e2e4d0ae0215f6e Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 11 Jan 2020 17:12:10 +0000 Subject: [PATCH 057/243] New custom gamma option for video. --- _docs/history.html | 1 + .../sourceforge/opencamera/MainActivity.java | 3 ++ .../opencamera/MyApplicationInterface.java | 20 +++++++++ .../opencamera/PreferenceKeys.java | 2 + .../cameracontroller/CameraController.java | 4 +- .../cameracontroller/CameraController1.java | 2 +- .../cameracontroller/CameraController2.java | 43 ++++++++++++++----- .../preview/ApplicationInterface.java | 1 + .../preview/BasicApplicationInterface.java | 5 +++ .../opencamera/preview/Preview.java | 4 +- app/src/main/res/values/arrays.xml | 38 ++++++++++++++++ app/src/main/res/values/strings.xml | 19 ++++++++ app/src/main/res/xml/preferences.xml | 10 +++++ 13 files changed, 138 insertions(+), 14 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 34f64dce5..63d50a322 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -61,6 +61,7 @@ FIXED Recording video on Android 8+ could leave zero-size files if size approa filesize, but a restart did not occur. FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. +ADDED New custom gamma option for video recording. UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. UPDATED Don't set video digital stabilization when in photo mode. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 4c719f7f1..82fa98734 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4036,6 +4036,9 @@ public class MainActivity extends Activity { case TONEMAPPROFILE_LOG: string_id = R.string.video_log; break; + case TONEMAPPROFILE_GAMMA: + string_id = R.string.preference_video_gamma; + break; case TONEMAPPROFILE_JTLOG: string_id = R.string.preference_video_jtlog; break; diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 4d8f46a76..4707aa279 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -733,6 +733,8 @@ public class MyApplicationInterface extends BasicApplicationInterface { case "strong": case "extra_strong": return CameraController.TonemapProfile.TONEMAPPROFILE_LOG; + case "gamma": + return CameraController.TonemapProfile.TONEMAPPROFILE_GAMMA; case "jtlog": return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOG; } @@ -756,12 +758,30 @@ public class MyApplicationInterface extends BasicApplicationInterface { return 100.0f; case "extra_strong": return 500.0f; + case "gamma": case "jtlog": return 0.0f; } return 0.0f; } + @Override + public float getVideoProfileGamma() { + String gamma_value = sharedPreferences.getString(PreferenceKeys.VideoProfileGammaPreferenceKey, "2.2"); + float gamma = 0.0f; + try { + gamma = Float.parseFloat(gamma_value); + if( MyDebug.LOG ) + Log.d(TAG, "gamma: " + gamma); + } + catch(NumberFormatException e) { + if( MyDebug.LOG ) + Log.e(TAG, "failed to parse gamma value: " + gamma_value); + e.printStackTrace(); + } + return gamma; + } + @Override public long getVideoMaxDurationPref() { String action = main_activity.getIntent().getAction(); diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index c28629318..017c27aa5 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -324,6 +324,8 @@ public class PreferenceKeys { public static final String VideoLogPreferenceKey = "preference_video_log"; + public static final String VideoProfileGammaPreferenceKey = "preference_video_profile_gamma"; + public static String getVideoMaxDurationPreferenceKey() { return "preference_video_max_duration"; } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 1a03cca4b..4a08ae593 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -451,14 +451,16 @@ public abstract class CameraController { public enum TonemapProfile { TONEMAPPROFILE_OFF, TONEMAPPROFILE_LOG, + TONEMAPPROFILE_GAMMA, TONEMAPPROFILE_JTLOG } /** Sets a tonemap profile. * @param tonemap_profile The type of the tonemap profile. * @param log_profile_strength Only relevant if tonemap_profile set to TONEMAPPROFILE_LOG. + * @param gamma Only relevant if tonemap_profile set to TONEMAPPROFILE_GAMMA */ - public abstract void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength); + public abstract void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength, float gamma); //public abstract boolean isLogProfile(); public abstract int getJpegQuality(); public abstract void setJpegQuality(int quality); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 132a5fda0..5f303f508 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -890,7 +890,7 @@ public class CameraController1 extends CameraController { } @Override - public void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength) { + public void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength, float gamma) { // not supported for CameraController1! } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index d1dc330b1..680ac4f41 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -277,7 +277,8 @@ public class CameraController2 extends CameraController { private Integer default_optical_stabilization; private boolean video_stabilization; private TonemapProfile tonemap_profile = TonemapProfile.TONEMAPPROFILE_OFF; - private float log_profile_strength; + private float log_profile_strength; // for TONEMAPPROFILE_LOG + private float gamma_profile; // for TONEMAPPROFILE_GAMMA private Integer default_tonemap_mode; // since we don't know what a device's tonemap mode is, we save it so we can switch back to it private Range ae_target_fps_range; private long sensor_frame_duration; @@ -793,16 +794,23 @@ public class CameraController2 extends CameraController { return out; } + private float getGammaProfile(float in) { + return (float)Math.pow(in, 1.0f/gamma_profile); + } + private void setTonemapProfile(CaptureRequest.Builder builder) { if( MyDebug.LOG ) { Log.d(TAG, "setTonemapProfile"); Log.d(TAG, "tonemap_profile: " + tonemap_profile); Log.d(TAG, "log_profile_strength: " + log_profile_strength); + Log.d(TAG, "gamma_profile: " + gamma_profile); Log.d(TAG, "default_tonemap_mode: " + default_tonemap_mode); } boolean have_tonemap_profile = tonemap_profile != TonemapProfile.TONEMAPPROFILE_OFF; if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_LOG && log_profile_strength == 0.0f ) have_tonemap_profile = false; + else if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_GAMMA && gamma_profile == 0.0f ) + have_tonemap_profile = false; if( have_tonemap_profile ) { if( default_tonemap_mode == null ) { @@ -815,6 +823,7 @@ public class CameraController2 extends CameraController { float [] values = null; switch( tonemap_profile ) { case TONEMAPPROFILE_LOG: + case TONEMAPPROFILE_GAMMA: // if changing this, make sure we don't exceed tonemap_log_max_curve_points_c // we want: // 0-15: step 1 (16 values) @@ -826,7 +835,7 @@ public class CameraController2 extends CameraController { values = new float[2*tonemap_log_max_curve_points_c]; for(int i=0;i<232;i+=step) { float in = ((float)i) / 255.0f; - float out = getLogProfile(in); + float out = (tonemap_profile==TonemapProfile.TONEMAPPROFILE_LOG) ? getLogProfile(in) : getGammaProfile(in); values[c++] = in; values[c++] = out; if( (c/2) % 16 == 0 ) { @@ -834,7 +843,7 @@ public class CameraController2 extends CameraController { } } values[c++] = 1.0f; - values[c++] = getLogProfile(1.0f); + values[c++] = (tonemap_profile==TonemapProfile.TONEMAPPROFILE_LOG) ? getLogProfile(1.0f) : getGammaProfile(1.0f); /*{ int n_values = 257; float [] values = new float [2*n_values]; @@ -862,20 +871,21 @@ public class CameraController2 extends CameraController { Log.d(TAG, "setting JTLog profile"); break; } - if( MyDebug.LOG ) - Log.d(TAG, "values: " + Arrays.toString(values)); // sRGB: - /*float [] values = new float []{0.0000f, 0.0000f, 0.0667f, 0.2864f, 0.1333f, 0.4007f, 0.2000f, 0.4845f, + /*values = new float []{0.0000f, 0.0000f, 0.0667f, 0.2864f, 0.1333f, 0.4007f, 0.2000f, 0.4845f, 0.2667f, 0.5532f, 0.3333f, 0.6125f, 0.4000f, 0.6652f, 0.4667f, 0.7130f, 0.5333f, 0.7569f, 0.6000f, 0.7977f, 0.6667f, 0.8360f, 0.7333f, 0.8721f, 0.8000f, 0.9063f, 0.8667f, 0.9389f, 0.9333f, 0.9701f, 1.0000f, 1.0000f};*/ - /*float [] values = new float []{0.0000f, 0.0000f, 0.05f, 0.3f, 0.1f, 0.4f, 0.2000f, 0.4845f, + /*values = new float []{0.0000f, 0.0000f, 0.05f, 0.3f, 0.1f, 0.4f, 0.2000f, 0.4845f, 0.2667f, 0.5532f, 0.3333f, 0.6125f, 0.4000f, 0.6652f, 0.5f, 0.78f, 1.0000f, 1.0000f};*/ - /*float [] values = new float []{0.0f, 0.0f, 0.05f, 0.4f, 0.1f, 0.54f, 0.2f, 0.6f, 0.3f, 0.65f, 0.4f, 0.7f, + /*values = new float []{0.0f, 0.0f, 0.05f, 0.4f, 0.1f, 0.54f, 0.2f, 0.6f, 0.3f, 0.65f, 0.4f, 0.7f, 0.5f, 0.78f, 1.0f, 1.0f};*/ - //float [] values = new float []{0.0f, 0.5f, 0.05f, 0.6f, 0.1f, 0.7f, 0.2f, 0.8f, 0.5f, 0.9f, 1.0f, 1.0f}; + //values = new float []{0.0f, 0.5f, 0.05f, 0.6f, 0.1f, 0.7f, 0.2f, 0.8f, 0.5f, 0.9f, 1.0f, 1.0f}; + + if( MyDebug.LOG ) + Log.d(TAG, "values: " + Arrays.toString(values)); if( values != null ) { builder.set(CaptureRequest.TONEMAP_MODE, CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE); TonemapCurve tonemap_curve = new TonemapCurve(values, values, values); @@ -3716,18 +3726,29 @@ public class CameraController2 extends CameraController { } @Override - public void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength) { + public void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength, float gamma) { if( MyDebug.LOG ) { Log.d(TAG, "setTonemapProfile: " + tonemap_profile); Log.d(TAG, "log_profile_strength: " + log_profile_strength); + Log.d(TAG, "gamma: " + gamma); } - if( camera_settings.tonemap_profile == tonemap_profile && camera_settings.log_profile_strength == log_profile_strength ) + if( camera_settings.tonemap_profile == tonemap_profile && + camera_settings.log_profile_strength == log_profile_strength && + camera_settings.gamma_profile == gamma ) return; // no change + camera_settings.tonemap_profile = tonemap_profile; + if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_LOG ) camera_settings.log_profile_strength = log_profile_strength; else camera_settings.log_profile_strength = 0.0f; + + if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_GAMMA ) + camera_settings.gamma_profile = gamma; + else + camera_settings.gamma_profile = 0.0f; + camera_settings.setTonemapProfile(previewBuilder); try { setRepeatingRequest(); diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java index 8983154ce..5df807e3f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java @@ -69,6 +69,7 @@ public interface ApplicationInterface { float getVideoCaptureRateFactor(); // return 1.0f for standard operation, less than 1.0 for slow motion, more than 1.0 for timelapse; consider using a higher fps for slow motion, see getVideoFPSPref() CameraController.TonemapProfile getVideoTonemapProfile(); // tonemap profile to use for video mode float getVideoLogProfileStrength(); // strength of the log profile for video mode, if getVideoTonemapProfile() returns TONEMAPPROFILE_LOG + float getVideoProfileGamma(); // gamma for video mode, if getVideoTonemapProfile() returns TONEMAPPROFILE_GAMMA long getVideoMaxDurationPref(); // time in ms after which to automatically stop video recording (return 0 for off) int getVideoRestartTimesPref(); // number of times to restart video recording after hitting max duration (return 0 for never auto-restarting) VideoMaxFileSize getVideoMaxFileSizePref() throws NoFreeStorageException; // see VideoMaxFileSize class for details diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java index 9233fcdb4..f887f2ebc 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java @@ -150,6 +150,11 @@ public abstract class BasicApplicationInterface implements ApplicationInterface return 0; } + @Override + public float getVideoProfileGamma() { + return 0; + } + @Override public long getVideoMaxDurationPref() { return 0; diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index ef6542dfb..5b792c027 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -1781,11 +1781,13 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } float video_log_profile_strength = (tonemap_profile == CameraController.TonemapProfile.TONEMAPPROFILE_LOG) ? applicationInterface.getVideoLogProfileStrength() : 0.0f; + float video_gamma = (tonemap_profile == CameraController.TonemapProfile.TONEMAPPROFILE_GAMMA) ? applicationInterface.getVideoProfileGamma() : 0.0f; if( MyDebug.LOG ) { Log.d(TAG, "tonemap_profile: " + tonemap_profile); Log.d(TAG, "video_log_profile_strength: " + video_log_profile_strength); + Log.d(TAG, "video_gamma: " + video_gamma); } - camera_controller.setTonemapProfile(tonemap_profile, video_log_profile_strength); + camera_controller.setTonemapProfile(tonemap_profile, video_log_profile_strength, video_gamma); } // in theory it shouldn't matter if we call setVideoHighSpeed(true) if is_video==false, as it should only have an effect diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 3ae52c5ba..9c2fdcbda 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -564,6 +564,7 @@ @string/preference_video_log_medium @string/preference_video_log_strong @string/preference_video_log_extra_strong + @string/preference_video_gamma @string/preference_video_jtlog @@ -573,8 +574,45 @@ medium strong extra_strong + gamma jtlog + + @string/preference_video_profile_gamma_1.0 + @string/preference_video_profile_gamma_1.5 + @string/preference_video_profile_gamma_1.8 + @string/preference_video_profile_gamma_2.0 + @string/preference_video_profile_gamma_2.2 + @string/preference_video_profile_gamma_2.3 + @string/preference_video_profile_gamma_2.4 + @string/preference_video_profile_gamma_2.5 + @string/preference_video_profile_gamma_2.6 + @string/preference_video_profile_gamma_2.7 + @string/preference_video_profile_gamma_2.8 + @string/preference_video_profile_gamma_2.9 + @string/preference_video_profile_gamma_3.0 + @string/preference_video_profile_gamma_3.1 + @string/preference_video_profile_gamma_3.2 + @string/preference_video_profile_gamma_4.0 + + + 1.0 + 1.5 + 1.8 + 2.0 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 3.0 + 3.1 + 3.2 + 4.0 + @string/preference_record_audio_src_camcorder @string/preference_record_audio_src_mic diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 236d83524..680bc032e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -910,7 +910,26 @@ Select remote device + Gamma JTLog + Video gamma value + Gamma value to use for video if video picture profile is set to Gamma\n%s + 1.0 + 1.5 + 1.8 + 2.0 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 3.0 + 3.1 + 3.2 + 4.0 diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 229afb91e..acffdb6ac 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1014,6 +1014,16 @@ android:defaultValue="off" /> + + + Date: Sat, 11 Jan 2020 22:20:08 +0000 Subject: [PATCH 058/243] Cache to reduce calls to View.getLocationOnScreen(), for performance. --- .../opencamera/ui/DrawPreview.java | 58 +++++++++++++------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index ac272cc82..aad4cb5e2 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -203,6 +203,12 @@ public class DrawPreview { private float view_angle_y_preview; private long last_view_angles_time; + private int take_photo_top; // coordinate (in canvas x coordinates) of top of the take photo icon + private long last_take_photo_top_time; + + private int top_icon_shift; // shift that may be needed for on-screen text to avoid clashing with icons (when arranged "along top") + private long last_top_icon_shift_time; + // OSD extra lines private String OSDLine1; private String OSDLine2; @@ -596,6 +602,8 @@ public class DrawPreview { focus_peaking_color_pref = Color.parseColor(focus_peaking_color); last_view_angles_time = 0; // force view angles to be recomputed + last_take_photo_top_time = 0; // force take_photo_top to be recomputed + last_top_icon_shift_time = 0; // for top_icon_shift to be recomputed has_settings = true; } @@ -1554,14 +1562,24 @@ public class DrawPreview { // 270 is portrait //text_base_y = canvas.getHeight() + (int)(0.5*gap_y); - View view = main_activity.findViewById(R.id.take_photo); - // align with "top" of the take_photo button, but remember to take the rotation into account! - view.getLocationOnScreen(gui_location); - int view_left = gui_location[0]; - preview.getView().getLocationOnScreen(gui_location); - int this_left = gui_location[0]; + + if( last_take_photo_top_time == 0 || time_ms > last_take_photo_top_time + 1000 ) { + /*if( MyDebug.LOG ) + Log.d(TAG, "update cached take_photo_top");*/ + // don't call this too often, for UI performance (due to calling View.getLocationOnScreen()) + View view = main_activity.findViewById(R.id.take_photo); + // align with "top" of the take_photo button, but remember to take the rotation into account! + view.getLocationOnScreen(gui_location); + int view_left = gui_location[0]; + preview.getView().getLocationOnScreen(gui_location); + int this_left = gui_location[0]; + take_photo_top = view_left - this_left; + + last_take_photo_top_time = time_ms; + } + // diff_x is the difference from the centre of the canvas to the position we want - int diff_x = view_left - ( this_left + canvas.getWidth()/2 ); + int diff_x = take_photo_top - canvas.getWidth()/2; /*if( MyDebug.LOG ) { Log.d(TAG, "view left: " + view_left); @@ -1843,19 +1861,25 @@ public class DrawPreview { int top_y = (int) (5 * scale + 0.5f); // convert dps to pixels View top_icon = main_activity.getMainUI().getTopIcon(); if( top_icon != null ) { - top_icon.getLocationOnScreen(gui_location); - int top_margin = gui_location[0] + top_icon.getWidth(); - preview.getView().getLocationOnScreen(gui_location); - int preview_left = gui_location[0]; - /*if( MyDebug.LOG ) - Log.d(TAG, "preview_left: " + preview_left);*/ - int shift = top_margin - preview_left; - if( shift > 0 ) { + if( last_top_icon_shift_time == 0 || time_ms > last_top_icon_shift_time + 1000 ) { + // avoid computing every time, due to cost of calling View.getLocationOnScreen() + /*if( MyDebug.LOG ) + Log.d(TAG, "update cached top_icon_shift");*/ + top_icon.getLocationOnScreen(gui_location); + int top_margin = gui_location[0] + top_icon.getWidth(); + preview.getView().getLocationOnScreen(gui_location); + int preview_left = gui_location[0]; + this.top_icon_shift = top_margin - preview_left; + + last_top_icon_shift_time = time_ms; + } + + if( this.top_icon_shift > 0 ) { if( ui_rotation == 90 || ui_rotation == 270 ) { - top_y += shift; + top_y += top_icon_shift; } else { - top_x += shift; + top_x += top_icon_shift; } } } -- GitLab From 258cb1d297b38876b1a9f0f71f5aa5ea881bc37b Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 12 Jan 2020 15:07:20 +0000 Subject: [PATCH 059/243] Fix logging for widget TAKE_PHOTO flag. --- .../net/sourceforge/opencamera/MainActivity.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 82fa98734..6b6a75963 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -201,12 +201,14 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) Log.d(TAG, "is_test: " + is_test); } - if( getIntent() != null && getIntent().getExtras() != null ) { + /*if( getIntent() != null && getIntent().getExtras() != null ) { // whether called from Take Photo widget - if( MyDebug.LOG ) { - //Log.d(TAG, "take_photo?: " + getIntent().getExtras().getBoolean(TakePhoto.TAKE_PHOTO)); - Log.d(TAG, "take_photo?: " + TakePhoto.TAKE_PHOTO); - } + if( MyDebug.LOG ) + Log.d(TAG, "take_photo?: " + getIntent().getExtras().getBoolean(TakePhoto.TAKE_PHOTO)); + }*/ + if( MyDebug.LOG ) { + // whether called from Take Photo widget + Log.d(TAG, "take_photo?: " + TakePhoto.TAKE_PHOTO); } if( getIntent() != null && getIntent().getAction() != null ) { // invoked via the manifest shortcut? -- GitLab From 28a51ea2568fc6389e88cc212f4c25629f4e610a Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 12 Jan 2020 15:23:14 +0000 Subject: [PATCH 060/243] Add support for FLAG_LAYOUT_NO_LIMITS; new tests testLayoutNoLimits and testLayoutNoLimitsStartup. --- _docs/history.html | 2 + .../opencamera/test/MainActivityTest.java | 100 +++++++++++++++++ .../opencamera/test/MainTests.java | 2 + .../sourceforge/opencamera/MainActivity.java | 106 +++++++++++++++++- .../net/sourceforge/opencamera/ui/MainUI.java | 30 +++++ 5 files changed, 239 insertions(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 63d50a322..5db5c1610 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -62,6 +62,8 @@ FIXED Recording video on Android 8+ could leave zero-size files if size approa FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. ADDED New custom gamma option for video recording. +UPDATED On devices with on-screen navigation buttons, camera preview can now display under these + buttons if required for wide aspect ratio (requires Android 5+). UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. UPDATED Don't set video digital stabilization when in photo mode. diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 63f08ba31..5600cfb07 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -63,6 +63,7 @@ import android.util.Log; import android.view.Display; import android.view.KeyEvent; import android.view.View; +import android.view.WindowManager; import android.widget.SeekBar; import android.widget.TextView; import android.widget.ZoomControls; @@ -95,6 +96,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ) { + // test switching camera + MainActivity.test_preview_want_no_limits_value = true; + switchToCamera(1); + Thread.sleep(1000); + assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + assertEquals(mActivity.getNavigationGap(), mActivity.getMainUI().test_navigation_gap); + MainActivity.test_preview_want_no_limits_value = false; + switchToCamera(0); + Thread.sleep(1000); + assertEquals(0, mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + assertEquals(0, mActivity.getMainUI().test_navigation_gap); + } + + // test switching to video and back + View switchVideoButton = mActivity.findViewById(net.sourceforge.opencamera.R.id.switch_video); + MainActivity.test_preview_want_no_limits_value = true; + clickView(switchVideoButton); + waitUntilCameraOpened(); + assertTrue(mPreview.isVideo()); + Thread.sleep(1000); + assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + assertEquals(mActivity.getNavigationGap(), mActivity.getMainUI().test_navigation_gap); + MainActivity.test_preview_want_no_limits_value = false; + clickView(switchVideoButton); + waitUntilCameraOpened(); + assertFalse(mPreview.isVideo()); + Thread.sleep(1000); + assertEquals(0, mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + assertEquals(0, mActivity.getMainUI().test_navigation_gap); + + // test after restart + MainActivity.test_preview_want_no_limits_value = true; + restart(); + Thread.sleep(1000); + assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + assertEquals(mActivity.getNavigationGap(), mActivity.getMainUI().test_navigation_gap); + } + + /** Tests the use of the FLAG_LAYOUT_NO_LIMITS flag introduced in 1.48, with the mode set from startup. + */ + public void testLayoutNoLimitsStartup() throws InterruptedException { + Log.d(TAG, "testLayoutNoLimitsStartup"); + + if( Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ) { + // we don't support FLAG_LAYOUT_NO_LIMITS + return; + } + + MainActivity.test_preview_want_no_limits = true; + MainActivity.test_preview_want_no_limits_value = true; + // need to restart for test_preview_want_no_limits static to take effect + restart(); + + setToDefault(); + + Thread.sleep(1000); + Log.d(TAG, "check FLAG_LAYOUT_NO_LIMITS"); + Log.d(TAG, "test_navigation_gap: " + mActivity.getMainUI().test_navigation_gap); + assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + assertEquals(mActivity.getNavigationGap(), mActivity.getMainUI().test_navigation_gap); + } + private void subTestTakePhotoPreviewPaused(boolean immersive_mode, boolean is_raw) throws InterruptedException { mPreview.count_cameraTakePicture = 0; diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java index 1c08a820a..3d33af3c4 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java @@ -70,6 +70,8 @@ public class MainTests { } suite.addTest(TestSuite.createTest(MainActivityTest.class, "testSettingsPrivacyPolicy")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testPreviewRotation")); + suite.addTest(TestSuite.createTest(MainActivityTest.class, "testLayoutNoLimits")); + suite.addTest(TestSuite.createTest(MainActivityTest.class, "testLayoutNoLimitsStartup")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testCameraModes")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testFailOpenCamera")); if( !MainActivityTest.test_camera2 ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 6b6a75963..daa4f5b46 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -79,6 +79,7 @@ import android.view.TextureView; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.WindowManager; import android.widget.EditText; import android.widget.ImageButton; @@ -131,6 +132,12 @@ public class MainActivity extends Activity { //private boolean ui_placement_right = true; + private boolean want_no_limits; // whether we want to run with FLAG_LAYOUT_NO_LIMITS + private boolean set_window_insets_listener; // whether we've enabled a setOnApplyWindowInsetsListener() + private int navigation_gap; + public static volatile boolean test_preview_want_no_limits; // test flag, if set to true then instead use test_preview_want_no_limits_value; needs to be static, as it needs to be set before activity is created to take effect + public static volatile boolean test_preview_want_no_limits_value; + private final ToastBoxer switch_video_toast = new ToastBoxer(); private final ToastBoxer screen_locked_toast = new ToastBoxer(); private final ToastBoxer stamp_toast = new ToastBoxer(); @@ -391,8 +398,38 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) Log.d(TAG, "onCreate: time after creating gesture detector: " + (System.currentTimeMillis() - debug_time)); - // set up listener to handle immersive mode options View decorView = getWindow().getDecorView(); + if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) { + // set a window insets listener to find the navigation_gap + if( MyDebug.LOG ) + Log.d(TAG, "set a window insets listener"); + this.set_window_insets_listener = true; + decorView.getRootView().setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { + if( MyDebug.LOG ) + Log.d(TAG, "inset: " + insets.getSystemWindowInsetRight()); + if( navigation_gap == 0 ) { + navigation_gap = insets.getSystemWindowInsetRight(); + if( MyDebug.LOG ) + Log.d(TAG, "navigation_gap is " + navigation_gap); + // Sometimes when this callback is called, the navigation_gap may still be 0 even if + // the device doesn't have physical navigation buttons - we need to wait + // until we have found a non-zero value before switching to no limits. + // On devices with physical navigation bar, navigation_gap should remain 0 + // (and there's no point setting FLAG_LAYOUT_NO_LIMITS) + if( want_no_limits && navigation_gap != 0 ) { + if( MyDebug.LOG ) + Log.d(TAG, "set FLAG_LAYOUT_NO_LIMITS"); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + } + return getWindow().getDecorView().getRootView().onApplyWindowInsets(insets); + } + }); + } + + // set up listener to handle immersive mode options decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() { @Override @@ -565,6 +602,10 @@ public class MainActivity extends Activity { Log.d(TAG, "onCreate: total time for Activity startup: " + (System.currentTimeMillis() - debug_time)); } + public int getNavigationGap() { + return want_no_limits ? navigation_gap : 0; + } + /* This method sets the preference defaults which are set specific for a particular device. * This method should be called when Open Camera is run for the very first time after installation, * or when the user has requested to "Reset settings". @@ -2381,6 +2422,12 @@ public class MainActivity extends Activity { showWhenLocked(false); } + if( want_no_limits && navigation_gap != 0 ) { + if( MyDebug.LOG ) + Log.d(TAG, "set FLAG_LAYOUT_NO_LIMITS"); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + setBrightnessForCamera(false); initImmersiveMode(); @@ -2409,6 +2456,11 @@ public class MainActivity extends Activity { // revert to standard screen blank behaviour getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + if( want_no_limits && navigation_gap != 0 ) { + if( MyDebug.LOG ) + Log.d(TAG, "clear FLAG_LAYOUT_NO_LIMITS"); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } if( set_lock_protect ) { // settings should still be protected by screen lock showWhenLocked(false); @@ -3477,6 +3529,58 @@ public class MainActivity extends Activity { Log.d(TAG, "cameraSetup"); debug_time = System.currentTimeMillis(); } + + boolean old_want_no_limits = want_no_limits; + this.want_no_limits = false; + if( set_window_insets_listener ) { + Point display_size = new Point(); + Display display = getWindowManager().getDefaultDisplay(); + display.getSize(display_size); + int display_width = Math.max(display_size.x, display_size.y); + int display_height = Math.min(display_size.x, display_size.y); + double display_aspect_ratio = ((double)display_width)/(double)display_height; + double preview_aspect_ratio = preview.getCurrentPreviewAspectRatio(); + if( MyDebug.LOG ) { + Log.d(TAG, "display_aspect_ratio: " + display_aspect_ratio); + Log.d(TAG, "preview_aspect_ratio: " + preview_aspect_ratio); + } + boolean preview_is_wide = preview_aspect_ratio > display_aspect_ratio + 1.0e-5f; + if( test_preview_want_no_limits ) { + preview_is_wide = test_preview_want_no_limits_value; + } + if( preview_is_wide ) { + if( MyDebug.LOG ) + Log.d(TAG, "preview is wide, set want_no_limits"); + this.want_no_limits = true; + + if( !old_want_no_limits ) { + if( MyDebug.LOG ) + Log.d(TAG, "need to change to FLAG_LAYOUT_NO_LIMITS"); + // Ideally we'd just go straight to FLAG_LAYOUT_NO_LIMITS mode, but then all calls to onApplyWindowInsets() + // end up returning a value of 0 for the navigation_gap! So we need to wait until we know the navigation_gap. + if( navigation_gap != 0 ) { + // already have navigation gap, can go straight into no limits mode + if( MyDebug.LOG ) + Log.d(TAG, "set FLAG_LAYOUT_NO_LIMITS"); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + // need to layout the UI again due to now taking the navigation gap into account + mainUI.layoutUI(); + } + else { + if( MyDebug.LOG ) + Log.d(TAG, "but navigation_gap is 0"); + } + } + } + else if( old_want_no_limits && navigation_gap != 0 ) { + if( MyDebug.LOG ) + Log.d(TAG, "clear FLAG_LAYOUT_NO_LIMITS"); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + // need to layout the UI again due to no longer taking the navigation gap into account + mainUI.layoutUI(); + } + } + if( this.supportsForceVideo4K() && preview.usingCamera2API() ) { if( MyDebug.LOG ) Log.d(TAG, "using Camera2 API, so can disable the force 4K option"); diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index be7f7feef..6313eff95 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -91,6 +91,7 @@ public class MainUI { private final Map test_ui_buttons = new Hashtable<>(); public int test_saved_popup_width; public int test_saved_popup_height; + public volatile int test_navigation_gap; public MainUI(MainActivity main_activity) { if( MyDebug.LOG ) @@ -249,6 +250,25 @@ public class MainUI { display.getSize(display_size); final int display_height = Math.min(display_size.x, display_size.y); + /*int navigation_gap = 0; + if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 ) { + final int display_width = Math.max(display_size.x, display_size.y); + Point real_display_size = new Point(); + display.getRealSize(real_display_size); + final int real_display_width = Math.max(real_display_size.x, real_display_size.y); + navigation_gap = real_display_width - display_width; + if( MyDebug.LOG ) { + Log.d(TAG, "display_width: " + display_width); + Log.d(TAG, "real_display_width: " + real_display_width); + Log.d(TAG, "navigation_gap: " + navigation_gap); + } + }*/ + int navigation_gap = main_activity.getNavigationGap(); + test_navigation_gap = navigation_gap; + if( MyDebug.LOG ) { + Log.d(TAG, "navigation_gap: " + navigation_gap); + } + if( !popup_container_only ) { // reset: @@ -282,6 +302,7 @@ public class MainUI { layoutParams.addRule(below, 0); layoutParams.addRule(left_of, 0); layoutParams.addRule(right_of, 0); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); } @@ -415,6 +436,7 @@ public class MainUI { layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); @@ -422,6 +444,7 @@ public class MainUI { layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); @@ -429,6 +452,7 @@ public class MainUI { layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); @@ -436,6 +460,7 @@ public class MainUI { layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); @@ -443,6 +468,7 @@ public class MainUI { layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); @@ -450,6 +476,7 @@ public class MainUI { layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); @@ -459,6 +486,7 @@ public class MainUI { layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); layoutParams.addRule(align_parent_top, 0); layoutParams.addRule(align_parent_bottom, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); view.setLayoutParams(layoutParams); view.setRotation(180.0f); // should always match the zoom_seekbar, so that zoom in and out are in the same directions @@ -475,12 +503,14 @@ public class MainUI { layoutParams.addRule(align_parent_right, 0); layoutParams.addRule(align_parent_top, 0); layoutParams.addRule(align_parent_bottom, 0); + layoutParams.setMargins(0, 0, 0, 0); } else { layoutParams.addRule(align_parent_left, 0); layoutParams.addRule(align_parent_right, RelativeLayout.TRUE); layoutParams.addRule(align_parent_top, 0); layoutParams.addRule(align_parent_bottom, RelativeLayout.TRUE); + layoutParams.setMargins(0, 0, navigation_gap, 0); // need to clear the others, in case we turn zoom controls on/off layoutParams.addRule(align_left, 0); layoutParams.addRule(align_right, 0); -- GitLab From e091495a4393fe4dbd33ab5cc0f7dd3cf6320293 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 12 Jan 2020 18:00:35 +0000 Subject: [PATCH 061/243] Refactor rename sizes to photo_sizes. --- .../opencamera/preview/Preview.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 5b792c027..e3bc6571f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -284,7 +284,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private List supported_preview_sizes; - private List sizes; + private List photo_sizes; private int current_size_index = -1; // this is an index into the sizes array, or -1 if sizes not yet set private boolean supports_video; @@ -1357,7 +1357,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu supports_raw = false; view_angle_x = 55.0f; // set a sensible default view_angle_y = 43.0f; // set a sensible default - sizes = null; + photo_sizes = null; current_size_index = -1; has_capture_rate_factor = false; capture_rate_factor = 1.0f; @@ -1826,8 +1826,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Log.d(TAG, "burst mode: current picture size doesn't support burst"); // set to next largest that supports burst CameraController.Size new_size = null; - for(int i=0;i new_size.width*new_size.height ) { current_size_index = i; @@ -1838,8 +1838,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( new_size == null ) { Log.e(TAG, "can't find burst-supporting picture size smaller than the current picture size"); // just find largest that supports burst - for(int i=0;i new_size.width*new_size.height ) { current_size_index = i; @@ -2016,7 +2016,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } this.minimum_focus_distance = camera_features.minimum_focus_distance; this.supports_face_detection = camera_features.supports_face_detection; - this.sizes = camera_features.picture_sizes; + this.photo_sizes = camera_features.picture_sizes; supported_flash_values = camera_features.supported_flash_values; supported_focus_values = camera_features.supported_focus_values; this.max_num_focus_areas = camera_features.max_num_focus_areas; @@ -2499,8 +2499,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( MyDebug.LOG ) Log.d(TAG, "set up picture sizes"); if( MyDebug.LOG ) { - for(int i=0;i current_size.width*current_size.height ) { current_size_index = i; current_size = size; @@ -2845,7 +2845,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } else { double targetRatio = ((double) profile.videoFrameWidth) / (double) profile.videoFrameHeight; - new_size = getOptimalVideoPictureSize(sizes, targetRatio); + new_size = getOptimalVideoPictureSize(photo_sizes, targetRatio); } } else { @@ -6820,14 +6820,14 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( MyDebug.LOG ) Log.d(TAG, "need to filter picture sizes for a burst mode"); List filtered_sizes = new ArrayList<>(); - for(CameraController.Size size : sizes) { + for(CameraController.Size size : photo_sizes) { if( size.supports_burst ) { filtered_sizes.add(size); } } return filtered_sizes; } - return this.sizes; + return this.photo_sizes; } /*public int getCurrentPictureSizeIndex() { @@ -6837,9 +6837,9 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu }*/ public CameraController.Size getCurrentPictureSize() { - if( current_size_index == -1 || sizes == null ) + if( current_size_index == -1 || photo_sizes == null ) return null; - return sizes.get(current_size_index); + return photo_sizes.get(current_size_index); } public VideoQualityHandler getVideoQualityHander() { -- GitLab From 5d2abb7bbbd97d8a8be659c9c402e9fe1d1f9159 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 12 Jan 2020 18:36:52 +0000 Subject: [PATCH 062/243] More info for photo and video resolutions on popup menu. --- _docs/history.html | 2 + .../opencamera/preview/Preview.java | 53 +++++++++++-------- .../sourceforge/opencamera/ui/PopupView.java | 4 +- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 5db5c1610..b5b947b96 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -66,6 +66,8 @@ UPDATED On devices with on-screen navigation buttons, camera preview can now dis buttons if required for wide aspect ratio (requires Android 5+). UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. +UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name + like FullHD, VGA etc for video). UPDATED Don't set video digital stabilization when in photo mode. UPDATED Moved video bitrate and frame rate options to debugging section. diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index e3bc6571f..4df482627 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -3266,7 +3266,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return width + ":" + height; } - private static String getMPString(int width, int height) { + public static String getMPString(int width, int height) { float mp = (width*height)/1000000.0f; return formatFloatToString(mp) + "MP"; } @@ -3280,45 +3280,52 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return "(" + getAspectRatio(width, height) + ", " + getMPString(width, height) + getBurstString(resources, supports_burst) + ")"; } - public String getCamcorderProfileDescriptionShort(String quality) { - if( camera_controller == null ) - return ""; - CamcorderProfile profile = getCamcorderProfile(quality); - // don't display MP here, as call to Preview.getMPString() here would contribute to poor performance (in PopupView)! - // this is meant to be a quick simple string - return profile.videoFrameWidth + "x" + profile.videoFrameHeight; - } - - public String getCamcorderProfileDescription(String quality) { - if( camera_controller == null ) - return ""; - CamcorderProfile profile = getCamcorderProfile(quality); + private String getCamcorderProfileDescriptionType(CamcorderProfile profile) { String type = ""; + // keep strings short, as displayed on the PopupView if( profile.videoFrameWidth == 3840 && profile.videoFrameHeight == 2160 ) { - type = "4K Ultra HD "; + type = "4K"; } else if( profile.videoFrameWidth == 1920 && profile.videoFrameHeight == 1080 ) { - type = "Full HD "; + type = "FullHD"; } else if( profile.videoFrameWidth == 1280 && profile.videoFrameHeight == 720 ) { - type = "HD "; + type = "HD"; } else if( profile.videoFrameWidth == 720 && profile.videoFrameHeight == 480 ) { - type = "SD "; + type = "SD"; } else if( profile.videoFrameWidth == 640 && profile.videoFrameHeight == 480 ) { - type = "VGA "; + type = "VGA"; } else if( profile.videoFrameWidth == 352 && profile.videoFrameHeight == 288 ) { - type = "CIF "; + type = "CIF"; } else if( profile.videoFrameWidth == 320 && profile.videoFrameHeight == 240 ) { - type = "QVGA "; + type = "QVGA"; } else if( profile.videoFrameWidth == 176 && profile.videoFrameHeight == 144 ) { - type = "QCIF "; + type = "QCIF"; } - return type + profile.videoFrameWidth + "x" + profile.videoFrameHeight + " " + getAspectRatioMPString(getResources(), profile.videoFrameWidth, profile.videoFrameHeight, true); + return type; + } + + public String getCamcorderProfileDescriptionShort(String quality) { + if( camera_controller == null ) + return ""; + CamcorderProfile profile = getCamcorderProfile(quality); + String type = getCamcorderProfileDescriptionType(profile); + String space = type.length() == 0 ? "" : " "; + return profile.videoFrameWidth + "x" + profile.videoFrameHeight + space + type; + } + + public String getCamcorderProfileDescription(String quality) { + if( camera_controller == null ) + return ""; + CamcorderProfile profile = getCamcorderProfile(quality); + String type = getCamcorderProfileDescriptionType(profile); + String space = type.length() == 0 ? "" : " "; + return type + space + profile.videoFrameWidth + "x" + profile.videoFrameHeight + " " + getAspectRatioMPString(getResources(), profile.videoFrameWidth, profile.videoFrameHeight, true); } public double getTargetRatio() { diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index 5cae2c4c8..9e1f49dd9 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -358,8 +358,8 @@ public class PopupView extends LinearLayout { final List picture_size_strings = new ArrayList<>(); for(int i=0;i Date: Sun, 12 Jan 2020 20:01:32 +0000 Subject: [PATCH 063/243] Refactor preference_immersive_mode entries/values to have translations in strings. --- app/src/main/res/values-az/arrays.xml | 12 ----------- app/src/main/res/values-az/strings.xml | 5 +++++ app/src/main/res/values-be/arrays.xml | 12 ----------- app/src/main/res/values-be/strings.xml | 4 ++++ app/src/main/res/values-cs/arrays.xml | 12 ----------- app/src/main/res/values-cs/strings.xml | 4 ++++ app/src/main/res/values-de/arrays.xml | 12 ----------- app/src/main/res/values-de/strings.xml | 4 ++++ app/src/main/res/values-es/arrays.xml | 12 ----------- app/src/main/res/values-es/strings.xml | 4 ++++ app/src/main/res/values-fr/arrays.xml | 12 ----------- app/src/main/res/values-fr/strings.xml | 4 ++++ app/src/main/res/values-hu/arrays.xml | 12 ----------- app/src/main/res/values-hu/strings.xml | 4 ++++ app/src/main/res/values-it/arrays.xml | 12 ----------- app/src/main/res/values-it/strings.xml | 4 ++++ app/src/main/res/values-ja/arrays.xml | 12 ----------- app/src/main/res/values-ja/strings.xml | 4 ++++ app/src/main/res/values-ko/arrays.xml | 12 ----------- app/src/main/res/values-ko/strings.xml | 4 ++++ app/src/main/res/values-nb/arrays.xml | 12 ----------- app/src/main/res/values-nb/strings.xml | 4 ++++ app/src/main/res/values-pl/arrays.xml | 12 ----------- app/src/main/res/values-pl/strings.xml | 4 ++++ app/src/main/res/values-pt-rBR/arrays.xml | 12 ----------- app/src/main/res/values-pt-rBR/strings.xml | 4 ++++ app/src/main/res/values-pt-rPT/arrays.xml | 12 ----------- app/src/main/res/values-pt-rPT/strings.xml | 4 ++++ app/src/main/res/values-ru/arrays.xml | 12 ----------- app/src/main/res/values-ru/strings.xml | 4 ++++ app/src/main/res/values-sl/arrays.xml | 12 ----------- app/src/main/res/values-sl/strings.xml | 4 ++++ app/src/main/res/values-tr/arrays.xml | 12 ----------- app/src/main/res/values-tr/strings.xml | 4 ++++ app/src/main/res/values-uk/arrays.xml | 12 ----------- app/src/main/res/values-uk/strings.xml | 4 ++++ app/src/main/res/values-vi/arrays.xml | 12 ----------- app/src/main/res/values-vi/strings.xml | 4 ++++ app/src/main/res/values-zh-rCN/arrays.xml | 12 ----------- app/src/main/res/values-zh-rCN/strings.xml | 5 ++++- app/src/main/res/values-zh-rTW/arrays.xml | 12 ----------- app/src/main/res/values-zh-rTW/strings.xml | 4 ++++ app/src/main/res/values/arrays.xml | 24 +++++++++++----------- app/src/main/res/values/strings.xml | 5 +++++ 44 files changed, 102 insertions(+), 265 deletions(-) diff --git a/app/src/main/res/values-az/arrays.xml b/app/src/main/res/values-az/arrays.xml index 91bb044fd..f6091336a 100644 --- a/app/src/main/res/values-az/arrays.xml +++ b/app/src/main/res/values-az/arrays.xml @@ -94,18 +94,6 @@ 0 180 - - Bağla - Hərəkət düyməsini gizlə - GUI gizlə - Hamısını gizlə - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Yox 3x3 diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 248066342..ecb21a533 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -311,4 +311,9 @@ Sol əllə işləyənlər üçün Sağ əllə işləyənlər üçün + Bağla + Hərəkət düyməsini gizlə + GUI gizlə + Hamısını gizlə + diff --git a/app/src/main/res/values-be/arrays.xml b/app/src/main/res/values-be/arrays.xml index 0f861c0ef..5bb6de23a 100644 --- a/app/src/main/res/values-be/arrays.xml +++ b/app/src/main/res/values-be/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Выключана - Хаваць віртуальныя кнопкі навігацыі на экране - Хаваць GUI - Хаваць усе - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Чырвоны Зялёны diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 057339b09..8347a9ffb 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -357,4 +357,8 @@ Тэкст з ценем Звычайны тэкст + Выключана + Хаваць віртуальныя кнопкі навігацыі на экране + Хаваць GUI + Хаваць усе diff --git a/app/src/main/res/values-cs/arrays.xml b/app/src/main/res/values-cs/arrays.xml index 4ffc81cdd..4cc0e8a6e 100644 --- a/app/src/main/res/values-cs/arrays.xml +++ b/app/src/main/res/values-cs/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Vypnuto - Skrýt pouze virtuální navigační tlačítka - Skrýt grafické rozhraní - Skrýt vše - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Červená Zelená diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index dd0d3c086..0a95a5751 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -361,4 +361,8 @@ Vystínovaný text Prostý text + Vypnuto + Skrýt pouze virtuální navigační tlačítka + Skrýt grafické rozhraní + Skrýt vše diff --git a/app/src/main/res/values-de/arrays.xml b/app/src/main/res/values-de/arrays.xml index b20ddf573..d1efcb095 100644 --- a/app/src/main/res/values-de/arrays.xml +++ b/app/src/main/res/values-de/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Nichts ausblenden - Nur Navigationstasten ausblenden - Alle Einstellelemente ausblenden - Alles ausblenden - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Rot Grün diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b8c0d70be..669bdaedd 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -823,4 +823,8 @@ Wähle eine Fernsteuerung + Nichts ausblenden + Nur Navigationstasten ausblenden + Alle Einstellelemente ausblenden + Alles ausblenden diff --git a/app/src/main/res/values-es/arrays.xml b/app/src/main/res/values-es/arrays.xml index a8c790100..2737fac05 100644 --- a/app/src/main/res/values-es/arrays.xml +++ b/app/src/main/res/values-es/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Apagado - Sólo ocultar los botones de navegación en pantalla - Ocultar interfaz de usuario - Ocultar todo - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Rojo Verde diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 354b9966f..61b6f7d1c 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -592,4 +592,8 @@ Texto sombreado Texto plano + Apagado + Sólo ocultar los botones de navegación en pantalla + Ocultar interfaz de usuario + Ocultar todo diff --git a/app/src/main/res/values-fr/arrays.xml b/app/src/main/res/values-fr/arrays.xml index 21e492c62..121eab85c 100644 --- a/app/src/main/res/values-fr/arrays.xml +++ b/app/src/main/res/values-fr/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Off - Masquer uniquement les boutons de navigation virtuelle de l\'écran - Masquer l\'interface graphique - Tout masquer - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Rouge Vert diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 61d56343d..328ef6c21 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -439,4 +439,8 @@ Texte ombré Texte brut + Off + Masquer uniquement les boutons de navigation virtuelle de l\'écran + Masquer l\'interface graphique + Tout masquer diff --git a/app/src/main/res/values-hu/arrays.xml b/app/src/main/res/values-hu/arrays.xml index 6eafb5d23..62be77f76 100644 --- a/app/src/main/res/values-hu/arrays.xml +++ b/app/src/main/res/values-hu/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Ki - Csak a virtuális navigációs gombok elrejtése - Kezelőfelület elrejtése - Minden elrejtése - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Piros Zöld diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index fd2c10055..525cbe147 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -497,4 +497,8 @@ Árnyékos szöveg Sima szöveg + Ki + Csak a virtuális navigációs gombok elrejtése + Kezelőfelület elrejtése + Minden elrejtése diff --git a/app/src/main/res/values-it/arrays.xml b/app/src/main/res/values-it/arrays.xml index 9fa703dbd..abdeb6efc 100644 --- a/app/src/main/res/values-it/arrays.xml +++ b/app/src/main/res/values-it/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Off - Nascondi solamente i bottoni di navigazione virtuali on-screen - Nascondi GUI - Nascondi tutto - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Rosso Verde diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5378761f3..42d8bda4b 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -525,4 +525,8 @@ Testo ombreggiato Testo piano + Off + Nascondi solamente i bottoni di navigazione virtuali on-screen + Nascondi GUI + Nascondi tutto diff --git a/app/src/main/res/values-ja/arrays.xml b/app/src/main/res/values-ja/arrays.xml index 712abb7f8..44fb33c61 100644 --- a/app/src/main/res/values-ja/arrays.xml +++ b/app/src/main/res/values-ja/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - オフ - スクリーンボタンのみ除外 - GUIを除外 - すべてを除外 - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 1dd4281d5..a707ef369 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -357,4 +357,8 @@ 影付き文字 普通の文字 + オフ + スクリーンボタンのみ除外 + GUIを除外 + すべてを除外 diff --git a/app/src/main/res/values-ko/arrays.xml b/app/src/main/res/values-ko/arrays.xml index ba079830a..57ef5437c 100644 --- a/app/src/main/res/values-ko/arrays.xml +++ b/app/src/main/res/values-ko/arrays.xml @@ -94,18 +94,6 @@ 0 180 - - 끄기 - 화면상의 가상 탐색 버튼만 숨기기 - GUI 숨기기 - 모두 숨기기 - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - 없음 3x3 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index ad5a38827..fea19da6b 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -323,4 +323,8 @@ 왼손잡이 사용자 인터페이스 오른손잡이 사용자 인터페이스 + 끄기 + 화면상의 가상 탐색 버튼만 숨기기 + GUI 숨기기 + 모두 숨기기 diff --git a/app/src/main/res/values-nb/arrays.xml b/app/src/main/res/values-nb/arrays.xml index 65a26d728..b1d5b42f1 100644 --- a/app/src/main/res/values-nb/arrays.xml +++ b/app/src/main/res/values-nb/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Av - Skjul bare de virtuelle navigasjonsknappene - Skjul grensesnittet - Skjul alt - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Rød Grønn diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index c9aadae57..1bfde97d3 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -547,4 +547,8 @@ Skyggelagt tekst Ren tekst + Av + Skjul bare de virtuelle navigasjonsknappene + Skjul grensesnittet + Skjul alt diff --git a/app/src/main/res/values-pl/arrays.xml b/app/src/main/res/values-pl/arrays.xml index 6ba9709d2..a5faaf049 100644 --- a/app/src/main/res/values-pl/arrays.xml +++ b/app/src/main/res/values-pl/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Wyłączone - Ukryj tylko przyciski nawigacyjne - Ukryj graficzny interfejs - Ukryj wszystko - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Czerwony Zielony diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 88036b933..bd8b601fc 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -473,4 +473,8 @@ Cieniowany tekst Czysty tekst + Wyłączone + Ukryj tylko przyciski nawigacyjne + Ukryj graficzny interfejs + Ukryj wszystko diff --git a/app/src/main/res/values-pt-rBR/arrays.xml b/app/src/main/res/values-pt-rBR/arrays.xml index b583d6ca3..68086d712 100644 --- a/app/src/main/res/values-pt-rBR/arrays.xml +++ b/app/src/main/res/values-pt-rBR/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Desligado - Somente esconder as teclas virtuais de navegação - Esconder IGU - Esconder tudo - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Red Green diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 8b62133df..7d0ebbb82 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -323,4 +323,8 @@ Interface para canhoto Interface para destro + Desligado + Somente esconder as teclas virtuais de navegação + Esconder IGU + Esconder tudo diff --git a/app/src/main/res/values-pt-rPT/arrays.xml b/app/src/main/res/values-pt-rPT/arrays.xml index ff854af8f..e464ce020 100644 --- a/app/src/main/res/values-pt-rPT/arrays.xml +++ b/app/src/main/res/values-pt-rPT/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Desligado - Apenas ocultar os botões de navegação virtuais - Ocultar interface - Ocultar tudo - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Vermelho Verde diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 84cbc11ab..f3d716a13 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -413,4 +413,8 @@ Texto sombreado Texto simples + Desligado + Apenas ocultar os botões de navegação virtuais + Ocultar interface + Ocultar tudo diff --git a/app/src/main/res/values-ru/arrays.xml b/app/src/main/res/values-ru/arrays.xml index b0bf2eb25..01d45dc4a 100644 --- a/app/src/main/res/values-ru/arrays.xml +++ b/app/src/main/res/values-ru/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Выключить - Скрыть кнопки навигации - Скрыть интерфейс - Скрыть все - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Красный Зеленый diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3a65c950d..fb7707628 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -910,4 +910,8 @@ Выбрать удаленное устройство + Выключить + Скрыть кнопки навигации + Скрыть интерфейс + Скрыть все diff --git a/app/src/main/res/values-sl/arrays.xml b/app/src/main/res/values-sl/arrays.xml index 30f1278b2..1a300e136 100644 --- a/app/src/main/res/values-sl/arrays.xml +++ b/app/src/main/res/values-sl/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Izk. - Skrij samo zaslonske gumbe za navidezno krmarjenje - Skrij gr. up. vmsnik - Skrij vse - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Rdeča Zelena diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 1c0b0cd8e..fe3b0b1c1 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -552,4 +552,8 @@ Osenčeno besedilo Golo besedilo + Izk. + Skrij samo zaslonske gumbe za navidezno krmarjenje + Skrij gr. up. vmsnik + Skrij vse diff --git a/app/src/main/res/values-tr/arrays.xml b/app/src/main/res/values-tr/arrays.xml index d31fec9ef..b0d049e35 100644 --- a/app/src/main/res/values-tr/arrays.xml +++ b/app/src/main/res/values-tr/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Kapalı - Sadece sanal ekran navigasyon butonlarını gizle - GUI(Grafik arayüz) gizle - Herşeyi gizle - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Kırmızı Yeşil diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 011a4fbad..382e228ef 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -360,4 +360,8 @@ Gölgeli yazı Düz yazı + Kapalı + Sadece sanal ekran navigasyon butonlarını gizle + GUI(Grafik arayüz) gizle + Herşeyi gizle diff --git a/app/src/main/res/values-uk/arrays.xml b/app/src/main/res/values-uk/arrays.xml index a5a9c9cfe..fc4ac7293 100644 --- a/app/src/main/res/values-uk/arrays.xml +++ b/app/src/main/res/values-uk/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Вимкнути - Приховати кнопки навігації - Приховати GUI - Приховати все - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Червоний Зелений diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index dc81774a0..d686933dc 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -498,4 +498,8 @@ Текст с тінью Звичайний текст + Вимкнути + Приховати кнопки навігації + Приховати GUI + Приховати все diff --git a/app/src/main/res/values-vi/arrays.xml b/app/src/main/res/values-vi/arrays.xml index dea394559..c23edde52 100644 --- a/app/src/main/res/values-vi/arrays.xml +++ b/app/src/main/res/values-vi/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - Tắt - Chỉ ẩn các nút điều hướng - Ẩn giao diện người dùng - Ẩn mọi thứ - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Đỏ Lục diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 91457294a..59f108dcf 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -780,4 +780,8 @@ Đổ bóng Thuần túy + Tắt + Chỉ ẩn các nút điều hướng + Ẩn giao diện người dùng + Ẩn mọi thứ diff --git a/app/src/main/res/values-zh-rCN/arrays.xml b/app/src/main/res/values-zh-rCN/arrays.xml index 6365bd34c..dae98a91f 100644 --- a/app/src/main/res/values-zh-rCN/arrays.xml +++ b/app/src/main/res/values-zh-rCN/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - 关闭 - 只隐藏屏幕上的虚拟导航按钮 - 隐藏图形用户界面 - 隐藏一切 - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - 红色 绿色 diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e3b25a280..2dd038dd5 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -826,5 +826,8 @@ ID - + 关闭 + 只隐藏屏幕上的虚拟导航按钮 + 隐藏图形用户界面 + 隐藏一切 diff --git a/app/src/main/res/values-zh-rTW/arrays.xml b/app/src/main/res/values-zh-rTW/arrays.xml index ac2b64d26..42fb1da33 100644 --- a/app/src/main/res/values-zh-rTW/arrays.xml +++ b/app/src/main/res/values-zh-rTW/arrays.xml @@ -104,18 +104,6 @@ 0 180 - - 關閉 - 只隱藏螢幕上的虛擬按鈕 - 隱藏圖形化使用者介面 - 隱藏全部 - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 03e47cbba..4299175b7 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -350,4 +350,8 @@ 左手使用者介面 右手使用者介面 + 關閉 + 只隱藏螢幕上的虛擬按鈕 + 隱藏圖形化使用者介面 + 隱藏全部 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 9c2fdcbda..a55b563d1 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -115,18 +115,6 @@ 0 180 - - Off - Only hide on-screen virtual navigation buttons - Hide GUI - Hide everything - - - immersive_mode_off - immersive_mode_low_profile - immersive_mode_gui - immersive_mode_everything - Red Green @@ -967,4 +955,16 @@ preference_panorama_save_all preference_panorama_save_all_plus_debug + + @string/preference_immersive_mode_off + @string/preference_immersive_mode_low_profile + @string/preference_immersive_mode_gui + @string/preference_immersive_mode_everything + + + immersive_mode_off + immersive_mode_low_profile + immersive_mode_gui + immersive_mode_everything + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 680bc032e..f99924362 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -931,6 +931,11 @@ 3.2 4.0 + Off + Only hide on-screen virtual navigation buttons + Hide GUI + Hide everything + Privacy policy -- GitLab From 1f7ae1f9f0133e13e8cd90c0b62bea9100f20368 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 12 Jan 2020 20:19:46 +0000 Subject: [PATCH 064/243] New immersive mode option to hide navigation buttons only; existing option renamed to say "dim". --- _docs/help.html | 6 ++++-- _docs/history.html | 2 ++ .../net/sourceforge/opencamera/MainActivity.java | 13 ++++++++++--- app/src/main/res/values-az/strings.xml | 2 +- app/src/main/res/values-be/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-nb/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt-rPT/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-sl/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values-vi/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/arrays.xml | 2 ++ app/src/main/res/values/strings.xml | 3 ++- 26 files changed, 41 insertions(+), 27 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index e549d968c..371b77046 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -691,8 +691,10 @@ default behaviour).

      make it more immersive (requires Android 4.4 or higher):

      • Off - Don't use immersive mode, and on-screen virtual navigation buttons are always visible.
      • -
      • Only hide on-screen virtual navigation buttons (default) - Don't use immersive mode, but on-screen virtual -navigation buttons are dimmed.
      • +
      • Only dim on-screen virtual navigation buttons (default) - Don't use immersive mode, but on-screen virtual +navigation buttons are dimmed. Note that some devices don't support virtual navigation buttons being dimmed, in +which case this option is the same as "Off".
      • +
      • Hide on-screen virtual navigation buttons - After a short delay, any on-screen virtual navigation buttons will disappear.
      • Hide GUI - After a short delay, any on-screen virtual navigation buttons will disappear, along with most of the GUI buttons. To exit this immersive mode, either touch on-screen, or swipe in from the top/bottom sides when the device is held in landscape (or left/right sides if held in portrait).
      • diff --git a/_docs/history.html b/_docs/history.html index b5b947b96..017c64651 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -64,6 +64,8 @@ FIXED Problem of on-screen level angle overlapping with shutter icon when usin ADDED New custom gamma option for video recording. UPDATED On devices with on-screen navigation buttons, camera preview can now display under these buttons if required for wide aspect ratio (requires Android 5+). +UPDATED New immersive mode option to hide navigation buttons only when in immersive mode; existing + option for hiding navigation buttons now renamed to say "dim". UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index daa4f5b46..6de267d5f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -440,13 +440,19 @@ public class MainActivity extends Activity { return; if( MyDebug.LOG ) Log.d(TAG, "onSystemUiVisibilityChange: " + visibility); + + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this); + String immersive_mode = sharedPreferences.getString(PreferenceKeys.ImmersiveModePreferenceKey, "immersive_mode_low_profile"); + boolean hide_ui = immersive_mode.equals("immersive_mode_gui") || immersive_mode.equals("immersive_mode_everything"); + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { if( MyDebug.LOG ) Log.d(TAG, "system bars now visible"); // The system bars are visible. Make any desired // adjustments to your UI, such as showing the action bar or // other navigational controls. - mainUI.setImmersiveMode(false); + if( hide_ui ) + mainUI.setImmersiveMode(false); setImmersiveTimer(); } else { @@ -455,7 +461,8 @@ public class MainActivity extends Activity { // The system bars are NOT visible. Make any desired // adjustments to your UI, such as hiding the action bar or // other navigational controls. - mainUI.setImmersiveMode(true); + if( hide_ui ) + mainUI.setImmersiveMode(true); } } }); @@ -2238,7 +2245,7 @@ public class MainActivity extends Activity { if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); String immersive_mode = sharedPreferences.getString(PreferenceKeys.ImmersiveModePreferenceKey, "immersive_mode_low_profile"); - if( immersive_mode.equals("immersive_mode_gui") || immersive_mode.equals("immersive_mode_everything") ) + if( immersive_mode.equals("immersive_mode_navigation") || immersive_mode.equals("immersive_mode_gui") || immersive_mode.equals("immersive_mode_everything") ) return true; } return false; diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index ecb21a533..a11cb6b33 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -312,7 +312,7 @@ Sağ əllə işləyənlər üçün Bağla - Hərəkət düyməsini gizlə + Hərəkət düyməsini gizlə GUI gizlə Hamısını gizlə diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 8347a9ffb..52f46cd45 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -358,7 +358,7 @@ Звычайны тэкст Выключана - Хаваць віртуальныя кнопкі навігацыі на экране + Хаваць віртуальныя кнопкі навігацыі на экране Хаваць GUI Хаваць усе diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 0a95a5751..416442c93 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -362,7 +362,7 @@ Prostý text Vypnuto - Skrýt pouze virtuální navigační tlačítka + Skrýt pouze virtuální navigační tlačítka Skrýt grafické rozhraní Skrýt vše diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 669bdaedd..9dd5fa7e5 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -824,7 +824,7 @@ Wähle eine Fernsteuerung Nichts ausblenden - Nur Navigationstasten ausblenden + Nur Navigationstasten ausblenden Alle Einstellelemente ausblenden Alles ausblenden diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 61b6f7d1c..81f2e7e88 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -593,7 +593,7 @@ Texto plano Apagado - Sólo ocultar los botones de navegación en pantalla + Sólo ocultar los botones de navegación en pantalla Ocultar interfaz de usuario Ocultar todo diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 328ef6c21..f36abbc05 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -440,7 +440,7 @@ Texte brut Off - Masquer uniquement les boutons de navigation virtuelle de l\'écran + Masquer uniquement les boutons de navigation virtuelle de l\'écran Masquer l\'interface graphique Tout masquer diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 525cbe147..2d2132236 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -498,7 +498,7 @@ Sima szöveg Ki - Csak a virtuális navigációs gombok elrejtése + Csak a virtuális navigációs gombok elrejtése Kezelőfelület elrejtése Minden elrejtése diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 42d8bda4b..786218c0f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -526,7 +526,7 @@ Testo piano Off - Nascondi solamente i bottoni di navigazione virtuali on-screen + Nascondi solamente i bottoni di navigazione virtuali on-screen Nascondi GUI Nascondi tutto diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index a707ef369..39eb06eb1 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -358,7 +358,7 @@ 普通の文字 オフ - スクリーンボタンのみ除外 + スクリーンボタンのみ除外 GUIを除外 すべてを除外 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index fea19da6b..bb5175534 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -324,7 +324,7 @@ 오른손잡이 사용자 인터페이스 끄기 - 화면상의 가상 탐색 버튼만 숨기기 + 화면상의 가상 탐색 버튼만 숨기기 GUI 숨기기 모두 숨기기 diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 1bfde97d3..12d457e70 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -548,7 +548,7 @@ Ren tekst Av - Skjul bare de virtuelle navigasjonsknappene + Skjul bare de virtuelle navigasjonsknappene Skjul grensesnittet Skjul alt diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index bd8b601fc..3c8e49455 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -474,7 +474,7 @@ Czysty tekst Wyłączone - Ukryj tylko przyciski nawigacyjne + Ukryj tylko przyciski nawigacyjne Ukryj graficzny interfejs Ukryj wszystko diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 7d0ebbb82..6cd1b9fa1 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -324,7 +324,7 @@ Interface para destro Desligado - Somente esconder as teclas virtuais de navegação + Somente esconder as teclas virtuais de navegação Esconder IGU Esconder tudo diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index f3d716a13..c3e7c95b5 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -414,7 +414,7 @@ Texto simples Desligado - Apenas ocultar os botões de navegação virtuais + Apenas ocultar os botões de navegação virtuais Ocultar interface Ocultar tudo diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fb7707628..ea379fa07 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -911,7 +911,7 @@ Выбрать удаленное устройство Выключить - Скрыть кнопки навигации + Скрыть кнопки навигации Скрыть интерфейс Скрыть все diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index fe3b0b1c1..b8dc63b7f 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -553,7 +553,7 @@ Golo besedilo Izk. - Skrij samo zaslonske gumbe za navidezno krmarjenje + Skrij samo zaslonske gumbe za navidezno krmarjenje Skrij gr. up. vmsnik Skrij vse diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 382e228ef..2d4d53076 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -361,7 +361,7 @@ Düz yazı Kapalı - Sadece sanal ekran navigasyon butonlarını gizle + Sadece sanal ekran navigasyon butonlarını gizle GUI(Grafik arayüz) gizle Herşeyi gizle diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index d686933dc..2f31cfed2 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -499,7 +499,7 @@ Звичайний текст Вимкнути - Приховати кнопки навігації + Приховати кнопки навігації Приховати GUI Приховати все diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 59f108dcf..bb8e3d0e3 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -781,7 +781,7 @@ Thuần túy Tắt - Chỉ ẩn các nút điều hướng + Chỉ ẩn các nút điều hướng Ẩn giao diện người dùng Ẩn mọi thứ diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 2dd038dd5..6264180e2 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -827,7 +827,7 @@ ID 关闭 - 只隐藏屏幕上的虚拟导航按钮 + 只隐藏屏幕上的虚拟导航按钮 隐藏图形用户界面 隐藏一切 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 4299175b7..7800204e6 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -351,7 +351,7 @@ 右手使用者介面 關閉 - 只隱藏螢幕上的虛擬按鈕 + 只隱藏螢幕上的虛擬按鈕 隱藏圖形化使用者介面 隱藏全部 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index a55b563d1..f3b470b5d 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -958,12 +958,14 @@ @string/preference_immersive_mode_off @string/preference_immersive_mode_low_profile + @string/preference_immersive_mode_navigation @string/preference_immersive_mode_gui @string/preference_immersive_mode_everything immersive_mode_off immersive_mode_low_profile + immersive_mode_navigation immersive_mode_gui immersive_mode_everything diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f99924362..366ea9308 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -932,7 +932,8 @@ 4.0 Off - Only hide on-screen virtual navigation buttons + Only dim on-screen virtual navigation buttons + Hide on-screen virtual navigation buttons Hide GUI Hide everything -- GitLab From d597638a8e3798291689455e1d1218fc65789efe Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 15 Jan 2020 22:27:04 +0000 Subject: [PATCH 065/243] Add FAQ about switching to a new phone; fix missing close bracket. --- _docs/help.html | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/_docs/help.html b/_docs/help.html index 371b77046..f899bc9ac 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -1188,13 +1188,22 @@ external SD card, see "How can I save to my external SD card?" above. Otherwise:
        • If Settings/More camera controls/"Use Storage Access Framework" is enabled, in some cases the permission may be lost, try rechoosing the save location (from - Settings/More camera controls/"Save location".
        • + Settings/More camera controls/"Save location").
        • If not using Storage Access Framework, but you have changed the save location, it may be you've chosen somewhere where applications don't have permission to save files.
        • Or sometimes simply restarting the devices fixes such problems.
        +

        I switched to a new phone, and now something doesn't work! - Google's auto-backup will +typically transfer settings to a new phone, but this may mean a camera-specific setting is no +longer relevant. In particular, if you set a non-default save location, it may be that the path is +not valid on the new device, or if using Settings/More camera controls/"Use Storage Access Framework", +you may need to rechoose the save location (from Settings/More camera controls/"Save location") to +grant permission to the new device. You can use Settings/Settings manager/"Reset settings" to reset +Open Camera to its original state, to rule out any issues from an Android backup from another +device.

        +

        My pictures are being rotated/cropped! - This likely means the auto-level option is on. (If they're being rotated even when the phone is held level, it may mean the accelerometer sensor on your device isn't calibrated.) It's off by default, but you may have accidentally switched it on. To turn off, go to the "popup" menu -- GitLab From 43b7faae112cab6e2c3002b7ddead5a04aedcdc8 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 15 Jan 2020 22:48:17 +0000 Subject: [PATCH 066/243] New ArraySeekBarPreference. --- .../opencamera/ui/ArraySeekBarPreference.java | 231 ++++++++++++++++++ .../res/layout/arrayseekbarpreference.xml | 18 ++ 2 files changed, 249 insertions(+) create mode 100644 app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java create mode 100644 app/src/main/res/layout/arrayseekbarpreference.xml diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java b/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java new file mode 100644 index 000000000..a27bdb412 --- /dev/null +++ b/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java @@ -0,0 +1,231 @@ +package net.sourceforge.opencamera.ui; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.DialogPreference; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; + +import net.sourceforge.opencamera.R; + +/** This contains a custom preference to display a seekbar in place of a ListPreference. + */ +public class ArraySeekBarPreference extends DialogPreference { + private static final String TAG = "ArraySeekBarPreference"; + + private SeekBar seekbar; + private TextView textView; + + private CharSequence [] entries; // user readable strings + private CharSequence [] values; // values corresponding to each string + + private final String default_value; + private String value; // current saved value of this preference (note that this is intentionally not updated when the seekbar changes, as we don't save until the user clicks ok) + private boolean value_set; + + public ArraySeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + String namespace = "http://schemas.android.com/apk/res/android"; + this.default_value = attrs.getAttributeValue(namespace, "defaultValue"); + this.setEntries(attrs.getAttributeResourceValue(namespace, "entries", 0)); + this.setEntryValues(attrs.getAttributeResourceValue(namespace, "entryValues", 0)); + + setDialogLayoutResource(R.layout.arrayseekbarpreference); + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + + if( entries == null || values == null ) { + throw new IllegalStateException("ArraySeekBarPreference requires entries and entryValues array"); + } + else if( entries.length != values.length ) { + throw new IllegalStateException("ArraySeekBarPreference requires entries and entryValues arrays of same length"); + } + + this.seekbar = view.findViewById(R.id.arrayseekbarpreference_seekbar); + this.textView = view.findViewById(R.id.arrayseekbarpreference_value); + + seekbar.setMax(entries.length-1); + { + int index = getValueIndex(); + if( index == -1 ) { + // If we're here, it means the stored value isn't in the values array. + // ListPreference just shows a dialog with no selected entry, but that doesn't really work for + // a seekbar that needs to show the current position! So instead, set the position to the default. + if( default_value != null && values != null ) { + for(int i = values.length - 1; i >= 0; i--) { + if( values[i].equals(default_value) ) { + index = i; + break; + } + } + } + } + if( index >= 0 ) + seekbar.setProgress(index); + } + seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + String new_entry = entries[progress].toString(); + textView.setText(new_entry); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + + String new_entry = entries[seekbar.getProgress()].toString(); + textView.setText(new_entry); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if( positiveResult && values != null ) { + int progress = seekbar.getProgress(); + String new_value = values[progress].toString(); + if( callChangeListener(new_value) ) { + setValue(new_value); + } + } + } + + private void setEntries(CharSequence[] entries) { + this.entries = entries; + } + + private void setEntries(int entries) { + setEntries(getContext().getResources().getTextArray(entries)); + } + + private void setEntryValues(CharSequence[] values) { + this.values = values; + } + + private void setEntryValues(int values) { + setEntryValues(getContext().getResources().getTextArray(values)); + } + + @Override + public CharSequence getSummary() { + CharSequence summary = super.getSummary(); + if( summary != null ) { + CharSequence entry = getEntry(); + return String.format(summary.toString(), entry == null ? "" : entry); + } + else + return null; + } + + /** Returns the index of the current value in the values array, or -1 if not found. + */ + private int getValueIndex() { + if( value != null && values != null ) { + // go backwards for compatibility with ListPreference in cases with duplicate values + for(int i = values.length - 1; i >= 0; i--) { + if( values[i].equals(value) ) { + return i; + } + } + } + return -1; + } + + /** Returns the human readable string of the current value. + */ + private CharSequence getEntry() { + int index = getValueIndex(); + return index >= 0 && entries != null ? entries[index] : null; + } + + private void setValue(String value) { + final boolean changed = !TextUtils.equals(this.value, value); + if( changed || !value_set ) { + this.value = value; + value_set = true; + persistString(value); + if( changed ) { + notifyChanged(); + } + } + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getString(index); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setValue(restoreValue ? getPersistedString(value) : (String) defaultValue); + } + + @Override + protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + if( isPersistent() ) { + return superState; + } + + final SavedState state = new SavedState(superState); + state.value = value; + return state; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if( state == null || !state.getClass().equals(SavedState.class) ) { + super.onRestoreInstanceState(state); + return; + } + + SavedState myState = (SavedState)state; + super.onRestoreInstanceState(myState.getSuperState()); + setValue(myState.value); + } + + private static class SavedState extends BaseSavedState { + String value; + + SavedState(Parcel source) { + super(source); + value = source.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(value); + } + + SavedState(Parcelable superState) { + super(superState); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} diff --git a/app/src/main/res/layout/arrayseekbarpreference.xml b/app/src/main/res/layout/arrayseekbarpreference.xml new file mode 100644 index 000000000..97c97f4c9 --- /dev/null +++ b/app/src/main/res/layout/arrayseekbarpreference.xml @@ -0,0 +1,18 @@ + + + + + -- GitLab From 5957155c7cf23838a8f36c30b2e32002a87672b7 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 15 Jan 2020 22:48:39 +0000 Subject: [PATCH 067/243] Use new ArraySeekBarPreference for gamma video. --- app/src/main/res/xml/preferences.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index acffdb6ac..b3dc3467e 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1015,7 +1015,7 @@ /> - Date: Wed, 15 Jan 2020 23:29:18 +0000 Subject: [PATCH 068/243] Fix crash if entries/entryValues not specified in xml. --- .../opencamera/ui/ArraySeekBarPreference.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java b/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java index a27bdb412..dfa6e72e5 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java @@ -33,8 +33,13 @@ public class ArraySeekBarPreference extends DialogPreference { String namespace = "http://schemas.android.com/apk/res/android"; this.default_value = attrs.getAttributeValue(namespace, "defaultValue"); - this.setEntries(attrs.getAttributeResourceValue(namespace, "entries", 0)); - this.setEntryValues(attrs.getAttributeResourceValue(namespace, "entryValues", 0)); + + int entries_id = attrs.getAttributeResourceValue(namespace, "entries", 0); + if( entries_id > 0 ) + this.setEntries(entries_id); + int values_id = attrs.getAttributeResourceValue(namespace, "entryValues", 0); + if( values_id > 0 ) + this.setEntryValues(values_id); setDialogLayoutResource(R.layout.arrayseekbarpreference); } -- GitLab From b8953c74790b84bb48610f7ece4b250886a5d7da Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 15 Jan 2020 23:30:05 +0000 Subject: [PATCH 069/243] New option for alpha value to use for ghost image option. --- _docs/help.html | 5 ++++- _docs/history.html | 1 + .../opencamera/MyApplicationInterface.java | 19 +++++++++++++++++++ .../opencamera/MyPreferenceFragment.java | 14 ++++++++++++++ .../opencamera/PreferenceKeys.java | 2 ++ .../opencamera/ui/ArraySeekBarPreference.java | 4 ++-- .../opencamera/ui/DrawPreview.java | 6 ++++-- app/src/main/res/values/strings.xml | 3 +++ app/src/main/res/xml/preferences.xml | 7 +++++++ 9 files changed, 56 insertions(+), 5 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index f899bc9ac..4759c2ed9 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -589,7 +589,7 @@ default behaviour).

      Ghost image - You can overlay a previous photo. This is useful for aligning photos (e.g., for stop - motion animation).

      + motion animation). This can also be used to create a custom "grid", by selecting an image with transparency.

      • Last photo taken - When you take a photo, a ghost of that photo will be displayed. The ghost is reset either by leaving and returning to Open Camera, switching between photo/video modes, or turning @@ -600,6 +600,9 @@ default behaviour).

        load the selected image.
      +

      Ghost image opacity - If a "Ghost image" is selected, this option controls how transparent/opaque the ghost +image should be drawn with.

      +

      Focus assist - If enabled, this will show a zoomed in view on the camera preview when in manual focus mode, and you are changing the manual focus distance. Similarly in focus bracketing mode, the preview will zoom in when changing the focus distances to bracket between. Note not supported when recording video.

      diff --git a/_docs/history.html b/_docs/history.html index 017c64651..e7e64503f 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -62,6 +62,7 @@ FIXED Recording video on Android 8+ could leave zero-size files if size approa FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. ADDED New custom gamma option for video recording. +ADDED New option for alpha value to use for ghost image option. UPDATED On devices with on-screen navigation buttons, camera preview can now display under these buttons if required for wide aspect ratio (requires Android 5+). UPDATED New immersive mode option to hide navigation buttons only when in immersive mode; existing diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 4707aa279..32d4951a6 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -1112,6 +1112,25 @@ public class MyApplicationInterface extends BasicApplicationInterface { return auto_stabilise && main_activity.supportsAutoStabilise(); } + /** Returns the alpha value to use for ghost image, as a number from 0 to 255. + * Note that we store the preference as a percentage from 0 to 100, but scale this to 0 to 255. + */ + public int getGhostImageAlpha() { + String ghost_image_alpha_value = sharedPreferences.getString(PreferenceKeys.GhostImageAlphaPreferenceKey, "50"); + int ghost_image_alpha; + try { + ghost_image_alpha = Integer.parseInt(ghost_image_alpha_value); + } + catch(NumberFormatException e) { + if( MyDebug.LOG ) + Log.e(TAG, "failed to parse ghost_image_alpha_value: " + ghost_image_alpha_value); + e.printStackTrace(); + ghost_image_alpha = 50; + } + ghost_image_alpha = (int)(ghost_image_alpha*2.55f+0.1f); + return ghost_image_alpha; + } + public String getStampPref() { return sharedPreferences.getString(PreferenceKeys.StampPreferenceKey, "preference_stamp_no"); } diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 265ac83ff..2364e0023 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -2,6 +2,7 @@ package net.sourceforge.opencamera; import net.sourceforge.opencamera.cameracontroller.CameraController; import net.sourceforge.opencamera.preview.Preview; +import net.sourceforge.opencamera.ui.ArraySeekBarPreference; import net.sourceforge.opencamera.ui.FolderChooserDialog; import android.app.Activity; @@ -283,6 +284,19 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared lp.setEntryValues(values); } + { + final int n_ghost_image_alpha = 20; + CharSequence [] entries = new CharSequence[n_ghost_image_alpha]; + CharSequence [] values = new CharSequence[n_ghost_image_alpha]; + for(int i=0;iHide GUI Hide everything + Ghost image opacity + Alpha value to use for ghost images. A lower value means more transparent, 100%% means opaque.\n%s + Privacy policy diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index b3dc3467e..e99e2670d 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -329,6 +329,13 @@ android:defaultValue="preference_ghost_image_off" /> + + Date: Thu, 16 Jan 2020 23:49:10 +0000 Subject: [PATCH 070/243] Downscale bitmap if necessary to device resolution in loadBitmap() - fixes poor performance with huge ghost images. --- _docs/history.html | 1 + .../opencamera/ui/DrawPreview.java | 51 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index e7e64503f..881410806 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -69,6 +69,7 @@ UPDATED New immersive mode option to hide navigation buttons only when in immers option for hiding navigation buttons now renamed to say "dim". UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. +UPDATED Improved performance when display ghost image larger than device's resolution. UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name like FullHD, VGA etc for video). UPDATED Don't set video digital stabilization when in photo mode. diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index c4b5a84d8..614b7a5d1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -32,6 +32,7 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; @@ -45,6 +46,7 @@ import android.preference.PreferenceManager; import android.provider.MediaStore; import android.util.Log; import android.util.Pair; +import android.view.Display; import android.view.Surface; import android.view.View; @@ -626,13 +628,60 @@ public class DrawPreview { /** Loads the bitmap from the uri. File is optional, and is used on pre-Android 7 devices to * read the exif orientation. + * The image will be downscaled if required to be comparable to the preview width. */ private Bitmap loadBitmap(Uri uri, File file) throws IOException { if( MyDebug.LOG ) Log.d(TAG, "loadBitmap: " + uri); Bitmap bitmap; try { - bitmap = MediaStore.Images.Media.getBitmap(main_activity.getContentResolver(), uri); + //bitmap = MediaStore.Images.Media.getBitmap(main_activity.getContentResolver(), uri); + + int sample_size = 1; + { + // attempt to compute appropriate scaling + BitmapFactory.Options bounds = new BitmapFactory.Options(); + bounds.inJustDecodeBounds = true; + InputStream input = main_activity.getContentResolver().openInputStream(uri); + BitmapFactory.decodeStream(input, null, bounds); + if( input != null ) + input.close(); + + if( bounds.outWidth != -1 && bounds.outHeight != -1 ) { + // compute appropriate scaling + int image_size = Math.max(bounds.outWidth, bounds.outHeight); + + Point point = new Point(); + Display display = main_activity.getWindowManager().getDefaultDisplay(); + display.getSize(point); + int display_size = Math.max(point.x, point.y); + + int ratio = (int) Math.ceil((double) image_size / display_size); + sample_size = Integer.highestOneBit(ratio); + if( MyDebug.LOG ) { + Log.d(TAG, "display_size: " + display_size); + Log.d(TAG, "image_size: " + image_size); + Log.d(TAG, "ratio: " + ratio); + Log.d(TAG, "sample_size: " + sample_size); + } + } + else { + if( MyDebug.LOG ) + Log.e(TAG, "failed to obtain width/height of bitmap"); + } + } + + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inMutable = false; + options.inSampleSize = sample_size; + InputStream input = main_activity.getContentResolver().openInputStream(uri); + bitmap = BitmapFactory.decodeStream(input, null, options); + if( input != null ) + input.close(); + if( MyDebug.LOG && bitmap != null ) { + Log.d(TAG, "bitmap width: " + bitmap.getWidth()); + Log.d(TAG, "bitmap height: " + bitmap.getHeight()); + } } catch(Exception e) { // Although Media.getBitmap() is documented as only throwing FileNotFoundException, IOException -- GitLab From c34721fa4d32282b69affa2f212323c157794d31 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 17 Jan 2020 23:07:27 +0000 Subject: [PATCH 071/243] Fix typo. --- _docs/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 881410806..57f6e36e0 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -69,7 +69,7 @@ UPDATED New immersive mode option to hide navigation buttons only when in immers option for hiding navigation buttons now renamed to say "dim". UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. -UPDATED Improved performance when display ghost image larger than device's resolution. +UPDATED Improved performance when displaying ghost image larger than device's resolution. UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name like FullHD, VGA etc for video). UPDATED Don't set video digital stabilization when in photo mode. -- GitLab From 1b7f9b7f1ca81e1f782dac6e0ec0c6137c53ab27 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 17 Jan 2020 23:50:36 +0000 Subject: [PATCH 072/243] Disable some options if not relevant. --- app/src/main/res/xml/preferences.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index e99e2670d..792b2abf8 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1079,6 +1079,7 @@ android:entries="@array/preference_record_audio_src_entries" android:entryValues="@array/preference_record_audio_src_values" android:defaultValue="audio_src_camcorder" + android:dependency="preference_record_audio" /> -- GitLab From 2c3058e415dda4fa42b5404138165b1de73fd71d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 18 Jan 2020 00:00:01 +0000 Subject: [PATCH 073/243] More zebra stripe values 93-99%. --- _docs/history.html | 1 + app/src/main/res/values-de/strings.xml | 5 +++++ app/src/main/res/values-ru/strings.xml | 5 +++++ app/src/main/res/values-zh-rCN/strings.xml | 5 +++++ app/src/main/res/values/arrays.xml | 10 ++++++++++ app/src/main/res/values/strings.xml | 5 +++++ 6 files changed, 31 insertions(+) diff --git a/_docs/history.html b/_docs/history.html index 57f6e36e0..e686cbd9d 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -63,6 +63,7 @@ FIXED Problem of on-screen level angle overlapping with shutter icon when usin preview aspect ratio. ADDED New custom gamma option for video recording. ADDED New option for alpha value to use for ghost image option. +ADDED More zebra stripe values 93-99%. UPDATED On devices with on-screen navigation buttons, camera preview can now display under these buttons if required for wide aspect ratio (requires Android 5+). UPDATED New immersive mode option to hide navigation buttons only when in immersive mode; existing diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 9dd5fa7e5..7e770d362 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -779,6 +779,11 @@ 70% 80% 90% + 93% + 95% + 97% + 98% + 99% 100% Fokus-Peaking diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ea379fa07..1baca9848 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -826,6 +826,11 @@ 70% 80% 90% + 93% + 95% + 97% + 98% + 99% 100% Снижение фокусировки diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 6264180e2..93f505171 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -774,6 +774,11 @@ 70% 80% 90% + 93% + 95% + 97% + 98% + 99% 100% 对焦峰值 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index f3b470b5d..8d938b518 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -920,6 +920,11 @@ @string/preference_zebra_stripes_70pc @string/preference_zebra_stripes_80pc @string/preference_zebra_stripes_90pc + @string/preference_zebra_stripes_93pc + @string/preference_zebra_stripes_95pc + @string/preference_zebra_stripes_97pc + @string/preference_zebra_stripes_98pc + @string/preference_zebra_stripes_99pc @string/preference_zebra_stripes_100pc @@ -927,6 +932,11 @@ 179 204 230 + 237 + 242 + 247 + 250 + 252 255 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8f5159a0d..792d006a0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -826,6 +826,11 @@ 70% 80% 90% + 93% + 95% + 97% + 98% + 99% 100% Focus peaking -- GitLab From 3e0224fac661b616852b18a107e135369b373fd0 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 18 Jan 2020 00:36:40 +0000 Subject: [PATCH 074/243] Options to control zebra stripe colours. --- _docs/history.html | 1 + .../opencamera/MyPreferenceFragment.java | 6 +++++ .../opencamera/PreferenceKeys.java | 4 ++++ .../opencamera/preview/Preview.java | 14 ++++++++++- .../opencamera/ui/DrawPreview.java | 9 +++++++- app/src/main/res/values/arrays.xml | 18 +++++++++++++++ app/src/main/res/values/strings.xml | 11 +++++++++ app/src/main/res/xml/preferences.xml | 20 ++++++++++++++++ app/src/main/rs/histogram_compute.rs | 23 +++++++++++++------ 9 files changed, 97 insertions(+), 9 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index e686cbd9d..6913d389b 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -64,6 +64,7 @@ FIXED Problem of on-screen level angle overlapping with shutter icon when usin ADDED New custom gamma option for video recording. ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. +ADDED Options to control zebra stripe colours. UPDATED On devices with on-screen navigation buttons, camera preview can now display under these buttons if required for wide aspect ratio (requires Android 5+). UPDATED New immersive mode option to hide navigation buttons only when in immersive mode; existing diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 2364e0023..8ce988c40 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -656,6 +656,12 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared pref = findPreference("preference_zebra_stripes"); pg.removePreference(pref); + pref = findPreference("preference_zebra_stripes_foreground_color"); + pg.removePreference(pref); + + pref = findPreference("preference_zebra_stripes_background_color"); + pg.removePreference(pref); + pref = findPreference("preference_focus_peaking"); pg.removePreference(pref); diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index 05a4884b7..777fd4a29 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -262,6 +262,10 @@ public class PreferenceKeys { public static final String ZebraStripesPreferenceKey = "preference_zebra_stripes"; + public static final String ZebraStripesForegroundColorPreferenceKey = "preference_zebra_stripes_foreground_color"; + + public static final String ZebraStripesBackgroundColorPreferenceKey = "preference_zebra_stripes_background_color"; + public static final String FocusPeakingPreferenceKey = "preference_focus_peaking"; public static final String FocusPeakingColorPreferenceKey = "preference_focus_peaking_color"; diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 4df482627..9252e8cfb 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -137,6 +137,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private boolean want_zebra_stripes; // whether to generate zebra stripes bitmap, requires want_preview_bitmap==true private int zebra_stripes_threshold; // pixels with max rgb value equal to or greater than this threshold are marked with zebra stripes + private int zebra_stripes_color_foreground; + private int zebra_stripes_color_background; private Bitmap zebra_stripes_bitmap_buffer; private Bitmap zebra_stripes_bitmap; @@ -7521,9 +7523,11 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return this.histogram; } - public void enableZebraStripes(int zebra_stripes_threshold) { + public void enableZebraStripes(int zebra_stripes_threshold, int zebra_stripes_color_foreground, int zebra_stripes_color_background) { this.want_zebra_stripes = true; this.zebra_stripes_threshold = zebra_stripes_threshold; + this.zebra_stripes_color_foreground = zebra_stripes_color_foreground; + this.zebra_stripes_color_background = zebra_stripes_color_background; if( this.zebra_stripes_bitmap_buffer == null ) { createZebraStripesBitmap(); } @@ -7763,6 +7767,14 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Allocation output_allocation = Allocation.createFromBitmap(preview.rs, zebra_stripes_bitmap_buffer); histogramScript.set_zebra_stripes_threshold(preview.zebra_stripes_threshold); + histogramScript.set_zebra_stripes_foreground_r(Color.red(preview.zebra_stripes_color_foreground)); + histogramScript.set_zebra_stripes_foreground_g(Color.green(preview.zebra_stripes_color_foreground)); + histogramScript.set_zebra_stripes_foreground_b(Color.blue(preview.zebra_stripes_color_foreground)); + histogramScript.set_zebra_stripes_foreground_a(Color.alpha(preview.zebra_stripes_color_foreground)); + histogramScript.set_zebra_stripes_background_r(Color.red(preview.zebra_stripes_color_background)); + histogramScript.set_zebra_stripes_background_g(Color.green(preview.zebra_stripes_color_background)); + histogramScript.set_zebra_stripes_background_b(Color.blue(preview.zebra_stripes_color_background)); + histogramScript.set_zebra_stripes_background_a(Color.alpha(preview.zebra_stripes_color_background)); histogramScript.set_zebra_stripes_width(zebra_stripes_bitmap_buffer.getWidth()/20); if( MyDebug.LOG ) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 614b7a5d1..ad24afc0f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -95,6 +95,8 @@ public class DrawPreview { private Preview.HistogramType histogram_type; private boolean want_zebra_stripes; private int zebra_stripes_threshold; + private int zebra_stripes_color_foreground; + private int zebra_stripes_color_background; private boolean want_focus_peaking; private int focus_peaking_color_pref; @@ -600,6 +602,11 @@ public class DrawPreview { } want_zebra_stripes = zebra_stripes_threshold != 0 & main_activity.supportsPreviewBitmaps(); + String zebra_stripes_color_foreground_value = sharedPreferences.getString(PreferenceKeys.ZebraStripesForegroundColorPreferenceKey, "#ff000000"); + zebra_stripes_color_foreground = Color.parseColor(zebra_stripes_color_foreground_value); + String zebra_stripes_color_background_value = sharedPreferences.getString(PreferenceKeys.ZebraStripesBackgroundColorPreferenceKey, "#ffffffff"); + zebra_stripes_color_background = Color.parseColor(zebra_stripes_color_background_value); + String focus_peaking_pref = sharedPreferences.getString(PreferenceKeys.FocusPeakingPreferenceKey, "preference_focus_peaking_off"); want_focus_peaking = !focus_peaking_pref.equals("preference_focus_peaking_off") && main_activity.supportsPreviewBitmaps(); String focus_peaking_color = sharedPreferences.getString(PreferenceKeys.FocusPeakingColorPreferenceKey, "#ffffff"); @@ -2377,7 +2384,7 @@ public class DrawPreview { preview.disableHistogram(); if( want_zebra_stripes ) - preview.enableZebraStripes(zebra_stripes_threshold); + preview.enableZebraStripes(zebra_stripes_threshold, zebra_stripes_color_foreground, zebra_stripes_color_background); else preview.disableZebraStripes(); diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8d938b518..f1533190d 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -979,4 +979,22 @@ immersive_mode_gui immersive_mode_everything + + @string/preference_zebra_stripes_color_black + @string/preference_zebra_stripes_color_red + @string/preference_zebra_stripes_color_orange + + + #ff000000 + #fff44336 + #ffff9800 + + + @string/preference_zebra_stripes_color_white + @string/preference_zebra_stripes_color_transparent + + + #ffffffff + #00000000 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 792d006a0..4b1c13fb6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -945,6 +945,17 @@ Ghost image opacity Alpha value to use for ghost images. A lower value means more transparent, 100%% means opaque.\n%s + Zebra stripes foreground color + Color to use for the foreground stripe when showing zebra stripes.\n%s + Zebra stripes background color + Color to use for the background stripe when showing zebra stripes.\n%s + + Black + Red + Orange + Transparent + White + Privacy policy diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 792b2abf8..a3d034714 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -446,6 +446,26 @@ android:defaultValue="0" /> + + + + + + Date: Sat, 18 Jan 2020 18:41:19 +0000 Subject: [PATCH 075/243] Shouldn't display new gamma video preference if not supported. --- .../java/net/sourceforge/opencamera/MyPreferenceFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 8ce988c40..014c108f9 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -704,6 +704,10 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared Preference pref = findPreference("preference_video_log"); PreferenceGroup pg = (PreferenceGroup)this.findPreference("preference_screen_video_settings"); pg.removePreference(pref); + + pref = findPreference("preference_video_profile_gamma"); + pg = (PreferenceGroup)this.findPreference("preference_screen_video_settings"); + pg.removePreference(pref); } final float camera_view_angle_x = bundle.getFloat("camera_view_angle_x"); -- GitLab From 02213c3d6e4a2ed5fc95a36bc5a6685cb0a6fc71 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 18 Jan 2020 22:06:01 +0000 Subject: [PATCH 076/243] Fix for devices without on-screen navigation buttons. --- .../opencamera/test/MainActivityTest.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 5600cfb07..20ae16b60 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -4548,7 +4548,10 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Sat, 18 Jan 2020 22:06:14 +0000 Subject: [PATCH 077/243] JPEG quality ignored on S10e. --- _docs/devices.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/_docs/devices.html b/_docs/devices.html index c82ca7e15..7808d5e6f 100644 --- a/_docs/devices.html +++ b/_docs/devices.html @@ -170,6 +170,11 @@ manual controls, RAW and 120fps video.

    • Slow motion and high speed frame rate video doesn't work (see below for more details).
    • The maximum manual shutter speed allowed for third party camera applications is 0.1s (most devices seem to allow at least 0.5s).
    • +
    • The "Image quality" setting has no effect for JPEGs (unless post-processing options such as auto-level or + photo stamp are applied). This has also been reported for other Samsung devices; I also have the same + issue with other third party camera applications on my S10e. See + this thread + for details.

    Both rear physical cameras are available to Open Camera; also the two modes for the front camera ("cropped" and "wide") are available to Open Camera.

    -- GitLab From 3f6f7acfa86b4d42a250dcdf57d2f68a27c34417 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 19 Jan 2020 01:19:18 +0000 Subject: [PATCH 078/243] New JTLNP1 video profile; also enforce a minimum of 64 points to improve behaviour on devices. --- .../sourceforge/opencamera/MainActivity.java | 3 + .../opencamera/MyApplicationInterface.java | 3 + .../cameracontroller/CameraController.java | 3 +- .../cameracontroller/CameraController2.java | 79 ++++++++++++++++++- app/src/main/res/values/arrays.xml | 2 + app/src/main/res/values/strings.xml | 1 + 6 files changed, 87 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 6de267d5f..552759415 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4155,6 +4155,9 @@ public class MainActivity extends Activity { case TONEMAPPROFILE_JTLOG: string_id = R.string.preference_video_jtlog; break; + case TONEMAPPROFILE_JTLNP1: + string_id = R.string.preference_video_jtlnp1; + break; } if( string_id != 0 ) { simple = false; diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 32d4951a6..063e5112b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -737,6 +737,8 @@ public class MyApplicationInterface extends BasicApplicationInterface { return CameraController.TonemapProfile.TONEMAPPROFILE_GAMMA; case "jtlog": return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOG; + case "jtlnp1": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLNP1; } return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; } @@ -760,6 +762,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { return 500.0f; case "gamma": case "jtlog": + case "jtlnp1": return 0.0f; } return 0.0f; diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 4a08ae593..74a1c644c 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -452,7 +452,8 @@ public abstract class CameraController { TONEMAPPROFILE_OFF, TONEMAPPROFILE_LOG, TONEMAPPROFILE_GAMMA, - TONEMAPPROFILE_JTLOG + TONEMAPPROFILE_JTLOG, + TONEMAPPROFILE_JTLNP1 } /** Sets a tonemap profile. diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 680ac4f41..d8be86e64 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -46,6 +46,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.support.annotation.NonNull; import android.util.Log; +import android.util.Pair; import android.util.Range; import android.util.SizeF; import android.view.Display; @@ -79,7 +80,7 @@ public class CameraController2 extends CameraController { private boolean supports_photo_video_recording; private final static int tonemap_log_max_curve_points_c = 64; - private final static float [] jtlog_values = new float[] { + private final static float [] jtlog_values_base = new float[] { 0.0000f, 0.0000f, 0.0230f, 0.2295f, 0.0280f, 0.2783f, 0.0319f, 0.3049f, 0.0369f, 0.3321f, 0.0430f, 0.3589f, 0.0500f, 0.3844f, 0.0583f, 0.4098f, 0.0680f, 0.4351f, 0.0800f, 0.4619f, 0.0930f, 0.4870f, 0.1051f, 0.5076f, 0.1180f, 0.5275f, 0.1430f, 0.5612f, 0.1680f, 0.5904f, 0.1930f, 0.6162f, 0.2180f, 0.6395f, 0.2430f, 0.6608f, @@ -88,6 +89,12 @@ public class CameraController2 extends CameraController { 0.5680f, 0.8470f, 0.5930f, 0.8575f, 0.6180f, 0.8677f, 0.6430f, 0.8776f, 0.6680f, 0.8872f, 0.6930f, 0.8966f, 0.7180f, 0.9057f, 0.7430f, 0.9145f, 1.0000f, 1.0000f }; + private final float [] jtlog_values; + private final static float [] jtlnp1_values_base = new float[] { + 0.0f, 0.0f, 0.01f, 0.06f, 0.02f, 0.1f, 0.03f, 0.13f, 0.1f, 0.27f, 0.73f, 0.9f, 0.79f, 0.93f, + 0.84f, 0.95f, 1.0f, 1.0f + }; + private final float [] jtlnp1_values; private final ErrorCallback preview_error_cb; private final ErrorCallback camera_error_cb; @@ -870,6 +877,11 @@ public class CameraController2 extends CameraController { if( MyDebug.LOG ) Log.d(TAG, "setting JTLog profile"); break; + case TONEMAPPROFILE_JTLNP1: + values = jtlnp1_values; + if( MyDebug.LOG ) + Log.d(TAG, "setting JTLNP1 profile"); + break; } // sRGB: @@ -1783,6 +1795,10 @@ public class CameraController2 extends CameraController { media_action_sound.load(MediaActionSound.START_VIDEO_RECORDING); media_action_sound.load(MediaActionSound.STOP_VIDEO_RECORDING); media_action_sound.load(MediaActionSound.SHUTTER_CLICK); + + // expand tonemap curves + jtlog_values = enforceMinTonemapCurvePoints(jtlog_values_base); + jtlnp1_values = enforceMinTonemapCurvePoints(jtlnp1_values_base); } @Override @@ -1821,7 +1837,63 @@ public class CameraController2 extends CameraController { } } } - + + /** Enforce a minimum number of points in tonemap curves - needed due to Galaxy S10e having wrong behaviour if fewer + * than 16 points?! OnePlus 3T meanwhile has more gradual behaviour where it gets better at 64 points. + */ + private float [] enforceMinTonemapCurvePoints(float[] in_values) { + if( MyDebug.LOG ) { + Log.d(TAG, "enforceMinTonemapCurvePoints: " + Arrays.toString(in_values)); + Log.d(TAG, "length: " + in_values.length/2); + } + final int min_points_c = 64; + //final int min_points_c = 16; + if( in_values.length >= 2*min_points_c ) { + if( MyDebug.LOG ) + Log.d(TAG, "already enough points"); + return in_values; // fine + } + List> points = new ArrayList<>(); + for(int i=0;i point = new Pair<>(in_values[2*i], in_values[2*i+1]); + points.add(point); + } + + while( points.size() < min_points_c ) { + // find largest interval, and subdivide + int largest_indx = 0; + float largest_dist = 0.0f; + for(int i=0;i p0 = points.get(i); + Pair p1 = points.get(i+1); + float dist = p1.first - p0.first; + if( dist > largest_dist ) { + largest_indx = i; + largest_dist = dist; + } + } + if( MyDebug.LOG ) + Log.d(TAG, "largest indx " + largest_indx + " dist: " + largest_dist); + Pair p0 = points.get(largest_indx); + Pair p1 = points.get(largest_indx+1); + float mid_x = 0.5f*(p0.first + p1.first); + float mid_y = 0.5f*(p0.second + p1.second); + if( MyDebug.LOG ) + Log.d(TAG, " insert: " + mid_x + " , " + mid_y); + points.add(largest_indx+1, new Pair<>(mid_x, mid_y)); + } + + float [] out_values = new float[2*points.size()]; + for(int i=0;i point = points.get(i); + out_values[2*i] = point.first; + out_values[2*i+1] = point.second; + if( MyDebug.LOG ) + Log.d(TAG, "out point[" + i + "]: " + point.first + " , " + point.second); + } + return out_values; + } + private void closePictureImageReader() { if( MyDebug.LOG ) Log.d(TAG, "closePictureImageReader()"); @@ -2357,7 +2429,8 @@ public class CameraController2 extends CameraController { // profiles we support camera_features.supports_tonemap_curve = tonemap_max_curve_points >= tonemap_log_max_curve_points_c && - tonemap_max_curve_points >= jtlog_values.length; + tonemap_max_curve_points >= jtlog_values.length && + tonemap_max_curve_points >= jtlnp1_values.length; } else { if( MyDebug.LOG ) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index f1533190d..d52b8d3c5 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -554,6 +554,7 @@ @string/preference_video_log_extra_strong @string/preference_video_gamma @string/preference_video_jtlog + @string/preference_video_jtlnp1 off @@ -564,6 +565,7 @@ extra_strong gamma jtlog + jtlnp1 @string/preference_video_profile_gamma_1.0 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4b1c13fb6..493ee41c7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -917,6 +917,7 @@ Gamma JTLog + JTLNP1 Video gamma value Gamma value to use for video if video picture profile is set to Gamma\n%s 1.0 -- GitLab From 50f370f050bffb8497d1cebee1f5cd9e20465786 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 19 Jan 2020 17:33:49 +0000 Subject: [PATCH 079/243] Improve behaviour for log and gamma profile. --- _docs/history.html | 2 + .../opencamera/MyApplicationInterface.java | 15 +- .../cameracontroller/CameraController2.java | 145 ++++++++++++++---- 3 files changed, 132 insertions(+), 30 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 6913d389b..91865c16a 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -65,6 +65,8 @@ ADDED New custom gamma option for video recording. ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. ADDED Options to control zebra stripe colours. +UPDATED Improvements for log profiles for video recording. Please note that this means the behaviour + of these profiles has changed! UPDATED On devices with on-screen navigation buttons, camera preview can now display under these buttons if required for wide aspect ratio (requires Android 5+). UPDATED New immersive mode option to hide navigation buttons only when in immersive mode; existing diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 063e5112b..2be39559c 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -750,7 +750,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { switch( video_log ) { case "off": return 0.0f; - case "fine": + /*case "fine": return 1.0f; case "low": return 5.0f; @@ -758,6 +758,19 @@ public class MyApplicationInterface extends BasicApplicationInterface { return 10.0f; case "strong": return 100.0f; + case "extra_strong": + return 500.0f;*/ + // need a range of values as behaviour can vary between devices - e.g., "fine" has more effect on Nexus 6 than + // other devices such as OnePlus 3T or Galaxy S10e + // recalibrated in v1.48 to correspond to improvements made in CameraController2 + case "fine": + return 10.0f; + case "low": + return 32.0f; + case "medium": + return 100.0f; + case "strong": + return 224.0f; case "extra_strong": return 500.0f; case "gamma": diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index d8be86e64..7ff9fa6e1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -781,7 +781,7 @@ public class CameraController2 extends CameraController { private float getLogProfile(float in) { //final float black_level = 4.0f/255.0f; - final float power = 1.0f/2.2f; + //final float power = 1.0f/2.2f; final float log_A = log_profile_strength; /*float out; if( in <= black_level ) { @@ -795,7 +795,8 @@ public class CameraController2 extends CameraController { float out = (float) (Math.log1p(log_A * in) / Math.log1p(log_A)); // apply gamma - out = (float)Math.pow(out, power); + // update: no longer need to do this with improvements made in 1.48 onwards + //out = (float)Math.pow(out, power); //out = Math.max(out, 0.5f); return out; @@ -819,6 +820,11 @@ public class CameraController2 extends CameraController { else if( tonemap_profile == TonemapProfile.TONEMAPPROFILE_GAMMA && gamma_profile == 0.0f ) have_tonemap_profile = false; + // to use test_new, also need to uncomment the test code in setFocusValue() to call setTonemapProfile() + /*boolean test_new = this.af_mode == CaptureRequest.CONTROL_AF_MODE_AUTO; // testing + if( test_new ) + have_tonemap_profile = false;*/ + if( have_tonemap_profile ) { if( default_tonemap_mode == null ) { // save the default tonemap_mode @@ -831,44 +837,104 @@ public class CameraController2 extends CameraController { switch( tonemap_profile ) { case TONEMAPPROFILE_LOG: case TONEMAPPROFILE_GAMMA: - // if changing this, make sure we don't exceed tonemap_log_max_curve_points_c - // we want: - // 0-15: step 1 (16 values) - // 16-47: step 2 (16 values) - // 48-111: step 4 (16 values) - // 112-231 : step 8 (15 values) - // 232-255: step 24 (1 value) - int step = 1, c = 0; - values = new float[2*tonemap_log_max_curve_points_c]; - for(int i=0;i<232;i+=step) { - float in = ((float)i) / 255.0f; - float out = (tonemap_profile==TonemapProfile.TONEMAPPROFILE_LOG) ? getLogProfile(in) : getGammaProfile(in); - values[c++] = in; - values[c++] = out; - if( (c/2) % 16 == 0 ) { - step *= 2; - } - } - values[c++] = 1.0f; - values[c++] = (tonemap_profile==TonemapProfile.TONEMAPPROFILE_LOG) ? getLogProfile(1.0f) : getGammaProfile(1.0f); - /*{ - int n_values = 257; - float [] values = new float [2*n_values]; + { + // better to use uniformly spaced values, otherwise we get a weird looking effect - this can be + // seen most prominently when using gamma 1.0f, which should look linear (and hence be independent + // of the x values we use) + // can be reproduced on at least OnePlus 3T and Galaxy S10e (although the exact behaviour of the + // poor results is different on those devices) + int n_values = tonemap_log_max_curve_points_c; + //int n_values = test_new ? 32 : 128; + values = new float [2*n_values]; + int c = 0; for(int i=0;i Date: Sun, 19 Jan 2020 17:40:05 +0000 Subject: [PATCH 080/243] Add gamma value on toast for gamma profile. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 552759415..d9ea0a6e6 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4162,6 +4162,9 @@ public class MainActivity extends Activity { if( string_id != 0 ) { simple = false; toast_string += "\n" + getResources().getString(string_id); + if( tonemap_profile == CameraController.TonemapProfile.TONEMAPPROFILE_GAMMA ) { + toast_string += " " + applicationInterface.getVideoProfileGamma(); + } } else { Log.e(TAG, "unknown tonemap_profile: " + tonemap_profile); -- GitLab From 7b9582bb47d88dbf7fa8490eb2cfca5d0bc2c4c4 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 19 Jan 2020 18:26:05 +0000 Subject: [PATCH 081/243] More disabling of preferences when not relevant. --- _docs/history.html | 2 + .../opencamera/MyPreferenceFragment.java | 55 +++++++++++++++++++ app/src/main/res/xml/preferences.xml | 7 ++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 91865c16a..ef66716c2 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -77,6 +77,8 @@ UPDATED Improved performance when displaying ghost image larger than device's re UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name like FullHD, VGA etc for video). UPDATED Don't set video digital stabilization when in photo mode. +UPDATED Disable some preferences if only relevant for another nearby option that isn't currently + enabled. UPDATED Moved video bitrate and frame rate options to debugging section. Version 1.47.3 (2019/10/20) diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 014c108f9..c34127200 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -1561,6 +1561,61 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared } }); } + + setupDependencies(); + } + + /** Programmatically set up dependencies for preference types (e.g., ListPreference) that don't + * support this in xml (such as SwitchPreference and CheckBoxPreference). + */ + private void setupDependencies() { + // set up dependency for preference_audio_noise_control_sensitivity on preference_audio_control + ListPreference pref = (ListPreference)findPreference("preference_audio_control"); + if( pref != null ) { // may be null if preference not supported + pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference arg0, Object newValue) { + String value = newValue.toString(); + setAudioNoiseControlSensitivityDependency(value); + return true; + } + }); + setAudioNoiseControlSensitivityDependency(pref.getValue()); // ensure dependency is enabled/disabled as required for initial value + } + + // set up dependency for preference_video_profile_gamma on preference_video_log + pref = (ListPreference)findPreference("preference_video_log"); + if( pref != null ) { // may be null if preference not supported + pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference arg0, Object newValue) { + String value = newValue.toString(); + setVideoProfileGammaDependency(value); + return true; + } + }); + setVideoProfileGammaDependency(pref.getValue()); // ensure dependency is enabled/disabled as required for initial value + } + } + + private void setAudioNoiseControlSensitivityDependency(String newValue) { + Preference dependent = findPreference("preference_audio_noise_control_sensitivity"); + if( dependent != null ) { // just in case + boolean enable_dependent = "noise".equals(newValue); + if( MyDebug.LOG ) + Log.d(TAG, "clicked audio control: " + newValue + " enable_dependent: " + enable_dependent); + dependent.setEnabled(enable_dependent); + } + } + + private void setVideoProfileGammaDependency(String newValue) { + Preference dependent = findPreference("preference_video_profile_gamma"); + if( dependent != null ) { // just in case + boolean enable_dependent = "gamma".equals(newValue); + if( MyDebug.LOG ) + Log.d(TAG, "clicked video log: " + newValue + " enable_dependent: " + enable_dependent); + dependent.setEnabled(enable_dependent); + } } /* The user clicked the privacy policy preference. diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index a3d034714..4c5bf4f2f 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -198,11 +198,14 @@ android:entries="@array/preference_remote_type_entries" android:entryValues="@array/preference_remote_type_values" android:defaultValue="preference_remote_type_kraken" + android:dependency="preference_enable_remote" /> + android:title="@string/preference_select_remote" + android:dependency="preference_enable_remote" + > @@ -213,6 +216,7 @@ android:title="@string/preference_remote_disconnect_screen_dim" android:summary="@string/preference_remote_disconnect_screen_dim_summary" android:defaultValue="false" + android:dependency="preference_enable_remote" /> -- GitLab From b8154f8acdd086d9c19a4860dd354847008d3537 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 19 Jan 2020 19:51:18 +0000 Subject: [PATCH 082/243] Update comments. --- .../opencamera/cameracontroller/CameraController2.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 7ff9fa6e1..d1ccab307 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -821,9 +821,9 @@ public class CameraController2 extends CameraController { have_tonemap_profile = false; // to use test_new, also need to uncomment the test code in setFocusValue() to call setTonemapProfile() - /*boolean test_new = this.af_mode == CaptureRequest.CONTROL_AF_MODE_AUTO; // testing - if( test_new ) - have_tonemap_profile = false;*/ + //boolean test_new = this.af_mode == CaptureRequest.CONTROL_AF_MODE_AUTO; // testing + //if( test_new ) + // have_tonemap_profile = false; if( have_tonemap_profile ) { if( default_tonemap_mode == null ) { @@ -4152,7 +4152,7 @@ public class CameraController2 extends CameraController { camera_settings.af_mode = focus_mode; camera_settings.setFocusMode(previewBuilder); camera_settings.setFocusDistance(previewBuilder); // also need to set distance, in case changed between infinity, manual or other modes - //camera_settings.setTonemapProfile(previewBuilder); // testing - if using focus mode to test video profiles + //camera_settings.setTonemapProfile(previewBuilder); // testing - if using focus mode to test video profiles, see test_new flag try { setRepeatingRequest(); } -- GitLab From b0cac1e641f3ba4514517b8ffb5626faa13b7730 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 21 Jan 2020 22:52:40 +0000 Subject: [PATCH 083/243] Fix comment. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index d9ea0a6e6..8575be21c 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1620,7 +1620,7 @@ public class MainActivity extends Activity { class PreferencesListener implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "PreferencesListener"; - private boolean any_significant_change; // whether any changes that require updateForSettings have been made since startListening() + private boolean any_significant_change; // whether any changes have been made since startListening() private boolean any_change; // whether any changes that require updateForSettings have been made since startListening() void startListening() { -- GitLab From 2ae3ed511cbe07320b243116f6b7f4d0f70384fe Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 21 Jan 2020 23:35:10 +0000 Subject: [PATCH 084/243] Support for REC709 and sRGB video profiles. --- _docs/history.html | 3 +- .../sourceforge/opencamera/MainActivity.java | 20 ++ .../opencamera/MyApplicationInterface.java | 13 +- .../cameracontroller/CameraController.java | 4 +- .../cameracontroller/CameraController1.java | 8 +- .../cameracontroller/CameraController2.java | 173 +++++++++++------- app/src/main/res/values/arrays.xml | 4 + app/src/main/res/values/strings.xml | 2 + 8 files changed, 154 insertions(+), 73 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index ef66716c2..ff0cb4651 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -61,7 +61,8 @@ FIXED Recording video on Android 8+ could leave zero-size files if size approa filesize, but a restart did not occur. FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. -ADDED New custom gamma option for video recording. +ADDED Option to specify REC709 or sRGB profile for video recording. +ADDED New custom gamma profile option for video recording. ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. ADDED Options to control zebra stripe colours. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 8575be21c..456b3d678 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -2061,6 +2061,20 @@ public class MainActivity extends Activity { } } } + + if( !need_reopen ) { + CameraController.TonemapProfile old_tonemap_profile = preview.getCameraController().getTonemapProfile(); + if( old_tonemap_profile != CameraController.TonemapProfile.TONEMAPPROFILE_OFF ) { + CameraController.TonemapProfile new_tonemap_profile = applicationInterface.getVideoTonemapProfile(); + if( new_tonemap_profile != CameraController.TonemapProfile.TONEMAPPROFILE_OFF && new_tonemap_profile != old_tonemap_profile ) { + // needed for Galaxy S10e when changing from TONEMAP_MODE_CONTRAST_CURVE to TONEMAP_MODE_PRESET_CURVE, + // otherwise the contrast curve remains active! + if( MyDebug.LOG ) + Log.d(TAG, "switching between tonemap profiles"); + need_reopen = true; + } + } + } } if( MyDebug.LOG ) { Log.d(TAG, "updateForSettings: time after check need_reopen: " + (System.currentTimeMillis() - debug_time)); @@ -4146,6 +4160,12 @@ public class MainActivity extends Activity { if( applicationInterface.getVideoTonemapProfile() != CameraController.TonemapProfile.TONEMAPPROFILE_OFF && preview.supportsTonemapCurve() ) { int string_id = 0; switch( tonemap_profile ) { + case TONEMAPPROFILE_REC709: + string_id = R.string.preference_video_rec709; + break; + case TONEMAPPROFILE_SRGB: + string_id = R.string.preference_video_srgb; + break; case TONEMAPPROFILE_LOG: string_id = R.string.video_log; break; diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 2be39559c..17024d7e2 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -727,6 +727,10 @@ public class MyApplicationInterface extends BasicApplicationInterface { switch( video_log ) { case "off": return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; + case "rec709": + return CameraController.TonemapProfile.TONEMAPPROFILE_REC709; + case "srgb": + return CameraController.TonemapProfile.TONEMAPPROFILE_SRGB; case "fine": case "low": case "medium": @@ -749,6 +753,11 @@ public class MyApplicationInterface extends BasicApplicationInterface { // remember to update getVideoTonemapProfile() if adding/changing modes switch( video_log ) { case "off": + case "rec709": + case "srgb": + case "gamma": + case "jtlog": + case "jtlnp1": return 0.0f; /*case "fine": return 1.0f; @@ -773,10 +782,6 @@ public class MyApplicationInterface extends BasicApplicationInterface { return 224.0f; case "extra_strong": return 500.0f; - case "gamma": - case "jtlog": - case "jtlnp1": - return 0.0f; } return 0.0f; } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 74a1c644c..62b2fea1f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -450,6 +450,8 @@ public abstract class CameraController { public abstract boolean getVideoStabilization(); public enum TonemapProfile { TONEMAPPROFILE_OFF, + TONEMAPPROFILE_REC709, + TONEMAPPROFILE_SRGB, TONEMAPPROFILE_LOG, TONEMAPPROFILE_GAMMA, TONEMAPPROFILE_JTLOG, @@ -462,7 +464,7 @@ public abstract class CameraController { * @param gamma Only relevant if tonemap_profile set to TONEMAPPROFILE_GAMMA */ public abstract void setTonemapProfile(TonemapProfile tonemap_profile, float log_profile_strength, float gamma); - //public abstract boolean isLogProfile(); + public abstract TonemapProfile getTonemapProfile(); public abstract int getJpegQuality(); public abstract void setJpegQuality(int quality); public abstract int getZoom(); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 5f303f508..7f91a7e99 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -894,11 +894,11 @@ public class CameraController1 extends CameraController { // not supported for CameraController1! } - /*@Override - public boolean isLogProfile() { + @Override + public TonemapProfile getTonemapProfile() { // not supported for CameraController1! - return false; - }*/ + return TonemapProfile.TONEMAPPROFILE_OFF; + } public int getJpegQuality() { Camera.Parameters parameters = this.getParameters(); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index d1ccab307..135e4cdda 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -833,10 +833,58 @@ public class CameraController2 extends CameraController { Log.d(TAG, "default_tonemap_mode: " + default_tonemap_mode); } - float [] values = null; - switch( tonemap_profile ) { - case TONEMAPPROFILE_LOG: - case TONEMAPPROFILE_GAMMA: + final boolean use_preset_curve = true; + //final boolean use_preset_curve = false; // test + //final boolean use_preset_curve = test_new; // test + if( use_preset_curve && tonemap_profile == TonemapProfile.TONEMAPPROFILE_REC709 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) { + if( MyDebug.LOG ) + Log.d(TAG, "set TONEMAP_PRESET_CURVE_REC709"); + builder.set(CaptureRequest.TONEMAP_MODE, CaptureRequest.TONEMAP_MODE_PRESET_CURVE); + builder.set(CaptureRequest.TONEMAP_PRESET_CURVE, CaptureRequest.TONEMAP_PRESET_CURVE_REC709); + } + else if( use_preset_curve && tonemap_profile == TonemapProfile.TONEMAPPROFILE_SRGB && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) { + if( MyDebug.LOG ) + Log.d(TAG, "set TONEMAP_PRESET_CURVE_SRGB"); + builder.set(CaptureRequest.TONEMAP_MODE, CaptureRequest.TONEMAP_MODE_PRESET_CURVE); + builder.set(CaptureRequest.TONEMAP_PRESET_CURVE, CaptureRequest.TONEMAP_PRESET_CURVE_SRGB); + } + else { + if( MyDebug.LOG ) + Log.d(TAG, "handle via TONEMAP_MODE_CONTRAST_CURVE / TONEMAP_CURVE"); + float [] values = null; + switch( tonemap_profile ) { + case TONEMAPPROFILE_REC709: + // y = 4.5x if x < 0.018, else y = 1.099*x^0.45 - 0.099 + float [] x_values = new float[] { + 0.0000f, 0.0667f, 0.1333f, 0.2000f, + 0.2667f, 0.3333f, 0.4000f, 0.4667f, + 0.5333f, 0.6000f, 0.6667f, 0.7333f, + 0.8000f, 0.8667f, 0.9333f, 1.0000f + }; + values = new float[2*x_values.length]; + int c = 0; + for(float x_value : x_values) { + float out; + if( x_value < 0.018f ) { + out = 4.5f * x_value; + } + else { + out = (float)(1.099*Math.pow(x_value, 0.45) - 0.099); + } + values[c++] = x_value; + values[c++] = out; + } + break; + case TONEMAPPROFILE_SRGB: + values = new float [] { + 0.0000f, 0.0000f, 0.0667f, 0.2864f, 0.1333f, 0.4007f, 0.2000f, 0.4845f, + 0.2667f, 0.5532f, 0.3333f, 0.6125f, 0.4000f, 0.6652f, 0.4667f, 0.7130f, + 0.5333f, 0.7569f, 0.6000f, 0.7977f, 0.6667f, 0.8360f, 0.7333f, 0.8721f, + 0.8000f, 0.9063f, 0.8667f, 0.9389f, 0.9333f, 0.9701f, 1.0000f, 1.0000f + }; + break; + case TONEMAPPROFILE_LOG: + case TONEMAPPROFILE_GAMMA: { // better to use uniformly spaced values, otherwise we get a weird looking effect - this can be // seen most prominently when using gamma 1.0f, which should look linear (and hence be independent @@ -846,13 +894,11 @@ public class CameraController2 extends CameraController { int n_values = tonemap_log_max_curve_points_c; //int n_values = test_new ? 32 : 128; values = new float [2*n_values]; - int c = 0; for(int i=0;i @string/preference_video_log_off + @string/preference_video_rec709 + @string/preference_video_srgb @string/preference_video_log_fine @string/preference_video_log_low @string/preference_video_log_medium @@ -558,6 +560,8 @@ off + rec709 + srgb fine low medium diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 493ee41c7..4f706a24e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -915,6 +915,8 @@ Select remote device + REC709 + sRGB Gamma JTLog JTLNP1 -- GitLab From ba5de1de587f9a4a42b2da6f572d2bbbfaa9ac56 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 00:17:25 +0000 Subject: [PATCH 085/243] HDR and NR photo modes now limited to maximum resolution of 22 megapixels (to avoid risk of running out of memory on devices with large camera resolutions); new tests for max mp and burst behaviour. --- _docs/help.html | 19 +- _docs/history.html | 2 + .../opencamera/test/MainActivityTest.java | 208 ++++++++++++++++++ .../opencamera/test/MainTests.java | 2 + .../opencamera/MyApplicationInterface.java | 24 +- .../preview/ApplicationInterface.java | 43 +++- .../preview/BasicApplicationInterface.java | 2 +- .../opencamera/preview/Preview.java | 81 ++++++- 8 files changed, 364 insertions(+), 17 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 4759c2ed9..2e83d32bd 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -756,9 +756,22 @@ features and other options. You can disable this dialog from being displayed if

    Photo settings - Select to access the following controls:

    -

    Camera resolution - Select the resolution of photo images taken by the camera. Note that if -auto-level is enabled, images will in general come out as a slightly lower resolution -(due to the rotation and cropping that's required).

    +

    Camera resolution - Select the resolution of photo images taken by the camera.

    +
      +
    • If auto-level is enabled, images will in general come out as a + slightly lower resolution (due to the rotation and cropping that's required). +
    • +
    • Note that in some photo modes, the actual photo mode may be different to that selected here. + For example, advanced photo modes such as HDR, NR, Fast Burst, Expo Bracketing may have a + maximum supported resolution - if the resolution selected here is too high, the largest + allowed resolution will instead be used. To see the resolution currently used (or to change + it), see the "Camera resolution" setting on the popup menu. +
    • +
    • The resolution setting is ignored altogether in Panorama mode. +
    • +
    + +

    Image quality - The image quality of saved JPEG or WebP images. Higher means better quality, but the image files will take up more storage space. Note that 100% does not necessarily mean there is no lossy compression, rather that there is minimum diff --git a/_docs/history.html b/_docs/history.html index ff0cb4651..ef4978af0 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -74,6 +74,8 @@ UPDATED New immersive mode option to hide navigation buttons only when in immers option for hiding navigation buttons now renamed to say "dim". UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or back facing. +UPDATED HDR and NR photo modes now limited to maximum resolution of 22 megapixels (to avoid risk of + running out of memory on devices with large camera resolutions). UPDATED Improved performance when displaying ghost image larger than device's resolution. UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name like FullHD, VGA etc for video). diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 20ae16b60..c3d9f7661 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -1026,6 +1026,214 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 all_picture_sizes = new ArrayList<>(mPreview.getSupportedPictureSizes(false)); + final List std_picture_sizes = new ArrayList<>(mPreview.getSupportedPictureSizes(true)); + assertEquals(all_picture_sizes, std_picture_sizes); + assertTrue(all_picture_sizes.contains(std_size)); + + // switch to the photo mode and check we reduce the resolution + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mActivity); + SharedPreferences.Editor editor = settings.edit(); + editor.putString(PreferenceKeys.PhotoModePreferenceKey, photo_mode_preference); + editor.apply(); + updateForSettings(); + assertSame(mActivity.getApplicationInterface().getPhotoMode(), photo_mode); + + CameraController.Size new_size = mPreview.getCurrentPictureSize(); + Log.d(TAG, "new_size: " + new_size.width + " x " + new_size.height); + if( expect_reduce_resolution ) { + assertFalse(new_size.equals(std_size)); + assertTrue(new_size.width*new_size.height <= max_mp); + } + else { + assertEquals(new_size, std_size); + } + if( expect_supports_burst ) { + assertTrue(new_size.supports_burst); + } + final List all_picture_sizes_new = new ArrayList<>(mPreview.getSupportedPictureSizes(false)); + final List picture_sizes_new = new ArrayList<>(mPreview.getSupportedPictureSizes(true)); + assertEquals(all_picture_sizes, all_picture_sizes_new); + if( expect_reduce_resolution ) { + assertTrue(picture_sizes_new.size() < all_picture_sizes.size()); + // check the filtered modes are a subset of all of them + assertTrue(all_picture_sizes.containsAll(picture_sizes_new)); + // check all of the filtered modes satisfy the max_mp + for(CameraController.Size size : picture_sizes_new) { + assertTrue(size.width*size.height <= max_mp); + } + } + else { + assertEquals(all_picture_sizes, picture_sizes_new); + } + if( expect_supports_burst ) { + // check all of the filtered modes support burst + for(CameraController.Size size : picture_sizes_new) { + assertTrue(size.supports_burst); + } + } + // check the filtered modes include the chosen mode + assertTrue(picture_sizes_new.contains(new_size)); + + // pause and resume, check resolutions unchanged + pauseAndResume(); + assertSame(mActivity.getApplicationInterface().getPhotoMode(), photo_mode); + CameraController.Size new_size2 = mPreview.getCurrentPictureSize(); + assertEquals(new_size, new_size2); + final List all_picture_sizes_new2 = new ArrayList<>(mPreview.getSupportedPictureSizes(false)); + final List picture_sizes_new2 = new ArrayList<>(mPreview.getSupportedPictureSizes(true)); + assertEquals(all_picture_sizes_new, all_picture_sizes_new2); + assertEquals(picture_sizes_new, picture_sizes_new2); + + CameraController.Size change_to_size = null; + String settings_size = ""; + if( test_change_resolution ) { + // test changing the resolution in the new mode + + // save old resolution + settings_size = settings.getString(PreferenceKeys.getResolutionPreferenceKey(mPreview.getCameraId()), ""); + + // find a different resolution + for(CameraController.Size size : picture_sizes_new) { + if( !size.equals(new_size) ) { + change_to_size = size; + break; + } + } + assertNotNull(change_to_size); + Log.d(TAG, "set size to " + change_to_size.width + " x " + change_to_size.height); + settings = PreferenceManager.getDefaultSharedPreferences(mActivity); + editor = settings.edit(); + editor.putString(PreferenceKeys.getResolutionPreferenceKey(mPreview.getCameraId()), change_to_size.width + " " + change_to_size.height); + editor.apply(); + updateForSettings(); + + CameraController.Size new_size3 = mPreview.getCurrentPictureSize(); + assertEquals(change_to_size, new_size3); + assertFalse(new_size.equals(new_size3)); + } + + // switch back to STD, and check we return to the original resolution (or not, if test_change_resolution==true) + settings = PreferenceManager.getDefaultSharedPreferences(mActivity); + editor = settings.edit(); + editor.putString(PreferenceKeys.PhotoModePreferenceKey, "preference_photo_mode_std"); + editor.apply(); + updateForSettings(); + assertSame(mActivity.getApplicationInterface().getPhotoMode(), MyApplicationInterface.PhotoMode.Standard); + + new_size = mPreview.getCurrentPictureSize(); + if( test_change_resolution ) { + assertEquals(change_to_size, new_size); + } + else { + assertEquals(std_size, new_size); + } + final List all_picture_sizes2 = new ArrayList<>(mPreview.getSupportedPictureSizes(false)); + final List std_picture_sizes2 = new ArrayList<>(mPreview.getSupportedPictureSizes(true)); + assertEquals(all_picture_sizes, all_picture_sizes2); + assertEquals(all_picture_sizes, std_picture_sizes2); + assertTrue(std_picture_sizes2.contains(new_size)); + + if( test_change_resolution ) { + // set back, so we don't confuse later parts of the test + settings = PreferenceManager.getDefaultSharedPreferences(mActivity); + editor = settings.edit(); + editor.putString(PreferenceKeys.getResolutionPreferenceKey(mPreview.getCameraId()), settings_size); + editor.apply(); + updateForSettings(); + } + } + + /* Ensures that we enforce a maximum resolution correctly in some photo modes. + */ + public void testResolutionMaxMP() { + Log.d(TAG, "testResolutionMaxMP"); + + setToDefault(); + + CameraController.Size std_size = mPreview.getCurrentPictureSize(); + assertNotNull(std_size); + Log.d(TAG, "std_size: " + std_size.width + " x " + std_size.height); + + int max_mp = (std_size.width*std_size.height-100); + mActivity.getApplicationInterface().test_max_mp = max_mp; + Log.d(TAG, "test_max_mp: " + mActivity.getApplicationInterface().test_max_mp); + + if( mActivity.supportsHDR() ) { + subTestResolutionMaxMP("preference_photo_mode_hdr", MyApplicationInterface.PhotoMode.HDR, max_mp, false, true, true); + subTestResolutionMaxMP("preference_photo_mode_hdr", MyApplicationInterface.PhotoMode.HDR, max_mp, true, true, true); + } + if( mActivity.supportsNoiseReduction() ) { + subTestResolutionMaxMP("preference_photo_mode_noise_reduction", MyApplicationInterface.PhotoMode.NoiseReduction, max_mp, false, true, true); + subTestResolutionMaxMP("preference_photo_mode_noise_reduction", MyApplicationInterface.PhotoMode.NoiseReduction, max_mp, true, true, true); + } + if( mActivity.supportsDRO() ) { + subTestResolutionMaxMP("preference_photo_mode_dro", MyApplicationInterface.PhotoMode.DRO, max_mp, false, false, false); + subTestResolutionMaxMP("preference_photo_mode_dro", MyApplicationInterface.PhotoMode.DRO, max_mp, true, false, false); + } + } + + /* Ensures that we handle correctly when the largest resolution doesn't support burst. + */ + public void testResolutionBurst() { + Log.d(TAG, "testResolutionBurst"); + + if( !mPreview.usingCamera2API() ) { + Log.d(TAG, "test requires camera2 api"); + return; + } + + setToDefault(); + + mPreview.test_burst_resolution = true; + pauseAndResume(); // needed for test_burst_resolution to take effect + + CameraController.Size std_size = mPreview.getCurrentPictureSize(); + // check the test_burst_resolution flag took effect: + assertFalse(std_size.supports_burst); + + // now find the maximum mp that supports burst + final List all_picture_sizes = new ArrayList<>(mPreview.getSupportedPictureSizes(false)); + int max_mp = 0; + for(CameraController.Size size : all_picture_sizes) { + if( size.supports_burst ) { + int mp = size.width*size.height; + max_mp = Math.max(max_mp, mp); + } + } + Log.d(TAG, "max_mp: " + max_mp); + assertTrue(max_mp < std_size.width*std_size.height); + + if( mActivity.supportsHDR() ) { + subTestResolutionMaxMP("preference_photo_mode_hdr", MyApplicationInterface.PhotoMode.HDR, max_mp, false, true, true); + subTestResolutionMaxMP("preference_photo_mode_hdr", MyApplicationInterface.PhotoMode.HDR, max_mp, true, true, true); + } + if( mActivity.supportsNoiseReduction() ) { + subTestResolutionMaxMP("preference_photo_mode_noise_reduction", MyApplicationInterface.PhotoMode.NoiseReduction, max_mp, false, true, true); + subTestResolutionMaxMP("preference_photo_mode_noise_reduction", MyApplicationInterface.PhotoMode.NoiseReduction, max_mp, true, true, true); + } + if( mActivity.supportsDRO() ) { + subTestResolutionMaxMP("preference_photo_mode_dro", MyApplicationInterface.PhotoMode.DRO, max_mp, false, false, false); + subTestResolutionMaxMP("preference_photo_mode_dro", MyApplicationInterface.PhotoMode.DRO, max_mp, true, false, false); + } + if( mActivity.supportsFastBurst() ) { + subTestResolutionMaxMP("preference_photo_mode_fast_burst", MyApplicationInterface.PhotoMode.FastBurst, max_mp, false, true, true); + subTestResolutionMaxMP("preference_photo_mode_fast_burst", MyApplicationInterface.PhotoMode.FastBurst, max_mp, true, true, true); + } + } + /* Tests camera error handling. */ public void testOnError() { diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java index 3d33af3c4..06468d86c 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java @@ -29,6 +29,8 @@ public class MainTests { suite.addTest(TestSuite.createTest(MainActivityTest.class, "testHDRRestart")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testPreviewSize")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testPreviewSizeWYSIWYG")); + suite.addTest(TestSuite.createTest(MainActivityTest.class, "testResolutionMaxMP")); + suite.addTest(TestSuite.createTest(MainActivityTest.class, "testResolutionBurst")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testAutoFocus")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testAutoFocusCorners")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testPopup")); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 17024d7e2..82aa1c1ac 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -142,6 +142,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { // for testing: public volatile int test_n_videos_scanned; + public volatile int test_max_mp; MyApplicationInterface(MainActivity main_activity, Bundle savedInstanceState) { long debug_time = 0; @@ -449,14 +450,17 @@ public class MyApplicationInterface extends BasicApplicationInterface { } @Override - public Pair getCameraResolutionPref() { - if( getPhotoMode() == PhotoMode.Panorama ) { + public Pair getCameraResolutionPref(CameraResolutionConstraints constraints) { + PhotoMode photo_mode = getPhotoMode(); + if( photo_mode == PhotoMode.Panorama ) { CameraController.Size best_size = choosePanoramaResolution(main_activity.getPreview().getSupportedPictureSizes(false)); return new Pair<>(best_size.width, best_size.height); } + String resolution_value = sharedPreferences.getString(PreferenceKeys.getResolutionPreferenceKey(cameraId), ""); if( MyDebug.LOG ) Log.d(TAG, "resolution_value: " + resolution_value); + Pair result = null; if( resolution_value.length() > 0 ) { // parse the saved size, and make sure it is still valid int index = resolution_value.indexOf(' '); @@ -478,7 +482,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { int resolution_h = Integer.parseInt(resolution_h_s); if( MyDebug.LOG ) Log.d(TAG, "resolution_h: " + resolution_h); - return new Pair<>(resolution_w, resolution_h); + result = new Pair<>(resolution_w, resolution_h); } catch(NumberFormatException exception) { if( MyDebug.LOG ) @@ -486,7 +490,19 @@ public class MyApplicationInterface extends BasicApplicationInterface { } } } - return null; + + if( photo_mode == PhotoMode.NoiseReduction || photo_mode == PhotoMode.HDR ) { + // set a maximum resolution for modes that require decompressing multiple images for processing, + // due to risk of running out of memory! + constraints.has_max_mp = true; + constraints.max_mp = 22000000; // max of 22MP + //constraints.max_mp = 7800000; // test! + if( main_activity.is_test && test_max_mp != 0 ) { + constraints.max_mp = test_max_mp; + } + } + + return result; } /** getImageQualityPref() returns the image quality used for the Camera Controller for taking a diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java index 5df807e3f..611da7b3e 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java @@ -9,9 +9,11 @@ import android.content.Context; import android.graphics.Canvas; import android.location.Location; import android.net.Uri; +import android.util.Log; import android.util.Pair; import android.view.MotionEvent; +import net.sourceforge.opencamera.MyDebug; import net.sourceforge.opencamera.cameracontroller.CameraController; import net.sourceforge.opencamera.cameracontroller.RawImage; @@ -57,7 +59,46 @@ public interface ApplicationInterface { String getCameraNoiseReductionModePref(); // CameraController.NOISE_REDUCTION_MODE_DEFAULT for device default, or "off", "minimal", "fast", "high_quality" String getISOPref(); // "auto" for auto-ISO, otherwise a numerical value; see documentation for Preview.supportsISORange(). int getExposureCompensationPref(); // 0 for default - Pair getCameraResolutionPref(); // return null to let Preview choose size + + class CameraResolutionConstraints { + private static final String TAG = "CameraResConstraints"; + + public boolean has_max_mp; + public int max_mp; + + boolean hasConstraints() { + return has_max_mp; + } + + boolean satisfies(CameraController.Size size) { + if( this.has_max_mp && size.width * size.height > this.max_mp ) { + if( MyDebug.LOG ) + Log.d(TAG, "size index larger than max_mp: " + this.max_mp); + return false; + } + return true; + } + } + /** The resolution to use for photo mode. + * If the returned resolution is not supported by the device, or this method returns null, then + * the preview will choose a size, and then call setCameraResolutionPref() with the chosen + * size. + * If the returned resolution is supported by the device, setCameraResolutionPref() will be + * called with the returned resolution. + * Note that even if the device supports the resolution in general, the Preview may choose a + * different resolution in some circumstances: + * * A burst mode as been requested, but the resolution does not support burst. + * * A constraint has been set via constraints. + * In such cases, the resolution actually in use should be found by calling + * Preview.getCurrentPictureSize() rather than relying on the setCameraResolutionPref(). (The + * logic behind this is that if a resolution is not supported by the device at all, it's good + * practice to correct the preference stored in user settings; but this shouldn't be done if + * the resolution is changed for something more temporary such as enabling burst mode.) + * @param constraints Optional constraints that may be set. If the returned resolution does not + * satisfy these constraints, then the preview will choose the closest + * resolution that does. + */ + Pair getCameraResolutionPref(CameraResolutionConstraints constraints); // return null to let Preview choose size int getImageQualityPref(); // jpeg quality for taking photos; "90" is a recommended default boolean getFaceDetectionPref(); // whether to use face detection mode String getVideoQualityPref(); // should be one of Preview.getSupportedVideoQuality() (use Preview.getCamcorderProfile() or Preview.getCamcorderProfileDescription() for details); or return "" to let Preview choose quality diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java index f887f2ebc..9b214f384 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java @@ -91,7 +91,7 @@ public abstract class BasicApplicationInterface implements ApplicationInterface } @Override - public Pair getCameraResolutionPref() { + public Pair getCameraResolutionPref(CameraResolutionConstraints constraints) { return null; } diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 9252e8cfb..6c67afa32 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -287,6 +287,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private List supported_preview_sizes; private List photo_sizes; + private ApplicationInterface.CameraResolutionConstraints photo_size_constraints; private int current_size_index = -1; // this is an index into the sizes array, or -1 if sizes not yet set private boolean supports_video; @@ -376,6 +377,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu public volatile boolean test_ticker_called; // set from MySurfaceView or CanvasView public volatile boolean test_called_next_output_file; public volatile boolean test_runtime_on_video_stop; // force throwing a RuntimeException when stopping video (this usually happens naturally when stopping video too soon) + public volatile boolean test_burst_resolution; public Preview(ApplicationInterface applicationInterface, ViewGroup parent) { if( MyDebug.LOG ) { @@ -1361,6 +1363,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu view_angle_y = 43.0f; // set a sensible default photo_sizes = null; current_size_index = -1; + photo_size_constraints = null; has_capture_rate_factor = false; capture_rate_factor = 1.0f; video_high_speed = false; @@ -1821,8 +1824,12 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu setupBurstMode(); if( camera_controller.isBurstOrExpo() ) { - // check photo resolution supports burst + if( MyDebug.LOG ) + Log.d(TAG, "check photo resolution supports burst"); CameraController.Size current_size = getCurrentPictureSize(); + if( MyDebug.LOG && current_size != null ) { + Log.d(TAG, "current_size: " + current_size.width + " x " + current_size.height + " supports_burst? " + current_size.supports_burst); + } if( current_size != null && !current_size.supports_burst ) { if( MyDebug.LOG ) Log.d(TAG, "burst mode: current picture size doesn't support burst"); @@ -2019,6 +2026,18 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu this.minimum_focus_distance = camera_features.minimum_focus_distance; this.supports_face_detection = camera_features.supports_face_detection; this.photo_sizes = camera_features.picture_sizes; + if( test_burst_resolution ) { + // this flag means we pretend the largest resolution doesn't support burst + CameraController.Size current_size = null; + for(int i=0;i current_size.width*current_size.height ) { + current_size = size; + } + } + if( current_size != null ) + current_size.supports_burst = false; + } supported_flash_values = camera_features.supported_flash_values; supported_focus_values = camera_features.supported_focus_values; this.max_num_focus_areas = camera_features.max_num_focus_areas; @@ -2507,7 +2526,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } } current_size_index = -1; - Pair resolution = applicationInterface.getCameraResolutionPref(); + photo_size_constraints = new ApplicationInterface.CameraResolutionConstraints(); + Pair resolution = applicationInterface.getCameraResolutionPref(photo_size_constraints); if( resolution != null ) { int resolution_w = resolution.first; int resolution_h = resolution.second; @@ -2545,8 +2565,43 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu // now save, so it's available for PreferenceActivity applicationInterface.setCameraResolutionPref(current_size.width, current_size.height); + + // check against constraints + // we intentionally do this after calling applicationInterface.setCameraResolutionPref() (as the constraints are + // used to just temporarily change resolution, e.g., if a maximum resolution has been enforced for HDR or NR photo + // mode, but we don't want to update the saved resolution preference in such cases + if( !photo_size_constraints.satisfies(current_size) ) { + if( MyDebug.LOG ) + Log.d(TAG, "current size index fail to satisfy constraints"); + CameraController.Size new_size = null; + // find the largest size that satisfies the constraint + for(int i=0;i new_size.width*new_size.height ) { + current_size_index = i; + new_size = size; + } + } + } + if( new_size == null ) { + Log.e(TAG, "can't find picture size that satisfies the constraints!"); + // so just choose the smallest + for(int i=0;i getSupportedPictureSizes(boolean check_burst) { + public List getSupportedPictureSizes(boolean check_supported) { if( MyDebug.LOG ) Log.d(TAG, "getSupportedPictureSizes"); - if( check_burst && camera_controller != null && camera_controller.isBurstOrExpo() ) { + boolean is_burst = ( camera_controller != null && camera_controller.isBurstOrExpo() ); + boolean has_constraints = photo_size_constraints != null && photo_size_constraints.hasConstraints(); + if( check_supported && ( is_burst || has_constraints ) ) { if( MyDebug.LOG ) - Log.d(TAG, "need to filter picture sizes for a burst mode"); + Log.d(TAG, "need to filter picture sizes for burst mode and/or constraints"); List filtered_sizes = new ArrayList<>(); for(CameraController.Size size : photo_sizes) { - if( size.supports_burst ) { + if( is_burst && !size.supports_burst ) { + // burst mode not supported + } + else if( !photo_size_constraints.satisfies(size) ) { + // doesn't satisfy imposed constraints + } + else { filtered_sizes.add(size); } } -- GitLab From 5312485f949c235eb6a46e38f045704e3e8bacfa Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 00:17:36 +0000 Subject: [PATCH 086/243] Fix typo. --- _docs/help.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/help.html b/_docs/help.html index 2e83d32bd..e8b9ccc6e 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -162,7 +162,7 @@ a panel with various controls:

    To get rid of this panel, either click the Exposure button again, or click elsewhere on the screen.

    -

    Popup iconPopop menu - Opens the popup menu for quick access to changing +

    Popup iconPopup menu - Opens the popup menu for quick access to changing various options:

    • Flash - Typical options are off, auto, on and torch mode. For front cameras without a real flash, flash and torch options will be available which instead work by making the screen light up (note, front screen flash "auto" is only available with Camera2 API).
    • -- GitLab From 7546deb31b1ff3f65453d3f230585a7771411a7d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 00:28:11 +0000 Subject: [PATCH 087/243] Display current photo mode in settings/about. --- .../sourceforge/opencamera/MainActivity.java | 70 +++++++++++-------- .../opencamera/MyPreferenceFragment.java | 4 ++ 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 456b3d678..75b8600c5 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1751,6 +1751,7 @@ public class MainActivity extends Activity { bundle.putInt("nCameras", preview.getCameraControllerManager().getNumberOfCameras()); bundle.putString("camera_api", this.preview.getCameraAPI()); bundle.putBoolean("using_android_l", this.preview.usingCamera2API()); + bundle.putString("photo_mode_string", getPhotoModeString(applicationInterface.getPhotoMode(), true)); bundle.putBoolean("supports_auto_stabilise", this.supports_auto_stabilise); bundle.putBoolean("supports_flash", this.preview.supportsFlash()); bundle.putBoolean("supports_force_video_4k", this.supports_force_video_4k); @@ -4096,6 +4097,44 @@ public class MainActivity extends Activity { return changed_auto_stabilise_toast; } + private String getPhotoModeString(MyApplicationInterface.PhotoMode photo_mode, boolean string_for_std) { + String photo_mode_string = null; + switch( photo_mode ) { + case Standard: + if( string_for_std ) + photo_mode_string = getResources().getString(R.string.photo_mode_standard_full); + break; + case DRO: + photo_mode_string = getResources().getString(R.string.photo_mode_dro); + break; + case HDR: + photo_mode_string = getResources().getString(R.string.photo_mode_hdr); + break; + case ExpoBracketing: + photo_mode_string = getResources().getString(R.string.photo_mode_expo_bracketing_full); + break; + case FocusBracketing: { + photo_mode_string = getResources().getString(R.string.photo_mode_focus_bracketing_full); + int n_images = applicationInterface.getFocusBracketingNImagesPref(); + photo_mode_string += " (" + n_images + ")"; + break; + } + case FastBurst: { + photo_mode_string = getResources().getString(R.string.photo_mode_fast_burst_full); + int n_images = applicationInterface.getBurstNImages(); + photo_mode_string += " (" + n_images + ")"; + break; + } + case NoiseReduction: + photo_mode_string = getResources().getString(R.string.photo_mode_noise_reduction_full); + break; + case Panorama: + photo_mode_string = getResources().getString(R.string.photo_mode_panorama_full); + break; + } + return photo_mode_string; + } + /** Displays a toast with information about the current preferences. * If always_show is true, the toast is always displayed; otherwise, we only display * a toast if it's important to notify the user (i.e., unusual non-default settings are @@ -4238,36 +4277,7 @@ public class MainActivity extends Activity { toast_string += " " + current_size.width + "x" + current_size.height; } - String photo_mode_string = null; - switch( photo_mode ) { - case DRO: - photo_mode_string = getResources().getString(R.string.photo_mode_dro); - break; - case HDR: - photo_mode_string = getResources().getString(R.string.photo_mode_hdr); - break; - case ExpoBracketing: - photo_mode_string = getResources().getString(R.string.photo_mode_expo_bracketing_full); - break; - case FocusBracketing: { - photo_mode_string = getResources().getString(R.string.photo_mode_focus_bracketing_full); - int n_images = applicationInterface.getFocusBracketingNImagesPref(); - photo_mode_string += " (" + n_images + ")"; - break; - } - case FastBurst: { - photo_mode_string = getResources().getString(R.string.photo_mode_fast_burst_full); - int n_images = applicationInterface.getBurstNImages(); - photo_mode_string += " (" + n_images + ")"; - break; - } - case NoiseReduction: - photo_mode_string = getResources().getString(R.string.photo_mode_noise_reduction_full); - break; - case Panorama: - photo_mode_string = getResources().getString(R.string.photo_mode_panorama_full); - break; - } + String photo_mode_string = getPhotoModeString(photo_mode, false); if( photo_mode_string != null ) { toast_string += (toast_string.length()==0 ? "" : "\n") + getResources().getString(R.string.photo_mode) + ": " + photo_mode_string; simple = false; diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index c34127200..1d282e412 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -99,6 +99,8 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared final String camera_api = bundle.getString("camera_api"); + final String photo_mode_string = bundle.getString("photo_mode_string"); + final boolean using_android_l = bundle.getBoolean("using_android_l"); if( MyDebug.LOG ) Log.d(TAG, "using_android_l: " + using_android_l); @@ -1130,6 +1132,8 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared about_string.append(nCameras); about_string.append("\nCamera API: "); about_string.append(camera_api); + about_string.append("\nPhoto mode: "); + about_string.append(photo_mode_string==null ? "UNKNOWN" : photo_mode_string); { String last_video_error = sharedPreferences.getString("last_video_error", ""); if( last_video_error.length() > 0 ) { -- GitLab From 0d4c8ee0f3e5eb24a89dda8965d348255a634381 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 18:22:05 +0000 Subject: [PATCH 088/243] Detect ultra-wide cameras for toast (for Camera2 API). --- _docs/history.html | 2 +- .../sourceforge/opencamera/MainActivity.java | 10 +-- .../cameracontroller/CameraController2.java | 24 +------ .../CameraControllerManager.java | 7 ++ .../CameraControllerManager1.java | 8 +++ .../CameraControllerManager2.java | 67 +++++++++++++++++++ app/src/main/res/values/strings.xml | 3 + 7 files changed, 95 insertions(+), 26 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index ef4978af0..5111a7ed6 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -73,7 +73,7 @@ UPDATED On devices with on-screen navigation buttons, camera preview can now dis UPDATED New immersive mode option to hide navigation buttons only when in immersive mode; existing option for hiding navigation buttons now renamed to say "dim". UPDATED Show toast with camera id on startup if camera isn't set to the default camera for front or - back facing. + back facing. Toast for cameras also displays whether ultra-wide, when using Camera2 API. UPDATED HDR and NR photo modes now limited to maximum resolution of 22 megapixels (to avoid risk of running out of memory on devices with large camera resolutions). UPDATED Improved performance when displaying ghost image larger than device's resolution. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 75b8600c5..aadcb2b5c 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1492,10 +1492,12 @@ public class MainActivity extends Activity { if( preview.getCameraControllerManager().getNumberOfCameras() > 2 ) { // telling the user which camera is pointless for only two cameras, but on devices that now // expose many cameras it can be confusing, so show a toast to at least display the id - String toast_string = getResources().getString( - preview.getCameraControllerManager().isFrontFacing(cameraId) ? R.string.front_camera : R.string.back_camera ) + - " : " + getResources().getString(R.string.camera_id) + " " + cameraId; - preview.showToast(null, toast_string); + String description = preview.getCameraControllerManager().getDescription(this, cameraId); + if( description != null ) { + String toast_string = description + ": "; + toast_string += getResources().getString(R.string.camera_id) + " " + cameraId; + preview.showToast(null, toast_string); + } } } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 135e4cdda..70a17a904 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -2573,27 +2573,9 @@ public class CameraController2 extends CameraController { if( MyDebug.LOG ) Log.d(TAG, "supports_tonemap_curve?: " + camera_features.supports_tonemap_curve); - { - // Calculate view angles - // Note this is an approximation (see http://stackoverflow.com/questions/39965408/what-is-the-android-camera2-api-equivalent-of-camera-parameters-gethorizontalvie ). - // This does not take into account the aspect ratio of the preview or camera, it's up to the caller to do this (e.g., see Preview.getViewAngleX(), getViewAngleY()). - Rect active_size = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); - SizeF physical_size = characteristics.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE); - android.util.Size pixel_size = characteristics.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE); - float [] focal_lengths = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS); - //camera_features.view_angle_x = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getWidth(), (2.0 * focal_lengths[0]))); - //camera_features.view_angle_y = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getHeight(), (2.0 * focal_lengths[0]))); - float frac_x = ((float)active_size.width())/(float)pixel_size.getWidth(); - float frac_y = ((float)active_size.height())/(float)pixel_size.getHeight(); - camera_features.view_angle_x = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getWidth() * frac_x, (2.0 * focal_lengths[0]))); - camera_features.view_angle_y = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getHeight() * frac_y, (2.0 * focal_lengths[0]))); - if( MyDebug.LOG ) { - Log.d(TAG, "frac_x: " + frac_x); - Log.d(TAG, "frac_y: " + frac_y); - Log.d(TAG, "view_angle_x: " + camera_features.view_angle_x); - Log.d(TAG, "view_angle_y: " + camera_features.view_angle_y); - } - } + SizeF view_angle = CameraControllerManager2.computeViewAngles(characteristics); + camera_features.view_angle_x = view_angle.getWidth(); + camera_features.view_angle_y = view_angle.getHeight(); return camera_features; } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager.java index a4b9217e7..c6da5bcd8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager.java @@ -1,9 +1,16 @@ package net.sourceforge.opencamera.cameracontroller; +import android.content.Context; + /** Provides additional support related to the Android camera APIs. This is to * support functionality that doesn't require a camera to have been opened. */ public abstract class CameraControllerManager { public abstract int getNumberOfCameras(); public abstract boolean isFrontFacing(int cameraId); + + /** Tries to return a textual description for the camera, such as front/back, along with extra + * details if possible such as "ultra-wide". Will be null if no description can be determined. + */ + public abstract String getDescription(Context context, int cameraId); } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager1.java index e02691fee..b24bcedde 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager1.java @@ -1,7 +1,9 @@ package net.sourceforge.opencamera.cameracontroller; import net.sourceforge.opencamera.MyDebug; +import net.sourceforge.opencamera.R; +import android.content.Context; import android.hardware.Camera; import android.util.Log; @@ -29,4 +31,10 @@ public class CameraControllerManager1 extends CameraControllerManager { return false; } } + + @Override + public String getDescription(Context context, int cameraId) { + boolean is_front_facing = isFrontFacing(cameraId); + return context.getResources().getString(is_front_facing ? R.string.front_camera : R.string.back_camera); + } } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager2.java index 27032a267..aa8d2f15d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraControllerManager2.java @@ -1,14 +1,17 @@ package net.sourceforge.opencamera.cameracontroller; import net.sourceforge.opencamera.MyDebug; +import net.sourceforge.opencamera.R; import android.annotation.TargetApi; import android.content.Context; +import android.graphics.Rect; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; import android.os.Build; import android.util.Log; +import android.util.SizeF; /** Provides support using Android 5's Camera 2 API * android.hardware.camera2.*. @@ -61,6 +64,70 @@ public class CameraControllerManager2 extends CameraControllerManager { return false; } + @Override + public String getDescription(Context context, int cameraId) { + CameraManager manager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE); + String description = null; + try { + String cameraIdS = manager.getCameraIdList()[cameraId]; + CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIdS); + + switch( characteristics.get(CameraCharacteristics.LENS_FACING) ) { + case CameraMetadata.LENS_FACING_FRONT: + description = context.getResources().getString(R.string.front_camera); + break; + case CameraMetadata.LENS_FACING_BACK: + description = context.getResources().getString(R.string.back_camera); + break; + case CameraMetadata.LENS_FACING_EXTERNAL: + description = context.getResources().getString(R.string.external_camera); + break; + default: + Log.e(TAG, "unknown camera type"); + return null; + } + + SizeF view_angle = CameraControllerManager2.computeViewAngles(characteristics); + if( view_angle.getWidth() > 90.5f ) { + // count as ultra-wide + description += ", " + context.getResources().getString(R.string.ultrawide); + } + } + catch(Throwable e) { + // see note under isFrontFacing() why we catch anything, not just CameraAccessException + if( MyDebug.LOG ) + Log.e(TAG, "exception trying to get camera characteristics"); + e.printStackTrace(); + } + return description; + } + + /** Helper class to compute view angles from the CameraCharacteristics. + * @return The width and height of the returned size represent the x and y view angles in + * degrees. + */ + static SizeF computeViewAngles(CameraCharacteristics characteristics) { + // Note this is an approximation (see http://stackoverflow.com/questions/39965408/what-is-the-android-camera2-api-equivalent-of-camera-parameters-gethorizontalvie ). + // This does not take into account the aspect ratio of the preview or camera, it's up to the caller to do this (e.g., see Preview.getViewAngleX(), getViewAngleY()). + Rect active_size = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); + SizeF physical_size = characteristics.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE); + android.util.Size pixel_size = characteristics.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE); + float [] focal_lengths = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS); + //camera_features.view_angle_x = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getWidth(), (2.0 * focal_lengths[0]))); + //camera_features.view_angle_y = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getHeight(), (2.0 * focal_lengths[0]))); + float frac_x = ((float)active_size.width())/(float)pixel_size.getWidth(); + float frac_y = ((float)active_size.height())/(float)pixel_size.getHeight(); + float view_angle_x = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getWidth() * frac_x, (2.0 * focal_lengths[0]))); + float view_angle_y = (float)Math.toDegrees(2.0 * Math.atan2(physical_size.getHeight() * frac_y, (2.0 * focal_lengths[0]))); + if( MyDebug.LOG ) { + Log.d(TAG, "frac_x: " + frac_x); + Log.d(TAG, "frac_y: " + frac_y); + Log.d(TAG, "view_angle_x: " + view_angle_x); + Log.d(TAG, "view_angle_y: " + view_angle_y); + } + return new SizeF(view_angle_x, view_angle_y); + } + /* Returns true if the device supports the required hardware level, or better. * See https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL . * From Android N, higher levels than "FULL" are possible, that will have higher integer values. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4f706a24e..e3ff4d11e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -959,6 +959,9 @@ Transparent White + External camera + Ultra-wide + Privacy policy -- GitLab From 01cb19c71a62699d66df05bf3b1d3e8384737524 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 20:42:31 +0000 Subject: [PATCH 089/243] Replace CameraControllerManager.isFrontFacing() with getFacing(). --- _docs/history.html | 1 + .../opencamera/test/MainActivityTest.java | 57 +++++++++++++++---- .../sourceforge/opencamera/MainActivity.java | 6 +- .../opencamera/MyApplicationInterface.java | 3 +- .../cameracontroller/CameraController.java | 6 ++ .../CameraControllerManager.java | 4 +- .../CameraControllerManager1.java | 25 +++++--- .../CameraControllerManager2.java | 14 ++++- .../net/sourceforge/opencamera/ui/MainUI.java | 18 ++++-- app/src/main/res/values/strings.xml | 3 + 10 files changed, 108 insertions(+), 29 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 5111a7ed6..6aeb86d9e 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -83,6 +83,7 @@ UPDATED Don't set video digital stabilization when in photo mode. UPDATED Disable some preferences if only relevant for another nearby option that isn't currently enabled. UPDATED Moved video bitrate and frame rate options to debugging section. +UPDATED Improved UI support for "external" cameras (if detecting with Camera2 API). Version 1.47.3 (2019/10/20) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index c3d9f7661..4e7aeb537 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -3238,7 +3238,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 0 ) { CameraControllerManager camera_controller_manager = preview.getCameraControllerManager(); - boolean front_facing = camera_controller_manager.isFrontFacing(cameraId); + CameraController.Facing front_facing = camera_controller_manager.getFacing(cameraId); if( MyDebug.LOG ) Log.d(TAG, "front_facing: " + front_facing); if( camera_controller_manager.getNumberOfCameras() > 2 ) { boolean camera_is_default = true; for(int i=0;i 2 ) { // telling the user which camera is pointless for only two cameras, but on devices that now // expose many cameras it can be confusing, so show a toast to at least display the id diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 82aa1c1ac..d00576f1a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -2509,8 +2509,9 @@ public class MyApplicationInterface extends BasicApplicationInterface { if( MyDebug.LOG ) Log.d(TAG, "switchToCamera: " + front_facing); int n_cameras = main_activity.getPreview().getCameraControllerManager().getNumberOfCameras(); + CameraController.Facing want_facing = front_facing ? CameraController.Facing.FACING_FRONT : CameraController.Facing.FACING_BACK; for(int i=0;iExternal camera Ultra-wide + Switch to external camera + Switch camera + Privacy policy -- GitLab From e96b21b870742e27d13a73646e98c366cd00c539 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 20:43:36 +0000 Subject: [PATCH 090/243] Remove uncommented parameter. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 3ff1d2109..ed5c58dec 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1506,7 +1506,6 @@ public class MainActivity extends Activity { /** * Selects the next camera on the phone - in practice, switches between * front and back cameras - * @param view */ public void clickedSwitchCamera(View view) { if( MyDebug.LOG ) -- GitLab From 9fff43d207230cfa8b00136969bfddaee7ee0d75 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 26 Jan 2020 21:09:17 +0000 Subject: [PATCH 091/243] Replace CameraController.isFrontFacing() with getFacing(). --- .../opencamera/MyApplicationInterface.java | 2 +- .../cameracontroller/CameraController.java | 4 ++- .../cameracontroller/CameraController1.java | 14 ++++++-- .../cameracontroller/CameraController2.java | 32 ++++++++++++++----- .../opencamera/preview/Preview.java | 10 +++--- .../opencamera/ui/DrawPreview.java | 2 +- 6 files changed, 45 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index d00576f1a..9421faa75 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -2900,7 +2900,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { if( do_auto_stabilise && main_activity.test_low_memory ) level_angle = 45.0; // I have received crashes where camera_controller was null - could perhaps happen if this thread was running just as the camera is closing? - boolean is_front_facing = main_activity.getPreview().getCameraController() != null && main_activity.getPreview().getCameraController().isFrontFacing(); + boolean is_front_facing = main_activity.getPreview().getCameraController() != null && (main_activity.getPreview().getCameraController().getFacing() == CameraController.Facing.FACING_FRONT); boolean mirror = is_front_facing && sharedPreferences.getString(PreferenceKeys.FrontCameraMirrorKey, "preference_front_camera_mirror_no").equals("preference_front_camera_mirror_photo"); String preference_stamp = this.getStampPref(); String preference_textstamp = this.getTextStampPref(); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 2c4e9a677..3d0785e40 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -545,7 +545,9 @@ public abstract class CameraController { FACING_EXTERNAL, FACING_UNKNOWN // returned if the Camera API returned an error or an unknown type } - public abstract boolean isFrontFacing(); + /** Returns whether the camera is front, back or external. + */ + public abstract Facing getFacing(); public abstract void unlock(); /** Call to initialise video recording, should call before MediaRecorder.prepare(). * @param video_recorder The media recorder object. diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 7f91a7e99..87539a61a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -208,7 +208,7 @@ public class CameraController1 extends CameraController { Log.d(TAG, "flash supported"); } else { - if( isFrontFacing() ) { + if( getFacing() == Facing.FACING_FRONT ) { if( MyDebug.LOG ) Log.d(TAG, "front-screen with no flash"); output_modes.clear(); // clear any pre-existing mode (see note above about Samsung Galaxy S7) @@ -1874,8 +1874,16 @@ public class CameraController1 extends CameraController { return camera_info.orientation; } - public boolean isFrontFacing() { - return (camera_info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT); + @Override + public Facing getFacing() { + switch( camera_info.facing ) { + case Camera.CameraInfo.CAMERA_FACING_FRONT: + return Facing.FACING_FRONT; + case Camera.CameraInfo.CAMERA_FACING_BACK: + return Facing.FACING_BACK; + } + Log.e(TAG, "unknown camera_facing: " + camera_info.facing); + return Facing.FACING_UNKNOWN; } public void unlock() { diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 70a17a904..2c3c85e81 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -70,7 +70,7 @@ public class CameraController2 extends CameraController { private CameraCharacteristics characteristics; // cached characteristics (use this for values that need to be frequently accessed, e.g., per frame, to improve performance); private int characteristics_sensor_orientation; - private boolean characteristics_is_front_facing; + private Facing characteristics_facing; private List zoom_ratios; private int current_zoom_value; @@ -297,7 +297,7 @@ public class CameraController2 extends CameraController { exif_orientation = ExifInterface.ORIENTATION_NORMAL; break; case 90: - exif_orientation = isFrontFacing() ? + exif_orientation = (getFacing() == Facing.FACING_FRONT) ? ExifInterface.ORIENTATION_ROTATE_270 : ExifInterface.ORIENTATION_ROTATE_90; break; @@ -305,7 +305,7 @@ public class CameraController2 extends CameraController { exif_orientation = ExifInterface.ORIENTATION_ROTATE_180; break; case 270: - exif_orientation = isFrontFacing() ? + exif_orientation = (getFacing() == Facing.FACING_FRONT) ? ExifInterface.ORIENTATION_ROTATE_90 : ExifInterface.ORIENTATION_ROTATE_270; break; @@ -1701,10 +1701,26 @@ public class CameraController2 extends CameraController { Log.d(TAG, "successfully obtained camera characteristics"); // now read cached values characteristics_sensor_orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); - characteristics_is_front_facing = characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT; + + switch( characteristics.get(CameraCharacteristics.LENS_FACING) ) { + case CameraMetadata.LENS_FACING_FRONT: + characteristics_facing = Facing.FACING_FRONT; + break; + case CameraMetadata.LENS_FACING_BACK: + characteristics_facing = Facing.FACING_BACK; + break; + case CameraMetadata.LENS_FACING_EXTERNAL: + characteristics_facing = Facing.FACING_EXTERNAL; + break; + default: + Log.e(TAG, "unknown camera_facing: " + characteristics.get(CameraCharacteristics.LENS_FACING)); + characteristics_facing = Facing.FACING_UNKNOWN; + break; + } + if( MyDebug.LOG ) { Log.d(TAG, "characteristics_sensor_orientation: " + characteristics_sensor_orientation); - Log.d(TAG, "characteristics_is_front_facing: " + characteristics_is_front_facing); + Log.d(TAG, "characteristics_facing: " + characteristics_facing); } CameraController2.this.camera = cam; @@ -2456,7 +2472,7 @@ public class CameraController2 extends CameraController { camera_features.supported_flash_values.add("flash_red_eye"); } } - else if( isFrontFacing() ) { + else if( (getFacing() == Facing.FACING_FRONT) ) { camera_features.supported_flash_values = new ArrayList<>(); camera_features.supported_flash_values.add("flash_off"); camera_features.supported_flash_values.add("flash_frontscreen_auto"); @@ -6775,9 +6791,9 @@ public class CameraController2 extends CameraController { } @Override - public boolean isFrontFacing() { + public Facing getFacing() { // cached for performance, as this method is frequently called from Preview.onOrientationChanged - return characteristics_is_front_facing; + return characteristics_facing; } @Override diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 6c67afa32..f04681968 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -467,7 +467,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( !using_android_l ) { // see http://developer.android.com/reference/android/hardware/Camera.Face.html#rect // Need mirror for front camera - boolean mirror = camera_controller.isFrontFacing(); + boolean mirror = (camera_controller.getFacing() == CameraController.Facing.FACING_FRONT); camera_to_preview_matrix.setScale(mirror ? -1 : 1, 1); int display_orientation = camera_controller.getDisplayOrientation(); if( MyDebug.LOG ) { @@ -479,7 +479,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu // Unfortunately the transformation for Android L API isn't documented, but this seems to work for Nexus 6. // This is the equivalent code for android.hardware.Camera.setDisplayOrientation, but we don't actually use setDisplayOrientation() // for CameraController2, except testing on Nexus 6 shows that we shouldn't change "result" for front facing camera. - boolean mirror = camera_controller.isFrontFacing(); + boolean mirror = (camera_controller.getFacing() == CameraController.Facing.FACING_FRONT); camera_to_preview_matrix.setScale(1, mirror ? -1 : 1); int degrees = getDisplayRotationDegrees(); int result = (camera_controller.getCameraOrientation() - degrees + 360) % 360; @@ -3672,7 +3672,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu this.current_orientation = orientation % 360; int new_rotation; int camera_orientation = camera_controller.getCameraOrientation(); - if( camera_controller.isFrontFacing() ) { + if( (camera_controller.getFacing() == CameraController.Facing.FACING_FRONT) ) { new_rotation = (camera_orientation - orientation + 360) % 360; } else { @@ -3715,7 +3715,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu int result; if( device_orientation == Configuration.ORIENTATION_PORTRAIT ) { // should be equivalent to onOrientationChanged(270) - if( camera_controller.isFrontFacing() ) { + if( (camera_controller.getFacing() == CameraController.Facing.FACING_FRONT) ) { result = (camera_orientation + 90) % 360; } else { @@ -3740,7 +3740,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } else { // should be equivalent to onOrientationChanged(90) - if( camera_controller.isFrontFacing() ) { + if( (camera_controller.getFacing() == CameraController.Facing.FACING_FRONT) ) { result = (camera_orientation + 270) % 360; } else { diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index ad24afc0f..f6292f8f3 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -2598,7 +2598,7 @@ public class DrawPreview { } last_image_matrix.preRotate(this_ui_rotation, bitmap.getWidth()/2.0f, bitmap.getHeight()/2.0f); if( flip_front ) { - boolean is_front_facing = camera_controller != null && camera_controller.isFrontFacing(); + boolean is_front_facing = camera_controller != null && (camera_controller.getFacing() == CameraController.Facing.FACING_FRONT); if( is_front_facing && !sharedPreferences.getString(PreferenceKeys.FrontCameraMirrorKey, "preference_front_camera_mirror_no").equals("preference_front_camera_mirror_photo") ) { last_image_matrix.preScale(-1.0f, 1.0f, bitmap.getWidth()/2.0f, 0.0f); } -- GitLab From a355f0fc8df96f1b40a9d345401575d9542599e1 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 27 Jan 2020 15:24:36 +0000 Subject: [PATCH 092/243] Improve toasts for manual focus and exposure compensation sliders - stop them jittering due to different lengths. --- .../net/sourceforge/opencamera/preview/Preview.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index f04681968..e25caea09 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -346,7 +346,10 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private final float [] new_geo_direction = new float[3]; private final DecimalFormat decimal_format_1dp = new DecimalFormat("#.#"); - private final DecimalFormat decimal_format_2dp = new DecimalFormat("#.##"); + + // use use '0' instead of '#' to display e.g. 1.20 instead of 1.2, so that text lengths are consistent (e.g., for the + // toasts shown when changing sliders for manual focus distance or exposure compensation). + private final DecimalFormat decimal_format_2dp_force0 = new DecimalFormat("0.00"); /* If the user touches to focus in continuous mode, and in photo mode, we switch the camera_controller to autofocus mode. * autofocus_in_continuous_mode is set to true when this happens; the runnable reset_continuous_focus_runnable @@ -3890,7 +3893,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu String focus_distance_s; if( new_focus_distance > 0.0f ) { float real_focus_distance = 1.0f / new_focus_distance; - focus_distance_s = decimal_format_2dp.format(real_focus_distance) + getResources().getString(R.string.metres_abbreviation); + focus_distance_s = decimal_format_2dp_force0.format(real_focus_distance) + getResources().getString(R.string.metres_abbreviation); } else { focus_distance_s = getResources().getString(R.string.infinite); @@ -4002,7 +4005,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu public String getExposureCompensationString(int exposure) { float exposure_ev = exposure * exposure_step; - return getResources().getString(R.string.exposure_compensation) + " " + (exposure > 0 ? "+" : "") + decimal_format_2dp.format(exposure_ev) + " EV"; + // show a "+" even for exactly 0, so that we have a consistent text length (useful for the toast when adjusting the exposure compensation slider) + return getResources().getString(R.string.exposure_compensation) + " " + (exposure >= 0 ? "+" : "") + decimal_format_2dp_force0.format(exposure_ev) + " EV"; } public String getISOString(int iso) { -- GitLab From e4b3a712eb61409243ad786dac5429aaf3fde92f Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 27 Jan 2020 15:25:38 +0000 Subject: [PATCH 093/243] Improve look of the fake toasts (used for seekbars) - use outline style, consistent with on-screen preview text. --- _docs/history.html | 1 + .../opencamera/preview/Preview.java | 41 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 6aeb86d9e..0ec4aa38f 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -84,6 +84,7 @@ UPDATED Disable some preferences if only relevant for another nearby option that enabled. UPDATED Moved video bitrate and frame rate options to debugging section. UPDATED Improved UI support for "external" cameras (if detecting with Camera2 API). +UPDATED Improved look of on-screen text for manual/exposure sliders. Version 1.47.3 (2019/10/20) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index e25caea09..4eb0969f0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -55,6 +55,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.SurfaceTexture; +import android.graphics.Typeface; import android.hardware.SensorEvent; import android.hardware.SensorManager; import android.location.Location; @@ -7151,12 +7152,19 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private final Rect bounds = new Rect(); private final Rect sub_bounds = new Rect(); private final RectF rect = new RectF(); + private final boolean style_outline; // if true, display text with outline rather than background - RotatedTextView(String text, int offset_y, Context context) { + RotatedTextView(String text, int offset_y, boolean style_outline, Context context) { super(context); this.lines = text.split("\n"); this.offset_y = offset_y; + this.style_outline = style_outline; + + if( style_outline ) { + // outline style looks clearer when using bold text + this.paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + } } void setText(String text) { @@ -7171,7 +7179,9 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu protected void onDraw(Canvas canvas) { final float scale = Preview.this.getResources().getDisplayMetrics().density; paint.setTextSize(14 * scale + 0.5f); // convert dps to pixels - paint.setShadowLayer(1, 0, 1, Color.BLACK); + if( !style_outline ) { + paint.setShadowLayer(1, 0, 1, Color.BLACK); + } //paint.getTextBounds(text, 0, text.length(), bounds); boolean first_line = true; for(String line : lines) { @@ -7213,15 +7223,30 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu rect.bottom = canvas.getHeight()/2.0f + bounds.bottom + padding + offset_y; paint.setStyle(Paint.Style.FILL); - paint.setColor(Color.rgb(50, 50, 50)); - //canvas.drawRect(rect, paint); - final float radius = (24 * scale + 0.5f); // convert dps to pixels - canvas.drawRoundRect(rect, radius, radius, paint); + if( !style_outline ) { + paint.setColor(Color.rgb(50, 50, 50)); + //paint.setColor(Color.argb(32, 0, 0, 0)); + //canvas.drawRect(rect, paint); + final float radius = (24 * scale + 0.5f); // convert dps to pixels + canvas.drawRoundRect(rect, radius, radius, paint); + } paint.setColor(Color.WHITE); int ypos = canvas.getHeight()/2 + offset_y - ((lines.length-1) * height)/2; for(String line : lines) { canvas.drawText(line, canvas.getWidth()/2.0f - bounds.width()/2.0f, ypos, paint); + + if( style_outline ) { + // draw outline + int current_color = paint.getColor(); + paint.setColor(Color.BLACK); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(1); + canvas.drawText(line, canvas.getWidth()/2.0f - bounds.width()/2.0f, ypos, paint); + paint.setStyle(Paint.Style.FILL); + paint.setColor(current_color); + } + ypos += height; } canvas.restore(); @@ -7291,7 +7316,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu fake_toast_handler.removeCallbacksAndMessages(null); } else { - active_fake_toast = new RotatedTextView(message, offset_y, activity); + active_fake_toast = new RotatedTextView(message, offset_y, true, activity); Activity activity = (Activity) Preview.this.getContext(); final FrameLayout rootLayout = activity.findViewById(android.R.id.content); rootLayout.addView(active_fake_toast); @@ -7354,7 +7379,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Log.d(TAG, "created new toast: " + toast); if( clear_toast != null ) clear_toast.toast = toast; - View text = new RotatedTextView(message, offset_y, activity); + View text = new RotatedTextView(message, offset_y, false, activity); toast.setView(text); last_toast_time_ms = time_now; } -- GitLab From d56e74e7ea6c6a5d0daef46c45c3cfbd421d1ec0 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 27 Jan 2020 21:59:08 +0000 Subject: [PATCH 094/243] Remove link. --- _docs/credits.html | 1 - _docs/devices.html | 1 - _docs/help.html | 1 - _docs/history.html | 1 - _docs/index.html | 1 - _docs/info.html | 1 - _docs/privacy_oc.html | 1 - 7 files changed, 7 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index 896850bac..2e77cd00a 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -88,7 +88,6 @@

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      diff --git a/_docs/devices.html b/_docs/devices.html index 7808d5e6f..1e8f6e38a 100644 --- a/_docs/devices.html +++ b/_docs/devices.html @@ -226,7 +226,6 @@ manual controls, RAW and 120fps video.

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      diff --git a/_docs/help.html b/_docs/help.html index e8b9ccc6e..438a6d5e3 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -1434,7 +1434,6 @@ miss it, there's only limited number of characters for me to reply).

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      diff --git a/_docs/history.html b/_docs/history.html index 0ec4aa38f..21bd4e47d 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -1561,7 +1561,6 @@ First release.

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      diff --git a/_docs/index.html b/_docs/index.html index d6605b2b3..5eb810f2a 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -294,7 +294,6 @@ of old versions; but no need to mention CC0 media which doesn't require attribut

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      diff --git a/_docs/info.html b/_docs/info.html index e54b35cb7..11f210a69 100644 --- a/_docs/info.html +++ b/_docs/info.html @@ -115,7 +115,6 @@ Thanks!

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      diff --git a/_docs/privacy_oc.html b/_docs/privacy_oc.html index 742cc0414..975846988 100644 --- a/_docs/privacy_oc.html +++ b/_docs/privacy_oc.html @@ -101,7 +101,6 @@ that use our services".

      Open Camera Privacy Policy.

      This website uses icons from third party sources, see licences.

      Open Camera on Sourceforge.

      -

      More of my Free software.


      -- GitLab From beed945e7bd4d7a5f030ebae153d4e0c49fe99f9 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 27 Jan 2020 22:12:49 +0000 Subject: [PATCH 095/243] Merge the camera id/front/back toast with the general info toast, to avoid two toasts showing in a row. --- .../sourceforge/opencamera/MainActivity.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index ed5c58dec..19073a47f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -146,6 +146,7 @@ public class MainActivity extends Activity { private final ToastBoxer exposure_lock_toast = new ToastBoxer(); private final ToastBoxer audio_control_toast = new ToastBoxer(); private boolean block_startup_toast = false; // used when returning from Settings/Popup - if we're displaying a toast anyway, don't want to display the info toast too + private String push_info_toast_text; // can be used to "push" extra text to the info text for showPhotoVideoToast() // application shortcuts: static private final String ACTION_SHORTCUT_CAMERA = "net.sourceforge.opencamera.SHORTCUT_CAMERA"; @@ -1108,7 +1109,7 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) Log.d(TAG, "camera_is_default: " + camera_is_default); if( !camera_is_default ) { - this.showCameraIdToast(cameraId); + this.pushCameraIdToast(cameraId); } } } @@ -1488,9 +1489,9 @@ public class MainActivity extends Activity { return cameraId; } - private void showCameraIdToast(int cameraId) { + private void pushCameraIdToast(int cameraId) { if( MyDebug.LOG ) - Log.d(TAG, "showCameraIdToast: " + cameraId); + Log.d(TAG, "pushCameraIdToast: " + cameraId); if( preview.getCameraControllerManager().getNumberOfCameras() > 2 ) { // telling the user which camera is pointless for only two cameras, but on devices that now // expose many cameras it can be confusing, so show a toast to at least display the id @@ -1498,7 +1499,8 @@ public class MainActivity extends Activity { if( description != null ) { String toast_string = description + ": "; toast_string += getResources().getString(R.string.camera_id) + " " + cameraId; - preview.showToast(null, toast_string); + //preview.showToast(null, toast_string); + this.push_info_toast_text = toast_string; } } } @@ -1519,7 +1521,7 @@ public class MainActivity extends Activity { if( this.preview.canSwitchCamera() ) { int cameraId = getNextCameraId(); - showCameraIdToast(cameraId); + pushCameraIdToast(cameraId); View switchCameraButton = findViewById(R.id.switch_camera); switchCameraButton.setEnabled(false); // prevent slowdown if user repeatedly clicks @@ -4389,9 +4391,18 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) { Log.d(TAG, "toast_string: " + toast_string); Log.d(TAG, "simple?: " + simple); + Log.d(TAG, "push_info_toast_text: " + push_info_toast_text); } - if( !simple || always_show ) + if( !simple || always_show ) { + if( push_info_toast_text != null ) { + toast_string = push_info_toast_text + "\n" + toast_string; + } preview.showToast(switch_video_toast, toast_string); + } + else if( push_info_toast_text != null ) { + preview.showToast(switch_video_toast, push_info_toast_text); + } + push_info_toast_text = null; // reset } private void freeAudioListener(boolean wait_until_done) { -- GitLab From ab742aced60534bce671785690b32fb3acdadb42 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 28 Jan 2020 23:02:50 +0000 Subject: [PATCH 096/243] Refactor code to userSwitchToCamera(). --- .../sourceforge/opencamera/MainActivity.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 19073a47f..9c1797d2e 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1505,6 +1505,18 @@ public class MainActivity extends Activity { } } + private void userSwitchToCamera(int cameraId) { + if( MyDebug.LOG ) + Log.d(TAG, "userSwitchToCamera: " + cameraId); + View switchCameraButton = findViewById(R.id.switch_camera); + switchCameraButton.setEnabled(false); // prevent slowdown if user repeatedly clicks + applicationInterface.reset(); + this.preview.setCamera(cameraId); + switchCameraButton.setEnabled(true); + // no need to call mainUI.setSwitchCameraContentDescription - this will be called from PreviewcameraSetup when the + // new camera is opened + } + /** * Selects the next camera on the phone - in practice, switches between * front and back cameras @@ -1523,13 +1535,7 @@ public class MainActivity extends Activity { pushCameraIdToast(cameraId); - View switchCameraButton = findViewById(R.id.switch_camera); - switchCameraButton.setEnabled(false); // prevent slowdown if user repeatedly clicks - applicationInterface.reset(); - this.preview.setCamera(cameraId); - switchCameraButton.setEnabled(true); - // no need to call mainUI.setSwitchCameraContentDescription - this will be called from PreviewcameraSetup when the - // new camera is opened + userSwitchToCamera(cameraId); } } -- GitLab From 8ba49e90db20d0aadd89310c90318e9a29fc9d57 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 28 Jan 2020 23:39:02 +0000 Subject: [PATCH 097/243] Fix testSwitchResolution due to recent changes in popup resolution text. --- .../opencamera/test/MainActivityTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 4e7aeb537..b1ba71b06 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -1270,7 +1270,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Tue, 28 Jan 2020 23:40:05 +0000 Subject: [PATCH 098/243] Combine flash and focus toasts (needed to fix testAutoFocus, due to new Android behaviour for toasts blocking UI). --- .../java/net/sourceforge/opencamera/preview/Preview.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 4eb0969f0..2975719d1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -300,8 +300,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private Toast last_toast; private long last_toast_time_ms; - private final ToastBoxer flash_toast = new ToastBoxer(); - private final ToastBoxer focus_toast = new ToastBoxer(); + private final ToastBoxer focus_flash_toast = new ToastBoxer(); private final ToastBoxer take_photo_toast = new ToastBoxer(); private final ToastBoxer pause_video_toast = new ToastBoxer(); @@ -4549,7 +4548,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( MyDebug.LOG ) Log.d(TAG, " found entry: " + i); if( !initial ) { - showToast(flash_toast, flash_entries[i]); + showToast(focus_flash_toast, flash_entries[i]); } break; } @@ -4664,7 +4663,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( !quiet ) { String focus_entry = findFocusEntryForValue(focus_value); if( focus_entry != null ) { - showToast(focus_toast, focus_entry); + showToast(focus_flash_toast, focus_entry); } } this.setFocusValue(focus_value, auto_focus); -- GitLab From c290fd82c43d3cd58f8d3d0b1737345a9cbeae38 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 29 Jan 2020 00:20:26 +0000 Subject: [PATCH 099/243] Add comment for needing sleep. --- .../java/net/sourceforge/opencamera/test/MainActivityTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index b1ba71b06..d94ee8334 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -1268,7 +1268,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Wed, 29 Jan 2020 00:20:36 +0000 Subject: [PATCH 100/243] Fix for testTakeVideoSubtitles, testTakeVideoSubtitlesGPS. --- .../java/net/sourceforge/opencamera/test/MainActivityTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index d94ee8334..c5a396f23 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -5854,7 +5854,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Wed, 29 Jan 2020 00:24:21 +0000 Subject: [PATCH 101/243] Fix for when allow_failure==true (for testTakeVideoForceFailure). --- .../net/sourceforge/opencamera/test/MainActivityTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index c5a396f23..3b5715151 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -5854,8 +5854,10 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Wed, 29 Jan 2020 22:41:35 +0000 Subject: [PATCH 102/243] Use fake toast for info toast; clear fake toasts when clicking preview. --- _docs/help.html | 3 +- .../sourceforge/opencamera/MainActivity.java | 5 +- .../opencamera/preview/Preview.java | 54 ++++++++++++++++--- app/src/main/res/values/strings.xml | 4 +- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 438a6d5e3..c5e5f799b 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -743,7 +743,8 @@ flash modes won't show on the popup menu. Also note that it is not possible to e icon for taking a photo (or recording video). Uncheck if you'd rather take photos by other methods (e.g., if your device has a hardware shutter button, or using the volume keys).

      -

      Show "toast" messages - Whether to display "toasts" (these are the popup messages that appear with information).

      +

      Show on-screen messages - Open Camera will sometimes display temporary on-screen text with information (in some + cases using "toasts"). This option can be used to disable them.

      Show What's New dialog - When updating to a major new version, Open Camera displays a dialog explaining the new features and other options. You can disable this dialog from being displayed if you prefer.

      diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 9c1797d2e..86d3603b2 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4399,14 +4399,15 @@ public class MainActivity extends Activity { Log.d(TAG, "simple?: " + simple); Log.d(TAG, "push_info_toast_text: " + push_info_toast_text); } + final boolean use_fake_toast = true; if( !simple || always_show ) { if( push_info_toast_text != null ) { toast_string = push_info_toast_text + "\n" + toast_string; } - preview.showToast(switch_video_toast, toast_string); + preview.showToast(switch_video_toast, toast_string, use_fake_toast); } else if( push_info_toast_text != null ) { - preview.showToast(switch_video_toast, push_info_toast_text); + preview.showToast(switch_video_toast, push_info_toast_text, use_fake_toast); } push_info_toast_text = null; // reset } diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 2975719d1..248843138 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -561,6 +561,9 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( MyDebug.LOG ) Log.d(TAG, "touch event at : " + event.getX() + " , " + event.getY() + " at time " + event.getEventTime()); + // doesn't seem a bad idea to clear fake toasts (touching screen gets rid of standard toasts on Android 10+ at least) + this.clearActiveFakeToast(); + boolean was_paused = !this.is_preview_started; if( MyDebug.LOG ) Log.d(TAG, "was_paused: " + was_paused); @@ -7255,6 +7258,36 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private final Handler fake_toast_handler = new Handler(); private RotatedTextView active_fake_toast = null; + public void clearActiveFakeToast() { + clearActiveFakeToast(false); + } + + /** Removes any fake toast, if it exists. + * @param called_from_handler Should be false, unless called from the fake_toast_handler. + */ + private void clearActiveFakeToast(boolean called_from_handler) { + if( !called_from_handler ) { + // important to remove the callback, otherwise when it runs, it may end up deleting a + // new fake toast that is created after this method call, but before the callback runs + fake_toast_handler.removeCallbacksAndMessages(null); + } + // run on UI thread, to avoid threading issues + final Activity activity = (Activity)this.getContext(); + activity.runOnUiThread(new Runnable() { + public void run() { + if( active_fake_toast != null ) { + if( MyDebug.LOG ) + Log.d(TAG, "remove fake toast: " + active_fake_toast); + ViewParent parent = active_fake_toast.getParent(); + if( parent != null ) { + ((ViewGroup)parent).removeView(active_fake_toast); + } + active_fake_toast = null; + } + } + }); + } + public void showToast(final ToastBoxer clear_toast, final int message_id) { showToast(clear_toast, getResources().getString(message_id), false); } @@ -7291,6 +7324,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu * means that the toasts don't have the fade out effect. */ private void showToast(final ToastBoxer clear_toast, final String message, final int offset_y_dp, final boolean use_fake_toast) { + //final boolean use_fake_toast = true; + //final boolean use_fake_toast = old_use_fake_toast; if( !applicationInterface.getShowToastsPref() ) { return; } @@ -7300,7 +7335,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu final Activity activity = (Activity)this.getContext(); // We get a crash on emulator at least if Toast constructor isn't run on main thread (e.g., the toast for taking a photo when on timer). // Also see http://stackoverflow.com/questions/13267239/toast-from-a-non-ui-thread - // Also for the use_fake_toast code, running the creation code, and the postDelayed code, on the UI thread avoids threading issues + // Also for the use_fake_toast code, running the creation code, and the postDelayed code (and the code in clearActiveFakeToast()), on the UI thread avoids threading issues activity.runOnUiThread(new Runnable() { public void run() { final float scale = Preview.this.getResources().getDisplayMetrics().density; @@ -7309,28 +7344,31 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( use_fake_toast ) { if( active_fake_toast != null ) { // re-use existing fake toast + if( MyDebug.LOG ) + Log.d(TAG, "re-use fake toast: " + active_fake_toast); active_fake_toast.setText(message); active_fake_toast.setOffsetY(offset_y); active_fake_toast.invalidate(); // make sure the view is redrawn - fake_toast_handler.removeCallbacksAndMessages(null); } else { active_fake_toast = new RotatedTextView(message, offset_y, true, activity); + if( MyDebug.LOG ) + Log.d(TAG, "create new fake toast: " + active_fake_toast); Activity activity = (Activity) Preview.this.getContext(); final FrameLayout rootLayout = activity.findViewById(android.R.id.content); rootLayout.addView(active_fake_toast); } + // in theory the fake_toast_handler should only have a callback on it if re-using an existing fake toast, + // but we remove callbacks always just in case + fake_toast_handler.removeCallbacksAndMessages(null); + fake_toast_handler.postDelayed(new Runnable() { @Override public void run() { if( MyDebug.LOG ) - Log.d(TAG, "remove fake toast: " + active_fake_toast); - ViewParent parent = active_fake_toast.getParent(); - if( parent != null ) { - ((ViewGroup)parent).removeView(active_fake_toast); - } - active_fake_toast = null; + Log.d(TAG, "destroy fake toast due to time expired"); + clearActiveFakeToast(true); } }, 2000); // supposedly matches Toast.LENGTH_SHORT diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ec934f5f..a19469c3f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -157,8 +157,8 @@ Grid Show a crop guide A crop guide displays a rectangle showing what the specified aspect ratio looks like - useful if you plan to crop the photo/video afterwards to a different aspect ratio. Requires WYSIWYG photo mode, or being in video mode.\n%s - Show \"toast\" messages - Whether to display the popup \"toast\" messages + Show on-screen messages + Whether to display temporary on-screen info messages Show thumbnail animation Display moving thumbnail animation when taking a photo Show border when taking photo -- GitLab From 6ea28669c2826ee020dd7ae23531a02c3bc1db12 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 30 Jan 2020 21:55:53 +0000 Subject: [PATCH 103/243] Document Zebra stripes foreground/background colour. --- _docs/help.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/_docs/help.html b/_docs/help.html index c5e5f799b..45a153ede 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -652,11 +652,14 @@ image should be drawn with.

      since these modes are able to better handle a high dynamic range. Also note that enabling zebra stripes may use more battery.

      +

      Zebra stripes foreground/background colour - If "Show zebra stripes" is enabled, these options allow you to +choose the colours of the stripes.

      +

      Focus peaking - Allows displaying on-screen highlights to indicate edges (contours) that are in-focus (only available if Camera2 API is used). This is particularly useful in conjunction with manual focus mode, to help show which regions of the image are in focus. Note that enabling focus peaking may use more battery.

      -

      Focus peaking color - This controls the color to be used for the highlights when Focus Peaking is enabled.

      +

      Focus peaking color - This controls the color to be used for the highlights when "Focus peaking" is enabled.

      Show audio level meter - If selected, when recording video an on-screen meter will display the current audio level.

      -- GitLab From 041ac52b69aec48906b38b31943ab8d4de4fcda6 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 30 Jan 2020 23:51:44 +0000 Subject: [PATCH 104/243] Add/update comments related to preference whitelisting. --- .../sourceforge/opencamera/MainActivity.java | 66 +++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 86d3603b2..1367cb980 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1631,8 +1631,8 @@ public class MainActivity extends Activity { class PreferencesListener implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "PreferencesListener"; - private boolean any_significant_change; // whether any changes have been made since startListening() - private boolean any_change; // whether any changes that require updateForSettings have been made since startListening() + private boolean any_significant_change; // whether any changes that require updateForSettings have been made since startListening() + private boolean any_change; // whether any changes have been made since startListening() void startListening() { if( MyDebug.LOG ) @@ -1662,23 +1662,32 @@ public class MainActivity extends Activity { switch( key ) { // we whitelist preferences where we're sure that we don't need to call updateForSettings() if they've changed + //case "preference_face_detection": // need to update camera controller case "preference_timer": case "preference_burst_mode": case "preference_burst_interval": - //case "preference_ghost_image": // don't whitelist this, as may need to reload ghost image (at fullscreen resolution) if "last" is enabled case "preference_touch_capture": case "preference_pause_preview": case "preference_shutter_sound": case "preference_timer_beep": case "preference_timer_speak": case "preference_volume_keys": + //case "preference_audio_control": // need to update the UI case "preference_audio_noise_control_sensitivity": + //case "preference_enable_remote": // handled below + //case "preference_remote_type": + //case "preference_remote_device_name": // handled below + //case "preference_remote_disconnect_screen_dim": + //case "preference_water_type": // handled below + //case "preference_save_location": // we could probably whitelist this, but accessed it a lot of places... case "preference_using_saf": case "preference_save_photo_prefix": case "preference_save_video_prefix": case "preference_save_zulu_time": case "preference_show_when_locked": case "preference_startup_focus": + //case "preference_preview_size": // need to update preview + //case "preference_ghost_image": // don't whitelist this, as may need to reload ghost image (at fullscreen resolution) if "last" is enabled case "preference_show_zoom": case "preference_show_angle": case "preference_show_angle_line": @@ -1692,12 +1701,37 @@ public class MainActivity extends Activity { case "preference_show_iso": case "preference_grid": case "preference_crop_guide": - case "preference_show_toasts": case "preference_thumbnail_animation": case "preference_take_photo_border": + //case "preference_rotate_preview": // need to update the Preview + //case "preference_ui_placement": // need to update the UI + //case "preference_immersive_mode": // probably could whitelist? + //case "preference_show_face_detection": // need to update the UI + //case "preference_show_cycle_flash": // need to update the UI + //case "preference_show_auto_level": // need to update the UI + //case "preference_show_stamp": // need to update the UI + //case "preference_show_textstamp": // need to update the UI + //case "preference_show_store_location": // need to update the UI + //case "preference_show_cycle_raw": // need to update the UI + //case "preference_show_white_balance_lock": // need to update the UI + //case "preference_show_exposure_lock": // need to update the UI + //case "preference_show_zoom_controls": // need to update the UI + //case "preference_show_zoom_slider_controls": // need to update the UI + //case "preference_show_take_photo": // need to update the UI + case "preference_show_toasts": case "preference_keep_display_on": case "preference_max_brightness": + //case "preference_resolution": // need to set up camera controller and preview + //case "preference_quality": // need to set up camera controller + //case "preference_image_format": // need to set up camera controller (as it can affect the image quality that we set) + //case "preference_raw": // need to update as it affects how we set up camera controller + //case "preference_raw_expo_bracketing": // as above + //case "preference_raw_focus_bracketing": // as above + //case "preference_nr_save": // we could probably whitelist this, but have not done so in case in future we allow RAW to be saved for the base image //case "preference_hdr_save_expo": // we need to update if this is changed, as it affects whether we request RAW or not in HDR mode when RAW is enabled + //case "preference_expo_bracketing_n_images": // need to set up camera controller + //case "preference_expo_bracketing_stops": // need to set up camera controller + //case "preference_panorama_save": // we could probably whitelist this, but have not done so in case in future we allow RAW to be saved for the base images case "preference_front_camera_mirror": case "preference_stamp": case "preference_stamp_dateformat": @@ -1707,13 +1741,34 @@ public class MainActivity extends Activity { case "preference_stamp_fontsize": case "preference_stamp_font_color": case "preference_stamp_style": + //case "preference_camera2_fake_flash": // need to update camera controller + //case "preference_camera2_fast_burst": // could probably whitelist? + //case "preference_camera2_photo_video_recording": // need to update camera controller case "preference_background_photo_saving": + //case "preference_video_quality": // need to update camera controller and preview + //case "preference_video_stabilization": // need to update camera controller + //case "preference_video_output_format": // could probably whitelist, but safest to restart camera + //case "preference_video_log": // need to update camera controller + //case "preference_video_profile_gamma": // as above + //case "preference_video_max_duration": // could probably whitelist, but safest to restart camera + //case "preference_video_restart": // could probably whitelist, but safest to restart camera + //case "preference_video_max_filesize": // could probably whitelist, but safest to restart camera + //case "preference_video_restart_max_filesize": // could probably whitelist, but safest to restart camera case "preference_record_audio": case "preference_record_audio_src": case "preference_record_audio_channels": case "preference_lock_video": case "preference_video_subtitle": + //case "preference_video_bitrate": // could probably whitelist, but safest to restart camera + //case "preference_video_fps": // could probably whitelist, but safest to restart camera + //case "preference_force_video_4k": // could probably whitelist, but safest to restart camera + //case "preference_location": // need to enable/disable gps listeners etc + //case "preference_gps_direction": // need to update listeners case "preference_require_location": + //case "preference_antibanding": // need to set up camera controller + //case "preference_edge_mode": // need to set up camera controller + //case "preference_noise_reduction_mode": // need to set up camera controller + //case "preference_camera_api": // no point whitelisting as we restart anyway if( MyDebug.LOG ) Log.d(TAG, "this change doesn't require update"); break; @@ -2214,7 +2269,7 @@ public class MainActivity extends Activity { preferencesListener.stopListening(); // Update the cached settings in DrawPreview - // Note that some GUI related settings won't trigger preferencesListener.anyChanges(), so + // Note that some GUI related settings won't trigger preferencesListener.anyChange(), so // we always call this. Perhaps we could add more classifications to PreferencesListener // to mark settings that need us to update DrawPreview but not call updateForSettings(). // However, DrawPreview.updateSettings() should be a quick function (the main point is @@ -2222,7 +2277,6 @@ public class MainActivity extends Activity { applicationInterface.getDrawPreview().updateSettings(); if( preferencesListener.anyChange() ) { - // in case face detection etc enabled/disabled in settings: mainUI.updateOnScreenIcons(); } -- GitLab From cdca0833c535dabb2e7a5ce8e5ba01aceac16896 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 31 Jan 2020 00:15:12 +0000 Subject: [PATCH 105/243] Whitelist some more settings. --- .../sourceforge/opencamera/MainActivity.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 1367cb980..27b7231e8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1679,6 +1679,7 @@ public class MainActivity extends Activity { //case "preference_remote_device_name": // handled below //case "preference_remote_disconnect_screen_dim": //case "preference_water_type": // handled below + case "preference_lock_orientation": //case "preference_save_location": // we could probably whitelist this, but accessed it a lot of places... case "preference_using_saf": case "preference_save_photo_prefix": @@ -1688,6 +1689,8 @@ public class MainActivity extends Activity { case "preference_startup_focus": //case "preference_preview_size": // need to update preview //case "preference_ghost_image": // don't whitelist this, as may need to reload ghost image (at fullscreen resolution) if "last" is enabled + case "ghost_image_alpha": + case "preference_focus_assist": case "preference_show_zoom": case "preference_show_angle": case "preference_show_angle_line": @@ -1699,6 +1702,13 @@ public class MainActivity extends Activity { case "preference_show_time": case "preference_free_memory": case "preference_show_iso": + case "preference_histogram": + case "preference_zebra_stripes": + case "preference_zebra_stripes_foreground_color": + case "preference_zebra_stripes_background_color": + case "preference_focus_peaking": + case "preference_focus_peaking_color": + case "preference_show_video_max_amp": case "preference_grid": case "preference_crop_guide": case "preference_thumbnail_animation": @@ -1719,6 +1729,7 @@ public class MainActivity extends Activity { //case "preference_show_zoom_slider_controls": // need to update the UI //case "preference_show_take_photo": // need to update the UI case "preference_show_toasts": + case "preference_show_whats_new": case "preference_keep_display_on": case "preference_max_brightness": //case "preference_resolution": // need to set up camera controller and preview @@ -1729,14 +1740,20 @@ public class MainActivity extends Activity { //case "preference_raw_focus_bracketing": // as above //case "preference_nr_save": // we could probably whitelist this, but have not done so in case in future we allow RAW to be saved for the base image //case "preference_hdr_save_expo": // we need to update if this is changed, as it affects whether we request RAW or not in HDR mode when RAW is enabled + case "preference_hdr_contrast_enhancement": //case "preference_expo_bracketing_n_images": // need to set up camera controller //case "preference_expo_bracketing_stops": // need to set up camera controller + case "preference_panorama_crop": //case "preference_panorama_save": // we could probably whitelist this, but have not done so in case in future we allow RAW to be saved for the base images case "preference_front_camera_mirror": + case "preference_exif_artist": + case "preference_exif_copyright": case "preference_stamp": case "preference_stamp_dateformat": case "preference_stamp_timeformat": case "preference_stamp_gpsformat": + case "preference_stamp_geo_address": + case "preference_units_distance": case "preference_textstamp": case "preference_stamp_fontsize": case "preference_stamp_font_color": @@ -1762,6 +1779,8 @@ public class MainActivity extends Activity { //case "preference_video_bitrate": // could probably whitelist, but safest to restart camera //case "preference_video_fps": // could probably whitelist, but safest to restart camera //case "preference_force_video_4k": // could probably whitelist, but safest to restart camera + case "preference_video_low_power_check": + case "preference_video_flash": //case "preference_location": // need to enable/disable gps listeners etc //case "preference_gps_direction": // need to update listeners case "preference_require_location": -- GitLab From 21caaa4cc94f06190f0ca73aa1ccee68f48dc262 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 1 Feb 2020 17:25:38 +0000 Subject: [PATCH 106/243] New icon for supporting devices with multiple cameras. --- _docs/baseline_add_a_photo_white_48.png | Bin 0 -> 1725 bytes _docs/help.html | 25 ++- _docs/history.html | 5 + _docs/index.html | 1 + .../opencamera/test/MainActivityTest.java | 114 ++++++---- .../sourceforge/opencamera/MainActivity.java | 195 +++++++++++++++++- .../opencamera/MyPreferenceFragment.java | 12 ++ .../opencamera/PreferenceKeys.java | 2 + .../net/sourceforge/opencamera/ui/MainUI.java | 14 ++ .../baseline_add_a_photo_white_48.png | Bin 0 -> 583 bytes .../baseline_add_a_photo_white_48.png | Bin 0 -> 422 bytes .../baseline_add_a_photo_white_48.png | Bin 0 -> 763 bytes .../baseline_add_a_photo_white_48.png | Bin 0 -> 1123 bytes .../baseline_add_a_photo_white_48.png | Bin 0 -> 1498 bytes app/src/main/res/layout/activity_main.xml | 23 +++ app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/preferences.xml | 8 + 17 files changed, 352 insertions(+), 50 deletions(-) create mode 100644 _docs/baseline_add_a_photo_white_48.png create mode 100644 app/src/main/res/drawable-hdpi/baseline_add_a_photo_white_48.png create mode 100644 app/src/main/res/drawable-mdpi/baseline_add_a_photo_white_48.png create mode 100644 app/src/main/res/drawable-xhdpi/baseline_add_a_photo_white_48.png create mode 100644 app/src/main/res/drawable-xxhdpi/baseline_add_a_photo_white_48.png create mode 100644 app/src/main/res/drawable-xxxhdpi/baseline_add_a_photo_white_48.png diff --git a/_docs/baseline_add_a_photo_white_48.png b/_docs/baseline_add_a_photo_white_48.png new file mode 100644 index 0000000000000000000000000000000000000000..17a587b41c4d79237ddb7572b51191359e35af4f GIT binary patch literal 1725 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4kiW$hTLBd@);Ny7>k44ofy`glX=O&z`&C3 z=iS3V-gS;buz zHF4PK?Qj*GDDm+3{tv(%uQV(ws{Oa{xU^1i)a{u~cYf~O@hzn5%l*w~ zW=gKhuCCtgzo>t9oma^OCP@WWqXQv)QBhG+Qc_BfySH!O9;4^(_CD!U^MZ5rx?8-i zO+F!D?7)@MAaa61a{^sPP3_`ZJp{rB+U!znc%fBlNmn||_w zTrp#R5j z-@g6*JNI1Oa&y*SngU;b{P^+kVdERMDlPU%Hcl0(-nPSun`Td761>1MH$Xu^;Wu}l zV%oCvNov2>F>RdYw|w?zL3943b#pUc6qPdAC2EK$EpFs7)SYE9fhki`LSn&Uwjc%F zzkmOhTycPeRxnedLEoZvjOs71+wyL=?J~Q~!Q*qkqSzcg;a^y$-`7B<*%#9GX~#Q2p}Ikx|}v9+~!p2t$b6_YJF;)<)P zW}Qq?n6S`_VXpbDcc)K#^OSAAsiU_%zGI0o)5Ck8e%dTKc=y#=<1LKSV`5_7ym@or z_lqe8KCKe>?YLjfnKS3k{ri)1nOW|hIdkUA7n9>1nfldCn4~e7az!M5|1oaHory)B}cP3(FmpjVHer zE6_VKVe0vF=T2lW-b~5L;(Eo>d@#&X;oaT4vRbmMX57oMxu-bQ>!!R$soIf%JP}vL z#jO`F2Hv@S>QvV~26px5&z?=l_+T{uynFh7=7(kFR$4m>l9Qc{e=l$9o8AYKyCVBc zJuF*Ha@v8XvpCB{r_}W6b`&(uc=h1q;)IEb%+K~|wip`;N^TR>6WCm#XdcbCE=^5c zedhb*g^bsncR0M-Go7vfxU>7W2CECRdemmrUy({;b!tm1i_0_LzJGOOOTfzOuS-&- zH!@8}Zsu9HX%Jpx&Gl=X|X7Y%DAi z&MjhLV$`ec=_+VE@aK<>v2f(P%yz4)&;L)@#oT(Z-$HT1_1CW9p2x~XTu(kNvj3zU zD!aGT{r6@KsW}212Rdg=Wi>3StIM;yHlbV~vg(z>&5xz>4<&d$zm(pjdswjMtBfbT2|mpZ94W^I+)(>8O`|D?o! z^F7tCKU+9)!Tafby}fJKuP-i~@3-#kV>UB0voB%)bd0U6PI=D_lM&@mklY&ib2EdI zwp>4V5W9u0z=5+zk~Vs%ByCPU^pu;MJLZ$0w3ULu0bN~vef7znOU#~0Y_i>vl9t9c zU0+X+E0n#&O+mCp`cl2t)Fz)c>l+~#S{F@wEM&oVpK+m_-+P10%&hAobQaB7JZZ}>W8ra8aML1jk1)t9}db6v3o zmzJ3qbtcac>UgZ>`@LDp%bnMU^GkotXHVD7@yDk)EDho;o!&E#ZF^;Txw{*4FjJ_O zXkYZCT{E2)CLC>USfnBIeQT-u)vT>o`Ok2*G}fz4KKcB!tz`C&l{sdo|M-{sY?V6u zqh?=%!HRQTmsZ~A;W9~j_3c~O`-A@@7S!`@R{VBeiPZ>NEWrx#+?TI^%Ug0-mkBc} S-(g^2VDNPHb6Mw<&;$T^%nfS* literal 0 HcmV?d00001 diff --git a/_docs/help.html b/_docs/help.html index 45a153ede..1eab7851c 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -125,7 +125,17 @@ a photo. In some cases, you can also hold (long press) for a continuous burst:

      Switch Camera iconSwitch camera - Switches between front and back camera (if your -device has two cameras).

      +device has both front and back cameras). If your device has more than one front and/or back camera, then this will switch +between the first front and back camera.

      + +

      Switch multi-camera iconSwitch multi-camera icon - + This icon only shows on devices with more than one front and/or back cameras, and allows you to switch between those + cameras. For example, a device might have two back cameras, one standard and one ultra-wide, this icon will switch between + the standard and ultra-wide camera. + If Settings/On screen GUI/"Multiple cameras icon" is disabled, then this icon will not show; instead the "Switch camera" + icon can by used to cycle through all the cameras. + Note that some devices do not allow third party applications to access their multiple cameras, in which case Open Camera isn't + able to use them.

      Lock Exposure iconExposure lock - Click to lock or unlock the exposure. When locked, the icon will change to Exposure Locked icon. Locking the exposure means @@ -752,6 +762,11 @@ rather take photos by other methods (e.g., if your device has a hardware shutter

      Show What's New dialog - When updating to a major new version, Open Camera displays a dialog explaining the new features and other options. You can disable this dialog from being displayed if you prefer.

      +

      Multiple cameras icon - This option only shows on devices with more than one front and/or back cameras. When +enabled (the default), such devices will have two on-screen icons: one to switch between front/back cameras, and another +to switch between the multiple front or back cameras. If this option is disabled, only a single icon will show, which +will cycle between all cameras.

      +

      Keep display on - Whether to force keeping the screen display on, while the main Open Camera UI is active.

      Force maximum brightness - Whether to force the screen display to maximum brightness.

      @@ -1231,9 +1246,11 @@ and untick Auto-level.

      Why doesn't Open Camera support dual / multiple cameras? - Open Camera supports switching between all cameras that are made available to third party applications. Usually this means front and back cameras, but some devices have -dual back-facing cameras - in some cases the extra camera isn't made available to third party applications, so it isn't -possible for Open Camera to support them. Even where they are, since there is no current standard on what the extra -cameras are used for, it can't do anything with them other than allowing you to switch between them.

      +multiple front and/or back-facing cameras. Use the +Switch multi-camera iconswitch multi-camera icon +to switch between multiple front or back cameras. In some cases the extra cameras aren't made available to third party +applications, so it isn't possible for Open Camera to support them. Even where they are, since there is no current standard +on what the extra cameras are used for, it can't do anything with them other than allowing you to switch between them.

      Why doesn't Open Camera support the maximum video resolution on my device? - If you are using Camera2 API, make sure that you're not in slow motion mode (see "Speed" under diff --git a/_docs/history.html b/_docs/history.html index 21bd4e47d..5a9c55b2b 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -61,6 +61,11 @@ FIXED Recording video on Android 8+ could leave zero-size files if size approa filesize, but a restart did not occur. FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. +ADDED New icon for switching between multiple cameras. If your device has multiple front and/or + back cameras, then the existing icon to switch cameras will switch between the first front + and back camera; the new icon will instead cycle between the multiple front or back cameras. + If you prefer the old behaviour, then disable + Settings/On screen GUI/"Multiple cameras icon". ADDED Option to specify REC709 or sRGB profile for video recording. ADDED New custom gamma profile option for video recording. ADDED New option for alpha value to use for ghost image option. diff --git a/_docs/index.html b/_docs/index.html index 5eb810f2a..3a801c63d 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -212,6 +212,7 @@ Also see "Can I use the Open Camera source code in my app?" under the https://google.github.io/material-design-icons/, by Google, under Apache license version 2.0 (some cases include modifications, no need to credit me). In particular: + baseline_add_a_photo_white_48.png, baseline_bluetooth_white_48.png, baseline_check_white_48.png, baseline_close_white_48.png, baseline_filter_vintage_white_48.png, baseline_folder_open_white_48.png, baseline_highlight_white_48.png, diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 3b5715151..e4824960c 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -3187,6 +3187,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); if( !immersive_mode ) { assertTrue(exposureButton.getVisibility() == exposureVisibility); @@ -3576,6 +3581,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); + assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); @@ -4260,6 +4267,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); @@ -4546,6 +4556,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == exposureVisibility); assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); @@ -4577,6 +4589,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == exposureVisibility); assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); @@ -4611,7 +4625,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == exposureVisibility); assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); @@ -4627,6 +4642,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == exposureVisibility); assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); @@ -4669,6 +4686,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); @@ -4725,6 +4745,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == exposureVisibility); assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); @@ -4890,6 +4898,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); + assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); // store status to compare with later int exposureVisibility = exposureButton.getVisibility(); @@ -4933,6 +4943,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); @@ -5040,6 +5052,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); // flash and focus etc default visibility tested in another test // but store status to compare with later @@ -5087,6 +5101,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); @@ -5376,6 +5392,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); // flash and focus etc default visibility tested in another test // but store status to compare with later @@ -5433,7 +5451,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); @@ -5673,6 +5692,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); + assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); // but store status to compare with later int exposureVisibility = exposureButton.getVisibility(); @@ -5723,6 +5744,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); + assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); assertTrue(audioControlButton.getVisibility() == ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); } assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); @@ -7285,6 +7308,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); // flash and focus etc default visibility tested in another test // but store status to compare with later @@ -7320,6 +7345,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); @@ -8462,6 +8489,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == (mPreview.supportsExposures() ? View.VISIBLE : View.GONE)); assertTrue(exposureLockButton.getVisibility() == (mPreview.supportsExposureLock() ? View.VISIBLE : View.GONE)); @@ -8552,7 +8581,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == (mPreview.supportsExposures() ? View.VISIBLE : View.GONE)); assertTrue(exposureLockButton.getVisibility() == (mPreview.supportsExposureLock() ? View.VISIBLE : View.GONE)); @@ -11068,6 +11098,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == View.VISIBLE); assertTrue(exposureLockButton.getVisibility() == View.VISIBLE); @@ -11107,6 +11139,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); + assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); assertTrue(exposureButton.getVisibility() == View.VISIBLE); assertTrue(exposureLockButton.getVisibility() == View.VISIBLE); diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 27b7231e8..1a5662593 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -138,6 +138,16 @@ public class MainActivity extends Activity { public static volatile boolean test_preview_want_no_limits; // test flag, if set to true then instead use test_preview_want_no_limits_value; needs to be static, as it needs to be set before activity is created to take effect public static volatile boolean test_preview_want_no_limits_value; + // whether this is a multi-camera device (note, this isn't simply having more than 1 camera, but also having more than one with the same facing) + // note that in most cases, code should check the MultiCamButtonPreferenceKey preference as well as the is_multi_cam flag, + // this can be done via isMultiCamEnabled(). + private boolean is_multi_cam; + // These lists are lists of camera IDs with the same "facing" (front, back or external). + // Only initialised if is_multi_cam==true. + private List back_camera_ids; + private List front_camera_ids; + private List other_camera_ids; + private final ToastBoxer switch_video_toast = new ToastBoxer(); private final ToastBoxer screen_locked_toast = new ToastBoxer(); private final ToastBoxer stamp_toast = new ToastBoxer(); @@ -314,9 +324,61 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) Log.d(TAG, "onCreate: time after creating preview: " + (System.currentTimeMillis() - debug_time)); + // Setup multi-camera buttons (must be done after creating preview so we know which Camera API is being used, + // and before initialising on-screen visibility). + // We only allow the separate icon for switching cameras if: + // - there are at least 2 types of "facing" camera, and + // - there are at least 2 cameras with the same "facing". + // If there are multiple cameras but all with different "facing", then the switch camera + // icon is used to iterate over all cameras. + // If there are more than two cameras, but all cameras have the same "facing, we still stick + // with using the switch camera icon to iterate over all cameras. + int n_cameras = preview.getCameraControllerManager().getNumberOfCameras(); + if( n_cameras > 2 ) { + this.back_camera_ids = new ArrayList<>(); + this.front_camera_ids = new ArrayList<>(); + this.other_camera_ids = new ArrayList<>(); + for(int i=0;i= 2 || front_camera_ids.size() >= 2 || other_camera_ids.size() >= 2; + int n_facing = 0; + if( back_camera_ids.size() > 0 ) + n_facing++; + if( front_camera_ids.size() > 0 ) + n_facing++; + if( other_camera_ids.size() > 0 ) + n_facing++; + this.is_multi_cam = multi_same_facing && n_facing >= 2; + //this.is_multi_cam = false; // test + if( MyDebug.LOG ) { + Log.d(TAG, "multi_same_facing: " + multi_same_facing); + Log.d(TAG, "n_facing: " + n_facing); + Log.d(TAG, "is_multi_cam: " + is_multi_cam); + } + + if( !is_multi_cam ) { + this.back_camera_ids = null; + this.front_camera_ids = null; + this.other_camera_ids = null; + } + } + // initialise on-screen button visibility View switchCameraButton = findViewById(R.id.switch_camera); - switchCameraButton.setVisibility(preview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE); + switchCameraButton.setVisibility(n_cameras > 1 ? View.VISIBLE : View.GONE); + // switchMultiCameraButton visibility updated below in mainUI.updateOnScreenIcons(), as it also depends on user preference View speechRecognizerButton = findViewById(R.id.audio_control); speechRecognizerButton.setVisibility(View.GONE); // disabled by default, until the speech recognizer is created if( MyDebug.LOG ) @@ -614,6 +676,41 @@ public class MainActivity extends Activity { return want_no_limits ? navigation_gap : 0; } + /** Whether this is a multi camera device, and the user preference is set to enable the multi-camera button. + */ + public boolean isMultiCamEnabled() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + return is_multi_cam && sharedPreferences.getBoolean(PreferenceKeys.MultiCamButtonPreferenceKey, true); + } + + /** Whether the icon switch_multi_camera should be displayed. This is if the following are all + * true: + * - The device is a multi camera device (MainActivity.is_multi_cam==true). + * - The user preference for using the separate icons is enabled + * (PreferenceKeys.MultiCamButtonPreferenceKey). + * - For the current camera ID, there is only one camera with the same front/back/external + * "facing" (e.g., imagine a device with two back cameras, but only one front camera). + */ + public boolean showSwitchMultiCamIcon() { + if( isMultiCamEnabled() ) { + int cameraId = preview.getCameraId(); + switch( preview.getCameraControllerManager().getFacing(cameraId) ) { + case FACING_BACK: + if( back_camera_ids.size() > 0 ) + return true; + break; + case FACING_FRONT: + if( front_camera_ids.size() > 0 ) + return true; + break; + default: + if( other_camera_ids.size() > 0 ) + return true; + break; + } + } + return false; + } /* This method sets the preference defaults which are set specific for a particular device. * This method should be called when Open Camera is run for the very first time after installation, * or when the user has requested to "Reset settings". @@ -1473,6 +1570,8 @@ public class MainActivity extends Activity { } /* Returns the cameraId that the "Switch camera" button will switch to. + * Note that this may not necessarily be the next camera ID, on multi camera devices (if + * isMultiCamEnabled() returns true). */ public int getNextCameraId() { if( MyDebug.LOG ) @@ -1481,8 +1580,33 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) Log.d(TAG, "current cameraId: " + cameraId); if( this.preview.canSwitchCamera() ) { - int n_cameras = preview.getCameraControllerManager().getNumberOfCameras(); - cameraId = (cameraId+1) % n_cameras; + if( isMultiCamEnabled() ) { + // don't use preview.getCameraController(), as it may be null if user quickly switches between cameras + switch( preview.getCameraControllerManager().getFacing(cameraId) ) { + case FACING_BACK: + if( front_camera_ids.size() > 0 ) + cameraId = front_camera_ids.get(0); + else if( other_camera_ids.size() > 0 ) + cameraId = other_camera_ids.get(0); + break; + case FACING_FRONT: + if( other_camera_ids.size() > 0 ) + cameraId = other_camera_ids.get(0); + else if( back_camera_ids.size() > 0 ) + cameraId = back_camera_ids.get(0); + break; + default: + if( back_camera_ids.size() > 0 ) + cameraId = back_camera_ids.get(0); + else if( front_camera_ids.size() > 0 ) + cameraId = front_camera_ids.get(0); + break; + } + } + else { + int n_cameras = preview.getCameraControllerManager().getNumberOfCameras(); + cameraId = (cameraId+1) % n_cameras; + } } if( MyDebug.LOG ) Log.d(TAG, "next cameraId: " + cameraId); @@ -1509,11 +1633,15 @@ public class MainActivity extends Activity { if( MyDebug.LOG ) Log.d(TAG, "userSwitchToCamera: " + cameraId); View switchCameraButton = findViewById(R.id.switch_camera); - switchCameraButton.setEnabled(false); // prevent slowdown if user repeatedly clicks + View switchMultiCameraButton = findViewById(R.id.switch_multi_camera); + // prevent slowdown if user repeatedly clicks: + switchCameraButton.setEnabled(false); + switchMultiCameraButton.setEnabled(false); applicationInterface.reset(); this.preview.setCamera(cameraId); switchCameraButton.setEnabled(true); - // no need to call mainUI.setSwitchCameraContentDescription - this will be called from PreviewcameraSetup when the + switchMultiCameraButton.setEnabled(true); + // no need to call mainUI.setSwitchCameraContentDescription - this will be called from Preview.cameraSetup when the // new camera is opened } @@ -1532,9 +1660,62 @@ public class MainActivity extends Activity { this.closePopup(); if( this.preview.canSwitchCamera() ) { int cameraId = getNextCameraId(); + if( !isMultiCamEnabled() ) { + pushCameraIdToast(cameraId); + } + else { + // In multi-cam mode, no need to show the toast when just switching between front and back cameras. + // But it is useful to clear an active fake toast, otherwise have issue if the user uses + // clickedSwitchMultiCamera() (which displays a fake toast for the camera via the info toast), then + // immediately uses clickedSwitchCamera() - the toast for the wrong camera will still be lingering + // until it expires, which looks a bit strange. + // (If using non-fake toasts, this isn't an issue, at least on Android 10+, as now toasts seem to + // disappear when the user touches the screen anyway.) + preview.clearActiveFakeToast(); + } + userSwitchToCamera(cameraId); + } + } + public void clickedSwitchMultiCamera(View view) { + if( MyDebug.LOG ) + Log.d(TAG, "clickedSwitchMultiCamera"); + if( !isMultiCamEnabled() ) { + Log.e(TAG, "switch multi camera icon shouldn't have been visible"); + return; + } + if( preview.isOpeningCamera() ) { + if( MyDebug.LOG ) + Log.d(TAG, "already opening camera in background thread"); + return; + } + this.closePopup(); + if( this.preview.canSwitchCamera() ) { + List camera_set; + // don't use preview.getCameraController(), as it may be null if user quickly switches between cameras + switch( preview.getCameraControllerManager().getFacing(preview.getCameraId()) ) { + case FACING_BACK: + camera_set = back_camera_ids; + break; + case FACING_FRONT: + camera_set = front_camera_ids; + break; + default: + camera_set = other_camera_ids; + break; + } + int cameraId; + int indx = camera_set.indexOf(preview.getCameraId()); + if( indx == -1 ) { + Log.e(TAG, "camera id not in current camera set"); + // this shouldn't happen, but if it does, revert to the first camera id in the set + cameraId = camera_set.get(0); + } + else { + indx = (indx+1) % camera_set.size(); + cameraId = camera_set.get(indx); + } pushCameraIdToast(cameraId); - userSwitchToCamera(cameraId); } } @@ -1730,6 +1911,7 @@ public class MainActivity extends Activity { //case "preference_show_take_photo": // need to update the UI case "preference_show_toasts": case "preference_show_whats_new": + case "preference_multi_cam_button": case "preference_keep_display_on": case "preference_max_brightness": //case "preference_resolution": // need to set up camera controller and preview @@ -1865,6 +2047,7 @@ public class MainActivity extends Activity { bundle.putBoolean("supports_white_balance_temperature", this.preview.supportsWhiteBalanceTemperature()); bundle.putInt("white_balance_temperature_min", this.preview.getMinimumWhiteBalanceTemperature()); bundle.putInt("white_balance_temperature_max", this.preview.getMaximumWhiteBalanceTemperature()); + bundle.putBoolean("is_multi_cam", this.is_multi_cam); bundle.putBoolean("supports_optical_stabilization", this.preview.supportsOpticalStabilization()); bundle.putBoolean("optical_stabilization_enabled", this.preview.getOpticalStabilization()); bundle.putBoolean("supports_video_stabilization", this.preview.supportsVideoStabilization()); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 1d282e412..52308c75f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -476,6 +476,10 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared pg.removePreference(pref); } + final boolean is_multi_cam = bundle.getBoolean("is_multi_cam"); + if( MyDebug.LOG ) + Log.d(TAG, "is_multi_cam: " + is_multi_cam); + /* Set up video resolutions. Note that this will be the resolutions for either standard or high speed frame rate (where the latter may also include being in slow motion mode), depending on the current setting when @@ -606,6 +610,12 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared pg.removePreference(pref); } + if( !is_multi_cam ) { + Preference pref = findPreference("preference_multi_cam_button"); + PreferenceGroup pg = (PreferenceGroup)this.findPreference("preference_screen_gui"); + pg.removePreference(pref); + } + if( !supports_raw ) { Preference pref = findPreference("preference_show_cycle_raw"); PreferenceGroup pg = (PreferenceGroup)this.findPreference("preference_screen_gui"); @@ -1130,6 +1140,8 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared about_string.append(cameraId); about_string.append("\nNo. of cameras: "); about_string.append(nCameras); + about_string.append("\nMulti-camera?: "); + about_string.append(is_multi_cam); about_string.append("\nCamera API: "); about_string.append(camera_api); about_string.append("\nPhoto mode: "); diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index 777fd4a29..8f9e06a6f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -198,6 +198,8 @@ public class PreferenceKeys { return "preference_startup_focus"; } + public static final String MultiCamButtonPreferenceKey = "preference_multi_cam_button"; + public static String getKeepDisplayOnPreferenceKey() { return "preference_keep_display_on"; } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 44e2a9064..0dfa3826a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -448,6 +448,11 @@ public class MainUI { view.setLayoutParams(layoutParams); setViewRotation(view, ui_rotation); + view = main_activity.findViewById(R.id.switch_multi_camera); + layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); + view.setLayoutParams(layoutParams); + setViewRotation(view, ui_rotation); + view = main_activity.findViewById(R.id.pause_video); layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); layoutParams.addRule(align_parent_left, 0); @@ -947,6 +952,7 @@ public class MainUI { Log.d(TAG, "setImmersiveMode: set visibility: " + visibility); // n.b., don't hide share and trash buttons, as they require immediate user input for us to continue View switchCameraButton = main_activity.findViewById(R.id.switch_camera); + View switchMultiCameraButton = main_activity.findViewById(R.id.switch_multi_camera); View switchVideoButton = main_activity.findViewById(R.id.switch_video); View exposureButton = main_activity.findViewById(R.id.exposure); View exposureLockButton = main_activity.findViewById(R.id.exposure_lock); @@ -966,6 +972,8 @@ public class MainUI { View zoomSeekBar = main_activity.findViewById(R.id.zoom_seekbar); if( main_activity.getPreview().getCameraControllerManager().getNumberOfCameras() > 1 ) switchCameraButton.setVisibility(visibility); + if( main_activity.showSwitchMultiCamIcon() ) + switchMultiCameraButton.setVisibility(visibility); switchVideoButton.setVisibility(visibility); if( main_activity.supportsExposureButton() ) exposureButton.setVisibility(visibility); @@ -1062,6 +1070,7 @@ public class MainUI { final int visibility = is_panorama_recording ? View.GONE : (show_gui_photo && show_gui_video) ? View.VISIBLE : View.GONE; // for UI that is hidden while taking photo or video final int visibility_video = is_panorama_recording ? View.GONE : show_gui_photo ? View.VISIBLE : View.GONE; // for UI that is only hidden while taking photo View switchCameraButton = main_activity.findViewById(R.id.switch_camera); + View switchMultiCameraButton = main_activity.findViewById(R.id.switch_multi_camera); View switchVideoButton = main_activity.findViewById(R.id.switch_video); View exposureButton = main_activity.findViewById(R.id.exposure); View exposureLockButton = main_activity.findViewById(R.id.exposure_lock); @@ -1077,6 +1086,8 @@ public class MainUI { View popupButton = main_activity.findViewById(R.id.popup); if( main_activity.getPreview().getCameraControllerManager().getNumberOfCameras() > 1 ) switchCameraButton.setVisibility(visibility); + if( main_activity.showSwitchMultiCamIcon() ) + switchMultiCameraButton.setVisibility(visibility); switchVideoButton.setVisibility(visibility); if( main_activity.supportsExposureButton() ) exposureButton.setVisibility(visibility_video); // still allow exposure when recording video @@ -1227,6 +1238,9 @@ public class MainUI { this.updateAutoLevelIcon(); this.updateCycleFlashIcon(); this.updateFaceDetectionIcon(); + + View switchMultiCameraButton = main_activity.findViewById(R.id.switch_multi_camera); + switchMultiCameraButton.setVisibility(main_activity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE); } public void audioControlStarted() { diff --git a/app/src/main/res/drawable-hdpi/baseline_add_a_photo_white_48.png b/app/src/main/res/drawable-hdpi/baseline_add_a_photo_white_48.png new file mode 100644 index 0000000000000000000000000000000000000000..be070f73b6842e4b4d35fe3ef341291d9642601c GIT binary patch literal 583 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4B@p-y9hEy=Vy~4QURe{Ly zkIjh{5(yGc90GcJOoy0T9x}DHGcYx!?ge+g8Wi0O>1ih0AyE=b9~6l6Yf{f`xHLn1IYnQ#Fst zf6`bFO7DA^f8PD(=k5)Lj<3w`&k|)>y}N0};qS{>b!UrBG1KiZThSBZK6AeAf_TDx}f=Qc6jJsKkTvMxbLrR!;}zlQAV z1)`xxcJcc(eYjt{DSh^Weec{>oT_eK;8Ct8nfh%}M{d)#tMOt9I$c-PUi7T??q}Y< z#9|lk0W}V_MK6k%otWq#!o7QeaGc)D1E$edi(V9Mi zh0-)%7y1AHnSUIa;gbA{Pb*#i3ftVumS&N}!^$c_Et>rwoVy-O2-?2iBB)2M`qdZq q_`Ji9)ve#m^^ovheRb7E`%eqPC{e;9hRJPTocq&m-H=i3UNtTVN!F;CMZ;D zVs^s1@9Jg0e6wr*cJ+EcXi$HBBjVR47QM!qIlexc3)f`-c5vTjd%Wg^)dv16o1f0J ziQCqGjWKf9lg!lJ&!s99{b#%_ea%pQ^OD+m-)-#Q8pF1QbXq45?szdxJ5>DpBJ2 zNA`Aswub_3i4tv!EfQ@8Er|^RhXmRL_zoMi2(&RIaxn88Heiu(;%HZFasKh|KSO`s ztG#dTeXp=*`14`ut9OFuKVNEm#$40DUofBl1Ebvm_8FfUQ_wh9d5 zDlJF(8saW8-|Lp!pi#wO_aMMdLEA@1^5U~LE%iA8i#^*7?Oiz{1Oq3Bu*7`yd6egH zNZEZ8v!b$@9-Gg~6Z0${e?HH2LQP1SWzP=b4bS|H7MwoT+psLf<$7zwz9oxJF+0c2 zG+1zY=aNT9%MQ3~3s`hsi1%3uN6UZbyAD*D>3& z%}hC((NHz8<3_umfRm6l*;s z>XWP!+E#{dUH?SRVMSQ}45?MMrvDqbw@M|wa(tWriGN4f>S&+PtNZ5GJNU0Xr7|O; z>yXC(hW_SzYkw`;aK@fN>ly#im;8^e9B^~c{;XXUETUx1Slr|zzj&X9%*IW^3~za! zukvttESST3WJ++JE$9Bo-1!GqOt`__;P~q2w^kP3Yc@;g*3E1>%aGy8b?T1MlU~Vq zAIS>~R5Uvdlr_}3njezA!QWsJ&E$LS8}pZ)rx798TQGk;u^ODDh`M ze?dj{?5tyNjcx52I_fLGoU<`bI(1eenJ2Gfql4H9rbq?ult!HitX76doJ|hLm;yH( zvR|Fv_$O$c?u2-!+e|-QVWIn-r0H8BN>EoA-V&7m{l{#w>g z)!Q8ExVfKf-{kOPs`3QZO<*T2cyr?TBu+)=T`@(+By+3oe4fksez~kh>bVJR6$R(Q z#gIfBuOyp141w z>q$ey^iQl_k{*2=r$sdu=~^!K4w~j5t+$k+=#q%ke8mpC@-Q=bAPiX%w?8ik;l)0GBoXW+b z$v=r(tB2tV+ou@;6O{!Gnm4gE@#ppbddt)4P_M9GHN1#nR}I4ydw~Nz+fv+G`SKZ5 zd7cPM`pxx(=F8LjGK#E%vNqW-o71)N$ItRgFa2d|?THRQmzF#!=<%BWJg)C> z!<0>4J0?CZJSg(?Pqeb-0?!kZI*cMVKbTl-cuXR>$MBfM=gvRu)_0zE|6ibXk%57M N!PC{xWt~$(69D?~<0t?C literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_add_a_photo_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_add_a_photo_white_48.png new file mode 100644 index 0000000000000000000000000000000000000000..fbe202d967424bd09636f789d007451896d8f941 GIT binary patch literal 1498 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE694rhB3_q?e>0w}CUFhlJ7*fIb<{~2_0|N(> z!vFc}IQazh1Q-|^o^_oOR$yRc62L*+zbEUkZCxv)%zpuqqXr^J19-$84Mi49v?cA3 z=t`1k>rT{YOO(*-Qj%y}sL{4iL#{1Jqiqq0)%3slyG?}uBs2BrcjvulZ^-(4S$~d- z`n!iSKEE$k^UG|QvCLu#V}hsi9Y^K^P0kzrm}dxw#IRjpFxWcZfq6!+W;fe`rQ%Gy z53X%yD|qY3yrXO}W6bU=40%WAWHMaml#)8IR<)G(!L=r5e*F_4md`ePHdAjQTfzKA z-k!`mwk}xA7*oAy4db0z0T&t82~RO?i1wE{u(fY8!yj*5jZB8^yQB`Royk_9dxasd z)U+Y`ywriU8`%o7mods*W{^6-$h*L#fh|DFfmuUSs!Vt02Pc>5+)*-x2N-$J?RYY+ zBm7=uCWE!z%gc*YI5mpTDSPuyn9u(%(?gBL8{`>6d%XLgpoA*J9xcMz91_nJ9W384s7nYso&7Jip zA>Qb*AG3qM(E^|D4*z||%iSkWTH`lOC+ z{fups8XD>h`8@>;KI%I7XmEBgaCsHHif-@_`mp+j?`z4Qq6@U#<_Jt)uDVd-;s?zG z5j`t5s^k}cJKC|+o^jpL4n?y+V#-zjSXOj09={AIpp`!TdZqDb<9R?hVm~ z4|rz3N;404fW&OMqYcIKOlOWZXqD+|N{TNJ-z}e@!B(a)|7)qO%nwMOH%(8w-y6!c5cjj|R! z@b`RqJ;#Y{cla5;J71W;w8J(j=l7Rd%|+^LJsWg|nB&Uq4><7bIJ9k=gu%_f4Dv}1 zyt~7u^lpEtS8mVHQr3S^_g}s42gL)u5*G?9Y}dSZZ!kAhc)%R(mULvfJmZ3_e1ROp zKT;388@vsZdU*Sjj_kE(j62$4Wmx(9kwedq59$tQ=1E-C`;}Sa^g*4$#)IiycWtgc z^M0l^D>?-k^`9)&=geq`XH=NPGNsr{K+uE9?H_AHfRI4J`Ld)sPo<~_$qnJ2jb?_k zql%O|IcEHlWSBLHsq|P*l80~50_J^e70Y#2UU<~3bI)R0$chag%o%Jvy;w?SOgJ`U zGtYc0w)xBldQ%*FwcU=?q#xy$T{VfZ_Jb|M78T`h7K@Iu#wz_Pd0F5!cT>s{(F}$N zp)Te*0@(}$WHkJgXg`>F4jLOY*Gqy!<|kF9^b>5(V(N0HHq1&EoC`lgDC%-lVU4` z1e@7z#GKKd9-^w86=QtNhdJfLG2Vqs9Gat-F)U#G^zC4STO9@f z`5D85bcUsjCJmPuq#QCCAQ`;)rWp5?Xa6SU8an3YDcpXT9-ZBMe>hLl~OB!0>#uq-Y#_vzN-S;zK0>2`a?l67w3?&?=l z_omBgTvm2lyZzBLhnz*n9F%LaU0qze9A*~Jo3X*+;2d+Ms3|GBOQ!^RX~K!0Px2Mc XPS@!Dt-6YVfq}u()z4*}Q$iB}W@~G# literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b602e98e8..b5a02f493 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -39,6 +39,29 @@ android:backgroundTintMode="src_in" /> + + Switch to external camera Switch camera + Switch between multiple cameras + Multiple cameras icon + If enabled, use separate buttons to switch between front/back cameras, and to switch between multiple front/back facing cameras. If disabled, the Switch Camera icon will cycle through all cameras. diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 4c5bf4f2f..a02e095b6 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -680,6 +680,14 @@ android:defaultValue="true" /> + + + Date: Sat, 1 Feb 2020 20:09:39 +0000 Subject: [PATCH 107/243] Testing for new multiple camera behaviour. --- .../opencamera/test/MainActivityTest.java | 157 +++++++++++++++++- .../opencamera/test/PhotoTests.java | 2 + .../sourceforge/opencamera/MainActivity.java | 64 ++++--- 3 files changed, 190 insertions(+), 33 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index e4824960c..ec983e175 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -11,8 +11,10 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; import net.sourceforge.opencamera.MyPreferenceFragment; import net.sourceforge.opencamera.PanoramaProcessorException; @@ -4255,23 +4257,75 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 camera_ids) throws InterruptedException { + if( mActivity.showSwitchMultiCamIcon() ) { + int cameraId = mPreview.getCameraId(); + CameraController.Facing facing = mPreview.getCameraControllerManager().getFacing(cameraId); + + do { + Log.d(TAG, "testing multi cam button..."); + View switchMultiCameraButton = mActivity.findViewById(net.sourceforge.opencamera.R.id.switch_multi_camera); + clickView(switchMultiCameraButton); + waitUntilCameraOpened(); + + int new_cameraId = mPreview.getCameraId(); + Log.d(TAG, "multi cam button switched to " + new_cameraId); + Log.d(TAG, "camera_ids was: " + camera_ids); + assertTrue(new_cameraId != cameraId); + assertFalse(camera_ids.contains(new_cameraId)); + camera_ids.add(new_cameraId); + + CameraController.Facing new_facing = mPreview.getCameraControllerManager().getFacing(new_cameraId); + assertEquals(facing, new_facing); + + subTestTakePhoto(false, false, true, true, false, false, false, false); + } + while( mActivity.getNextMultiCameraId() != cameraId ); + } + } + + /** Tests taking a photo with multiple cameras. + * Also tests the content descriptions for switch camera button. + * And tests that we save the current camera when pausing and resuming. + * @param cycle_all_cameras If true, expect that the Switch Camera icon cycles through all + * cameras. + * @param test_multi_cam If true, also test cycling through cameras using the switch multi + * camera icon. If true, then cycle_all_cameras must be false. Should + * only be true on multi-camera devices. + */ + private void subTestTakePhotoMultiCameras(boolean cycle_all_cameras, boolean test_multi_cam) throws InterruptedException { + Log.d(TAG, "subTestTakePhotoMultiCameras"); int n_cameras = mPreview.getCameraControllerManager().getNumberOfCameras(); if( n_cameras <= 1 ) { return; } + + if( test_multi_cam ) { + assertFalse(cycle_all_cameras); + assertTrue(mActivity.isMultiCamEnabled()); + } + + int orig_cameraId = mPreview.getCameraId(); + Set camera_ids = new HashSet<>(); + camera_ids.add(orig_cameraId); + boolean done_front_test = false; - for(int i=0;i camera_set; + // don't use preview.getCameraController(), as it may be null if user quickly switches between cameras + switch( preview.getCameraControllerManager().getFacing(preview.getCameraId()) ) { + case FACING_BACK: + camera_set = back_camera_ids; + break; + case FACING_FRONT: + camera_set = front_camera_ids; + break; + default: + camera_set = other_camera_ids; + break; + } + int cameraId; + int indx = camera_set.indexOf(preview.getCameraId()); + if( indx == -1 ) { + Log.e(TAG, "camera id not in current camera set"); + // this shouldn't happen, but if it does, revert to the first camera id in the set + cameraId = camera_set.get(0); + } + else { + indx = (indx+1) % camera_set.size(); + cameraId = camera_set.get(indx); + } + if( MyDebug.LOG ) + Log.d(TAG, "next multi cameraId: " + cameraId); + return cameraId; + } + private void pushCameraIdToast(int cameraId) { if( MyDebug.LOG ) Log.d(TAG, "pushCameraIdToast: " + cameraId); @@ -1691,30 +1730,7 @@ public class MainActivity extends Activity { } this.closePopup(); if( this.preview.canSwitchCamera() ) { - List camera_set; - // don't use preview.getCameraController(), as it may be null if user quickly switches between cameras - switch( preview.getCameraControllerManager().getFacing(preview.getCameraId()) ) { - case FACING_BACK: - camera_set = back_camera_ids; - break; - case FACING_FRONT: - camera_set = front_camera_ids; - break; - default: - camera_set = other_camera_ids; - break; - } - int cameraId; - int indx = camera_set.indexOf(preview.getCameraId()); - if( indx == -1 ) { - Log.e(TAG, "camera id not in current camera set"); - // this shouldn't happen, but if it does, revert to the first camera id in the set - cameraId = camera_set.get(0); - } - else { - indx = (indx+1) % camera_set.size(); - cameraId = camera_set.get(indx); - } + int cameraId = getNextMultiCameraId(); pushCameraIdToast(cameraId); userSwitchToCamera(cameraId); } -- GitLab From 1a0a6c47a65978ce2ecf24ecad6390b5c8cd7084 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 19:21:59 +0000 Subject: [PATCH 108/243] Add documentation of toast_message parameter. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 549aeee23..c78aa2839 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -2278,6 +2278,9 @@ public class MainActivity extends Activity { /** Must be called when an settings (as stored in SharedPreferences) are made, so we can update the * camera, and make any other necessary changes. + * @param toast_message If non-null, display this toast instead of the usual camera "startup" toast + * that's shown in showPhotoVideoToast(). If non-null but an empty string, then + * this means no toast is shown at all. * @param keep_popup If false, the popup will be closed and destroyed. Set to true if you're sure * that the changed setting isn't one that requires the PopupView to be recreated */ -- GitLab From 72f8f4947955e4f713507641a09d9d6c5c137b3b Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 19:27:19 +0000 Subject: [PATCH 109/243] Make toasts for switching to/from manual ISO consistent with toasts when changing manual ISO/exposure. --- .../java/net/sourceforge/opencamera/preview/Preview.java | 2 +- app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 248843138..43255930a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -7304,7 +7304,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu showToast(clear_toast, message, 32, use_fake_toast); } - private void showToast(final String message, final int offset_y_dp, final boolean use_fake_toast) { + public void showToast(final String message, final int offset_y_dp, final boolean use_fake_toast) { showToast(null, message, offset_y_dp, use_fake_toast); } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 0dfa3826a..579890086 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -1719,7 +1719,8 @@ public class MainUI { // also reset exposure time when changing from manual to auto from the popup menu: editor.putLong(PreferenceKeys.ExposureTimePreferenceKey, CameraController.EXPOSURE_TIME_DEFAULT); editor.apply(); - main_activity.updateForSettings("ISO: " + toast_option); + preview.showToast("ISO: " + toast_option, 0, true); // supply offset_y_dp to be consistent with preview.setExposure(), preview.setISO() + main_activity.updateForSettings(""); // already showed the toast, so block from showing again } else if( old_iso.equals(CameraController.ISO_DEFAULT) ) { if( MyDebug.LOG ) @@ -1756,7 +1757,8 @@ public class MainUI { } editor.apply(); - main_activity.updateForSettings("ISO: " + toast_option); + preview.showToast("ISO: " + toast_option, 0, true); // supply offset_y_dp to be consistent with preview.setExposure(), preview.setISO() + main_activity.updateForSettings(""); // already showed the toast, so block from showing again } else { if( MyDebug.LOG ) -- GitLab From b541fc32f949014ae7d643ccd1ad6a85f5c97f98 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 20:24:06 +0000 Subject: [PATCH 110/243] Refactor code to showManualFocusSeekbar(). --- .../java/net/sourceforge/opencamera/MainActivity.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index c78aa2839..fe6261d04 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4189,12 +4189,17 @@ public class MainActivity extends Activity { setManualFocusSeekBarVisibility(is_target_distance); } - void setManualFocusSeekBarVisibility(final boolean is_target_distance) { - SeekBar focusSeekBar = findViewById(is_target_distance ? R.id.focus_bracketing_target_seekbar : R.id.focus_seekbar); + public boolean showManualFocusSeekbar(final boolean is_target_distance) { boolean is_visible = preview.getCurrentFocusValue() != null && this.getPreview().getCurrentFocusValue().equals("focus_mode_manual2"); if( is_target_distance ) { is_visible = is_visible && (applicationInterface.getPhotoMode() == MyApplicationInterface.PhotoMode.FocusBracketing) && !preview.isVideo(); } + return is_visible; + } + + void setManualFocusSeekBarVisibility(final boolean is_target_distance) { + boolean is_visible = showManualFocusSeekbar(is_target_distance); + SeekBar focusSeekBar = findViewById(is_target_distance ? R.id.focus_bracketing_target_seekbar : R.id.focus_seekbar); final int visibility = is_visible ? View.VISIBLE : View.GONE; focusSeekBar.setVisibility(visibility); } -- GitLab From 0f45fbce2e116c3437ea91e3dc6aba592fe3768e Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 20:24:35 +0000 Subject: [PATCH 111/243] Add comments. --- app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 579890086..31fab3fc1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -550,9 +550,11 @@ public class MainUI { // set seekbar info int width_dp; if( ui_rotation == 0 || ui_rotation == 180 ) { + // landscape width_dp = 350; } else { + // portrait width_dp = 250; // prevent being too large on smaller devices (e.g., Galaxy Nexus or smaller) int max_width_dp = getMaxHeightDp(true); -- GitLab From c615a595322795ed04a3ec6084270856569b4002 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 21:01:20 +0000 Subject: [PATCH 112/243] Add comments. --- app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 31fab3fc1..cfda4762d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -572,13 +572,17 @@ public class MainUI { setViewRotation(view, ui_rotation); view.setTranslationX(0.0f); view.setTranslationY(0.0f); + if( ui_rotation == 90 || ui_rotation == 270 ) { + // portrait view.setTranslationX(2*height_pixels); } else if( ui_rotation == 0 ) { + // landscape (or upside-down landscape if ui-left) view.setTranslationY(height_pixels); } else { + // upside-down landscape (or landscape if ui-left) view.setTranslationY(-1*height_pixels); } -- GitLab From 7f7ff4ced82a578b5ae86aad29b3d28033fa6fda Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 21:11:11 +0000 Subject: [PATCH 113/243] Improve background shading for seekbars, e.g., so exposure panel doesn't cover preview as much. --- app/src/main/res/values/colors.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 1eb90b97a..565681788 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,6 +1,6 @@ - #80000000 + #20000000 #20000000 #ff000000 -- GitLab From 5e5b2b145d4fe86b484bae401e51d24d58464486 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 21:35:59 +0000 Subject: [PATCH 114/243] Device specific fix for Samsung Galaxy devices and custom log/flat video profiles (problems with max white values if more than 32 control points). --- .../cameracontroller/CameraController2.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 2c3c85e81..709f53496 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -65,6 +65,7 @@ public class CameraController2 extends CameraController { private CameraDevice camera; private String cameraIdS; + private final boolean is_samsung; private final boolean is_samsung_s7; // Galaxy S7 or Galaxy S7 Edge private CameraCharacteristics characteristics; @@ -892,7 +893,17 @@ public class CameraController2 extends CameraController { // can be reproduced on at least OnePlus 3T and Galaxy S10e (although the exact behaviour of the // poor results is different on those devices) int n_values = tonemap_log_max_curve_points_c; + if( is_samsung ) { + // unfortunately odd bug on Samsung devices (at least S7 and S10e) where if more than 32 control points, + // the maximum brightness value is reduced (can best be seen with 64 points, and using gamma==1.0) + // note that Samsung devices also need at least 16 control points + // we choose 32 rather than 16, as better to have more points for finer curve where possible + n_values = 32; + } //int n_values = test_new ? 32 : 128; + //int n_values = 32; + if( MyDebug.LOG ) + Log.d(TAG, "n_values: " + n_values); values = new float [2*n_values]; for(int i=0;i= 2*min_points_c ) { if( MyDebug.LOG ) Log.d(TAG, "already enough points"); -- GitLab From 0b8a3764755330e0034e9a954b9cc41180912318 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 2 Feb 2020 22:43:42 +0000 Subject: [PATCH 115/243] Remove unused import. --- app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index f6292f8f3..b7b4b67d9 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -43,7 +43,6 @@ import android.net.Uri; import android.os.BatteryManager; import android.os.Build; import android.preference.PreferenceManager; -import android.provider.MediaStore; import android.util.Log; import android.util.Pair; import android.view.Display; -- GitLab From 4e674107de53b5af4598165c7875d945dc00500a Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 13:29:03 +0000 Subject: [PATCH 116/243] Update version name to 1.48wip. --- app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e2f60d5d1..fff3ff15f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ -- GitLab From 06694be0bfc878c857d5ebf818168c4321f3c359 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 13:31:04 +0000 Subject: [PATCH 117/243] More video profiles; further tweaks for video profiles for Samsung Galaxy devices. --- .../sourceforge/opencamera/MainActivity.java | 14 +- .../opencamera/MyApplicationInterface.java | 18 +- .../cameracontroller/CameraController.java | 6 +- .../cameracontroller/CameraController2.java | 179 ++++++++++++++++-- app/src/main/res/values/arrays.xml | 10 +- app/src/main/res/values/strings.xml | 4 + 6 files changed, 211 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index fe6261d04..9bbf538ac 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4505,8 +4505,20 @@ public class MainActivity extends Activity { case TONEMAPPROFILE_JTLOG: string_id = R.string.preference_video_jtlog; break; - case TONEMAPPROFILE_JTLNP1: + case TONEMAPPROFILE_JTLOGV2: + string_id = R.string.preference_video_jtlogv2; + break; + case TONEMAPPROFILE_JTLOGV3: + string_id = R.string.preference_video_jtlogv3; + break; + /*case TONEMAPPROFILE_JTLNP1: string_id = R.string.preference_video_jtlnp1; + break;*/ + case TONEMAPPROFILE_JTLIN1: + string_id = R.string.preference_video_jtlin1; + break; + case TONEMAPPROFILE_JTLIN2: + string_id = R.string.preference_video_jtlin2; break; } if( string_id != 0 ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 9421faa75..ace4501e4 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -757,8 +757,16 @@ public class MyApplicationInterface extends BasicApplicationInterface { return CameraController.TonemapProfile.TONEMAPPROFILE_GAMMA; case "jtlog": return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOG; - case "jtlnp1": - return CameraController.TonemapProfile.TONEMAPPROFILE_JTLNP1; + case "jtlogv2": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOGV2; + case "jtlogv3": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOGV3; + /*case "jtlnp1": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLNP1;*/ + case "jtlin1": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLIN1; + case "jtlin2": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLIN2; } return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; } @@ -773,7 +781,11 @@ public class MyApplicationInterface extends BasicApplicationInterface { case "srgb": case "gamma": case "jtlog": - case "jtlnp1": + case "jtlogv2": + case "jtlogv3": + //case "jtlnp1": + case "jtlin1": + case "jtlin2": return 0.0f; /*case "fine": return 1.0f; diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 3d0785e40..546f5b4bf 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -455,7 +455,11 @@ public abstract class CameraController { TONEMAPPROFILE_LOG, TONEMAPPROFILE_GAMMA, TONEMAPPROFILE_JTLOG, - TONEMAPPROFILE_JTLNP1 + TONEMAPPROFILE_JTLOGV2, + TONEMAPPROFILE_JTLOGV3, + //TONEMAPPROFILE_JTLNP1 + TONEMAPPROFILE_JTLIN1, + TONEMAPPROFILE_JTLIN2 } /** Sets a tonemap profile. diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 709f53496..b9fa1a969 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -91,11 +91,130 @@ public class CameraController2 extends CameraController { 0.7180f, 0.9057f, 0.7430f, 0.9145f, 1.0000f, 1.0000f }; private final float [] jtlog_values; - private final static float [] jtlnp1_values_base = new float[] { + private final static float [] jtlogv2_values_base = new float[] { + 0.0000f, 0.0000f, + 0.0070f, 0.0700f, + 0.0140f, 0.1400f, + 0.0230f, 0.2295f, + 0.0280f, 0.2783f, + 0.0369f, 0.3321f, + 0.0500f, 0.3844f, + 0.0680f, 0.4351f, + 0.0930f, 0.4870f, + 0.1180f, 0.5275f, + 0.1430f, 0.5612f, + 0.1680f, 0.5904f, + 0.1930f, 0.6162f, + 0.2180f, 0.6395f, + 0.2430f, 0.6608f, + 0.2680f, 0.6804f, + 0.2930f, 0.6986f, + 0.3430f, 0.7318f, + 0.3930f, 0.7615f, + 0.4430f, 0.7885f, + 0.4930f, 0.8132f, + 0.5430f, 0.8361f, + 0.5930f, 0.8575f, + 0.6430f, 0.8776f, + 0.6930f, 0.8966f, + 0.7430f, 0.9145f, + 0.8000f, 0.9330f, + 0.8500f, 0.9500f, + 0.9000f, 0.9670f, + 0.9700f, 0.9900f, + 1.00f, 1.00f, + }; + private final float [] jtlogv2_values; + private final static float [] jtlogv3_values_base = new float[] { + 0.0000f, 0.0000f, + 0.0020f, 0.0400f, + 0.0130f, 0.1500f, + 0.0220f, 0.2295f, + 0.0280f, 0.2783f, + 0.0369f, 0.3321f, + 0.0500f, 0.3844f, + 0.0680f, 0.4351f, + 0.0930f, 0.4870f, + 0.1180f, 0.5275f, + 0.1430f, 0.5612f, + 0.1680f, 0.5904f, + 0.1930f, 0.6162f, + 0.2180f, 0.6395f, + 0.2430f, 0.6608f, + 0.2680f, 0.6804f, + 0.2930f, 0.6986f, + 0.3430f, 0.7318f, + 0.3930f, 0.7615f, + 0.4430f, 0.7885f, + 0.4930f, 0.8132f, + 0.5430f, 0.8361f, + 0.5930f, 0.8575f, + 0.6430f, 0.8750f, + 0.6930f, 0.8930f, + 0.740f, 0.908f, + 0.8000f, 0.9230f, + 0.8600f, 0.9380f, + 0.9200f, 0.9535f, + 0.9900f, 0.9700f, + 1.00f, 1.00f, + }; + private final float [] jtlogv3_values; + /*private final static float [] jtlnp1_values_base = new float[] { 0.0f, 0.0f, 0.01f, 0.06f, 0.02f, 0.1f, 0.03f, 0.13f, 0.1f, 0.27f, 0.73f, 0.9f, 0.79f, 0.93f, 0.84f, 0.95f, 1.0f, 1.0f }; - private final float [] jtlnp1_values; + private final float [] jtlnp1_values;*/ + private final static float [] jtlin1_values_base = new float[] { + 0.000f, 0.000f, + 0.010f, 0.070f, + 0.020f, 0.120f, + 0.040f, 0.180f, + 0.080f, 0.260f, + 0.110f, 0.320f, + 0.160f, 0.370f, + 0.210f, 0.420f, + 0.260f, 0.470f, + 0.310f, 0.520f, + 0.360f, 0.570f, + 0.410f, 0.620f, + 0.460f, 0.670f, + 0.510f, 0.720f, + 0.565f, 0.770f, + 0.600f, 0.800f, + 0.660f, 0.840f, + 0.700f, 0.860f, + 0.740f, 0.880f, + 0.780f, 0.900f, + 0.860f, 0.940f, + 0.930f, 0.970f, + 1.000f, 1.000f, + }; + private final float [] jtlin1_values; + private final static float [] jtlin2_values_base = new float[] { + 0.000f, 0.000f, + 0.007f, 0.080f, + 0.012f, 0.140f, + 0.040f, 0.260f, + 0.100f, 0.380f, + 0.150f, 0.430f, + 0.200f, 0.480f, + 0.250f, 0.530f, + 0.300f, 0.580f, + 0.350f, 0.630f, + 0.400f, 0.680f, + 0.450f, 0.730f, + 0.490f, 0.770f, + 0.530f, 0.790f, + 0.570f, 0.810f, + 0.610f, 0.830f, + 0.680f, 0.860f, + 0.750f, 0.890f, + 0.800f, 0.910f, + 0.900f, 0.950f, + 0.990f, 0.980f, + 1.000f, 1.000f, + }; + private final float [] jtlin2_values; private final ErrorCallback preview_error_cb; private final ErrorCallback camera_error_cb; @@ -896,8 +1015,9 @@ public class CameraController2 extends CameraController { if( is_samsung ) { // unfortunately odd bug on Samsung devices (at least S7 and S10e) where if more than 32 control points, // the maximum brightness value is reduced (can best be seen with 64 points, and using gamma==1.0) - // note that Samsung devices also need at least 16 control points - // we choose 32 rather than 16, as better to have more points for finer curve where possible + // note that Samsung devices also need at least 16 control points - or in some cases 32, see comments for + // enforceMinTonemapCurvePoints(). + // 32 is better than 16 anyway, as better to have more points for finer curve where possible. n_values = 32; } //int n_values = test_new ? 32 : 128; @@ -1000,10 +1120,30 @@ public class CameraController2 extends CameraController { if( MyDebug.LOG ) Log.d(TAG, "setting JTLog profile"); break; - case TONEMAPPROFILE_JTLNP1: + case TONEMAPPROFILE_JTLOGV2: + values = jtlogv2_values; + if( MyDebug.LOG ) + Log.d(TAG, "setting JTLogv2 profile"); + break; + case TONEMAPPROFILE_JTLOGV3: + values = jtlogv3_values; + if( MyDebug.LOG ) + Log.d(TAG, "setting JTLogv3 profile"); + break; + /*case TONEMAPPROFILE_JTLNP1: values = jtlnp1_values; if( MyDebug.LOG ) Log.d(TAG, "setting JTLNP1 profile"); + break;*/ + case TONEMAPPROFILE_JTLIN1: + values = jtlin1_values; + if( MyDebug.LOG ) + Log.d(TAG, "setting JTLin1 profile"); + break; + case TONEMAPPROFILE_JTLIN2: + values = jtlin2_values; + if( MyDebug.LOG ) + Log.d(TAG, "setting JTLin2 profile"); break; } @@ -1961,7 +2101,11 @@ public class CameraController2 extends CameraController { // expand tonemap curves jtlog_values = enforceMinTonemapCurvePoints(jtlog_values_base); - jtlnp1_values = enforceMinTonemapCurvePoints(jtlnp1_values_base); + jtlogv2_values = enforceMinTonemapCurvePoints(jtlogv2_values_base); + jtlogv3_values = enforceMinTonemapCurvePoints(jtlogv3_values_base); + //jtlnp1_values = enforceMinTonemapCurvePoints(jtlnp1_values_base); + jtlin1_values = enforceMinTonemapCurvePoints(jtlin1_values_base); + jtlin2_values = enforceMinTonemapCurvePoints(jtlin2_values_base); } @Override @@ -2002,7 +2146,7 @@ public class CameraController2 extends CameraController { } /** Enforce a minimum number of points in tonemap curves - needed due to Galaxy S10e having wrong behaviour if fewer - * than 16 points?! OnePlus 3T meanwhile has more gradual behaviour where it gets better at 64 points. + * than 16 or in some cases 32 points?! OnePlus 3T meanwhile has more gradual behaviour where it gets better at 64 points. */ private float [] enforceMinTonemapCurvePoints(float[] in_values) { if( MyDebug.LOG ) { @@ -2011,11 +2155,12 @@ public class CameraController2 extends CameraController { } int min_points_c = 64; if( is_samsung ) { - // unfortunately odd bug on Samsung devices (at least S7 and S10e) where if more than 32 control points, - // the maximum brightness value is reduced (can best be seen with 64 points, and using gamma==1.0) - // note that Samsung devices also need at least 16 control points - // So choose 16 for simplicity (seems to be no benefit to using 32 over 16, unlike OnePlus 3T devices as noted above) - min_points_c = 16; + // Unfortunately odd bug on Samsung devices (at least S7 and S10e) where if more than 32 control points, + // the maximum brightness value is reduced (can best be seen with 64 points, and using gamma==1.0). + // Also note that Samsung devices also need at least 16 control points, or in some cases 32, due to problem + // where things come out almost all black with some white. So choose 32! + //min_points_c = 16; + min_points_c = 32; } if( MyDebug.LOG ) Log.d(TAG, "min_points_c: " + min_points_c); @@ -2029,6 +2174,10 @@ public class CameraController2 extends CameraController { Pair point = new Pair<>(in_values[2*i], in_values[2*i+1]); points.add(point); } + if( points.size() < 2 ) { + Log.e(TAG, "less than 2 points?!"); + return in_values; + } while( points.size() < min_points_c ) { // find largest interval, and subdivide @@ -2601,7 +2750,11 @@ public class CameraController2 extends CameraController { camera_features.supports_tonemap_curve = tonemap_max_curve_points >= tonemap_log_max_curve_points_c && tonemap_max_curve_points >= jtlog_values.length && - tonemap_max_curve_points >= jtlnp1_values.length; + tonemap_max_curve_points >= jtlogv2_values.length && + tonemap_max_curve_points >= jtlogv3_values.length && + //tonemap_max_curve_points >= jtlnp1_values.length; + tonemap_max_curve_points >= jtlin1_values.length && + tonemap_max_curve_points >= jtlin2_values.length; } else { if( MyDebug.LOG ) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 5124f9163..6957af508 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -556,7 +556,10 @@ @string/preference_video_log_extra_strong @string/preference_video_gamma @string/preference_video_jtlog - @string/preference_video_jtlnp1 + @string/preference_video_jtlogv2 + @string/preference_video_jtlogv3 + @string/preference_video_jtlin1 + @string/preference_video_jtlin2 off @@ -569,7 +572,10 @@ extra_strong gamma jtlog - jtlnp1 + jtlogv2 + jtlogv3 + jtlin1 + jtlin2 @string/preference_video_profile_gamma_1.0 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4d16c6d43..496c08969 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -919,7 +919,11 @@ sRGB Gamma JTLog + JTLogv2 + JTLogv3 JTLNP1 + JTLin1 + JTLin2 Video gamma value Gamma value to use for video if video picture profile is set to Gamma\n%s 1.0 -- GitLab From c58df496793a80984f79cbabfd8c6b4e3e8bc711 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 13:31:17 +0000 Subject: [PATCH 118/243] Update copyright to 2020. --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 496c08969..7d24f0221 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -999,7 +999,7 @@ Open Source licences Open Camera - Open Camera is © 2013–2019 Mark Harman, released under the GPL v3 or later. Tap here for full licence text and terms of service. + Open Camera is © 2013–2020 Mark Harman, released under the GPL v3 or later. Tap here for full licence text and terms of service. Google\'s Material Design icons Open Camera uses icons from Google\'s Material Design icons (https://developer.android.com/design/downloads/index.html , -- GitLab From 245149595ee3fe00f309ef1b4d3f552aea7a918c Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 13:32:49 +0000 Subject: [PATCH 119/243] Convert tabs to spaces. --- .../cameracontroller/CameraController2.java | 214 +++++++++--------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index b9fa1a969..1d3ba7276 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -92,71 +92,71 @@ public class CameraController2 extends CameraController { }; private final float [] jtlog_values; private final static float [] jtlogv2_values_base = new float[] { - 0.0000f, 0.0000f, - 0.0070f, 0.0700f, - 0.0140f, 0.1400f, - 0.0230f, 0.2295f, - 0.0280f, 0.2783f, - 0.0369f, 0.3321f, - 0.0500f, 0.3844f, - 0.0680f, 0.4351f, - 0.0930f, 0.4870f, - 0.1180f, 0.5275f, - 0.1430f, 0.5612f, - 0.1680f, 0.5904f, - 0.1930f, 0.6162f, - 0.2180f, 0.6395f, - 0.2430f, 0.6608f, - 0.2680f, 0.6804f, - 0.2930f, 0.6986f, - 0.3430f, 0.7318f, - 0.3930f, 0.7615f, - 0.4430f, 0.7885f, - 0.4930f, 0.8132f, - 0.5430f, 0.8361f, - 0.5930f, 0.8575f, - 0.6430f, 0.8776f, - 0.6930f, 0.8966f, - 0.7430f, 0.9145f, - 0.8000f, 0.9330f, - 0.8500f, 0.9500f, - 0.9000f, 0.9670f, - 0.9700f, 0.9900f, - 1.00f, 1.00f, + 0.0000f, 0.0000f, + 0.0070f, 0.0700f, + 0.0140f, 0.1400f, + 0.0230f, 0.2295f, + 0.0280f, 0.2783f, + 0.0369f, 0.3321f, + 0.0500f, 0.3844f, + 0.0680f, 0.4351f, + 0.0930f, 0.4870f, + 0.1180f, 0.5275f, + 0.1430f, 0.5612f, + 0.1680f, 0.5904f, + 0.1930f, 0.6162f, + 0.2180f, 0.6395f, + 0.2430f, 0.6608f, + 0.2680f, 0.6804f, + 0.2930f, 0.6986f, + 0.3430f, 0.7318f, + 0.3930f, 0.7615f, + 0.4430f, 0.7885f, + 0.4930f, 0.8132f, + 0.5430f, 0.8361f, + 0.5930f, 0.8575f, + 0.6430f, 0.8776f, + 0.6930f, 0.8966f, + 0.7430f, 0.9145f, + 0.8000f, 0.9330f, + 0.8500f, 0.9500f, + 0.9000f, 0.9670f, + 0.9700f, 0.9900f, + 1.00f, 1.00f, }; private final float [] jtlogv2_values; private final static float [] jtlogv3_values_base = new float[] { - 0.0000f, 0.0000f, - 0.0020f, 0.0400f, - 0.0130f, 0.1500f, - 0.0220f, 0.2295f, - 0.0280f, 0.2783f, - 0.0369f, 0.3321f, - 0.0500f, 0.3844f, - 0.0680f, 0.4351f, - 0.0930f, 0.4870f, - 0.1180f, 0.5275f, - 0.1430f, 0.5612f, - 0.1680f, 0.5904f, - 0.1930f, 0.6162f, - 0.2180f, 0.6395f, - 0.2430f, 0.6608f, - 0.2680f, 0.6804f, - 0.2930f, 0.6986f, - 0.3430f, 0.7318f, - 0.3930f, 0.7615f, - 0.4430f, 0.7885f, - 0.4930f, 0.8132f, - 0.5430f, 0.8361f, - 0.5930f, 0.8575f, - 0.6430f, 0.8750f, - 0.6930f, 0.8930f, - 0.740f, 0.908f, - 0.8000f, 0.9230f, - 0.8600f, 0.9380f, - 0.9200f, 0.9535f, - 0.9900f, 0.9700f, - 1.00f, 1.00f, + 0.0000f, 0.0000f, + 0.0020f, 0.0400f, + 0.0130f, 0.1500f, + 0.0220f, 0.2295f, + 0.0280f, 0.2783f, + 0.0369f, 0.3321f, + 0.0500f, 0.3844f, + 0.0680f, 0.4351f, + 0.0930f, 0.4870f, + 0.1180f, 0.5275f, + 0.1430f, 0.5612f, + 0.1680f, 0.5904f, + 0.1930f, 0.6162f, + 0.2180f, 0.6395f, + 0.2430f, 0.6608f, + 0.2680f, 0.6804f, + 0.2930f, 0.6986f, + 0.3430f, 0.7318f, + 0.3930f, 0.7615f, + 0.4430f, 0.7885f, + 0.4930f, 0.8132f, + 0.5430f, 0.8361f, + 0.5930f, 0.8575f, + 0.6430f, 0.8750f, + 0.6930f, 0.8930f, + 0.740f, 0.908f, + 0.8000f, 0.9230f, + 0.8600f, 0.9380f, + 0.9200f, 0.9535f, + 0.9900f, 0.9700f, + 1.00f, 1.00f, }; private final float [] jtlogv3_values; /*private final static float [] jtlnp1_values_base = new float[] { @@ -165,54 +165,54 @@ public class CameraController2 extends CameraController { }; private final float [] jtlnp1_values;*/ private final static float [] jtlin1_values_base = new float[] { - 0.000f, 0.000f, - 0.010f, 0.070f, - 0.020f, 0.120f, - 0.040f, 0.180f, - 0.080f, 0.260f, - 0.110f, 0.320f, - 0.160f, 0.370f, - 0.210f, 0.420f, - 0.260f, 0.470f, - 0.310f, 0.520f, - 0.360f, 0.570f, - 0.410f, 0.620f, - 0.460f, 0.670f, - 0.510f, 0.720f, - 0.565f, 0.770f, - 0.600f, 0.800f, - 0.660f, 0.840f, - 0.700f, 0.860f, - 0.740f, 0.880f, - 0.780f, 0.900f, - 0.860f, 0.940f, - 0.930f, 0.970f, - 1.000f, 1.000f, + 0.000f, 0.000f, + 0.010f, 0.070f, + 0.020f, 0.120f, + 0.040f, 0.180f, + 0.080f, 0.260f, + 0.110f, 0.320f, + 0.160f, 0.370f, + 0.210f, 0.420f, + 0.260f, 0.470f, + 0.310f, 0.520f, + 0.360f, 0.570f, + 0.410f, 0.620f, + 0.460f, 0.670f, + 0.510f, 0.720f, + 0.565f, 0.770f, + 0.600f, 0.800f, + 0.660f, 0.840f, + 0.700f, 0.860f, + 0.740f, 0.880f, + 0.780f, 0.900f, + 0.860f, 0.940f, + 0.930f, 0.970f, + 1.000f, 1.000f, }; private final float [] jtlin1_values; private final static float [] jtlin2_values_base = new float[] { - 0.000f, 0.000f, - 0.007f, 0.080f, - 0.012f, 0.140f, - 0.040f, 0.260f, - 0.100f, 0.380f, - 0.150f, 0.430f, - 0.200f, 0.480f, - 0.250f, 0.530f, - 0.300f, 0.580f, - 0.350f, 0.630f, - 0.400f, 0.680f, - 0.450f, 0.730f, - 0.490f, 0.770f, - 0.530f, 0.790f, - 0.570f, 0.810f, - 0.610f, 0.830f, - 0.680f, 0.860f, - 0.750f, 0.890f, - 0.800f, 0.910f, - 0.900f, 0.950f, - 0.990f, 0.980f, - 1.000f, 1.000f, + 0.000f, 0.000f, + 0.007f, 0.080f, + 0.012f, 0.140f, + 0.040f, 0.260f, + 0.100f, 0.380f, + 0.150f, 0.430f, + 0.200f, 0.480f, + 0.250f, 0.530f, + 0.300f, 0.580f, + 0.350f, 0.630f, + 0.400f, 0.680f, + 0.450f, 0.730f, + 0.490f, 0.770f, + 0.530f, 0.790f, + 0.570f, 0.810f, + 0.610f, 0.830f, + 0.680f, 0.860f, + 0.750f, 0.890f, + 0.800f, 0.910f, + 0.900f, 0.950f, + 0.990f, 0.980f, + 1.000f, 1.000f, }; private final float [] jtlin2_values; -- GitLab From b4f6acbcdb434c25de7dd2567db8f96161f86cee Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 13:48:52 +0000 Subject: [PATCH 120/243] Add extra point to jtlogv3. --- .../opencamera/cameracontroller/CameraController2.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 1d3ba7276..ecf2f0c67 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -155,6 +155,7 @@ public class CameraController2 extends CameraController { 0.8000f, 0.9230f, 0.8600f, 0.9380f, 0.9200f, 0.9535f, + 0.9500f, 0.9600f, 0.9900f, 0.9700f, 1.00f, 1.00f, }; -- GitLab From 32b61ae5a76830c87d0d0f63c38f33d1d61796d3 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 16:18:09 +0000 Subject: [PATCH 121/243] Reduce delay again in updating text positions, due to caching getLocationOnScreen() results. --- .../net/sourceforge/opencamera/ui/MainUI.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index cfda4762d..cadf7e3a4 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -19,6 +19,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.media.AudioManager; import android.os.Build; +import android.os.Handler; import android.preference.PreferenceManager; import android.util.DisplayMetrics; import android.util.Log; @@ -65,6 +66,7 @@ public class MainUI { private UIPlacement ui_placement = UIPlacement.UIPLACEMENT_RIGHT; private View top_icon = null; private boolean view_rotate_animation; + private final static int view_rotate_animation_duration = 100; // duration in ms of the icon rotation animation private boolean immersive_mode; private boolean show_gui_photo = true; // result of call to showGUI() - false means a "reduced" GUI is displayed, whilst taking photo or video @@ -151,7 +153,7 @@ public class MainUI { rotate_by += 360.0f; // view.animate() modifies the view's rotation attribute, so it ends up equivalent to view.setRotation() // we use rotationBy() instead of rotation(), so we get the minimal rotation for clockwise vs anti-clockwise - view.animate().rotationBy(rotate_by).setDuration(100).setInterpolator(new AccelerateDecelerateInterpolator()).start(); + view.animate().rotationBy(rotate_by).setDuration(view_rotate_animation_duration).setInterpolator(new AccelerateDecelerateInterpolator()).start(); } public void layoutUI() { @@ -578,11 +580,11 @@ public class MainUI { view.setTranslationX(2*height_pixels); } else if( ui_rotation == 0 ) { - // landscape (or upside-down landscape if ui-left) + // landscape view.setTranslationY(height_pixels); } else { - // upside-down landscape (or landscape if ui-left) + // upside-down landscape view.setTranslationY(-1*height_pixels); } @@ -881,6 +883,26 @@ public class MainUI { view_rotate_animation = true; layoutUI(); view_rotate_animation = false; + + // Call DrawPreview.updateSettings() so that we reset calculations that depend on + // getLocationOnScreen() - since the result is affected by a View's rotation, we need + // to recompute - this also means we need to delay slightly until after the rotation + // animation is complete. + // To reproduce issues, rotate from upside-down-landscape to portrait, and observe + // the info-text placement (when using icons-along-top), or with on-screen angle + // displayed when in 16:9 preview. + // Potentially we could use Animation.setAnimationListener(), but we set a separate + // animation for every icon. + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + if( MyDebug.LOG ) + Log.d(TAG, "onOrientationChanged->postDelayed()"); + + main_activity.getApplicationInterface().getDrawPreview().updateSettings(); + } + }, view_rotate_animation_duration+20); } } } -- GitLab From 44f783c538e054047ef24a54a762921d8f971aa2 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 16:18:29 +0000 Subject: [PATCH 122/243] Add commented out logging. --- .../net/sourceforge/opencamera/ui/DrawPreview.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index b7b4b67d9..51c45df23 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -1633,6 +1633,11 @@ public class DrawPreview { take_photo_top = view_left - this_left; last_take_photo_top_time = time_ms; + /*if( MyDebug.LOG ) { + Log.d(TAG, "view_left: " + view_left); + Log.d(TAG, "this_left: " + this_left); + Log.d(TAG, "take_photo_top: " + take_photo_top); + }*/ } // diff_x is the difference from the centre of the canvas to the position we want @@ -1927,6 +1932,11 @@ public class DrawPreview { preview.getView().getLocationOnScreen(gui_location); int preview_left = gui_location[0]; this.top_icon_shift = top_margin - preview_left; + /*if( MyDebug.LOG ) { + Log.d(TAG, "preview_left: " + preview_left); + Log.d(TAG, "top_margin: " + top_margin); + Log.d(TAG, "top_icon_shift: " + top_icon_shift); + }*/ last_top_icon_shift_time = time_ms; } -- GitLab From b77c1fa00611c1e2c62f3f37c8628f9f011d9436 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 16:47:40 +0000 Subject: [PATCH 123/243] Incorrect layout for on-screen text when using "icons along top" with wide-screen aspect ratio and device held in upside-down landscape orientation. --- _docs/history.html | 2 ++ .../net/sourceforge/opencamera/ui/DrawPreview.java | 12 ++++++++++++ .../java/net/sourceforge/opencamera/ui/MainUI.java | 3 +++ 3 files changed, 17 insertions(+) diff --git a/_docs/history.html b/_docs/history.html index 5a9c55b2b..0ba56eab4 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -61,6 +61,8 @@ FIXED Recording video on Android 8+ could leave zero-size files if size approa filesize, but a restart did not occur. FIXED Problem of on-screen level angle overlapping with shutter icon when using a widescreen preview aspect ratio. +FIXED Incorrect layout for on-screen text when using "icons along top" with wide-screen aspect + ratio and device held in upside-down landscape orientation. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 51c45df23..7ec26a4bd 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -1628,6 +1628,11 @@ public class DrawPreview { // align with "top" of the take_photo button, but remember to take the rotation into account! view.getLocationOnScreen(gui_location); int view_left = gui_location[0]; + if( view.getRotation() == 180.0f ) { + // annoying behaviour that getLocationOnScreen takes the rotation into account, at least when + // entirely upside down + view_left -= view.getWidth(); + } preview.getView().getLocationOnScreen(gui_location); int this_left = gui_location[0]; take_photo_top = view_left - this_left; @@ -1929,6 +1934,11 @@ public class DrawPreview { Log.d(TAG, "update cached top_icon_shift");*/ top_icon.getLocationOnScreen(gui_location); int top_margin = gui_location[0] + top_icon.getWidth(); + if( top_icon.getRotation() == 180.0f ) { + // annoying behaviour that getLocationOnScreen takes the rotation into account, at least when + // entirely upside down + top_margin -= top_icon.getWidth(); + } preview.getView().getLocationOnScreen(gui_location); int preview_left = gui_location[0]; this.top_icon_shift = top_margin - preview_left; @@ -1943,9 +1953,11 @@ public class DrawPreview { if( this.top_icon_shift > 0 ) { if( ui_rotation == 90 || ui_rotation == 270 ) { + // portrait top_y += top_icon_shift; } else { + // landscape top_x += top_icon_shift; } } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index cadf7e3a4..636d36e0d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -893,6 +893,9 @@ public class MainUI { // displayed when in 16:9 preview. // Potentially we could use Animation.setAnimationListener(), but we set a separate // animation for every icon. + // Note, this seems to be unneeded due to the fix in DrawPreview for + // "getRotation() == 180.0f", but good to clear the cached values (e.g., in case we + // compute them during when the icons are being rotated). final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override -- GitLab From 449796f2ff3288a905e697f143d386346aa123cc Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 9 Feb 2020 21:04:57 +0000 Subject: [PATCH 124/243] Display camera ID on screen for multiple camera devices. --- _docs/help.html | 3 ++ _docs/history.html | 2 + .../sourceforge/opencamera/MainActivity.java | 7 +++ .../opencamera/MyPreferenceFragment.java | 8 +++- .../opencamera/PreferenceKeys.java | 2 + .../opencamera/ui/DrawPreview.java | 44 +++++++++++++++++-- app/src/main/res/values/strings.xml | 3 ++ app/src/main/res/xml/preferences.xml | 8 ++++ 8 files changed, 71 insertions(+), 6 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 1eab7851c..4b63d0bd5 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -636,6 +636,9 @@ image should be drawn with.

      Show time - Whether to display the current time.

      +

      Show camera ID - For devices with multiple front/back cameras. Whether to display the currently used camera ID. + This will be a value starting from 0, that distinguishes between the different cameras on your device.

      +

      Show free memory - Whether to display the remaining storage space of the device.

      Show ISO - If selected, the current ISO, exposure time and frame rate (FPS) will be displayed (only available if Camera2 diff --git a/_docs/history.html b/_docs/history.html index 0ba56eab4..051ff8c73 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -68,6 +68,8 @@ ADDED New icon for switching between multiple cameras. If your device has mult and back camera; the new icon will instead cycle between the multiple front or back cameras. If you prefer the old behaviour, then disable Settings/On screen GUI/"Multiple cameras icon". +ADDED Current camera ID now displayed on-screen (next to date/time) for devices with multiple + front/back cameras. This can be disabled under Settings/Camera preview/"Show camera ID". ADDED Option to specify REC709 or sRGB profile for video recording. ADDED New custom gamma profile option for video recording. ADDED New option for alpha value to use for ghost image option. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 9bbf538ac..fe22d0407 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -683,6 +683,13 @@ public class MainActivity extends Activity { return is_multi_cam && sharedPreferences.getBoolean(PreferenceKeys.MultiCamButtonPreferenceKey, true); } + /** Whether this is a multi camera device, whether or not the user preference is set to enable + * the multi-camera button. + */ + public boolean isMultiCam() { + return is_multi_cam; + } + /** Whether the icon switch_multi_camera should be displayed. This is if the following are all * true: * - The device is a multi camera device (MainActivity.is_multi_cam==true). diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 52308c75f..fcdf00e2d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -611,8 +611,12 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared } if( !is_multi_cam ) { - Preference pref = findPreference("preference_multi_cam_button"); - PreferenceGroup pg = (PreferenceGroup)this.findPreference("preference_screen_gui"); + Preference pref = findPreference("preference_show_camera_id"); + PreferenceGroup pg = (PreferenceGroup)this.findPreference("preference_preview"); + pg.removePreference(pref); + + pref = findPreference("preference_multi_cam_button"); + pg = (PreferenceGroup)this.findPreference("preference_screen_gui"); pg.removePreference(pref); } diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index 8f9e06a6f..c4407860a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -292,6 +292,8 @@ public class PreferenceKeys { public static final String ShowTimePreferenceKey = "preference_show_time"; + public static final String ShowCameraIDPreferenceKey = "preference_show_camera_id"; + public static final String ShowBatteryPreferenceKey = "preference_show_battery"; public static final String ShowGridPreferenceKey = "preference_grid"; diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 7ec26a4bd..b561fe99a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -62,6 +62,7 @@ public class DrawPreview { private boolean has_settings; private MyApplicationInterface.PhotoMode photoMode; private boolean show_time_pref; + private boolean show_camera_id_pref; private boolean show_free_memory_pref; private boolean show_iso_pref; private boolean show_video_max_amp_pref; @@ -112,6 +113,7 @@ public class DrawPreview { private final int [] temp_histogram_channel = new int[256]; // cached Rects for drawTextWithBackground() calls private Rect text_bounds_time; + private Rect text_bounds_camera_id; private Rect text_bounds_free_memory; private Rect text_bounds_angle_single; private Rect text_bounds_angle_double; @@ -128,6 +130,9 @@ public class DrawPreview { private String current_time_string; private long last_current_time_time; + private String camera_id_string; + private long last_camera_id_time; + private String iso_exposure_string; private boolean is_scanning; private long last_iso_exposure_time; @@ -482,6 +487,7 @@ public class DrawPreview { Log.d(TAG, "photoMode: " + photoMode); show_time_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowTimePreferenceKey, true); + show_camera_id_pref = main_activity.isMultiCam() && sharedPreferences.getBoolean(PreferenceKeys.ShowCameraIDPreferenceKey, true); show_free_memory_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowFreeMemoryPreferenceKey, true); show_iso_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowISOPreferenceKey, true); show_video_max_amp_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowVideoMaxAmpPreferenceKey, false); @@ -611,6 +617,7 @@ public class DrawPreview { String focus_peaking_color = sharedPreferences.getString(PreferenceKeys.FocusPeakingColorPreferenceKey, "#ffffff"); focus_peaking_color_pref = Color.parseColor(focus_peaking_color); + last_camera_id_time = 0; // in case camera id changed last_view_angles_time = 0; // force view angles to be recomputed last_take_photo_top_time = 0; // force take_photo_top to be recomputed last_top_icon_shift_time = 0; // for top_icon_shift to be recomputed @@ -1034,6 +1041,7 @@ public class DrawPreview { p.setTextAlign(Paint.Align.LEFT); int location_x = top_x; int location_y = top_y; + final int gap_x = (int) (8 * scale + 0.5f); // convert dps to pixels final int gap_y = (int) (0 * scale + 0.5f); // convert dps to pixels final int icon_gap_y = (int) (2 * scale + 0.5f); // convert dps to pixels if( ui_rotation == 90 || ui_rotation == 270 ) { @@ -1044,11 +1052,15 @@ public class DrawPreview { if( ui_rotation == 90 ) { location_y = canvas.getHeight() - location_y - (int) (20 * scale + 0.5f); } + boolean align_right = false; if( ui_rotation == 180 ) { location_x = canvas.getWidth() - location_x; p.setTextAlign(Paint.Align.RIGHT); + align_right = true; } + int first_line_height = 0; + int first_line_xshift = 0; if( show_time_pref ) { if( current_time_string == null || time_ms/1000 > last_current_time_time/1000 ) { // avoid creating a new calendar object every time @@ -1075,14 +1087,38 @@ public class DrawPreview { String bounds_time_string = "00:00:00"; p.getTextBounds(bounds_time_string, 0, bounds_time_string.length(), text_bounds_time); } + first_line_xshift += text_bounds_time.width() + gap_x; int height = applicationInterface.drawTextWithBackground(canvas, p, current_time_string, Color.WHITE, Color.BLACK, location_x, location_y, MyApplicationInterface.Alignment.ALIGNMENT_TOP, null, MyApplicationInterface.Shadow.SHADOW_OUTLINE, text_bounds_time); height += gap_y; - if( ui_rotation == 90 ) { - location_y -= height; + // don't update location_y yet, as we have time and cameraid shown on the same line + first_line_height = Math.max(first_line_height, height); + } + if( show_camera_id_pref && camera_controller != null ) { + if( camera_id_string == null || time_ms > last_camera_id_time + 10000 ) { + // cache string for performance + + camera_id_string = getContext().getResources().getString(R.string.camera_id) + ":" + preview.getCameraId(); // intentionally don't put a space + last_camera_id_time = time_ms; } - else { - location_y += height; + if( text_bounds_camera_id == null ) { + if( MyDebug.LOG ) + Log.d(TAG, "compute text_bounds_camera_id"); + text_bounds_camera_id = new Rect(); + p.getTextBounds(camera_id_string, 0, camera_id_string.length(), text_bounds_camera_id); } + int xpos = align_right ? location_x - first_line_xshift : location_x + first_line_xshift; + int height = applicationInterface.drawTextWithBackground(canvas, p, camera_id_string, Color.WHITE, Color.BLACK, xpos, location_y, MyApplicationInterface.Alignment.ALIGNMENT_TOP, null, MyApplicationInterface.Shadow.SHADOW_OUTLINE, text_bounds_camera_id); + height += gap_y; + // don't update location_y yet, as we have time and cameraid shown on the same line + first_line_height = Math.max(first_line_height, height); + } + // update location_y for first line (time and camera id) + if( ui_rotation == 90 ) { + // upside-down portrait + location_y -= first_line_height; + } + else { + location_y += first_line_height; } if( camera_controller != null && show_free_memory_pref ) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d24f0221..de5174105 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -972,6 +972,9 @@ Multiple cameras icon If enabled, use separate buttons to switch between front/back cameras, and to switch between multiple front/back facing cameras. If disabled, the Switch Camera icon will cycle through all cameras. + Show Camera ID + Display the current camera ID number on screen + Privacy policy diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index a02e095b6..46f0d7680 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -416,6 +416,14 @@ android:defaultValue="true" /> + + + Date: Sun, 9 Feb 2020 21:36:53 +0000 Subject: [PATCH 125/243] Further fix for getLocationOnScreen() issues. --- .../opencamera/ui/DrawPreview.java | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index b561fe99a..30ec86b5f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -363,6 +363,28 @@ public class DrawPreview { return main_activity; } + /** Computes the x coordinate on screen of left side of the view, equivalent to + * view.getLocationOnScreen(), but we undo the effect of the view's rotation. + * This is because getLocationOnScreen() will return the coordinates of the view's top-left + * *after* applying the rotation, when we want the top left of the icon as shown on screen. + * This should not be called every frame but instead should be cached, due to cost of calling + * view.getLocationOnScreen(). + */ + private int getViewOnScreenX(View view) { + view.getLocationOnScreen(gui_location); + int xpos = gui_location[0]; + int rotation = Math.round(view.getRotation()); + // rotation can be outside [0, 359] if the user repeatedly rotates in same direction! + rotation = (rotation % 360 + 360) % 360; // version of (rotation % 360) that work if rotation is -ve + /*if( MyDebug.LOG ) + Log.d(TAG, " mod rotation: " + rotation);*/ + if( rotation == 180 || rotation == 90 ) { + // annoying behaviour that getLocationOnScreen takes the rotation into account + xpos -= view.getWidth(); + } + return xpos; + } + /** Sets a current thumbnail for a photo or video just taken. Used for thumbnail animation, * and when ghosting the last image. */ @@ -1662,13 +1684,7 @@ public class DrawPreview { // don't call this too often, for UI performance (due to calling View.getLocationOnScreen()) View view = main_activity.findViewById(R.id.take_photo); // align with "top" of the take_photo button, but remember to take the rotation into account! - view.getLocationOnScreen(gui_location); - int view_left = gui_location[0]; - if( view.getRotation() == 180.0f ) { - // annoying behaviour that getLocationOnScreen takes the rotation into account, at least when - // entirely upside down - view_left -= view.getWidth(); - } + int view_left = getViewOnScreenX(view); preview.getView().getLocationOnScreen(gui_location); int this_left = gui_location[0]; take_photo_top = view_left - this_left; @@ -1968,17 +1984,12 @@ public class DrawPreview { // avoid computing every time, due to cost of calling View.getLocationOnScreen() /*if( MyDebug.LOG ) Log.d(TAG, "update cached top_icon_shift");*/ - top_icon.getLocationOnScreen(gui_location); - int top_margin = gui_location[0] + top_icon.getWidth(); - if( top_icon.getRotation() == 180.0f ) { - // annoying behaviour that getLocationOnScreen takes the rotation into account, at least when - // entirely upside down - top_margin -= top_icon.getWidth(); - } + int top_margin = getViewOnScreenX(top_icon) + top_icon.getWidth(); preview.getView().getLocationOnScreen(gui_location); int preview_left = gui_location[0]; this.top_icon_shift = top_margin - preview_left; /*if( MyDebug.LOG ) { + Log.d(TAG, "top_icon.getRotation(): " + top_icon.getRotation()); Log.d(TAG, "preview_left: " + preview_left); Log.d(TAG, "top_margin: " + top_margin); Log.d(TAG, "top_icon_shift: " + top_icon_shift); -- GitLab From 4dd6b441d94ad009eee1b7fc8d1186d02b60f7ac Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 11 Feb 2020 23:35:37 +0000 Subject: [PATCH 126/243] New option to disable long press actions. --- _docs/help.html | 4 ++++ _docs/history.html | 2 ++ .../net/sourceforge/opencamera/MainActivity.java | 16 ++++++++++++++++ .../sourceforge/opencamera/PreferenceKeys.java | 2 ++ app/src/main/res/values/strings.xml | 3 +++ app/src/main/res/xml/preferences.xml | 7 +++++++ 6 files changed, 34 insertions(+) diff --git a/_docs/help.html b/_docs/help.html index 4b63d0bd5..0da15eff6 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -575,6 +575,10 @@ be unavailable when your device is locked, you can disable this option.

      Perform auto-focus on startup - Whether Open Camera should auto-focus when starting the camera. Some devices have a bug where the flash turns on when this happens, so a workaround is to disable this option.

      +

      Allow long press actions - Some icons support a "long press" action (touching and holding on the icon). For example, +long press on the gallery icon to change the save location, or in some cases long press on the shutter icon will enable a +burst. If you prefer, you can disable these long press actions.

      +

      Calibrate level angle - The options Auto-level, "Show angle" and "Show angle line" rely on your device's ability to detect which orientation it's being held (the accelerometer). On some device's this might not be calibated correctly. If so, you can use this option to calibrate the acceleromer (or reset the calibration back to the diff --git a/_docs/history.html b/_docs/history.html index 051ff8c73..2b73815b9 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -75,6 +75,8 @@ ADDED New custom gamma profile option for video recording. ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. ADDED Options to control zebra stripe colours. +ADDED New option Settings/More camera controls/"Allow long press actions" to disable long press + actions. UPDATED Improvements for log profiles for video recording. Please note that this means the behaviour of these profiles has changed! UPDATED On devices with on-screen navigation buttons, camera preview can now display under these diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index fe22d0407..bfb57838c 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -420,6 +420,10 @@ public class MainActivity extends Activity { takePhotoButton.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { + if( !allowLongPress() ) { + // return false, so a regular click will still be triggered when the user releases the touch + return false; + } return longClickedTakePhoto(); } }); @@ -448,6 +452,10 @@ public class MainActivity extends Activity { galleryButton.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { + if( !allowLongPress() ) { + // return false, so a regular click will still be triggered when the user releases the touch + return false; + } //preview.showToast(null, "Long click"); longClickedGallery(); return true; @@ -718,6 +726,14 @@ public class MainActivity extends Activity { } return false; } + + /** Whether user preference is set to allow long press actions. + */ + private boolean allowLongPress() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + return sharedPreferences.getBoolean(PreferenceKeys.AllowLongPressPreferenceKey, true); + } + /* This method sets the preference defaults which are set specific for a particular device. * This method should be called when Open Camera is run for the very first time after installation, * or when the user has requested to "Reset settings". diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index c4407860a..b7882920f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -194,6 +194,8 @@ public class PreferenceKeys { return "preference_show_when_locked"; } + public static final String AllowLongPressPreferenceKey = "preference_allow_long_press"; + public static String getStartupFocusPreferenceKey() { return "preference_startup_focus"; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index de5174105..95b0c99e5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -975,6 +975,9 @@ Show Camera ID Display the current camera ID number on screen + Allow long press actions + Whether to allow long press actions (e.g., long press on gallery to change save location). + Privacy policy diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 46f0d7680..fbc73f885 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -302,6 +302,13 @@ android:defaultValue="true" /> + + Date: Wed, 12 Feb 2020 22:53:20 +0000 Subject: [PATCH 127/243] Improved placement of on-screen text (zoom, video recording time etc) to avoid focus seekbars in landscape mode. --- _docs/history.html | 2 ++ .../sourceforge/opencamera/MainActivity.java | 4 +-- .../opencamera/ui/DrawPreview.java | 25 ++++++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 2b73815b9..c84d8d1a5 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -95,6 +95,8 @@ UPDATED Disable some preferences if only relevant for another nearby option that enabled. UPDATED Moved video bitrate and frame rate options to debugging section. UPDATED Improved UI support for "external" cameras (if detecting with Camera2 API). +UPDATED Improved placement of on-screen text (zoom, video recording time etc) to avoid focus + seekbars in landscape mode. UPDATED Improved look of on-screen text for manual/exposure sliders. Version 1.47.3 (2019/10/20) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index bfb57838c..063c822f7 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -3990,12 +3990,12 @@ public class MainActivity extends Activity { } } else { - zoomSeekBar.setVisibility(View.INVISIBLE); // should be INVISIBLE not GONE, as the focus_seekbar is aligned to be left to this + zoomSeekBar.setVisibility(View.INVISIBLE); // should be INVISIBLE not GONE, as the focus_seekbar is aligned to be left to this; in future we might want this similarly for exposure panel } } else { zoomControls.setVisibility(View.GONE); - zoomSeekBar.setVisibility(View.INVISIBLE); // should be INVISIBLE not GONE, as the focus_seekbar is aligned to be left to this + zoomSeekBar.setVisibility(View.INVISIBLE); // should be INVISIBLE not GONE, as the focus_seekbar is aligned to be left to this; in future we might want this similarly for the exposure panel } if( MyDebug.LOG ) Log.d(TAG, "cameraSetup: time after setting up zoom: " + (System.currentTimeMillis() - debug_time)); diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 30ec86b5f..7056b945d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -1662,12 +1662,15 @@ public class DrawPreview { canvas.getHeight() / 2, p);*/ int gap_y = (int) (20 * scale + 0.5f); // convert dps to pixels int text_y = (int) (16 * scale + 0.5f); // convert dps to pixels + boolean avoid_ui = false; // fine tuning to adjust placement of text with respect to the GUI, depending on orientation if( ui_placement == MainUI.UIPlacement.UIPLACEMENT_TOP && ( ui_rotation == 0 || ui_rotation == 180 ) ) { - text_base_y = canvas.getHeight() - (int)(0.5*gap_y); + text_base_y = canvas.getHeight() - (int)(0.1*gap_y); + avoid_ui = true; } else if( ui_rotation == ( ui_placement == MainUI.UIPlacement.UIPLACEMENT_RIGHT ? 0 : 180 ) ) { - text_base_y = canvas.getHeight() - (int)(0.5*gap_y); + text_base_y = canvas.getHeight() - (int)(0.1*gap_y); + avoid_ui = true; } else if( ui_rotation == ( ui_placement == MainUI.UIPlacement.UIPLACEMENT_RIGHT ? 180 : 0 ) ) { text_base_y = canvas.getHeight() - (int)(2.5*gap_y); // leave room for GUI icons @@ -1676,8 +1679,6 @@ public class DrawPreview { // ui_rotation 90 is upside down portrait // 270 is portrait - //text_base_y = canvas.getHeight() + (int)(0.5*gap_y); - if( last_take_photo_top_time == 0 || time_ms > last_take_photo_top_time + 1000 ) { /*if( MyDebug.LOG ) Log.d(TAG, "update cached take_photo_top");*/ @@ -1735,6 +1736,22 @@ public class DrawPreview { text_base_y = canvas.getHeight()/2 + diff_x - (int)(0.5*gap_y); } + if( avoid_ui ) { + // avoid parts of the UI + View view = main_activity.findViewById(R.id.focus_seekbar); + if(view.getVisibility() == View.VISIBLE ) { + text_base_y -= view.getHeight(); + } + view = main_activity.findViewById(R.id.focus_bracketing_target_seekbar); + if(view.getVisibility() == View.VISIBLE ) { + text_base_y -= view.getHeight(); + } + /*view = main_activity.findViewById(R.id.sliders_container); + if(view.getVisibility() == View.VISIBLE ) { + text_base_y -= view.getHeight(); + }*/ + } + boolean draw_angle = has_level_angle && show_angle_pref; boolean draw_geo_direction = has_geo_direction && show_geo_direction_pref; if( draw_angle ) { -- GitLab From 9326d91cfcbe3f0f09c20994ef4a878c1132c8cb Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 12 Feb 2020 22:53:51 +0000 Subject: [PATCH 128/243] Add commented out code being tested for exposure UI placement. --- .../net/sourceforge/opencamera/ui/MainUI.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 636d36e0d..2a6879a4d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -588,6 +588,58 @@ public class MainUI { view.setTranslationY(-1*height_pixels); } + /* + // align sliders_container + RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)view.getLayoutParams(); + if( ui_rotation == 90 || ui_rotation == 270 ) { + // portrait + view.setTranslationX(2*height_pixels); + lp.addRule(left_of, 0); + lp.addRule(right_of, 0); + lp.addRule(above, 0); + lp.addRule(below, 0); + lp.addRule(align_parent_top, 0); + lp.addRule(align_parent_bottom, 0); + } + else if( ui_rotation == (ui_placement == UIPlacement.UIPLACEMENT_LEFT ? 180 : 0) ) { + // landscape (or upside-down landscape if ui-left) + view.setTranslationY(0); + lp.addRule(left_of, R.id.zoom_seekbar); + lp.addRule(right_of, 0); + + if( main_activity.showManualFocusSeekbar(true) ) { + lp.addRule(above, R.id.focus_bracketing_target_seekbar); + lp.addRule(below, 0); + lp.addRule(align_parent_top, 0); + lp.addRule(align_parent_bottom, 0); + } + else if( main_activity.showManualFocusSeekbar(false) ) { + lp.addRule(above, R.id.focus_seekbar); + lp.addRule(below, 0); + lp.addRule(align_parent_top, 0); + lp.addRule(align_parent_bottom, 0); + } + else { + lp.addRule(above, 0); + lp.addRule(below, 0); + lp.addRule(align_parent_top, 0); + lp.addRule(align_parent_bottom, RelativeLayout.TRUE); + } + } + else { + // upside-down landscape (or landscape if ui-left) + if( ui_rotation == 0 ) + view.setTranslationY(height_pixels); + else + view.setTranslationY(-1*height_pixels); + lp.addRule(left_of, 0); + lp.addRule(right_of, 0); + lp.addRule(above, 0); + lp.addRule(below, 0); + lp.addRule(align_parent_bottom, 0); + } + view.setLayoutParams(lp);*/ + view = main_activity.findViewById(R.id.exposure_seekbar); RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)view.getLayoutParams(); lp.width = width_pixels; @@ -1876,6 +1928,8 @@ public class MainUI { else { manual_white_balance_seek_bar.setVisibility(View.GONE); } + + //layoutUI(); // needed to update alignment of exposure UI } /** If the exposure panel is open, updates the selected ISO button to match the current ISO value, -- GitLab From 1b66719473b6ab1ac840bd425036536dccbe1b85 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 12 Feb 2020 23:01:09 +0000 Subject: [PATCH 129/243] Make exposure panel icons slightly smaller, so the panel is more compact. --- app/src/main/res/layout/activity_main.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b5a02f493..ae93f0e7b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -499,8 +499,8 @@ @@ -539,8 +539,8 @@ @@ -559,8 +559,8 @@ @@ -590,8 +590,8 @@ -- GitLab From 2c645450ad59496f246aa253315d329f15aaa947 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 13 Feb 2020 22:30:21 +0000 Subject: [PATCH 130/243] Focus seekbars overlapped with histogram in widescreen aspect ratio when using "Icons along top" UI placement. --- _docs/history.html | 2 + .../opencamera/ui/DrawPreview.java | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index c84d8d1a5..9b79a0bb4 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -63,6 +63,8 @@ FIXED Problem of on-screen level angle overlapping with shutter icon when usin preview aspect ratio. FIXED Incorrect layout for on-screen text when using "icons along top" with wide-screen aspect ratio and device held in upside-down landscape orientation. +FIXED Focus seekbars overlapped with histogram in widescreen aspect ratio when using "Icons along + top" UI placement. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 7056b945d..fe81c5d00 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -48,6 +48,7 @@ import android.util.Pair; import android.view.Display; import android.view.Surface; import android.view.View; +import android.widget.RelativeLayout; public class DrawPreview { private static final String TAG = "DrawPreview"; @@ -218,10 +219,15 @@ public class DrawPreview { private int top_icon_shift; // shift that may be needed for on-screen text to avoid clashing with icons (when arranged "along top") private long last_top_icon_shift_time; + private int focus_seekbars_margin_left = -1; // margin left that's been set for the focus seekbars + // OSD extra lines private String OSDLine1; private String OSDLine2; + private final static int histogram_width_dp = 100; + private final static int histogram_height_dp = 60; + public DrawPreview(MainActivity main_activity, MyApplicationInterface applicationInterface) { if( MyDebug.LOG ) Log.d(TAG, "DrawPreview"); @@ -644,6 +650,8 @@ public class DrawPreview { last_take_photo_top_time = 0; // force take_photo_top to be recomputed last_top_icon_shift_time = 0; // for top_icon_shift to be recomputed + focus_seekbars_margin_left = -1; // just in case?? + has_settings = true; } @@ -1518,8 +1526,8 @@ public class DrawPreview { if( histogram != null ) { /*if( MyDebug.LOG ) Log.d(TAG, "histogram length: " + histogram.length);*/ - final int histogram_width = (int) (100 * scale + 0.5f); // convert dps to pixels - final int histogram_height = (int) (60 * scale + 0.5f); // convert dps to pixels + final int histogram_width = (int) (histogram_width_dp * scale + 0.5f); // convert dps to pixels + final int histogram_height = (int) (histogram_height_dp * scale + 0.5f); // convert dps to pixels // n.b., if changing the histogram_height, remember to update focus_seekbar and // focus_bracketing_target_seekbar margins in activity_main.xml int location_x2 = location_x - flash_padding; @@ -2027,6 +2035,35 @@ public class DrawPreview { } } + { + /*int focus_seekbars_margin_left_dp = 85; + if( want_histogram ) + focus_seekbars_margin_left_dp += DrawPreview.histogram_height_dp;*/ + // 135 needed to make room for on-screen info lines in DrawPreview.onDrawInfoLines(), including the histogram + // but we also need to take the top_icon_shift into account, for widescreen aspect ratios and "icons along top" UI placement + int focus_seekbars_margin_left_dp = 135; + int new_focus_seekbars_margin_left = (int) (focus_seekbars_margin_left_dp * scale + 0.5f); // convert dps to pixels + if( top_icon_shift > 0 ) + new_focus_seekbars_margin_left += top_icon_shift; + + if( focus_seekbars_margin_left == -1 || new_focus_seekbars_margin_left != focus_seekbars_margin_left ) { + // we check whether focus_seekbars_margin_left has changed, in case there is a performance cost for setting layoutparams + this.focus_seekbars_margin_left = new_focus_seekbars_margin_left; + if( MyDebug.LOG ) + Log.d(TAG, "set focus_seekbars_margin_left to " + focus_seekbars_margin_left); + + View view = main_activity.findViewById(R.id.focus_seekbar); + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); + layoutParams.setMargins(focus_seekbars_margin_left, 0, 0, 0); + view.setLayoutParams(layoutParams); + + view = main_activity.findViewById(R.id.focus_bracketing_target_seekbar); + layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); + layoutParams.setMargins(focus_seekbars_margin_left, 0, 0, 0); + view.setLayoutParams(layoutParams); + } + } + int battery_x = top_x; int battery_y = top_y + (int) (5 * scale + 0.5f); int battery_width = (int) (5 * scale + 0.5f); // convert dps to pixels -- GitLab From b37bc2014502b168e9dba96f5136e2583b13fa15 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 13 Feb 2020 23:55:54 +0000 Subject: [PATCH 131/243] Fixed fake precapture timeouts for flash_frontscreen_torch. --- _docs/history.html | 1 + .../opencamera/cameracontroller/CameraController2.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 9b79a0bb4..fcba7f7d3 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -50,6 +50,7 @@

       Version 1.48 (Work in progress)
       
      +FIXED   Taking front camera photos with frontscreen torch was slow.
       FIXED   When using "Pause after taking photo", touching to unpause no longer
               triggers auto focus, or taking another photo for "Touch to capture".
       FIXED   Take photo widget issue.
      diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java
      index ecf2f0c67..9a79e93d0 100644
      --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java
      +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java
      @@ -6865,7 +6865,7 @@ public class CameraController2 extends CameraController {
                       }
                       // Don't need precapture if flash off or torch
                       // And currently has_iso manual mode doesn't support flash - but just in case that's changed later, we still probably don't want to be doing a precapture...
      -                if( camera_settings.has_iso || camera_settings.flash_value.equals("flash_off") || camera_settings.flash_value.equals("flash_torch") ) {
      +                if( camera_settings.has_iso || camera_settings.flash_value.equals("flash_off") || camera_settings.flash_value.equals("flash_torch") || camera_settings.flash_value.equals("flash_frontscreen_torch") ) {
                           call_takePictureAfterPrecapture = true;
                       }
                       else if( use_fake_precapture_mode ) {
      -- 
      GitLab
      
      
      From 0803b87ed74fed292e1ad40c1a50381b63a16c01 Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Thu, 13 Feb 2020 23:56:37 +0000
      Subject: [PATCH 132/243] Fix case for show camera ID.
      
      ---
       app/src/main/res/values/strings.xml | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
      index 95b0c99e5..31539b3d3 100644
      --- a/app/src/main/res/values/strings.xml
      +++ b/app/src/main/res/values/strings.xml
      @@ -972,7 +972,7 @@
           Multiple cameras icon
           If enabled, use separate buttons to switch between front/back cameras, and to switch between multiple front/back facing cameras. If disabled, the Switch Camera icon will cycle through all cameras.
       
      -    Show Camera ID
      +    Show camera ID
           Display the current camera ID number on screen
       
           Allow long press actions
      -- 
      GitLab
      
      
      From d678ba7a687b49c3e211048997ee9b08803dcd9f Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Fri, 14 Feb 2020 00:18:43 +0000
      Subject: [PATCH 133/243] Update comment.
      
      ---
       app/src/main/res/layout/activity_main.xml | 6 ++----
       1 file changed, 2 insertions(+), 4 deletions(-)
      
      diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
      index ae93f0e7b..f26fb0840 100644
      --- a/app/src/main/res/layout/activity_main.xml
      +++ b/app/src/main/res/layout/activity_main.xml
      @@ -139,8 +139,7 @@
               android:background="@color/seekbar_background"
               />
       
      -    
      +    
           
       
      -    
      +    
           
      Date: Sat, 15 Feb 2020 00:05:08 +0000
      Subject: [PATCH 134/243] Flash on and torch now supported for manual
       ISO/exposure.
      
      ---
       _docs/history.html                            |  1 +
       .../cameracontroller/CameraController2.java   | 53 +++++++++++--------
       .../opencamera/preview/Preview.java           | 24 ++++++++-
       3 files changed, 55 insertions(+), 23 deletions(-)
      
      diff --git a/_docs/history.html b/_docs/history.html
      index fcba7f7d3..23474679e 100644
      --- a/_docs/history.html
      +++ b/_docs/history.html
      @@ -73,6 +73,7 @@ ADDED   New icon for switching between multiple cameras. If your device has mult
               Settings/On screen GUI/"Multiple cameras icon".
       ADDED   Current camera ID now displayed on-screen (next to date/time) for devices with multiple
               front/back cameras. This can be disabled under Settings/Camera preview/"Show camera ID".
      +ADDED   Flash on and torch now supported for manual ISO/exposure.
       ADDED   Option to specify REC709 or sRGB profile for video recording.
       ADDED   New custom gamma profile option for video recording.
       ADDED   New option for alpha value to use for ghost image option.
      diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java
      index 9a79e93d0..eab7f2390 100644
      --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java
      +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java
      @@ -727,24 +727,13 @@ public class CameraController2 extends CameraController {
                       }
                       //builder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1000000000L);
                       //builder.set(CaptureRequest.SENSOR_FRAME_DURATION, 0L);
      -                // for now, flash is disabled when using manual iso - it seems to cause ISO level to jump to 100 on Nexus 6 when flash is turned on!
      -                builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
      -                // set flash via CaptureRequest.FLASH
      -                /*if( flash_value.equals("flash_off") ) {
      -                    builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
      -                }
      -                else if( flash_value.equals("flash_auto") ) {
      -                    builder.set(CaptureRequest.FLASH_MODE, is_still ? CameraMetadata.FLASH_MODE_SINGLE : CameraMetadata.FLASH_MODE_OFF);
      -                }
      -                else if( flash_value.equals("flash_on") ) {
      -                    builder.set(CaptureRequest.FLASH_MODE, is_still ? CameraMetadata.FLASH_MODE_SINGLE : CameraMetadata.FLASH_MODE_OFF);
      -                }
      -                else if( flash_value.equals("flash_torch") ) {
      +                // only need to account for FLASH_MODE_TORCH, otherwise we use fake flash mode for manual ISO
      +                if( flash_value.equals("flash_torch") ) {
                           builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
                       }
      -                else if( flash_value.equals("flash_red_eye") ) {
      -                    builder.set(CaptureRequest.FLASH_MODE, is_still ? CameraMetadata.FLASH_MODE_SINGLE : CameraMetadata.FLASH_MODE_OFF);
      -                }*/
      +                else {
      +                    builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
      +                }
                   }
                   else {
                       if( MyDebug.LOG ) {
      @@ -3592,6 +3581,7 @@ public class CameraController2 extends CameraController {
                       camera_settings.has_iso = false;
                       camera_settings.iso = 0;
                   }
      +            updateUseFakePrecaptureMode(camera_settings.flash_value);
       
                   if( camera_settings.setAEMode(previewBuilder, false) ) {
                       setRepeatingRequest();
      @@ -4502,6 +4492,8 @@ public class CameraController2 extends CameraController {
               }
               else if( burst_type != BurstType.BURSTTYPE_NONE )
                   use_fake_precapture_mode = true;
      +        else if( camera_settings.has_iso )
      +            use_fake_precapture_mode = true;
               else {
                   use_fake_precapture_mode = use_fake_precapture;
               }
      @@ -5500,7 +5492,7 @@ public class CameraController2 extends CameraController {
                   this.capture_follows_autofocus_hint = capture_follows_autofocus_hint;
                   this.autofocus_cb = cb;
                   try {
      -                if( use_fake_precapture_mode && !camera_settings.has_iso ) {
      +                if( use_fake_precapture_mode ) {
                           boolean want_flash = false;
                           if( camera_settings.flash_value.equals("flash_auto") || camera_settings.flash_value.equals("flash_frontscreen_auto") ) {
                               // calling fireAutoFlash() also caches the decision on whether to flash - otherwise if the flash fires now, we'll then think the scene is bright enough to not need the flash!
      @@ -5513,7 +5505,11 @@ public class CameraController2 extends CameraController {
                           if( want_flash ) {
                               if( MyDebug.LOG )
                                   Log.d(TAG, "turn on torch for fake flash");
      -                        afBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
      +                        if( !camera_settings.has_iso ) {
      +                            // in auto-mode, need to ensure CONTROL_AE_MODE isn't est to flash auto/on for torch to work
      +                            // in manual-mode, fine as CONTROL_AE_MODE will be off
      +                            afBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
      +                        }
                               afBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
                               test_fake_flash_focus++;
                               fake_precapture_torch_focus_performed = true;
      @@ -6705,7 +6701,11 @@ public class CameraController2 extends CameraController {
                       case "flash_on":
                           if(MyDebug.LOG)
                               Log.d(TAG, "turn on torch");
      -                    previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
      +                    if( !camera_settings.has_iso ) {
      +                        // in auto-mode, need to ensure CONTROL_AE_MODE isn't est to flash auto/on for torch to work
      +                        // in manual-mode, fine as CONTROL_AE_MODE will be off
      +                        previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
      +                    }
                           previewBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
                           test_fake_flash_precapture++;
                           fake_precapture_torch_performed = true;
      @@ -6864,8 +6864,7 @@ public class CameraController2 extends CameraController {
                           Log.d(TAG, "use_fake_precapture_mode: " + use_fake_precapture_mode);
                       }
                       // Don't need precapture if flash off or torch
      -                // And currently has_iso manual mode doesn't support flash - but just in case that's changed later, we still probably don't want to be doing a precapture...
      -                if( camera_settings.has_iso || camera_settings.flash_value.equals("flash_off") || camera_settings.flash_value.equals("flash_torch") || camera_settings.flash_value.equals("flash_frontscreen_torch") ) {
      +                if( camera_settings.flash_value.equals("flash_off") || camera_settings.flash_value.equals("flash_torch") || camera_settings.flash_value.equals("flash_frontscreen_torch") ) {
                           call_takePictureAfterPrecapture = true;
                       }
                       else if( use_fake_precapture_mode ) {
      @@ -7530,6 +7529,18 @@ public class CameraController2 extends CameraController {
                           state = STATE_WAITING_FAKE_PRECAPTURE_DONE;
                           precapture_state_change_time_ms = System.currentTimeMillis();
                       }
      +                else if( fake_precapture_turn_on_torch_id == null && camera_settings.has_iso && precapture_state_change_time_ms != -1 && System.currentTimeMillis() - precapture_state_change_time_ms > 100 ) {
      +                    // When using manual ISO, we can't make use of changes to the ae_state - but at the same time, we don't
      +                    // need ISO/exposure to re-adjust anyway.
      +                    // If fake_precapture_turn_on_torch_id != null, we still wait for the physical torch to turn on.
      +                    // But if fake_precapture_turn_on_torch_id==null (i.e., for flash_frontscreen_torch), just wait a short
      +                    // period to ensure the frontscreen flash has enabled.
      +                    if( MyDebug.LOG ) {
      +                        Log.d(TAG, "fake precapture started after: " + (System.currentTimeMillis() - precapture_state_change_time_ms));
      +                    }
      +                    state = STATE_WAITING_FAKE_PRECAPTURE_DONE;
      +                    precapture_state_change_time_ms = System.currentTimeMillis();
      +                }
                       else if( precapture_state_change_time_ms != -1 && System.currentTimeMillis() - precapture_state_change_time_ms > precapture_start_timeout_c ) {
                           // just in case
                           // always log error, so we can look for it when manually testing with logging disabled
      diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      index 43255930a..f832a94f2 100644
      --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      @@ -2470,12 +2470,29 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
                       applicationInterface.clearExposureTimePref();
                   }
       
      -            if( this.using_android_l && supported_flash_values != null ) {
      +            if( supported_flash_values != null ) {
      +                if( MyDebug.LOG )
      +                    Log.d(TAG, "restrict flash modes for manual mode");
      +                List new_supported_flash_values = new ArrayList<>();
      +                for(String supported_flash_value : supported_flash_values) {
      +                    switch( supported_flash_value ) {
      +                        case "flash_off":
      +                        case "flash_on":
      +                        case "flash_torch":
      +                        case "flash_frontscreen_on":
      +                        case "flash_frontscreen_torch":
      +                            new_supported_flash_values.add(supported_flash_value);
      +                            break;
      +                    }
      +                }
      +                supported_flash_values = new_supported_flash_values;
      +                /*
                       // flash modes not supported when using Camera2 and manual ISO
                       // (it's unclear flash is useful - ideally we'd at least offer torch, but ISO seems to reset to 100 when flash/torch is on!)
                       supported_flash_values = null;
                       if( MyDebug.LOG )
                           Log.d(TAG, "flash not supported in Camera2 manual mode");
      +                */
                   }
               }
               if( MyDebug.LOG ) {
      @@ -2771,7 +2788,10 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
                           if( !updateFlash(flash_value, false) ) { // don't need to save, as this is the value that's already saved
                               if( MyDebug.LOG )
                                   Log.d(TAG, "flash value no longer supported!");
      -                        updateFlash(0, true);
      +                        // if in manual ISO mode, we'll have restricted the available flash modes - so although we want to
      +                        // communicate this to the application, we don't want to save the new value we've chosen (otherwise
      +                        // if user goes to manual ISO and back, we might switch saved flash say from auto to off)
      +                        updateFlash(0, !is_manual_iso);
                           }
                       }
                       else {
      -- 
      GitLab
      
      
      From e4d51f006ef7c328fc92017c2f9fc009edf610a9 Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Sat, 15 Feb 2020 00:05:58 +0000
      Subject: [PATCH 135/243] Add comment.
      
      ---
       .../main/java/net/sourceforge/opencamera/preview/Preview.java   | 2 ++
       1 file changed, 2 insertions(+)
      
      diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      index f832a94f2..fe11102dc 100644
      --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java
      @@ -8190,6 +8190,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
               return this.supported_focus_values != null;
           }
       
      +    /** Whether flash is supported by the camera.
      +     */
           public boolean supportsFlash() {
               return this.supported_flash_values != null;
           }
      -- 
      GitLab
      
      
      From ee7fad94889ecd20a1bbdf620eaed19a6de90929 Mon Sep 17 00:00:00 2001
      From: Mark Harman 
      Date: Sat, 15 Feb 2020 00:08:07 +0000
      Subject: [PATCH 136/243] Update info on Camera API option.
      
      ---
       _docs/help.html | 8 ++++----
       1 file changed, 4 insertions(+), 4 deletions(-)
      
      diff --git a/_docs/help.html b/_docs/help.html
      index 0da15eff6..95df3b34b 100644
      --- a/_docs/help.html
      +++ b/_docs/help.html
      @@ -1103,12 +1103,12 @@ specified by using this option.

      my donation app.

      Camera API - If set to "Camera2 API", this enables support for the Camera2 API that was introduced -in Android 5. Changing this setting will cause Open Camera to restart. Camera2 API enables some new features +in Android 5. Changing this setting will cause Open Camera to restart. Camera2 API enables more advanced features (including manual ISO/exposure, manual focus, HDR, exposure bracketing). -Note that not all Android 5 devices have full support for the Camera2 API (Open Camera will only show this +Note that not all Android 5+ devices have full support for the Camera2 API (Open Camera will only show this option if at least one camera reports either "LIMITED" or "FULL" support for the API; "LEGACY" only devices are not supported). -Also note that even if devices support Camera2 API, many -devices have extremely poor support, leading to bugs such as poor flash behaviour, or video recording not working. +Also note that even if devices support Camera2 API, some +devices have poor support. These are not necessarily bugs in Open Camera, but problems with manufacturer support for Camera2 API. If you have problems with flash behaviour, try the "Use alternative flash method" setting under "Photo Settings". Please see here for more details on device compatibility.

      -- GitLab From 10cbc37f5cbb02889de111b3fef55b5b422b470f Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 15:06:02 +0000 Subject: [PATCH 137/243] Add new line between commented out lines. --- .../opencamera/cameracontroller/CameraController2.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index eab7f2390..b3216da8f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -932,6 +932,7 @@ public class CameraController2 extends CameraController { // to use test_new, also need to uncomment the test code in setFocusValue() to call setTonemapProfile() //boolean test_new = this.af_mode == CaptureRequest.CONTROL_AF_MODE_AUTO; // testing + //if( test_new ) // have_tonemap_profile = false; -- GitLab From 30d8760cde19f63f34bb0b30e42b825d71d1f6d6 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 16:11:46 +0000 Subject: [PATCH 138/243] Auto-open exposure UI when switching to manual white balance; highlight exposure icon red when exposure UI is open. --- _docs/history.html | 3 +++ _docs/index.html | 2 +- .../net/sourceforge/opencamera/MainActivity.java | 2 +- .../opencamera/MyApplicationInterface.java | 6 +++--- .../net/sourceforge/opencamera/ui/MainUI.java | 15 ++++++++++++--- .../net/sourceforge/opencamera/ui/PopupView.java | 5 +++++ .../res/drawable-hdpi/ic_exposure_red_48dp.png | Bin 0 -> 945 bytes .../res/drawable-mdpi/ic_exposure_red_48dp.png | Bin 0 -> 616 bytes .../res/drawable-xhdpi/ic_exposure_red_48dp.png | Bin 0 -> 1159 bytes .../res/drawable-xxhdpi/ic_exposure_red_48dp.png | Bin 0 -> 1624 bytes .../drawable-xxxhdpi/ic_exposure_red_48dp.png | Bin 0 -> 2165 bytes 11 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_exposure_red_48dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_exposure_red_48dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_exposure_red_48dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_exposure_red_48dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_exposure_red_48dp.png diff --git a/_docs/history.html b/_docs/history.html index 23474679e..2d89d4b1d 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -102,6 +102,9 @@ UPDATED Improved UI support for "external" cameras (if detecting with Camera2 AP UPDATED Improved placement of on-screen text (zoom, video recording time etc) to avoid focus seekbars in landscape mode. UPDATED Improved look of on-screen text for manual/exposure sliders. +UPDATED Exposure icon now highlights red when exposure UI is open. +UPDATED Exposure UI now auto-opens when switching to manual white balance (as exposure UI contains + the manual white balance temperature seekbar). Version 1.47.3 (2019/10/20) diff --git a/_docs/index.html b/_docs/index.html index 3a801c63d..9c95b0850 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -228,7 +228,7 @@ Also see "Can I use the Open Camera source code in my app?" under the k44ofy`glX=O&z`&C3 z=e(BO1m#w=Z zH>{a1&dxsd_2tVKic6M7=-m$PJvKAgdHMc7 zuglak#kJ+aR!_ft_Sx%KzkY?^dg`e4qM)+!+Pkk&F;BlVs;mylvblZlpXYA23WsQZ ziLg6Q8SX5e@MYpGxg|{k#Vd}D^kna8XqF-aN^)zJ*%~jPn>%sCx89*Fm(Cn##zqBVoeIqH{GpMUR6KG z_ONodWB$=+lP_~UnX9pX?kb~x*UI-HkC*GSe^h<4FYKt{{FQabS2We=OSN*;Ya8WR zW~}B&vOe^at~G6%#=J#zNwds? zr3$f67~ZnHRAJ9h^)R<|kan~>#Td26pj*lPPrm8Kk8@c?->}3UJ|UjQWy@YvFuBfE z&2Od;>r1OOcT&_&uvjVxJ1#rHxRTq*lh4Dn+jXMwgtbl2E~b1g*?!aawa&5&#VI$n zGA0Sm|2cQ@oV!7SDYrHhP2Qm}`Dud->r6d%6}66LnF$>VdPNRznv$k$Rz9`L-%)FN zW$s5h>^&+SyJZ&WXgFJLdegRO z&e{}>RKwuvJ}<9@jNP)*kT;!s7Vxnry)-esX>4j< zuEs5XNkO;jnq275;^NP}S#nF7HoTDYUbgb2*qz6r+jqP9@&`HoaAnfj^<0PZyV>3i z7pAP8$-d9=*4c}vy!M(HZ|+=rS$yp^<;%?9-}(o4%xF$*ohPiq-ojPX{6@`eqyPJ5 zJ`euXz| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_exposure_red_48dp.png b/app/src/main/res/drawable-mdpi/ic_exposure_red_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..2c800032750973bb67282a552f84a000c916fa17 GIT binary patch literal 616 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FU|>mi z^mSxl*x1kgCy|wbfq}EYBeIx*f$uN~Gak=hk;1^h_}A0LF(kwJ?abXlha5!On056N z4&Mlj3`l++9k8-z>(;q9eu~6trPXjqZ(V-j*tvxZHx*{|K0lv#?5=8K&Zg`yJW9ZM#J-da&$5D;zCk-K1Gg}`Npz*-SxZuWRIp?f?sU#O0^hCj#*|}dOR+|{IjGw zwB$?-6O`pxD;KeFU1KSJB_*?Y>Mpi5>ulCW2i$q?82l=4^5&510Xk3qxV@6-m}jQ7 zjV+>+-Ha`!%RGBg(Ye_ne^rkKCp~$aZpP()QP^&q|Fczx{ykhLx~x$$ZpleIYmeK) zrpAUs8EgRyD!5NvWH~Zk44ofy`glX=O&z`&C3 z=X4W0w?X-kxS6kb>;G3T3)_?uV{=2)|zrtK> zWy5A}y@@l9Jxnavvg=n@dGbWA0~zhxJCt4{=D&We z?8n0F6LE~eB6T)7TRu-US5CZ{IM4LzD_3QGM;DdtZ0z=%FP@XWmn$uFfsNyTO7UmG z?0*@unesvtCVc+jT58L=sr!S@?Y+5Qr&J!?_I~ZMG6VU_n_17!U;QBZd1i8d{FArY zDT)q1xG!IL_W7dIm6_|E8Kx?*mQ0^(pyJ>(?IE*}g2L+$jGP^c{UB0d{Rc)~=k*g* zYJ%GrUYqpg%<{w)Zl83l6FnFfulUgTovDjQzCw4wiw}+4nS40pD>M&G`OsL-Sw3qJf;4`;M&*?(x8<-s=3X*@P+ud2_R|KZDhVkT(( z@XU3?LayYqER{{I8JH)`-YZ!}Yy_WW_I6VvHeFTUTqXM9g|kqSe$Qc~`bc_&X=O{W1F` Q1_lNOPgg&ebxsLQ0657GIRF3v literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_exposure_red_48dp.png b/app/src/main/res/drawable-xxhdpi/ic_exposure_red_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..47818b9378c7334fe22a36859b39bdba3eb00a00 GIT binary patch literal 1624 zcmeAS@N?(olHy`uVBq!ia0y~yV3+{H9Bd2>4A0#j?OVX?8bWTm0p1^k4z_$L`jG)91^L|&I+j(Ap<{4XOhbMMBpWmzI2xfo-o6sxgH~vU3 z`uUl$nX7Vr!7U|HCIYZuo6noV@o!&c0PWefMN%%&A#p zFB7@(X3nd#AFidPt-CUPdVS^g9Y22FyEd&()NIm%UB`~!4{>wLF~YO{jn^>YVmd^ki5Zb--=~Bci&!a&TPDkU*&tpZOr?+{1@YzYh<8|2i>= z|J{dTvBwd>`w z*PcDYyW+V2THo(my49cj+qHC`--FVPI?P7D+$M{B{;wT+T(nmw}mv|-9bXFVT~L9Q_%ZK^RKZLBf9?g9bFV*1<#0@`Bw-30>NYC7Bn z0@!Lg-30T-;GEXX1fI1fZR-UE?BAGZhua2)w8&t&9c^WWWpt>d`? z6IVw?pPK`tfPXd17tSNaHcVD*A8Vu-w>sJ!6u2PRp>DzSi{s-A#RbeA$7Sjt`FR`3 zeJx(SN`0~U=1@7;zi~f=%QZb8o>2aHqR*sq2HW(`JM2fci2AN$R+{&sNLt|I5#{NO zg8nr{;sPI!XooWj`u`~s7Wk;5EY2wCU$lq6qhiw2QimgxZSt=ln$)9y@5;ut z_FJ8^(=*q!R!Rn3a+mY2=W8#kkz%YgZ#B$adU|z3hkETj78jeFACwdxo$UL}DCoa! z4qr#brsp{hN0QmqnU&SFV5qng5_!pWkHg8jRV_&X}@ zOv`jQ@_64FCM7xh6rljV$CXRuw)4n;vb^S9tJ|aOU$rNiTUqY^5;1{~KQyN{bR3WG zoXi}&BYpd#bH%cvZ#j3rm>m8gv*O0ZjqA)G&NTRa?T^Z?n>9iO(vG&gW`)_1q{)F-Ows2)6WWDO_da+RMP~p^t3)$!2-TAp4oY`;0Ma+03 zBUiVsyM=rGo9Ff%S*x^GL#`T(uDneX0x zyBfc5jfq(#)9Fb%{wHLg{hi%XU9DZTQtnyS>bVijzh8xVQKN;;Fu^Nproka;^ffL(jdUesMzH6F#cheb!NcRaCT5p?CI*~ Jvd$@?2>>ph3_*8t*cliY7>k44ofy`glX=O&z`&C3 z=fvP*7f)pox>^LwB1`x^TVZ_apM@cm@-``kY3*)k01 zpujKg?(uj3_SMGjRQO>RAAWr*_u**;d3k5g+}*vp>1F0u(GP*8$;s>XEnYlf{mROj zr=P1Ic1pAe4=t^@yE3@^%Jd^z@@)&Hjy+!A*m$qLt*x%2^!GP5!EZ;n*vmuBO-YLqhc|YtWvG91?{DW1H@%Jr-&xMjTe;Zb=aZX`A`hS4nXDeaet*Hk z^3oeCv`X`@JUKae{(0Nls^3SyzHX79c=GATZfSEf*7Ni4&$B2@+H93GVwTmCvk{E%zJD#D2SA2LnxeeReZ^uC8tn>3CDR zIx*$fdd5Q=TzeZ*Bu~uyCzO$w*DJ-;$<>^&R?2NzXv4yJ^U8KEjr47FIos27WA&C-`^8Y zn(=G*auJ5kD31TfqPHKrvM?l&LFL%C58fgSof{1Q2(dc6$>H7a!YH6U`>=jyty0d4 z<>~8pSO?EJ`YgI|wg%ta%UXHIyPW^85vgCCIvzb?xzs7&=tA zK?<~{O$E6`^kmQvRj!6jsk$H)k((syI++q&BYF29DSJ_2xnI`m+=tDwQeoY{XU>0n zVMExo>9*a04111G2kFiKsQE{T^+0_M_kI^fgY(BhV)xqO7ctEH46^UTjQ0u9c^EIn`hnr0elJss%)@v&))NMY_8W0c2yEGJ zBcjmEQU6oJ;h4a`QvnS;ihrgqW{`CJv3Mbaq{ENJiy8Wq|5Rx-9Ol?>$MrztP(B-L zfxtuab|#Cq53^kvWt@JTUChv@@aN+K20n#99~UxAQ~vXD5rdfWpO1?frYZe7xqv}T z>Cef94AT_3V*(xYEN9zHdXr7%bVKo&WWT)c+Gk!zJGpM z;q~Y_u4St0j^}CE*FO5lyQ=W0hC|P#x@X%J6Hae@_;Djk7w2g?^MD2kfx7YlhQl2D zqcs{FTkhM691uA4UX3e(;bFNr>jjq|cik9G1nRyAHgs^*n*}s*aMYItG;j(2%UQ@E zs_^HgGvg_jADcUwrZj#?7r(tQd_vlfqvylR?dw{vCElt?RIdSKYh=ZEr7# zBuHl3e@=h$Jlbf1nMi|b0H;p%9|y*14nO`nGTw9i@z;q_O!3dZg$!H|zYDVpaO~f| zN1x&0_u1E375;qK#?T@^X*#RIpNI#sj2!l2pI0%o$iM%zjG;x|`{N>p7Wt(q`xsi} zPoMnqoH2%f|Bs)a8fQ%X*f?Y9hco%^2c{(-eti0gP{)VGF*CIp9=fXeA%L^ACR6V#TE5o}#b5>HEZU zryR36RsKKz)z{ZFi>Y(f`!_l-^k#33XMU2M6}L)p!it*Guf?W4KL1?{?Ce*%Ic(xd z@!!pmxX@rto5P|*HzVJ^c{!hP)hfPlb5qxPRbH0`M&(N^y8U)Dy!M;B>+*%WwyTyo zD7idyyEfO(cG0qlFXuD1w5?mm{ArTN1eTdwf1Nv*eiVi}+agU_lN61=Rn^o?pOs}C*3f@`u5|95U8UZ>#h;~1 zISjl~v@`B(dU~37y58O3_AQyYtr4dlA3T`be}3NI!gnWylb;`^XXE*;P7g%&bjN1odYKMni!fkF d^*=58&t$Qnby?<3mEWN1+0)g}Wt~$(69A5{^;`e| literal 0 HcmV?d00001 -- GitLab From bc5923a5ad1a4897471519903824518d8490abd5 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 20:42:25 +0000 Subject: [PATCH 139/243] Aperture control, for devices that support this. (Camera2 API only.) --- _docs/help.html | 2 + _docs/history.html | 1 + .../sourceforge/opencamera/MainActivity.java | 6 +- .../opencamera/MyApplicationInterface.java | 25 +++++- .../cameracontroller/CameraController.java | 8 ++ .../cameracontroller/CameraController1.java | 5 ++ .../cameracontroller/CameraController2.java | 78 ++++++++++++++++++- .../preview/ApplicationInterface.java | 1 + .../preview/BasicApplicationInterface.java | 5 ++ .../opencamera/preview/Preview.java | 24 ++++++ .../opencamera/ui/DrawPreview.java | 7 ++ .../sourceforge/opencamera/ui/PopupView.java | 57 ++++++++++++++ app/src/main/res/values/strings.xml | 2 + 13 files changed, 215 insertions(+), 6 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 95df3b34b..7fe58a6f9 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -230,6 +230,8 @@ will be available which instead work by making the screen light up (note, front
  • Auto-level - Enable the auto-level feature for photos (see below). (Only available if the device has enough memory.)
  • +
  • Aperture - Allows changing the current camera aperture. Large numbers mean smaller aperture, which means less + light is allowed into the camera. (Only available on some devices, and if Camera2 API is used.)
  • Camera resolution - Change the photo resolution (also available under Settings/Photo Settings/"Camera resolution".
  • Video resolution - Change the photo resolution (also available under Settings/Video diff --git a/_docs/history.html b/_docs/history.html index 2d89d4b1d..58830ddec 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -73,6 +73,7 @@ ADDED New icon for switching between multiple cameras. If your device has mult Settings/On screen GUI/"Multiple cameras icon". ADDED Current camera ID now displayed on-screen (next to date/time) for devices with multiple front/back cameras. This can be disabled under Settings/Camera preview/"Show camera ID". +ADDED Aperture control, for devices that support this. (Camera2 API only.) ADDED Flash on and torch now supported for manual ISO/exposure. ADDED Option to specify REC709 or sRGB profile for video recording. ADDED New custom gamma profile option for video recording. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 919e19ffe..caa8f02b9 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1201,7 +1201,7 @@ public class MainActivity extends Activity { updateGalleryIcon(); // update in case images deleted whilst idle - applicationInterface.reset(); // should be called before opening the camera in preview.onResume() + applicationInterface.reset(false); // should be called before opening the camera in preview.onResume() preview.onResume(); @@ -1699,7 +1699,7 @@ public class MainActivity extends Activity { // prevent slowdown if user repeatedly clicks: switchCameraButton.setEnabled(false); switchMultiCameraButton.setEnabled(false); - applicationInterface.reset(); + applicationInterface.reset(true); this.preview.setCamera(cameraId); switchCameraButton.setEnabled(true); switchMultiCameraButton.setEnabled(true); @@ -1777,7 +1777,7 @@ public class MainActivity extends Activity { View switchVideoButton = findViewById(R.id.switch_video); switchVideoButton.setEnabled(false); // prevent slowdown if user repeatedly clicks - applicationInterface.reset(); + applicationInterface.reset(false); this.preview.switchVideo(false, true); switchVideoButton.setEnabled(true); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 24c5d442b..5cb0f46ff 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -137,6 +137,8 @@ public class MyApplicationInterface extends BasicApplicationInterface { private int cameraId = cameraId_default; private final static String nr_mode_default = "preference_nr_mode_normal"; private String nr_mode = nr_mode_default; + private final static float aperture_default = -1.0f; + private float aperture = aperture_default; // camera properties that aren't saved even in the bundle; these should be initialised/reset in reset() private int zoom_factor; // don't save zoom, as doing so tends to confuse users; other camera applications don't seem to save zoom when pause/resuming @@ -164,7 +166,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { this.imageSaver = new ImageSaver(main_activity); this.imageSaver.start(); - this.reset(); + this.reset(false); if( savedInstanceState != null ) { // load the things we saved in onSaveInstanceState(). if( MyDebug.LOG ) @@ -176,6 +178,9 @@ public class MyApplicationInterface extends BasicApplicationInterface { nr_mode = savedInstanceState.getString("nr_mode", nr_mode_default); if( MyDebug.LOG ) Log.d(TAG, "found nr_mode: " + nr_mode); + aperture = savedInstanceState.getFloat("aperture", aperture_default); + if( MyDebug.LOG ) + Log.d(TAG, "found aperture: " + aperture); } if( MyDebug.LOG ) @@ -195,6 +200,9 @@ public class MyApplicationInterface extends BasicApplicationInterface { if( MyDebug.LOG ) Log.d(TAG, "save nr_mode: " + nr_mode); state.putString("nr_mode", nr_mode); + if( MyDebug.LOG ) + Log.d(TAG, "save aperture: " + aperture); + state.putFloat("aperture", aperture); } void onDestroy() { @@ -1429,6 +1437,15 @@ public class MyApplicationInterface extends BasicApplicationInterface { return NRModePref.NRMODE_NORMAL; } + public void setAperture(float aperture) { + this.aperture = aperture; + } + + @Override + public float getAperturePref() { + return aperture; + } + @Override public int getExpoBracketingNImagesPref() { if( MyDebug.LOG ) @@ -2730,9 +2747,13 @@ public class MyApplicationInterface extends BasicApplicationInterface { /** Should be called to reset parameters which aren't expected to be saved (e.g., resetting zoom when application is paused, * when switching between photo/video modes, or switching cameras). */ - void reset() { + void reset(boolean switched_camera) { if( MyDebug.LOG ) Log.d(TAG, "reset"); + if( switched_camera ) { + // aperture is reset when switching camera, but not when application is paused or switching between photo/video etc + this.aperture = aperture_default; + } this.zoom_factor = 0; } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 546f5b4bf..228f501a8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -65,6 +65,7 @@ public abstract class CameraController { public List preview_sizes; public List supported_flash_values; public List supported_focus_values; + public float [] apertures; // may be null if not supported, else will have at least 2 values public int max_num_focus_areas; public float minimum_focus_distance; public boolean is_exposure_lock_supported; @@ -360,6 +361,7 @@ public abstract class CameraController { public abstract int getISO(); public abstract long getExposureTime(); public abstract boolean setExposureTime(long exposure_time); + public abstract void setAperture(float aperture); public abstract CameraController.Size getPictureSize(); public abstract void setPictureSize(int width, int height); public abstract CameraController.Size getPreviewSize(); @@ -601,6 +603,12 @@ public abstract class CameraController { } public long captureResultFrameDuration() { return 0; + } + public boolean captureResultHasAperture() { + return false; + } + public float captureResultAperture() { + return 0.0f; } /*public boolean captureResultHasFocusDistance() { return false; diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 87539a61a..100fdb20b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -717,6 +717,11 @@ public class CameraController1 extends CameraController { return false; } + @Override + public void setAperture(float aperture) { + // not supported for CameraController1 + } + @Override public CameraController.Size getPictureSize() { /*Camera.Parameters parameters = this.getParameters(); diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index b3216da8f..27831dbd6 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -330,6 +330,8 @@ public class CameraController2 extends CameraController { private long capture_result_exposure_time; private boolean capture_result_has_frame_duration; private long capture_result_frame_duration; + private boolean capture_result_has_aperture; + private float capture_result_aperture; /*private boolean capture_result_has_focus_distance; private float capture_result_focus_distance_min; private float capture_result_focus_distance_max;*/ @@ -389,6 +391,8 @@ public class CameraController2 extends CameraController { //private int flash_mode = CameraMetadata.FLASH_MODE_OFF; private int iso; private long exposure_time = EXPOSURE_TIME_DEFAULT; + private boolean has_aperture; + private float aperture; private Rect scalar_crop_region; // no need for has_scalar_crop_region, as we can set to null instead private boolean has_ae_exposure_compensation; private int ae_exposure_compensation; @@ -703,6 +707,19 @@ public class CameraController2 extends CameraController { return changed; } + private boolean setAperture(CaptureRequest.Builder builder) { + if( MyDebug.LOG ) + Log.d(TAG, "setAperture"); + // don't set at all if has_aperture==false + if( has_aperture ) { + if( MyDebug.LOG ) + Log.d(TAG, " aperture: " + aperture); + builder.set(CaptureRequest.LENS_APERTURE, aperture); + return true; + } + return false; + } + private boolean setAEMode(CaptureRequest.Builder builder, boolean is_still) { if( MyDebug.LOG ) Log.d(TAG, "setAEMode"); @@ -2755,6 +2772,15 @@ public class CameraController2 extends CameraController { if( MyDebug.LOG ) Log.d(TAG, "supports_tonemap_curve?: " + camera_features.supports_tonemap_curve); + float [] apertures = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES); + //float [] apertures = new float[]{1.5f, 1.9f, 2.0f, 2.2f, 2.4f, 4.0f, 8.0f, 16.0f}; // test + if( MyDebug.LOG ) + Log.d(TAG, "apertures: " + Arrays.toString(apertures)); + // no point supporting if only a single aperture + if( apertures != null && apertures.length > 1 ) { + camera_features.apertures = apertures; + } + SizeF view_angle = CameraControllerManager2.computeViewAngles(characteristics); camera_features.view_angle_x = view_angle.getWidth(); camera_features.view_angle_y = view_angle.getHeight(); @@ -3671,6 +3697,33 @@ public class CameraController2 extends CameraController { return true; } + @Override + public void setAperture(float aperture) { + if( MyDebug.LOG ) { + Log.d(TAG, "setAperture: " + aperture); + Log.d(TAG, "current aperture: " + camera_settings.aperture); + } + if( camera_settings.has_aperture && camera_settings.aperture == aperture ) { + if( MyDebug.LOG ) + Log.d(TAG, "already set"); + } + try { + camera_settings.has_aperture = true; + camera_settings.aperture = aperture; + if( camera_settings.setAperture(previewBuilder) ) { + setRepeatingRequest(); + } + } + catch(CameraAccessException e) { + if( MyDebug.LOG ) { + Log.e(TAG, "failed to set aperture"); + Log.e(TAG, "reason: " + e.getReason()); + Log.e(TAG, "message: " + e.getMessage()); + } + e.printStackTrace(); + } + } + @Override public Size getPictureSize() { return new Size(picture_width, picture_height); @@ -7091,7 +7144,17 @@ public class CameraController2 extends CameraController { public long captureResultFrameDuration() { return capture_result_frame_duration; } - + + @Override + public boolean captureResultHasAperture() { + return capture_result_has_aperture; + } + + @Override + public float captureResultAperture() { + return capture_result_aperture; + } + /* @Override public boolean captureResultHasFocusDistance() { @@ -7738,6 +7801,19 @@ public class CameraController2 extends CameraController { else { capture_result_has_focus_distance = false; }*/ + if( modified_from_camera_settings ) { + // see note above + } + else if( result.get(CaptureResult.LENS_APERTURE) != null ) { + capture_result_has_aperture = true; + capture_result_aperture = result.get(CaptureResult.LENS_APERTURE); + /*if( MyDebug.LOG ) { + Log.d(TAG, "capture_result_aperture: " + capture_result_aperture); + }*/ + } + else { + capture_result_has_aperture = false; + } { RggbChannelVector vector = result.get(CaptureResult.COLOR_CORRECTION_GAINS); if( modified_from_camera_settings ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java index 611da7b3e..c3475250b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java @@ -154,6 +154,7 @@ public interface ApplicationInterface { NRMODE_LOW_LIGHT } NRModePref getNRModePref(); // only relevant if getBurstForNoiseReduction() returns true; if this changes without reopening the preview's camera, call Preview.setupBurstMode() + float getAperturePref(); // get desired aperture (called if Preview.getSupportedApertures() returns non-null); return -1.0f for no preference boolean getOptimiseAEForDROPref(); // see CameraController doc for setOptimiseAEForDRO(). enum RawPref { RAWPREF_JPEG_ONLY, // JPEG only diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java index 9b214f384..58395005f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/BasicApplicationInterface.java @@ -348,6 +348,11 @@ public abstract class BasicApplicationInterface implements ApplicationInterface return NRModePref.NRMODE_NORMAL; } + @Override + public float getAperturePref() { + return -1.0f; + } + @Override public boolean getOptimiseAEForDROPref() { return false; diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index fe11102dc..215602656 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -317,6 +317,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private boolean can_disable_shutter_sound; private int tonemap_max_curve_points; private boolean supports_tonemap_curve; + private float [] supported_apertures; private boolean has_focus_area; private int focus_screen_x; private int focus_screen_y; @@ -2055,6 +2056,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu this.can_disable_shutter_sound = camera_features.can_disable_shutter_sound; this.tonemap_max_curve_points = camera_features.tonemap_max_curve_points; this.supports_tonemap_curve = camera_features.supports_tonemap_curve; + this.supported_apertures = camera_features.apertures; this.supports_white_balance_temperature = camera_features.supports_white_balance_temperature; this.min_temperature = camera_features.min_temperature; this.max_temperature = camera_features.max_temperature; @@ -2539,6 +2541,20 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Log.d(TAG, "setupCameraParameters: time after exposures: " + (System.currentTimeMillis() - debug_time)); } + if( supported_apertures != null ) { + // set up aperture + float aperture = applicationInterface.getAperturePref(); + if( aperture > 0.0f ) { + // check supported + for(float this_aperture : supported_apertures) { + if( this_aperture == aperture ) { + camera_controller.setAperture(aperture); + } + } + // else don't set any aperture (leave as the device default) + } + } + { if( MyDebug.LOG ) Log.d(TAG, "set up picture sizes"); @@ -6610,6 +6626,14 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return supports_tonemap_curve; } + /** Return the supported apertures for this camera. + */ + public float [] getSupportedApertures() { + if( MyDebug.LOG ) + Log.d(TAG, "getSupportedApertures"); + return supported_apertures; + } + public List getSupportedColorEffects() { if( MyDebug.LOG ) Log.d(TAG, "getSupportedColorEffects"); diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index fe81c5d00..67c452b89 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -112,6 +112,7 @@ public class DrawPreview { private final DateFormat dateFormatTimeInstance = DateFormat.getTimeInstance(); private final String ybounds_text; private final int [] temp_histogram_channel = new int[256]; + //private final DecimalFormat decimal_format_1dp_force0 = new DecimalFormat("0.0"); // cached Rects for drawTextWithBackground() calls private Rect text_bounds_time; private Rect text_bounds_camera_id; @@ -1223,6 +1224,12 @@ public class DrawPreview { iso_exposure_string += " "; iso_exposure_string += preview.getFrameDurationString(frame_duration); } + /*if( camera_controller.captureResultHasAperture() ) { + float aperture = camera_controller.captureResultAperture(); + if( iso_exposure_string.length() > 0 ) + iso_exposure_string += " F"; + iso_exposure_string += decimal_format_1dp_force0.format(aperture); + }*/ is_scanning = false; if( camera_controller.captureResultIsAEScanning() ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index 7376ca8a8..a45a190fb 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -8,6 +8,7 @@ import net.sourceforge.opencamera.R; import net.sourceforge.opencamera.cameracontroller.CameraController; import net.sourceforge.opencamera.preview.Preview; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -69,6 +70,8 @@ public class PopupView extends LinearLayout { private int repeat_mode_index = -1; private int grid_index = -1; + private final DecimalFormat decimal_format_1dp_force0 = new DecimalFormat("0.0"); + public PopupView(Context context) { super(context); if( MyDebug.LOG ) @@ -502,6 +505,60 @@ public class PopupView extends LinearLayout { if( MyDebug.LOG ) Log.d(TAG, "PopupView time 10: " + (System.nanoTime() - debug_time)); + if( preview.getSupportedApertures() != null ) { + if( MyDebug.LOG ) + Log.d(TAG, "add apertures"); + + addTitleToPopup(getResources().getString(R.string.aperture)); + + final List apertures = new ArrayList<>(); + final List apertures_strings = new ArrayList<>(); + float current_aperture = main_activity.getApplicationInterface().getAperturePref(); + String prefix = "F/"; + + boolean found_default = false; + String current_aperture_s = ""; + for(float aperture : preview.getSupportedApertures()) { + apertures.add(aperture); + String aperture_string = prefix + decimal_format_1dp_force0.format(aperture); + apertures_strings.add(aperture_string); + if( current_aperture == aperture ) { + found_default = true; + current_aperture_s = aperture_string; + } + } + + if( !found_default ) { + // read from Camera API + if( preview.getCameraController() != null && preview.getCameraController().captureResultHasAperture() ) { + current_aperture = preview.getCameraController().captureResultAperture(); + current_aperture_s = prefix + decimal_format_1dp_force0.format(current_aperture); + } + } + + addButtonOptionsToPopup(apertures_strings, -1, -1, "", current_aperture_s, 0, "TEST_APERTURE", new ButtonOptionsPopupListener() { + @Override + public void onClick(String option) { + if( MyDebug.LOG ) + Log.d(TAG, "clicked aperture: " + option); + int index = apertures_strings.indexOf(option); + if( index != -1 ) { + float new_aperture = apertures.get(index); + if( MyDebug.LOG ) + Log.d(TAG, "new_aperture: " + new_aperture); + main_activity.getApplicationInterface().setAperture(new_aperture); + if( preview.getCameraController() != null ) { + preview.getCameraController().setAperture(new_aperture); + } + } + else { + Log.e(TAG, "unknown aperture: " + option); + } + main_activity.getMainUI().destroyPopup(); // need to recreate popup for new selection + } + }); + } + if( !preview.isVideo() && photo_mode == MyApplicationInterface.PhotoMode.FastBurst ) { if( MyDebug.LOG ) Log.d(TAG, "add fast burst options"); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 31539b3d3..dc0028a12 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -978,6 +978,8 @@ Allow long press actions Whether to allow long press actions (e.g., long press on gallery to change save location). + Aperture + Privacy policy -- GitLab From 02060767f9e49799b9127803548a48ec9db08d4d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 20:43:53 +0000 Subject: [PATCH 140/243] Update comment now that flash supported for manual ISO. --- .../main/java/net/sourceforge/opencamera/preview/Preview.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 215602656..a0f9f8f2b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -2399,7 +2399,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } } - // must be done before setting flash modes, as we may remove flash modes if in manual mode + // must be done before setting flash modes, as we may remove flash modes if in manual mode (update: we now support flash for manual ISO anyway) if( MyDebug.LOG ) Log.d(TAG, "set up iso"); String value = applicationInterface.getISOPref(); -- GitLab From d39ab56d854c9f85abe8c933f2c9066c6f3bc26e Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 20:44:10 +0000 Subject: [PATCH 141/243] Improve look of popup menu, apply dark grek to titles. --- app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index a45a190fb..d0cacd7f0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -1471,6 +1471,7 @@ public class PopupView extends LinearLayout { text_view.setTextSize(TypedValue.COMPLEX_UNIT_DIP, title_text_size_dip); text_view.setTypeface(null, Typeface.BOLD); //text_view.setBackgroundColor(Color.GRAY); // debug + text_view.setBackgroundColor(Color.argb(255, 32, 32, 32)); this.addView(text_view); } -- GitLab From b3521a7591fd3f4bdfae9f8c578bc33565aa0cfd Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 21:02:49 +0000 Subject: [PATCH 142/243] Fix photo resolution text being too large for some devices. --- .../main/java/net/sourceforge/opencamera/ui/PopupView.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index d0cacd7f0..5dcd97567 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -1705,10 +1705,17 @@ public class PopupView extends LinearLayout { final TextView text_view = new TextView(this.getContext()); setArrayOptionsText(supported_options, title, text_view, title_in_options, title_in_options_first_only, current_index); + //text_view.setBackgroundColor(Color.GRAY); // debug text_view.setTextSize(TypedValue.COMPLEX_UNIT_DIP, standard_text_size_dip); text_view.setTextColor(Color.WHITE); text_view.setGravity(Gravity.CENTER); + text_view.setSingleLine(true); // if text too long for the button, we'd rather not have wordwrap, even if it means cutting some text off LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f); + // Yuck! We want the arrow_button_w to be fairly large so that users can touch the arrow buttons easily, but if + // the text is too much for the button size, we'd rather it extend into the arrow buttons (which the user won't see + // anyway, since the button backgrounds are transparent). + // Needed for OnePlus 3T and Nokia 8, for camera resolution + params.setMargins(-arrow_button_w/2, 0, -arrow_button_w/2, 0); text_view.setLayoutParams(params); final float scale = getResources().getDisplayMetrics().density; -- GitLab From aea35842e54d32d17886dc271cec988f8ecf2d70 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 21:07:57 +0000 Subject: [PATCH 143/243] Display toast for changing aperture. --- app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index 5dcd97567..24bab7e4d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -546,6 +546,7 @@ public class PopupView extends LinearLayout { float new_aperture = apertures.get(index); if( MyDebug.LOG ) Log.d(TAG, "new_aperture: " + new_aperture); + preview.showToast(null, getResources().getString(R.string.aperture) + ": " + option); main_activity.getApplicationInterface().setAperture(new_aperture); if( preview.getCameraController() != null ) { preview.getCameraController().setAperture(new_aperture); -- GitLab From 793468c1aff5c9ddc13695fe71cacf4de362d337 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 15 Feb 2020 21:11:42 +0000 Subject: [PATCH 144/243] Fix typo. --- _docs/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 58830ddec..fa5880e9e 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -99,7 +99,7 @@ UPDATED Don't set video digital stabilization when in photo mode. UPDATED Disable some preferences if only relevant for another nearby option that isn't currently enabled. UPDATED Moved video bitrate and frame rate options to debugging section. -UPDATED Improved UI support for "external" cameras (if detecting with Camera2 API). +UPDATED Improved UI support for "external" cameras (if detected/supported with Camera2 API). UPDATED Improved placement of on-screen text (zoom, video recording time etc) to avoid focus seekbars in landscape mode. UPDATED Improved look of on-screen text for manual/exposure sliders. -- GitLab From 56932517d0dc35627acb44ff2bb563668246598d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 14:01:46 +0000 Subject: [PATCH 145/243] updateCycleFlashIcon should update based on preview flash, rather than saved user pref, in case different (e.g., flash auto not supported for manual ISO). --- .../java/net/sourceforge/opencamera/ui/MainUI.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 58716961f..338eb2c90 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -1276,7 +1276,7 @@ public class MainUI { } public void updateCycleFlashIcon() { - String flash_value = main_activity.getApplicationInterface().getFlashPref(); + String flash_value = main_activity.getPreview().getCurrentFlashValue(); if( flash_value != null ) { ImageButton view = main_activity.findViewById(R.id.cycle_flash); switch( flash_value ) { @@ -1298,8 +1298,17 @@ public class MainUI { case "flash_red_eye": view.setImageResource(R.drawable.baseline_remove_red_eye_white_48); break; + default: + // just in case?? + Log.e(TAG, "unknown flash value " + flash_value); + view.setImageResource(R.drawable.flash_off); + break; } } + else { + ImageButton view = main_activity.findViewById(R.id.cycle_flash); + view.setImageResource(R.drawable.flash_off); + } } public void updateFaceDetectionIcon() { -- GitLab From bbe6430b66c3b77021d51e16d108caf3229ab8b6 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 14:01:59 +0000 Subject: [PATCH 146/243] Use material design palette for grey. --- app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index 24bab7e4d..356f64bc3 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -1472,7 +1472,7 @@ public class PopupView extends LinearLayout { text_view.setTextSize(TypedValue.COMPLEX_UNIT_DIP, title_text_size_dip); text_view.setTypeface(null, Typeface.BOLD); //text_view.setBackgroundColor(Color.GRAY); // debug - text_view.setBackgroundColor(Color.argb(255, 32, 32, 32)); + text_view.setBackgroundColor(Color.argb(255, 33, 33, 33)); // Grey 900 this.addView(text_view); } -- GitLab From b285ac1aa4105f4c931eb9506ef730b171345820 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 15:06:46 +0000 Subject: [PATCH 147/243] Shouldn't offer manual white balance if capabilities_manual_post_processing==false (previously we'd have offered the option, but not shown the temperature seekbar). --- _docs/history.html | 3 +++ .../opencamera/cameracontroller/CameraController2.java | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index fa5880e9e..159bfe2bd 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -66,6 +66,9 @@ FIXED Incorrect layout for on-screen text when using "icons along top" with wi ratio and device held in upside-down landscape orientation. FIXED Focus seekbars overlapped with histogram in widescreen aspect ratio when using "Icons along top" UI placement. +FIXED Was incorrectly offering manual white balance even if camera didn't support this + (inconsistency that the manual white balance option showed, even though the manual white + balance temperature seekbar wasn't shown). ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 27831dbd6..000bb58cf 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -79,6 +79,7 @@ public class CameraController2 extends CameraController { private boolean supports_face_detect_mode_full; private boolean supports_optical_stabilization; private boolean supports_photo_video_recording; + private boolean supports_white_balance_temperature; private final static int tonemap_log_max_curve_points_c = 64; private final static float [] jtlog_values_base = new float[] { @@ -2711,6 +2712,10 @@ public class CameraController2 extends CameraController { int [] white_balance_modes = characteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES); if( white_balance_modes != null ) { for(int value : white_balance_modes) { + // n.b., Galaxy S10e for front and ultra-wide cameras offers CONTROL_AWB_MODE_OFF despite + // capabilities_manual_post_processing==false; if we don't check for capabilities_manual_post_processing, + // adjusting white balance temperature seems to work, but seems safest to require + // capabilities_manual_post_processing anyway if( value == CameraMetadata.CONTROL_AWB_MODE_OFF && capabilities_manual_post_processing && allowManualWB() ) { camera_features.supports_white_balance_temperature = true; camera_features.min_temperature = min_white_balance_temperature_c; @@ -2718,6 +2723,7 @@ public class CameraController2 extends CameraController { } } } + supports_white_balance_temperature = camera_features.supports_white_balance_temperature; // see note above //if( capabilities_manual_sensor ) @@ -3148,7 +3154,7 @@ public class CameraController2 extends CameraController { for(int value2 : values2) { String this_value = convertWhiteBalance(value2); if( this_value != null ) { - if( value2 == CameraMetadata.CONTROL_AWB_MODE_OFF && !allowManualWB() ) { + if( value2 == CameraMetadata.CONTROL_AWB_MODE_OFF && !supports_white_balance_temperature ) { // filter } else { -- GitLab From c61e7bc1dbc96a2176538ca402c8b4b758ae892d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 15:07:06 +0000 Subject: [PATCH 148/243] Update comment. --- app/src/main/java/net/sourceforge/opencamera/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index caa8f02b9..d5aae351f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1784,7 +1784,7 @@ public class MainActivity extends Activity { mainUI.setTakePhotoIcon(); mainUI.setPopupIcon(); // needed as turning to video mode or back can turn flash mode off or back on - // ensure icons invisible if they're affected by being in video mode or not + // ensure icons invisible if they're affected by being in video mode or not (e.g., on-screen RAW icon) // (if enabling them, we'll make the icon visible later on) checkDisableGUIIcons(); -- GitLab From c4fc245b65f7b2bafeacaaabd19d78231f6b80ab Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 15:09:05 +0000 Subject: [PATCH 149/243] Implement skip_torch in cycleTorch() (skip_torch was always true, so no change of behaviour). --- .../main/java/net/sourceforge/opencamera/preview/Preview.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index a0f9f8f2b..d9f870617 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -4554,7 +4554,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Log.d(TAG, "cycleFlash()"); if( supported_flash_values != null ) { int new_flash_index = (current_flash_index+1) % supported_flash_values.size(); - if( supported_flash_values.get(new_flash_index).equals("flash_torch") ) { + if( skip_torch && supported_flash_values.get(new_flash_index).equals("flash_torch") ) { if( MyDebug.LOG ) Log.d(TAG, "cycle past torch"); new_flash_index = (new_flash_index+1) % supported_flash_values.size(); -- GitLab From 8e6a3687cce50dcca35fcbd7f5c55dcbc1e0f496 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 16:07:40 +0000 Subject: [PATCH 150/243] Add comment for recent updateCycleFlashIcon() change. --- app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 338eb2c90..171f11c26 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -1276,6 +1276,8 @@ public class MainUI { } public void updateCycleFlashIcon() { + // n.b., read from preview rather than saved application preference - so the icon updates correctly when in flash + // auto mode, but user switches to manual ISO where flash auto isn't supported String flash_value = main_activity.getPreview().getCurrentFlashValue(); if( flash_value != null ) { ImageButton view = main_activity.findViewById(R.id.cycle_flash); -- GitLab From f0a7af433e1ff66ac95422823db1f21eece7149c Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 16:26:36 +0000 Subject: [PATCH 151/243] Need to update on-screen icons if not supported for that camera (e.g., flash, RAW). --- _docs/history.html | 2 ++ .../sourceforge/opencamera/MainActivity.java | 25 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 159bfe2bd..9b31378ac 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -69,6 +69,8 @@ FIXED Focus seekbars overlapped with histogram in widescreen aspect ratio when FIXED Was incorrectly offering manual white balance even if camera didn't support this (inconsistency that the manual white balance option showed, even though the manual white balance temperature seekbar wasn't shown). +FIXED Option on-screen icons (such as flash, RAW) weren't updating correctly if switching to a + camera that didn't support that feature. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index d5aae351f..f0694fc7b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -2453,45 +2453,60 @@ public class MainActivity extends Activity { } } - private void checkDisableGUIIcons() { + /** Disables the optional on-screen icons if either user doesn't want to enable them, or not + * supported). Note that displaying icons is done via MainUI.showGUI. + * @return Whether an icon's visibility was changed. + */ + private boolean checkDisableGUIIcons() { if( MyDebug.LOG ) Log.d(TAG, "checkDisableGUIIcons"); + boolean changed = false; if( !mainUI.showExposureLockIcon() ) { View button = findViewById(R.id.exposure_lock); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showWhiteBalanceLockIcon() ) { View button = findViewById(R.id.white_balance_lock); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showCycleRawIcon() ) { View button = findViewById(R.id.cycle_raw); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showStoreLocationIcon() ) { View button = findViewById(R.id.store_location); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showTextStampIcon() ) { View button = findViewById(R.id.text_stamp); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showStampIcon() ) { View button = findViewById(R.id.stamp); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showAutoLevelIcon() ) { View button = findViewById(R.id.auto_level); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showCycleFlashIcon() ) { View button = findViewById(R.id.cycle_flash); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } if( !mainUI.showFaceDetectionIcon() ) { View button = findViewById(R.id.face_detection); + changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } + return changed; } public MyPreferenceFragment getPreferenceFragment() { @@ -4141,6 +4156,14 @@ public class MainActivity extends Activity { View exposureButton = findViewById(R.id.exposure); exposureButton.setVisibility(supportsExposureButton() && !mainUI.inImmersiveMode() ? View.VISIBLE : View.GONE); + // needed as availability of some icons is per-camera (e.g., flash, RAW) + // for making icons visible, this is done elsewhere in call to MainUI.showGUI() + if( checkDisableGUIIcons() ) { + if( MyDebug.LOG ) + Log.d(TAG, "cameraSetup: need to layoutUI as we hid some icons"); + mainUI.layoutUI(); + } + // need to update some icons, e.g., white balance and exposure lock due to them being turned off when pause/resuming mainUI.updateOnScreenIcons(); -- GitLab From 84c3310e32c1a96692daf0b260c149b63d6deca2 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 16:50:44 +0000 Subject: [PATCH 152/243] Don't show on-screen flash icon in video mode (since this icon doesn't show torch, and flash auto/on not supported in video mode); also fix Preview.cycleFlash to behave sensibly in video mode anyway. --- _docs/history.html | 2 + .../opencamera/preview/Preview.java | 37 ++++++++++++++++--- .../net/sourceforge/opencamera/ui/MainUI.java | 2 + 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 9b31378ac..8c7c73c2e 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -71,6 +71,8 @@ FIXED Was incorrectly offering manual white balance even if camera didn't supp balance temperature seekbar wasn't shown). FIXED Option on-screen icons (such as flash, RAW) weren't updating correctly if switching to a camera that didn't support that feature. +FIXED Don't show on-screen flash icon in video mode (since this icon doesn't show torch, and flash + auto/on not supported in video mode). ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index d9f870617..1ed375d75 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -4554,12 +4554,39 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Log.d(TAG, "cycleFlash()"); if( supported_flash_values != null ) { int new_flash_index = (current_flash_index+1) % supported_flash_values.size(); - if( skip_torch && supported_flash_values.get(new_flash_index).equals("flash_torch") ) { - if( MyDebug.LOG ) - Log.d(TAG, "cycle past torch"); - new_flash_index = (new_flash_index+1) % supported_flash_values.size(); + int start_index = new_flash_index; + boolean done = false; + while( !done ) { + done = true; + + if( skip_torch && supported_flash_values.get(new_flash_index).equals("flash_torch") ) { + if( MyDebug.LOG ) + Log.d(TAG, "cycle past torch"); + new_flash_index = (new_flash_index+1) % supported_flash_values.size(); + // don't bother setting done to false as we shouldn't have two torches in a row... + } + + if( is_video ) { + // check supported for video + String new_flash_value = supported_flash_values.get(new_flash_index); + if( !isFlashSupportedForVideo(new_flash_value) ) { + if( MyDebug.LOG ) + Log.d(TAG, "cycle past flash mode not supported for video: " + new_flash_value); + new_flash_index = (new_flash_index+1) % supported_flash_values.size(); + done = false; + } + } + + if( !done && new_flash_index == start_index ) { + // just in case, prevent infinite loop + Log.e(TAG, "flash looped to start - couldn't find valid flash!"); + break; + } + } + + if( done ) { + updateFlash(new_flash_index, save); } - updateFlash(new_flash_index, save); } } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 171f11c26..3c0f72a3f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -1010,6 +1010,8 @@ public class MainUI { public boolean showCycleFlashIcon() { if( !main_activity.getPreview().supportsFlash() ) return false; + if( main_activity.getPreview().isVideo() ) + return false; // no point showing flash icon in video mode, as we only allow flash auto and flash torch, and we don't support torch on the on-screen cycle flash icon SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(main_activity); return sharedPreferences.getBoolean(PreferenceKeys.ShowCycleFlashPreferenceKey, false); } -- GitLab From 7f562b211f0ade95b851f3c51a2be5646a064958 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 16 Feb 2020 20:26:40 +0000 Subject: [PATCH 153/243] Fix multi-cam icon showing if in immersive mode, when screen is turned off and on. --- .../java/net/sourceforge/opencamera/MainActivity.java | 9 ++++++++- .../main/java/net/sourceforge/opencamera/ui/MainUI.java | 3 --- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index f0694fc7b..c242828a1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1950,7 +1950,7 @@ public class MainActivity extends Activity { //case "preference_show_take_photo": // need to update the UI case "preference_show_toasts": case "preference_show_whats_new": - case "preference_multi_cam_button": + //case "preference_multi_cam_button": // need to update the UI case "preference_keep_display_on": case "preference_max_brightness": //case "preference_resolution": // need to set up camera controller and preview @@ -2506,6 +2506,13 @@ public class MainActivity extends Activity { changed = changed || (button.getVisibility() != View.GONE); button.setVisibility(View.GONE); } + if( !showSwitchMultiCamIcon() ) { + // also handle the multi-cam icon here, as this can change when switching between front/back cameras + // (e.g., if say a device only has multiple back cameras) + View button = findViewById(R.id.switch_multi_camera); + changed = changed || (button.getVisibility() != View.GONE); + button.setVisibility(View.GONE); + } return changed; } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 3c0f72a3f..01599e153 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -1334,9 +1334,6 @@ public class MainUI { this.updateAutoLevelIcon(); this.updateCycleFlashIcon(); this.updateFaceDetectionIcon(); - - View switchMultiCameraButton = main_activity.findViewById(R.id.switch_multi_camera); - switchMultiCameraButton.setVisibility(main_activity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE); } public void audioControlStarted() { -- GitLab From 657bac373f7a6d41cd0dba7d1002466f68e76b26 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 17 Feb 2020 23:12:08 +0000 Subject: [PATCH 154/243] Can't use try-with-resources yet due to min Android version. --- .../java/net/sourceforge/opencamera/StorageUtils.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index 5f5ec835f..3abcbbf98 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -527,7 +527,9 @@ public class StorageUtils { } String result = null; if( uri.getScheme() != null && uri.getScheme().equals("content") ) { - try( Cursor cursor = context.getContentResolver().query(uri, null, null, null, null) ) { + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(uri, null, null, null, null); if( cursor != null && cursor.moveToFirst() ) { final int column_index = cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME); result = cursor.getString(column_index); @@ -540,6 +542,10 @@ public class StorageUtils { Log.e(TAG, "Exception trying to find filename"); e.printStackTrace(); } + finally { + if (cursor != null) + cursor.close(); + } } if( result == null ) { if( MyDebug.LOG ) -- GitLab From 16750f40e79f35dc5f87b90f2e93f258d75b321c Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 17 Feb 2020 23:12:25 +0000 Subject: [PATCH 155/243] getFileName() can be package visibility. --- app/src/main/java/net/sourceforge/opencamera/StorageUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index 3abcbbf98..1bc99da7e 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -520,7 +520,7 @@ public class StorageUtils { * See https://developer.android.com/guide/topics/providers/document-provider.html and * http://stackoverflow.com/questions/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content . */ - public String getFileName(Uri uri) { + String getFileName(Uri uri) { if( MyDebug.LOG ) { Log.d(TAG, "getFileName: " + uri); Log.d(TAG, "uri has path: " + uri.getPath()); -- GitLab From 15e65c503ffb9bd1af042656f842900b9d8f179f Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 17 Feb 2020 23:25:41 +0000 Subject: [PATCH 156/243] Mark some strings as non-translatable. --- app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values/strings.xml | 30 +++++++++++----------- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7e770d362..eefe64dd8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -293,7 +293,6 @@ HDR Expo {} Belichtungsreihe - []]] Schnelle Fotofolge NR Rauschunterdrückung diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 81f2e7e88..cae3bb329 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -292,7 +292,6 @@ HDR BKT {} Horquillado de exposición - []]] Ráfaga rápida NR Reducción de ruido diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1baca9848..997ce851e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -293,7 +293,6 @@ HDR Expo {} Брекетинг экспозиции - []]] Серийная съемка NR Снижение шума diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index bb8e3d0e3..38ee7f951 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -292,7 +292,7 @@ HDR EXPO Phơi sáng mở rộng - FB + Chụp nhanh NR Giảm nhiễu diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 93f505171..523966784 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -614,7 +614,7 @@ HDR 包围曝光 包围曝光(Expo) - []]] + 快速连拍 NR 降噪(NR) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dc0028a12..863a2629f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ - Open Camera + Open Camera Settings Popup settings OK (This message won\'t show again) @@ -293,7 +293,7 @@ HDR Expo {} Exposure Bracketing - []]] + []]] Fast Burst NR Noise Reduction @@ -982,10 +982,10 @@ - Privacy policy - Tap to display privacy policy - Online privacy policy - + Privacy policy + Tap to display privacy policy + Online privacy policy + Open Camera accesses camera sensor and microphone data to fulfil its purpose as a camera. Microphone is also used for the optional \"Audio control\". \nAccess to files is needed to save resultant photos and videos to your device. @@ -1000,26 +1000,26 @@ \n*Apps/services such as cloud services on your device may auto-upload photos and videos that are saved on your device. - + (Your audio may be sent to remote\n servers by Android to perform speech\n recognition.) - Open Source licences - Open Camera - Open Camera is © 2013–2020 Mark Harman, released under the GPL v3 or later. Tap here for full licence text and terms of service. - Google\'s Material Design icons - Open Camera uses icons from Google\'s Material Design icons + Open Source licences + Open Camera + Open Camera is © 2013–2020 Mark Harman, released under the GPL v3 or later. Tap here for full licence text and terms of service. + Google\'s Material Design icons + Open Camera uses icons from Google\'s Material Design icons (https://developer.android.com/design/downloads/index.html , https://design.google.com/icons/ , https://github.com/google/material-design-icons/ , https://google.github.io/material-design-icons/) under the Apache license version 2.0. Some icons include modifications. Tap here for full licence text. - Online licences - Please tap here for full online licensing information (opens in your browser). + Online licences + Please tap here for full online licensing information (opens in your browser). - + [This dialog is shown when Open Camera is updated. You can disable it under Settings/On screen GUI/Show What\'s New dialog.] \n\nv1.47.3:\n -- GitLab From ef7ac64a31579eb6149f7042a6e7512ab2b3e91e Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 18 Feb 2020 22:47:10 +0000 Subject: [PATCH 157/243] Fix some warnings. --- .../opencamera/test/MainActivityTest.java | 8 +------- .../sourceforge/opencamera/GyroSensor.java | 5 +---- .../sourceforge/opencamera/HDRProcessor.java | 4 ++-- .../sourceforge/opencamera/ImageSaver.java | 1 - .../sourceforge/opencamera/MainActivity.java | 2 +- .../opencamera/MyApplicationInterface.java | 2 +- .../opencamera/MyPreferenceFragment.java | 2 +- .../cameracontroller/CameraController2.java | 4 ++-- .../CameraControllerManager1.java | 1 - .../opencamera/preview/Preview.java | 20 ++++++------------- .../remotecontrol/BluetoothLeService.java | 2 +- .../opencamera/ui/DrawPreview.java | 4 ++-- 12 files changed, 18 insertions(+), 37 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index ec983e175..364131961 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -11721,7 +11721,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Tue, 18 Feb 2020 23:58:43 +0000 Subject: [PATCH 158/243] Fix warnings. --- .../opencamera/test/MainActivityTest.java | 357 ------------------ .../sourceforge/opencamera/HDRProcessor.java | 5 +- .../sourceforge/opencamera/MainActivity.java | 1 - .../sourceforge/opencamera/StorageUtils.java | 2 - .../cameracontroller/CameraController1.java | 2 +- .../cameracontroller/CameraController2.java | 4 +- .../opencamera/preview/Preview.java | 2 - .../net/sourceforge/opencamera/ui/MainUI.java | 4 - 8 files changed, 5 insertions(+), 372 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 364131961..e5413ce7f 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -5777,7 +5777,6 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 bitmaps, boolean release_bitmaps, Bitmap output_bitmap, float hdr_alpha, int n_tiles, boolean ce_preserve_blacks, DROTonemappingAlgorithm dro_tonemapping_algorithm) throws HDRProcessorException { + private void processSingleImage(List bitmaps, boolean release_bitmaps, Bitmap output_bitmap, float hdr_alpha, int n_tiles, boolean ce_preserve_blacks, DROTonemappingAlgorithm dro_tonemapping_algorithm) { if( MyDebug.LOG ) Log.d(TAG, "processSingleImage"); @@ -1263,10 +1263,9 @@ public class HDRProcessor { * @param bitmap_avg_align Should be supplied if allocation_avg_align is non-null, and stores * the bitmap corresponding to the allocation_avg_align. * @param time_s Time, for debugging. - * @throws HDRProcessorException */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - private AvgData processAvgCore(Allocation allocation_out, Allocation allocation_avg, Bitmap bitmap_avg, Bitmap bitmap_new, int width, int height, float avg_factor, int iso, float zoom_factor, Allocation allocation_avg_align, Bitmap bitmap_avg_align, long time_s) throws HDRProcessorException { + private AvgData processAvgCore(Allocation allocation_out, Allocation allocation_avg, Bitmap bitmap_avg, Bitmap bitmap_new, int width, int height, float avg_factor, int iso, float zoom_factor, Allocation allocation_avg_align, Bitmap bitmap_avg_align, long time_s) { if( MyDebug.LOG ) { Log.d(TAG, "processAvgCore"); Log.d(TAG, "iso: " + iso); diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 9ccbadd85..17a2640bc 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1761,7 +1761,6 @@ public class MainActivity extends Activity { /** * Toggles Photo/Video mode - * @param view */ public void clickedSwitchVideo(View view) { if( MyDebug.LOG ) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index 1bc99da7e..2e38daf98 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -750,8 +750,6 @@ public class StorageUtils { } break; case MEDIA_TYPE_PREFS: - mimeType = "text/xml"; - break; case MEDIA_TYPE_GYRO_INFO: mimeType = "text/xml"; break; diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 100fdb20b..d95240a68 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -1902,7 +1902,7 @@ public class CameraController1 extends CameraController { } @Override - public void initVideoRecorderPostPrepare(MediaRecorder video_recorder, boolean want_photo_video_recording) throws CameraControllerException { + public void initVideoRecorderPostPrepare(MediaRecorder video_recorder, boolean want_photo_video_recording) { // no further actions necessary } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 05b5afeaf..2d4b6eae9 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -4946,7 +4946,7 @@ public class CameraController2 extends CameraController { } @Override - public void setPreviewDisplay(SurfaceHolder holder) throws CameraControllerException { + public void setPreviewDisplay(SurfaceHolder holder) { if( MyDebug.LOG ) { Log.d(TAG, "setPreviewDisplay"); Log.e(TAG, "SurfaceHolder not supported for CameraController2!"); @@ -4956,7 +4956,7 @@ public class CameraController2 extends CameraController { } @Override - public void setPreviewTexture(TextureView texture) throws CameraControllerException { + public void setPreviewTexture(TextureView texture) { if( MyDebug.LOG ) Log.d(TAG, "setPreviewTexture"); if( this.texture != null ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 5ff7576b0..be092a61b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -20,7 +20,6 @@ import net.sourceforge.opencamera.preview.camerasurface.MySurfaceView; import net.sourceforge.opencamera.preview.camerasurface.MyTextureView; import java.io.File; -import java.io.FileNotFoundException; //import java.io.FileOutputStream; import java.io.IOException; //import java.io.OutputStream; @@ -69,7 +68,6 @@ import android.os.Bundle; //import android.os.Environment; import android.os.Handler; import android.os.ParcelFileDescriptor; -import android.provider.DocumentsContract; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RSInvalidStateException; diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index 01599e153..d0c89ebe5 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -1470,7 +1470,6 @@ public class MainUI { if (mExposureLine == 0) { iso_buttons_container.setBackgroundColor(highlightColor); //iso_buttons_container.setAlpha(0.5f); - return; } else if (mExposureLine == 1) { iso_seekbar.setBackgroundColor(highlightColor); //iso_seekbar.setAlpha(0.5f); @@ -2117,7 +2116,6 @@ public class MainUI { /** * Higlights the next LinearLayout view - * @param highlight */ private void highlightPopupLine(boolean highlight, boolean goUp) { if( MyDebug.LOG ) { @@ -2165,8 +2163,6 @@ public class MainUI { * Highlights an icon on a horizontal line, such as flash mode, * focus mode, etc. Checks that the popup is open in case it is * wrongly called, so that it doesn't crash the app. - * @param highlight - * @param goLeft */ private void highlightPopupIcon(boolean highlight, boolean goLeft) { if( MyDebug.LOG ) { -- GitLab From 2dba2e107d1dcf9e94a1f21e60b1796183e67672 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 19 Feb 2020 23:51:53 +0000 Subject: [PATCH 159/243] Don't log location data (these were behind MyDebug.LOG so never active on gplay releases, but just to be safe). --- .../net/sourceforge/opencamera/ImageSaver.java | 17 +++-------------- .../opencamera/MyApplicationInterface.java | 7 +++---- .../sourceforge/opencamera/TextFormatter.java | 3 +-- .../cameracontroller/CameraController1.java | 3 +++ .../cameracontroller/CameraController2.java | 3 ++- .../sourceforge/opencamera/preview/Preview.java | 6 ++---- 6 files changed, 14 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java index f76270ab6..61dccf3aa 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java +++ b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java @@ -2088,8 +2088,7 @@ public class ImageSaver extends Thread { ypos -= diff_y; String gps_stamp = main_activity.getTextFormatter().getGPSString(preference_stamp_gpsformat, request.preference_units_distance, request.store_location, request.location, request.store_geo_direction, request.geo_direction); if( gps_stamp.length() > 0 ) { - if( MyDebug.LOG ) - Log.d(TAG, "stamp with location_string: " + gps_stamp); + // don't log gps_stamp, in case of privacy! Address address = null; if( request.store_location && !request.preference_stamp_geo_address.equals("preference_stamp_geo_address_no") ) { @@ -2103,8 +2102,8 @@ public class ImageSaver extends Thread { List
    addresses = geocoder.getFromLocation(request.location.getLatitude(), request.location.getLongitude(), 1); if( addresses != null && addresses.size() > 0 ) { address = addresses.get(0); + // don't log address, in case of privacy! if( MyDebug.LOG ) { - Log.d(TAG, "address: " + address); Log.d(TAG, "max line index: " + address.getMaxAddressLineIndex()); } } @@ -2134,8 +2133,7 @@ public class ImageSaver extends Thread { // we are displaying an address instead of GPS coords, but we still need to display the geo direction gps_stamp = main_activity.getTextFormatter().getGPSString(preference_stamp_gpsformat, request.preference_units_distance, false, null, request.store_geo_direction, request.geo_direction); if( gps_stamp.length() > 0 ) { - if( MyDebug.LOG ) - Log.d(TAG, "gps_stamp is now: " + gps_stamp); + // don't log gps_stamp, in case of privacy! applicationInterface.drawTextWithBackground(canvas, p, gps_stamp, color, Color.BLACK, width - offset_x, ypos, MyApplicationInterface.Alignment.ALIGNMENT_BOTTOM, null, draw_shadowed); ypos -= diff_y; } @@ -3104,13 +3102,6 @@ public class ImageSaver extends Thread { output = null; success = true; - /*Location location = null; - if( main_activity.getApplicationInterface().getGeotaggingPref() ) { - location = main_activity.getApplicationInterface().getLocation(); - if( MyDebug.LOG ) - Log.d(TAG, "location: " + location); - }*/ - // set last image for share/trash options for pause preview // Must be done before broadcastFile() (because on Android 7+ with non-SAF, we update // the LastImage's uri from the MediaScannerConnection.scanFile() callback from @@ -3127,8 +3118,6 @@ public class ImageSaver extends Thread { } if( saveUri == null ) { - //Uri media_uri = storageUtils.broadcastFileRaw(picFile, current_date, location); - //storageUtils.announceUri(media_uri, true, false); storageUtils.broadcastFile(picFile, true, false, false); } else { diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 5dfb3bcac..964283b84 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -1952,7 +1952,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { if( MyDebug.LOG ) { Log.d(TAG, "date_stamp: " + date_stamp); Log.d(TAG, "time_stamp: " + time_stamp); - Log.d(TAG, "gps_stamp: " + gps_stamp); + // don't log gps_stamp, in case of privacy! } String datetime_stamp = ""; @@ -1981,8 +1981,8 @@ public class MyApplicationInterface extends BasicApplicationInterface { List
    addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1); if( addresses != null && addresses.size() > 0 ) { address = addresses.get(0); + // don't log address, in case of privacy! if( MyDebug.LOG ) { - Log.d(TAG, "address: " + address); Log.d(TAG, "max line index: " + address.getMaxAddressLineIndex()); } } @@ -2016,8 +2016,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { Log.d(TAG, "not displaying gps coords, but need to display geo direction"); gps_stamp = main_activity.getTextFormatter().getGPSString(preference_stamp_gpsformat, preference_units_distance, false, null, store_geo_direction && main_activity.getPreview().hasGeoDirection(), geo_direction); if( gps_stamp.length() > 0 ) { - if( MyDebug.LOG ) - Log.d(TAG, "gps_stamp is now: " + gps_stamp); + // don't log gps_stamp, in case of privacy! subtitles.append(gps_stamp).append("\n"); } } diff --git a/app/src/main/java/net/sourceforge/opencamera/TextFormatter.java b/app/src/main/java/net/sourceforge/opencamera/TextFormatter.java index 79d3e55f0..d8b3f5d34 100644 --- a/app/src/main/java/net/sourceforge/opencamera/TextFormatter.java +++ b/app/src/main/java/net/sourceforge/opencamera/TextFormatter.java @@ -108,8 +108,7 @@ public class TextFormatter { gps_stamp += "" + Math.round(geo_angle) + (char)0x00B0; } } - if( MyDebug.LOG ) - Log.d(TAG, "gps_stamp: " + gps_stamp); + // don't log gps_stamp, in case of privacy! return gps_stamp; } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index d95240a68..2b3ce52f4 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -1308,6 +1308,9 @@ public class CameraController1 extends CameraController { } public void setLocationInfo(Location location) { + // don't log location, in case of privacy! + if( MyDebug.LOG ) + Log.d(TAG, "setLocationInfo"); Camera.Parameters parameters = this.getParameters(); parameters.removeGpsData(); parameters.setGpsTimestamp(System.currentTimeMillis() / 1000); // initialise to a value (from Android camera source) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 2d4b6eae9..75821d4a8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -4674,8 +4674,9 @@ public class CameraController2 extends CameraController { @Override public void setLocationInfo(Location location) { + // don't log location, in case of privacy! if( MyDebug.LOG ) - Log.d(TAG, "setLocationInfo: " + location.getLongitude() + " , " + location.getLatitude()); + Log.d(TAG, "setLocationInfo"); this.camera_settings.location = location; } diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index be092a61b..0de6bc4e0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -5356,9 +5356,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu boolean store_location = applicationInterface.getGeotaggingPref(); if( store_location && applicationInterface.getLocation() != null ) { Location location = applicationInterface.getLocation(); - if( MyDebug.LOG ) { - Log.d(TAG, "set video location: lat " + location.getLatitude() + " long " + location.getLongitude() + " accuracy " + location.getAccuracy()); - } + // don't log location, in case of privacy! local_video_recorder.setLocation((float)location.getLatitude(), (float)location.getLongitude()); } @@ -7515,7 +7513,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Location location = applicationInterface.getLocation(); if( MyDebug.LOG ) { Log.d(TAG, "updating parameters from location..."); - Log.d(TAG, "lat " + location.getLatitude() + " long " + location.getLongitude() + " accuracy " + location.getAccuracy() + " timestamp " + location.getTime()); + // don't log location, in case of privacy! } camera_controller.setLocationInfo(location); } -- GitLab From c6754a70e031c7d66b1c7fdb65a341070a84ccda Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 19 Feb 2020 23:56:48 +0000 Subject: [PATCH 160/243] Add comments for location access. --- .../net/sourceforge/opencamera/LocationSupplier.java | 11 ++++++++--- .../opencamera/MyApplicationInterface.java | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java b/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java index 1d02f6496..6aa5ff3e5 100644 --- a/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java +++ b/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java @@ -29,8 +29,11 @@ public class LocationSupplier { locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); } + /** If adding extra calls to this, consider whether explicit user permission is required, and whether + * privacy policy needs updating. + * Returns null if location not available. + */ public Location getLocation() { - // returns null if not available if( locationListeners == null ) return null; if( test_force_no_location ) @@ -98,13 +101,15 @@ public class LocationSupplier { } } - // returns false if location permission not available for either coarse or fine + /* Best to only call this from MainActivity.initLocation(). + * Returns false if location permission not available for either coarse or fine. + */ boolean setupLocationListener() { if( MyDebug.LOG ) Log.d(TAG, "setupLocationListener"); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); // Define a listener that responds to location updates - // we only set it up if store_location is true, to avoid unnecessarily wasting battery + // we only set it up if store_location is true, important for privacy and unnecessary battery use boolean store_location = sharedPreferences.getBoolean(PreferenceKeys.LocationPreferenceKey, false); if( store_location && locationListeners == null ) { // Note, ContextCompat.checkSelfPermission is meant to handle being called on any Android version, i.e., pre diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 964283b84..ad50e8d09 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -252,6 +252,10 @@ public class MyApplicationInterface extends BasicApplicationInterface { return false; } + /** If adding extra calls to this, consider whether explicit user permission is required, and whether + * privacy policy needs updating. + * Returns null if location not available. + */ @Override public Location getLocation() { return locationSupplier.getLocation(); -- GitLab From 36e08b6c533bc7faef27e7135142c3e78fd3f421 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Wed, 19 Feb 2020 23:57:16 +0000 Subject: [PATCH 161/243] Add extra guard on calls to initLocation(). --- .../java/net/sourceforge/opencamera/MainActivity.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 17a2640bc..ede937552 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -94,6 +94,8 @@ public class MainActivity extends Activity { private static int activity_count = 0; + private boolean app_is_paused = true; + private SensorManager mSensorManager; private Sensor mSensorAccelerometer; @@ -1174,6 +1176,7 @@ public class MainActivity extends Activity { debug_time = System.currentTimeMillis(); } super.onResume(); + this.app_is_paused = false; cancelImageSavingNotification(); @@ -1261,6 +1264,8 @@ public class MainActivity extends Activity { debug_time = System.currentTimeMillis(); } super.onPause(); // docs say to call this before freeing other things + this.app_is_paused = true; + mainUI.destroyPopup(); // important as user could change/reset settings from Android settings when pausing mSensorManager.unregisterListener(accelerometerListener); magneticSensor.unregisterMagneticListener(mSensorManager); @@ -4852,7 +4857,11 @@ public class MainActivity extends Activity { void initLocation() { if( MyDebug.LOG ) Log.d(TAG, "initLocation"); - if( !applicationInterface.getLocationSupplier().setupLocationListener() ) { + if( app_is_paused ) { + Log.e(TAG, "initLocation: app is paused!"); + // we shouldn't need this (as we only call initLocation() when active), but just in case we end up here after onPause... + } + else if( !applicationInterface.getLocationSupplier().setupLocationListener() ) { if( MyDebug.LOG ) Log.d(TAG, "location permission not available, so request permission"); permissionHandler.requestLocationPermission(); -- GitLab From efeaca92385e163e88a917b49a5b46a8dcb9a4b8 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 27 Feb 2020 00:27:02 +0000 Subject: [PATCH 162/243] Suppress some warnings. --- .../opencamera/test/MainActivityTest.java | 10 ++++++++++ app/src/main/AndroidManifest.xml | 4 +++- .../net/sourceforge/opencamera/HDRProcessor.java | 7 +++++++ .../opencamera/HDRProcessorException.java | 1 + .../java/net/sourceforge/opencamera/ImageSaver.java | 5 +++++ .../net/sourceforge/opencamera/MainActivity.java | 3 +++ .../opencamera/MyApplicationInterface.java | 2 ++ .../sourceforge/opencamera/PanoramaProcessor.java | 11 ++++++++++- .../opencamera/PanoramaProcessorException.java | 1 + .../net/sourceforge/opencamera/SpeechControl.java | 5 +++++ .../cameracontroller/CameraController2.java | 8 ++++++++ .../opencamera/preview/ApplicationInterface.java | 1 + .../net/sourceforge/opencamera/preview/Preview.java | 9 +++++++++ .../sourceforge/opencamera/preview/VideoProfile.java | 2 ++ .../opencamera/remotecontrol/BluetoothLeService.java | 1 + .../opencamera/remotecontrol/DeviceScanner.java | 1 + .../net/sourceforge/opencamera/ui/DrawPreview.java | 6 ++++-- .../java/net/sourceforge/opencamera/ui/MainUI.java | 12 ++++++++++-- .../net/sourceforge/opencamera/ui/PopupView.java | 1 + app/src/main/res/xml/preferences.xml | 3 +++ .../net/sourceforge/opencamera/test/UnitTest.java | 1 + 21 files changed, 88 insertions(+), 6 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index e5413ce7f..6e2632b5f 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -3257,6 +3257,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 inputs, String output_name, String gyro_debug_info_filename, float panorama_pics_per_screen, float camera_angle_x, float camera_angle_y, float gyro_tol_degrees) throws IOException, InterruptedException { Log.d(TAG, "subTestPanorama"); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fff3ff15f..316bd8911 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,12 @@ + tools:ignore="GoogleAppIndexingWarning"> + diff --git a/app/src/main/java/net/sourceforge/opencamera/HDRProcessor.java b/app/src/main/java/net/sourceforge/opencamera/HDRProcessor.java index b46a3bb2e..203879f21 100644 --- a/app/src/main/java/net/sourceforge/opencamera/HDRProcessor.java +++ b/app/src/main/java/net/sourceforge/opencamera/HDRProcessor.java @@ -49,6 +49,7 @@ public class HDRProcessor { // public for access by testing public int [] offsets_x = null; public int [] offsets_y = null; + @SuppressWarnings("CanBeFinal") public int sharp_index = 0; private enum HDRAlgorithm { @@ -301,6 +302,7 @@ public class HDRProcessor { } } + @SuppressWarnings("WeakerAccess") public interface SortCallback { /** This is called when the sort order for the input bitmaps is known, from darkest to brightest. * @param sort_order A list of length equal to the supplied bitmaps.size(). sort_order.get(i) @@ -1398,10 +1400,12 @@ public class HDRProcessor { if( bitmap_new_align != null ) { bitmap_new_align.recycle(); + //noinspection UnusedAssignment bitmap_new_align = null; } if( allocation_new_align != null ) { allocation_new_align.destroy(); + //noinspection UnusedAssignment allocation_new_align = null; } @@ -1538,12 +1542,14 @@ public class HDRProcessor { if( MyDebug.LOG ) Log.d(TAG, "release bitmap_avg"); bitmap_avg.recycle(); + //noinspection UnusedAssignment bitmap_avg = null; } if( bitmap_new != null ) { if( MyDebug.LOG ) Log.d(TAG, "release bitmap_new"); bitmap_new.recycle(); + //noinspection UnusedAssignment bitmap_new = null; } @@ -3025,6 +3031,7 @@ public class HDRProcessor { * @param allocation_in The input allocation. * @param width The width of the allocation. */ + @SuppressWarnings("unused") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private float computeSharpness(Allocation allocation_in, int width, long time_s) { if( MyDebug.LOG ) diff --git a/app/src/main/java/net/sourceforge/opencamera/HDRProcessorException.java b/app/src/main/java/net/sourceforge/opencamera/HDRProcessorException.java index 70f7a9b43..056e288db 100644 --- a/app/src/main/java/net/sourceforge/opencamera/HDRProcessorException.java +++ b/app/src/main/java/net/sourceforge/opencamera/HDRProcessorException.java @@ -2,6 +2,7 @@ package net.sourceforge.opencamera; /** Exception for HDRProcessor class. */ +@SuppressWarnings("WeakerAccess") public class HDRProcessorException extends Exception { final static public int INVALID_N_IMAGES = 0; // the supplied number of images is not supported final static public int UNEQUAL_SIZES = 1; // images not of the same resolution diff --git a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java index 61dccf3aa..e1ce193cc 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java +++ b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java @@ -1161,7 +1161,9 @@ public class ImageSaver extends Thread { xmlSerializer.flush(); } + @SuppressWarnings("WeakerAccess") public static class GyroDebugInfo { + @SuppressWarnings("unused") public static class GyroImageDebugInfo { public float [] vectorRight; // X axis public float [] vectorUp; // Y axis @@ -1234,6 +1236,7 @@ public class ImageSaver extends Thread { Log.d(TAG, "end tag, name: " + name); } + //noinspection SwitchStatementWithTooFewBranches switch( name ) { case gyro_info_image_tag: image_info = null; @@ -1435,6 +1438,7 @@ public class ImageSaver extends Thread { Log.d(TAG, "*** time for brighten: " + (System.currentTimeMillis() - this_time_s)); } avg_data.destroy(); + //noinspection UnusedAssignment avg_data = null; if( MyDebug.LOG ) { Log.d(TAG, "*** total time for saving NR image: " + (System.currentTimeMillis() - time_s)); @@ -2153,6 +2157,7 @@ public class ImageSaver extends Thread { if( MyDebug.LOG ) Log.d(TAG, "stamp text"); applicationInterface.drawTextWithBackground(canvas, p, request.preference_textstamp, color, Color.BLACK, width - offset_x, ypos, MyApplicationInterface.Alignment.ALIGNMENT_BOTTOM, null, draw_shadowed); + //noinspection UnusedAssignment ypos -= diff_y; } } diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index ede937552..33d43dbdf 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -2963,10 +2963,12 @@ public class MainActivity extends Activity { } // align dimensions if( display_size.x < display_size.y ) { + //noinspection SuspiciousNameCombination display_size.set(display_size.y, display_size.x); } if( bitmap_width < bitmap_height ) { int dummy = bitmap_width; + //noinspection SuspiciousNameCombination bitmap_width = bitmap_height; bitmap_height = dummy; } @@ -3591,6 +3593,7 @@ public class MainActivity extends Activity { final int clear_index = index; items[index++] = getResources().getString(R.string.clear_folder_history); final int new_index = index; + //noinspection UnusedAssignment items[index++] = getResources().getString(R.string.choose_another_folder); alertDialog.setItems(items, new DialogInterface.OnClickListener() { @Override diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index ad50e8d09..1716d0be5 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -1434,6 +1434,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { public NRModePref getNRModePref() { /*if( MyDebug.LOG ) Log.d(TAG, "nr_mode: " + nr_mode);*/ + //noinspection SwitchStatementWithTooFewBranches switch( nr_mode ) { case "preference_nr_mode_low_light": return NRModePref.NRMODE_LOW_LIGHT; @@ -1637,6 +1638,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { */ boolean isRawOnly(PhotoMode photo_mode) { if( isRawAllowed(photo_mode) ) { + //noinspection SwitchStatementWithTooFewBranches switch( sharedPreferences.getString(PreferenceKeys.RawPreferenceKey, "preference_raw_no") ) { case "preference_raw_only": return true; diff --git a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java index 21ce7fad6..4eda0b84e 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java +++ b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java @@ -218,7 +218,7 @@ public class PanoramaProcessor { * RGBA_8888. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - private List createLaplacianPyramid(ScriptC_pyramid_blending script,Bitmap bitmap, int n_levels, String name) { + private List createLaplacianPyramid(ScriptC_pyramid_blending script, Bitmap bitmap, int n_levels, @SuppressWarnings("unused") String name) { if( MyDebug.LOG ) Log.d(TAG, "createLaplacianPyramid"); long time_s = 0; @@ -1044,14 +1044,17 @@ public class PanoramaProcessor { }*/ ix_allocation.destroy(); + //noinspection UnusedAssignment ix_allocation = null; iy_allocation.destroy(); + //noinspection UnusedAssignment iy_allocation = null; if( MyDebug.LOG ) Log.d(TAG, "find local maxima for image: " + i); // reuse gs_allocation (since it's on the same U8 type that we want) Allocation local_max_features_allocation = gs_allocation; + //noinspection UnusedAssignment gs_allocation = null; /*featureDetectorScript.set_corner_threshold(100000000.0f); @@ -1190,9 +1193,11 @@ public class PanoramaProcessor { Log.d(TAG, "### image: " + i + " has " + points_arrays[i].length + " points"); strength_allocation.destroy(); + //noinspection UnusedAssignment strength_allocation = null; local_max_features_allocation.destroy(); + //noinspection UnusedAssignment local_max_features_allocation = null; } if( MyDebug.LOG ) @@ -1218,6 +1223,7 @@ public class PanoramaProcessor { } // generate candidate matches + //noinspection UnnecessaryLocalVariable final int max_match_dist_x = width; final int max_match_dist_y = height/16; final int max_match_dist2 = max_match_dist_x*max_match_dist_x + max_match_dist_y*max_match_dist_y; @@ -1972,6 +1978,7 @@ public class PanoramaProcessor { return new AutoAlignmentByFeatureResult(offset_x, offset_y, rotation, y_scale); } + @SuppressWarnings("unused") private Bitmap blend_panorama_alpha(Bitmap lhs, Bitmap rhs) { int width = lhs.getWidth(); int height = lhs.getHeight(); @@ -2478,6 +2485,7 @@ public class PanoramaProcessor { return ratio_brightnesses; } + @SuppressWarnings("unused") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void adjustExposures(List bitmaps, long time_s) { List histogramInfos = new ArrayList<>(); @@ -2821,6 +2829,7 @@ public class PanoramaProcessor { int align_y = 0; int dst_offset_x = dst_offset_x_values.get(i); + //noinspection UnusedAssignment boolean free_bitmap = false; int shift_stop_x = align_x; int centre_shift_x; diff --git a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessorException.java b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessorException.java index e41d3525f..c5dfc178a 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessorException.java +++ b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessorException.java @@ -2,6 +2,7 @@ package net.sourceforge.opencamera; /** Exception for PanoramaProcessor class. */ +@SuppressWarnings("WeakerAccess") public class PanoramaProcessorException extends Exception { final static public int INVALID_N_IMAGES = 0; // the supplied number of images is not supported final static public int UNEQUAL_SIZES = 1; // images not of the same resolution diff --git a/app/src/main/java/net/sourceforge/opencamera/SpeechControl.java b/app/src/main/java/net/sourceforge/opencamera/SpeechControl.java index 0debaa687..63800e7ee 100644 --- a/app/src/main/java/net/sourceforge/opencamera/SpeechControl.java +++ b/app/src/main/java/net/sourceforge/opencamera/SpeechControl.java @@ -93,6 +93,7 @@ class SpeechControl { if( !speechRecognizerIsStarted ) { if( MyDebug.LOG ) Log.d(TAG, "...but speech recognition already stopped"); + //noinspection UnnecessaryReturnStatement return; } } @@ -104,6 +105,7 @@ class SpeechControl { if( !speechRecognizerIsStarted ) { if( MyDebug.LOG ) Log.d(TAG, "...but speech recognition already stopped"); + //noinspection UnnecessaryReturnStatement return; } } @@ -161,6 +163,7 @@ class SpeechControl { if( !speechRecognizerIsStarted ) { if( MyDebug.LOG ) Log.d(TAG, "...but speech recognition already stopped"); + //noinspection UnnecessaryReturnStatement return; } } @@ -172,6 +175,7 @@ class SpeechControl { if( !speechRecognizerIsStarted ) { if( MyDebug.LOG ) Log.d(TAG, "...but speech recognition already stopped"); + //noinspection UnnecessaryReturnStatement return; } } @@ -183,6 +187,7 @@ class SpeechControl { if( !speechRecognizerIsStarted ) { if( MyDebug.LOG ) Log.d(TAG, "...but speech recognition already stopped"); + //noinspection UnnecessaryReturnStatement return; } } diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 75821d4a8..f4f5e27b7 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -721,6 +721,7 @@ public class CameraController2 extends CameraController { return false; } + @SuppressWarnings("SameReturnValue") private boolean setAEMode(CaptureRequest.Builder builder, boolean is_still) { if( MyDebug.LOG ) Log.d(TAG, "setAEMode"); @@ -764,6 +765,7 @@ public class CameraController2 extends CameraController { } // prefer to set flash via the ae mode (otherwise get even worse results), except for torch which we can't + //noinspection DuplicateBranchesInSwitch switch(flash_value) { case "flash_off": builder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON); @@ -2626,6 +2628,7 @@ public class CameraController2 extends CameraController { // would be good to not assume Open Camera runs in landscape mode (if we ever ran in portrait mode, // we'd still want display_size.x > display_size.y as preview resolutions also have width > height) if( display_size.x < display_size.y ) { + //noinspection SuspiciousNameCombination display_size.set(display_size.y, display_size.x); } if( MyDebug.LOG ) @@ -5920,6 +5923,7 @@ public class CameraController2 extends CameraController { Log.e(TAG, "message: " + e.getMessage()); } e.printStackTrace(); + //noinspection UnusedAssignment ok = false; jpeg_todo = false; raw_todo = false; @@ -5930,6 +5934,7 @@ public class CameraController2 extends CameraController { if( MyDebug.LOG ) Log.d(TAG, "captureSession already closed!"); e.printStackTrace(); + //noinspection UnusedAssignment ok = false; jpeg_todo = false; raw_todo = false; @@ -6324,6 +6329,7 @@ public class CameraController2 extends CameraController { Log.e(TAG, "message: " + e.getMessage()); } e.printStackTrace(); + //noinspection UnusedAssignment ok = false; jpeg_todo = false; raw_todo = false; @@ -6334,6 +6340,7 @@ public class CameraController2 extends CameraController { if( MyDebug.LOG ) Log.d(TAG, "captureSession already closed!"); e.printStackTrace(); + //noinspection UnusedAssignment ok = false; jpeg_todo = false; raw_todo = false; @@ -6665,6 +6672,7 @@ public class CameraController2 extends CameraController { Log.e(TAG, "message: " + e.getMessage()); } e.printStackTrace(); + //noinspection UnusedAssignment ok = false; jpeg_todo = false; raw_todo = false; diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java index c3475250b..d7a3f4ce8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/ApplicationInterface.java @@ -218,6 +218,7 @@ public interface ApplicationInterface { void setVideoQualityPref(String video_quality); void setZoomPref(int zoom); void requestCameraPermission(); // for Android 6+: called when trying to open camera, but CAMERA permission not available + @SuppressWarnings("SameReturnValue") boolean needsStoragePermission(); // return true if the preview should call requestStoragePermission() if WRITE_EXTERNAL_STORAGE not available (i.e., if the application needs storage permission, e.g., to save photos) void requestStoragePermission(); // for Android 6+: called when trying to open camera, but WRITE_EXTERNAL_STORAGE permission not available void requestRecordAudioPermission(); // for Android 6+: called when switching to (or starting up in) video mode, but RECORD_AUDIO permission not available diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 0de6bc4e0..8002cfc48 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -37,6 +37,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import android.Manifest; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; @@ -556,6 +557,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return areas; } + @SuppressWarnings("SameReturnValue") public boolean touchEvent(MotionEvent event) { if( MyDebug.LOG ) Log.d(TAG, "touch event at : " + event.getX() + " , " + event.getY() + " at time " + event.getEventTime()); @@ -685,6 +687,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } } + @SuppressWarnings("SameReturnValue") public boolean onDoubleTap() { if( MyDebug.LOG ) Log.d(TAG, "onDoubleTap()"); @@ -791,6 +794,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( camera_controller == null ) { if( MyDebug.LOG ) Log.d(TAG, "camera not opened!"); + //noinspection UnnecessaryReturnStatement return; } } @@ -2189,6 +2193,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu break; case 90: { float temp = avg_x; + //noinspection SuspiciousNameCombination avg_x = avg_y; avg_y = 1.0f-temp; break; @@ -3506,6 +3511,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu // display size is returned in portrait format! (To reproduce, enable "Maximise preview size"; or if that's // already enabled, change the setting off and on.) if( display_size.x < display_size.y ) { + //noinspection SuspiciousNameCombination display_size.set(display_size.y, display_size.x); } if( MyDebug.LOG ) @@ -7236,6 +7242,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu this.offset_y = offset_y; } + @SuppressLint("CanvasSize") @Override protected void onDraw(Canvas canvas) { final float scale = Preview.this.getResources().getDisplayMetrics().density; @@ -7355,6 +7362,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu showToast(clear_toast, message, false); } + @SuppressWarnings("WeakerAccess") public void showToast(final String message, final boolean use_fake_toast) { showToast(null, message, use_fake_toast); } @@ -7614,6 +7622,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu int rotation = getDisplayRotationDegrees(); if( rotation == 90 || rotation == 270 ) { int dummy = bitmap_width; + //noinspection SuspiciousNameCombination bitmap_width = bitmap_height; bitmap_height = dummy; } diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/VideoProfile.java b/app/src/main/java/net/sourceforge/opencamera/preview/VideoProfile.java index ec7b5fac8..8ebe7c1cb 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/VideoProfile.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/VideoProfile.java @@ -17,7 +17,9 @@ public class VideoProfile { public int audioSource; public int audioCodec; public int audioChannels; + @SuppressWarnings("WeakerAccess") public int audioBitRate; + @SuppressWarnings("WeakerAccess") public int audioSampleRate; public int fileFormat; public String fileExtension = "mp4"; diff --git a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java index 015b02790..b1d7883e1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java +++ b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java @@ -176,6 +176,7 @@ public class BluetoothLeService extends Service { if (gattServices == null) return; List mCharacteristicsWanted; + //noinspection SwitchStatementWithTooFewBranches switch( remote_device_type ) { case "preference_remote_type_kraken": mCharacteristicsWanted = KrakenGattAttributes.getDesiredCharacteristics(); diff --git a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/DeviceScanner.java b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/DeviceScanner.java index 6cde61f8b..61cb0390b 100644 --- a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/DeviceScanner.java +++ b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/DeviceScanner.java @@ -176,6 +176,7 @@ public class DeviceScanner extends ListActivity { @NonNull int[] grantResults) { if( MyDebug.LOG ) Log.d(TAG, "onRequestPermissionsResult: requestCode " + requestCode); + //noinspection SwitchStatementWithTooFewBranches switch (requestCode) { case REQUEST_LOCATION_PERMISSIONS: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index f2f057ebd..741bd69d8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -2050,8 +2050,10 @@ public class DrawPreview { // but we also need to take the top_icon_shift into account, for widescreen aspect ratios and "icons along top" UI placement int focus_seekbars_margin_left_dp = 135; int new_focus_seekbars_margin_left = (int) (focus_seekbars_margin_left_dp * scale + 0.5f); // convert dps to pixels - if( top_icon_shift > 0 ) + if( top_icon_shift > 0 ) { + //noinspection SuspiciousNameCombination new_focus_seekbars_margin_left += top_icon_shift; + } if( focus_seekbars_margin_left == -1 || new_focus_seekbars_margin_left != focus_seekbars_margin_left ) { // we check whether focus_seekbars_margin_left has changed, in case there is a performance cost for setting layoutparams @@ -2734,7 +2736,7 @@ public class DrawPreview { } } - private void drawGyroSpot(Canvas canvas, float distance_x, float distance_y, float dir_x, float dir_y, int radius_dp, boolean outline) { + private void drawGyroSpot(Canvas canvas, float distance_x, float distance_y, @SuppressWarnings("unused") float dir_x, @SuppressWarnings("unused") float dir_y, int radius_dp, boolean outline) { if( outline ) { p.setStyle(Paint.Style.STROKE); p.setStrokeWidth(stroke_width); diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java index d0c89ebe5..9d5adf279 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/MainUI.java @@ -241,9 +241,13 @@ public class MainUI { iconpanel_right_of = RelativeLayout.ABOVE; iconpanel_above = RelativeLayout.LEFT_OF; iconpanel_below = RelativeLayout.RIGHT_OF; + //noinspection SuspiciousNameCombination iconpanel_align_parent_left = RelativeLayout.ALIGN_PARENT_BOTTOM; + //noinspection SuspiciousNameCombination iconpanel_align_parent_right = RelativeLayout.ALIGN_PARENT_TOP; + //noinspection SuspiciousNameCombination iconpanel_align_parent_top = RelativeLayout.ALIGN_PARENT_LEFT; + //noinspection SuspiciousNameCombination iconpanel_align_parent_bottom = RelativeLayout.ALIGN_PARENT_RIGHT; } @@ -776,8 +780,10 @@ public class MainUI { else if( ui_placement == UIPlacement.UIPLACEMENT_TOP ) { view.setPivotX(0.0f); view.setPivotY(0.0f); - if( ui_rotation == 90 ) + if( ui_rotation == 90 ) { + //noinspection SuspiciousNameCombination view.setTranslationX(popup_height); + } else if( ui_rotation == 270 ) { view.setTranslationY(display_height); } @@ -786,8 +792,10 @@ public class MainUI { view.setPivotX(popup_width); view.setPivotY(ui_placement == UIPlacement.UIPLACEMENT_RIGHT ? 0.0f : popup_height); if( ui_placement == UIPlacement.UIPLACEMENT_RIGHT ) { - if( ui_rotation == 90 ) + if( ui_rotation == 90 ) { + //noinspection SuspiciousNameCombination view.setTranslationY( popup_width ); + } else if( ui_rotation == 270 ) view.setTranslationX( - popup_height ); } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index 356f64bc3..f993c8919 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -70,6 +70,7 @@ public class PopupView extends LinearLayout { private int repeat_mode_index = -1; private int grid_index = -1; + @SuppressWarnings("FieldCanBeLocal") private final DecimalFormat decimal_format_1dp_force0 = new DecimalFormat("0.0"); public PopupView(Context context) { diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index fbc73f885..5373f8b50 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -865,6 +865,7 @@ android:title="@string/preference_category_exif_tags" > + + + p1.a ) { float4 temp_p = p0; -- GitLab From 500beef9152573ff963a916bb02c2da9668fc7c2 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 27 Feb 2020 00:28:23 +0000 Subject: [PATCH 163/243] Fix some warnings. --- .../net/sourceforge/opencamera/PanoramaProcessor.java | 8 ++++---- .../opencamera/cameracontroller/CameraController1.java | 6 ++---- .../opencamera/remotecontrol/BluetoothLeService.java | 4 ++-- .../sourceforge/opencamera/ui/ArraySeekBarPreference.java | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java index 4eda0b84e..a72ea3f71 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java +++ b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java @@ -543,13 +543,13 @@ public class PanoramaProcessor { bitmap.recycle(); } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + /*@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void savePyramid(String name, List pyramid) { for(int i=0;i power ) power *= 2; return power; - } + }*/ private static int nextMultiple(int value, int multiple) { int remainder = value % multiple; diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java index 2b3ce52f4..1310a17ef 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController1.java @@ -1139,6 +1139,8 @@ public class CameraController1 extends CameraController { String flash_mode = ""; switch(flash_value) { case "flash_off": + case "flash_frontscreen_on": + case "flash_frontscreen_torch": flash_mode = Camera.Parameters.FLASH_MODE_OFF; break; case "flash_auto": @@ -1153,10 +1155,6 @@ public class CameraController1 extends CameraController { case "flash_red_eye": flash_mode = Camera.Parameters.FLASH_MODE_RED_EYE; break; - case "flash_frontscreen_on": - case "flash_frontscreen_torch": - flash_mode = Camera.Parameters.FLASH_MODE_OFF; - break; } return flash_mode; } diff --git a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java index b1d7883e1..b9a6f4b07 100644 --- a/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java +++ b/app/src/main/java/net/sourceforge/opencamera/remotecontrol/BluetoothLeService.java @@ -45,9 +45,9 @@ public class BluetoothLeService extends Service { private double currentTemp = -1; private double currentDepth = -1; - private static final int STATE_DISCONNECTED = 0; + /*private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; - private static final int STATE_CONNECTED = 2; + private static final int STATE_CONNECTED = 2;*/ public final static String ACTION_GATT_CONNECTED = "net.sourceforge.opencamera.Remotecontrol.ACTION_GATT_CONNECTED"; diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java b/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java index ba84ac059..33c477d04 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java @@ -16,7 +16,7 @@ import net.sourceforge.opencamera.R; /** This contains a custom preference to display a seekbar in place of a ListPreference. */ public class ArraySeekBarPreference extends DialogPreference { - private static final String TAG = "ArraySeekBarPreference"; + //private static final String TAG = "ArraySeekBarPreference"; private SeekBar seekbar; private TextView textView; -- GitLab From 4960a3b346d7f348b7890008028bb130ace29e40 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 27 Feb 2020 00:29:39 +0000 Subject: [PATCH 164/243] Fix some warnings. --- .../opencamera/cameracontroller/CameraController2.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index f4f5e27b7..8338c8326 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -340,8 +340,8 @@ public class CameraController2 extends CameraController { private enum RequestTagType { CAPTURE, // request is either for a regular non-burst capture, or the last of a burst capture sequence - CAPTURE_BURST_IN_PROGRESS, // request is for a burst capture, but isn't the last of the burst capture sequence - NONE // should be treated the same as if no tag had been set on the request - but allows the request tag type to be changed later + CAPTURE_BURST_IN_PROGRESS // request is for a burst capture, but isn't the last of the burst capture sequence + //NONE // should be treated the same as if no tag had been set on the request - but allows the request tag type to be changed later } /* The class that we use for setTag() and getTag() for capture requests. -- GitLab From dd6551992e489637bded1338fa9645020a6fbafb Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 27 Feb 2020 00:30:37 +0000 Subject: [PATCH 165/243] Suppress some warning types. --- .gitignore | 5 ++- .idea/inspectionProfiles/Project_Default.xml | 37 ++++++++++++++++++++ makesrcarchive.bat | 7 ++++ opencamera_source.txt | 22 +++++++++++- 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml diff --git a/.gitignore b/.gitignore index 124f2c1d2..46ed4410c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,10 @@ _other/ _saved/ .gradle/ -.idea/ + +.idea/* +!.idea/inspectionProfiles + build/ app/release/ gfx/ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..fbe320a41 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,37 @@ + + + + \ No newline at end of file diff --git a/makesrcarchive.bat b/makesrcarchive.bat index cb133fb90..59d3995b8 100644 --- a/makesrcarchive.bat +++ b/makesrcarchive.bat @@ -23,6 +23,13 @@ copy %src%\app\build.gradle %dst%\app\ mkdir %dst%\gradle xcopy %src%\gradle %dst%\gradle /E /Y +REM We copy the inspectionProfiles as this stores which Android inspection warnings/errors we've disabled; although +REM note this isn't part of the Git repository, due lots of other files in .idea/ that we don't want to be part of the +REM project. +mkdir %dst%\.idea +mkdir %dst%\.idea\inspectionProfiles +xcopy %src%\.idea\inspectionProfiles %dst%\.idea\inspectionProfiles /E /Y + mkdir %dst%\_docs REM xcopy %src%\_docs %dst%\_docs /E /Y copy %src%\_docs\credits.html %dst%\_docs diff --git a/opencamera_source.txt b/opencamera_source.txt index a3e05c79d..17776eb90 100644 --- a/opencamera_source.txt +++ b/opencamera_source.txt @@ -19,6 +19,26 @@ Preview: At a higher level, you might want to take the classes in Preview/ as we Application: You might prefer to use Open Camera in its entirety, as an Activity within your application (or possibly converting the MainActivity to a fragment). Consider whether Open Camera's Settings should be unified with the settings in your application. Accesses to SharedPreferences use the PreferencesKeys class to find the keys. +Android inspection warnings/errors +================================== + +The file .idea/inspectionProfiles/Project_Default.xml contains settings for Android inpsections (see Editor/Inspections). The following have been disabled: + +* AndroidLintUnusedResources - seems to give false information on res/ images, as well as complaining about renderscript files in build folders. +* BooleanMethodIsAlwaysInverted - Generates too many useless warnings. +* ConstantConditions - Unfortunately this seems broken when calling an Android SDK function where only a stub source is available, such that the inspection incorrectly things an exception is thrown. E.g., see calls to TouchUtils.clickView() in MainActivityTest, this inspection thinks that e.g. "i<8" in for loops is always true. +* EmptyMethod - Sometimes can be useful to explicitly have a subclassed empty method, to show I've intentionally left it empty rather than forgotten to consider it. +* EmptyStatementBody - These may be intentional. +* PointlessBooleanExpression - This complains too much about controlling codepaths with final boolean flags (e.g., "if( debug_switch && blah )"). +* SameParameterValue - A parameter may have been provided for future proofing even if callers currently only use one value. +* TrivialIf - This suggests replacing clear if statements with shorter but more convoluted boolean expressions. +* UnusedReturnValue - In some cases a function may return something even if not currently used, either for future proofing, or we used it in the past (and might use again in the future). Whilst a caller not checking the return can be an error, this check wouldn't pick that up so long as at least one caller checked the return. + +The following are enabled, but with modifications: + +* UnnecessaryLocalVariable - m_ignoreImmediatelyReturnedVariables is true. +* unused - parameter="protected", REPORT_PARAMETER_FOR_PUBLIC_METHODS is false (otherwise this complaints about parameters in overriden methods being unused); method="protected" (in some cases public unused methods may be added for future proofing). + Licence ======= @@ -30,4 +50,4 @@ Homepage: http://opencamera.org.uk/ Google Play download: https://play.google.com/store/apps/details?id=net.sourceforge.opencamera -Mark Harman 9 September 2018 +Mark Harman 27 February 2020 -- GitLab From 840d181d53bd96d8bc986d0ad515dcdeb55a311a Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 27 Feb 2020 00:34:40 +0000 Subject: [PATCH 166/243] Fix some warnings. --- .../java/net/sourceforge/opencamera/PanoramaProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java index a72ea3f71..b5bb01621 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java +++ b/app/src/main/java/net/sourceforge/opencamera/PanoramaProcessor.java @@ -497,6 +497,7 @@ public class PanoramaProcessor { } } + @SuppressWarnings("unused") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void saveAllocation(String name, Allocation allocation) { Bitmap bitmap; @@ -779,7 +780,7 @@ public class PanoramaProcessor { } } - private static void computeDistancesBetweenMatches(List matches, int st_indx, int nd_indx, int feature_descriptor_radius, List bitmaps, int [] pixels0, int [] pixels1) { + private static void computeDistancesBetweenMatches(List matches, int st_indx, int nd_indx, int feature_descriptor_radius, @SuppressWarnings("unused") List bitmaps, int [] pixels0, int [] pixels1) { final int wid = 2*feature_descriptor_radius+1; final int wid2 = wid*wid; for(int indx=st_indx;indx Date: Sat, 29 Feb 2020 14:32:39 +0000 Subject: [PATCH 167/243] Refactor PreferenceKeys methods to fields. --- .../opencamera/test/MainActivityTest.java | 136 +++++++++--------- .../sourceforge/opencamera/MainActivity.java | 26 ++-- .../opencamera/MyApplicationInterface.java | 44 +++--- .../opencamera/MyPreferenceFragment.java | 8 +- .../opencamera/PreferenceKeys.java | 134 +++++------------ .../sourceforge/opencamera/StorageUtils.java | 12 +- .../sourceforge/opencamera/ui/PopupView.java | 8 +- 7 files changed, 152 insertions(+), 216 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 6e2632b5f..16fce10ae 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -2070,7 +2070,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); @@ -8978,8 +8978,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 0 && !max_duration_value.equals("0") ) { String [] entries_array = getResources().getStringArray(R.array.preference_video_max_duration_entries); String [] values_array = getResources().getStringArray(R.array.preference_video_max_duration_values); @@ -4720,7 +4720,7 @@ public class MainActivity extends Activity { simple = false; } } - String timer = sharedPreferences.getString(PreferenceKeys.getTimerPreferenceKey(), "0"); + String timer = sharedPreferences.getString(PreferenceKeys.TimerPreferenceKey, "0"); if( !timer.equals("0") && photo_mode != MyApplicationInterface.PhotoMode.Panorama ) { String [] entries_array = getResources().getStringArray(R.array.preference_timer_entries); String [] values_array = getResources().getStringArray(R.array.preference_timer_values); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 1716d0be5..3910bb458 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -615,12 +615,12 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public boolean getVideoStabilizationPref() { - return sharedPreferences.getBoolean(PreferenceKeys.getVideoStabilizationPreferenceKey(), false); + return sharedPreferences.getBoolean(PreferenceKeys.VideoStabilizationPreferenceKey, false); } @Override public boolean getForce4KPref() { - return cameraId == 0 && sharedPreferences.getBoolean(PreferenceKeys.getForceVideo4KPreferenceKey(), false) && main_activity.supportsForceVideo4K(); + return cameraId == 0 && sharedPreferences.getBoolean(PreferenceKeys.ForceVideo4KPreferenceKey, false) && main_activity.supportsForceVideo4K(); } @Override @@ -630,7 +630,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public String getVideoBitratePref() { - return sharedPreferences.getString(PreferenceKeys.getVideoBitratePreferenceKey(), "default"); + return sharedPreferences.getString(PreferenceKeys.VideoBitratePreferenceKey, "default"); } @Override @@ -857,7 +857,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { } } - String video_max_duration_value = sharedPreferences.getString(PreferenceKeys.getVideoMaxDurationPreferenceKey(), "0"); + String video_max_duration_value = sharedPreferences.getString(PreferenceKeys.VideoMaxDurationPreferenceKey, "0"); long video_max_duration; try { video_max_duration = (long)Integer.parseInt(video_max_duration_value) * 1000; @@ -873,7 +873,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public int getVideoRestartTimesPref() { - String restart_value = sharedPreferences.getString(PreferenceKeys.getVideoRestartPreferenceKey(), "0"); + String restart_value = sharedPreferences.getString(PreferenceKeys.VideoRestartPreferenceKey, "0"); int remaining_restart_video; try { remaining_restart_video = Integer.parseInt(restart_value); @@ -903,7 +903,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { } } - String video_max_filesize_value = sharedPreferences.getString(PreferenceKeys.getVideoMaxFileSizePreferenceKey(), "0"); + String video_max_filesize_value = sharedPreferences.getString(PreferenceKeys.VideoMaxFileSizePreferenceKey, "0"); long video_max_filesize; try { video_max_filesize = Long.parseLong(video_max_filesize_value); @@ -930,7 +930,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { } } - return sharedPreferences.getBoolean(PreferenceKeys.getVideoRestartMaxFileSizePreferenceKey(), true); + return sharedPreferences.getBoolean(PreferenceKeys.VideoRestartMaxFileSizePreferenceKey, true); } @Override @@ -1017,12 +1017,12 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public boolean getVideoFlashPref() { - return sharedPreferences.getBoolean(PreferenceKeys.getVideoFlashPreferenceKey(), false); + return sharedPreferences.getBoolean(PreferenceKeys.VideoFlashPreferenceKey, false); } @Override public boolean getVideoLowPowerCheckPref() { - return sharedPreferences.getBoolean(PreferenceKeys.getVideoLowPowerCheckPreferenceKey(), true); + return sharedPreferences.getBoolean(PreferenceKeys.VideoLowPowerCheckPreferenceKey, true); } @Override @@ -1032,14 +1032,14 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public String getPreviewRotationPref() { - return sharedPreferences.getString(PreferenceKeys.getRotatePreviewPreferenceKey(), "0"); + return sharedPreferences.getString(PreferenceKeys.RotatePreviewPreferenceKey, "0"); } @Override public String getLockOrientationPref() { if( getPhotoMode() == PhotoMode.Panorama ) return "portrait"; // for now panorama only supports portrait - return sharedPreferences.getString(PreferenceKeys.getLockOrientationPreferenceKey(), "none"); + return sharedPreferences.getString(PreferenceKeys.LockOrientationPreferenceKey, "none"); } @Override @@ -1087,19 +1087,19 @@ public class MyApplicationInterface extends BasicApplicationInterface { public boolean getShutterSoundPref() { if( getPhotoMode() == PhotoMode.Panorama ) return false; - return sharedPreferences.getBoolean(PreferenceKeys.getShutterSoundPreferenceKey(), true); + return sharedPreferences.getBoolean(PreferenceKeys.ShutterSoundPreferenceKey, true); } @Override public boolean getStartupFocusPref() { - return sharedPreferences.getBoolean(PreferenceKeys.getStartupFocusPreferenceKey(), true); + return sharedPreferences.getBoolean(PreferenceKeys.StartupFocusPreferenceKey, true); } @Override public long getTimerPref() { if( getPhotoMode() == MyApplicationInterface.PhotoMode.Panorama ) return 0; // don't support timer with panorama - String timer_value = sharedPreferences.getString(PreferenceKeys.getTimerPreferenceKey(), "0"); + String timer_value = sharedPreferences.getString(PreferenceKeys.TimerPreferenceKey, "0"); long timer_delay; try { timer_delay = (long)Integer.parseInt(timer_value) * 1000; @@ -1117,12 +1117,12 @@ public class MyApplicationInterface extends BasicApplicationInterface { public String getRepeatPref() { if( getPhotoMode() == MyApplicationInterface.PhotoMode.Panorama ) return "1"; // don't support repeat with panorama - return sharedPreferences.getString(PreferenceKeys.getRepeatModePreferenceKey(), "1"); + return sharedPreferences.getString(PreferenceKeys.RepeatModePreferenceKey, "1"); } @Override public long getRepeatIntervalPref() { - String timer_value = sharedPreferences.getString(PreferenceKeys.getRepeatIntervalPreferenceKey(), "0"); + String timer_value = sharedPreferences.getString(PreferenceKeys.RepeatIntervalPreferenceKey, "0"); long timer_delay; try { float timer_delay_s = Float.parseFloat(timer_value); @@ -1155,17 +1155,17 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public boolean getRecordAudioPref() { - return sharedPreferences.getBoolean(PreferenceKeys.getRecordAudioPreferenceKey(), true); + return sharedPreferences.getBoolean(PreferenceKeys.RecordAudioPreferenceKey, true); } @Override public String getRecordAudioChannelsPref() { - return sharedPreferences.getString(PreferenceKeys.getRecordAudioChannelsPreferenceKey(), "audio_default"); + return sharedPreferences.getString(PreferenceKeys.RecordAudioChannelsPreferenceKey, "audio_default"); } @Override public String getRecordAudioSourcePref() { - return sharedPreferences.getString(PreferenceKeys.getRecordAudioSourcePreferenceKey(), "audio_src_camcorder"); + return sharedPreferences.getString(PreferenceKeys.RecordAudioSourcePreferenceKey, "audio_src_camcorder"); } public boolean getAutoStabilisePref() { @@ -1862,7 +1862,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { @Override public void startingVideo() { - if( sharedPreferences.getBoolean(PreferenceKeys.getLockVideoPreferenceKey(), false) ) { + if( sharedPreferences.getBoolean(PreferenceKeys.LockVideoPreferenceKey, false) ) { main_activity.lockScreen(); } main_activity.stopAudioListeners(); // important otherwise MediaRecorder will fail to start() if we have an audiolistener! Also don't want to have the speech recognizer going off @@ -2516,13 +2516,13 @@ public class MyApplicationInterface extends BasicApplicationInterface { Log.d(TAG, "timerBeep()"); Log.d(TAG, "remaining_time: " + remaining_time); } - if( sharedPreferences.getBoolean(PreferenceKeys.getTimerBeepPreferenceKey(), true) ) { + if( sharedPreferences.getBoolean(PreferenceKeys.TimerBeepPreferenceKey, true) ) { if( MyDebug.LOG ) Log.d(TAG, "play beep!"); boolean is_last = remaining_time <= 1000; main_activity.getSoundPoolManager().playSound(is_last ? R.raw.mybeep_hi : R.raw.mybeep); } - if( sharedPreferences.getBoolean(PreferenceKeys.getTimerSpeakPreferenceKey(), false) ) { + if( sharedPreferences.getBoolean(PreferenceKeys.TimerSpeakPreferenceKey, false) ) { if( MyDebug.LOG ) Log.d(TAG, "speak countdown!"); int remaining_time_s = (int)(remaining_time/1000); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 47fd808e6..9ad08acea 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -981,7 +981,7 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared if( pref.getKey().equals("preference_using_saf") ) { if( MyDebug.LOG ) Log.d(TAG, "user clicked saf"); - if( sharedPreferences.getBoolean(PreferenceKeys.getUsingSAFPreferenceKey(), false) ) { + if( sharedPreferences.getBoolean(PreferenceKeys.UsingSAFPreferenceKey, false) ) { if( MyDebug.LOG ) Log.d(TAG, "saf is now enabled"); // seems better to alway re-show the dialog when the user selects, to make it clear where files will be saved (as the SAF location in general will be different to the non-SAF one) @@ -1379,11 +1379,11 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared about_string.append(magnetic_accuracy); about_string.append("\nUsing SAF?: "); - about_string.append(sharedPreferences.getBoolean(PreferenceKeys.getUsingSAFPreferenceKey(), false)); - String save_location = sharedPreferences.getString(PreferenceKeys.getSaveLocationPreferenceKey(), "OpenCamera"); + about_string.append(sharedPreferences.getBoolean(PreferenceKeys.UsingSAFPreferenceKey, false)); + String save_location = sharedPreferences.getString(PreferenceKeys.SaveLocationPreferenceKey, "OpenCamera"); about_string.append("\nSave Location: "); about_string.append(save_location); - String save_location_saf = sharedPreferences.getString(PreferenceKeys.getSaveLocationSAFPreferenceKey(), ""); + String save_location_saf = sharedPreferences.getString(PreferenceKeys.SaveLocationSAFPreferenceKey, ""); about_string.append("\nSave Location SAF: "); about_string.append(save_location_saf); diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index b7882920f..3d87662ee 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -5,8 +5,6 @@ package net.sourceforge.opencamera; public class PreferenceKeys { // must be static, to safely call from other Activities - // arguably the static methods here that don't receive an argument could just be static final strings? Though we may want to change some of them to be cameraId-specific in future - /** If this preference is set, no longer show the intro dialog. */ public static final String FirstTimePreferenceKey = "done_first_time"; @@ -190,49 +188,29 @@ public class PreferenceKeys { public static final String DimWhenDisconnectedPreferenceKey = "preference_remote_disconnect_screen_dim"; - public static String getShowWhenLockedPreferenceKey() { - return "preference_show_when_locked"; - } + public static final String ShowWhenLockedPreferenceKey = "preference_show_when_locked"; public static final String AllowLongPressPreferenceKey = "preference_allow_long_press"; - public static String getStartupFocusPreferenceKey() { - return "preference_startup_focus"; - } + public static final String StartupFocusPreferenceKey = "preference_startup_focus"; public static final String MultiCamButtonPreferenceKey = "preference_multi_cam_button"; - public static String getKeepDisplayOnPreferenceKey() { - return "preference_keep_display_on"; - } + public static final String KeepDisplayOnPreferenceKey = "preference_keep_display_on"; - public static String getMaxBrightnessPreferenceKey() { - return "preference_max_brightness"; - } + public static final String MaxBrightnessPreferenceKey = "preference_max_brightness"; - public static String getUsingSAFPreferenceKey() { - return "preference_using_saf"; - } + public static final String UsingSAFPreferenceKey = "preference_using_saf"; - public static String getSaveLocationPreferenceKey() { - return "preference_save_location"; - } + public static final String SaveLocationPreferenceKey = "preference_save_location"; - public static String getSaveLocationSAFPreferenceKey() { - return "preference_save_location_saf"; - } + public static final String SaveLocationSAFPreferenceKey = "preference_save_location_saf"; - public static String getSavePhotoPrefixPreferenceKey() { - return "preference_save_photo_prefix"; - } + public static final String SavePhotoPrefixPreferenceKey = "preference_save_photo_prefix"; - public static String getSaveVideoPrefixPreferenceKey() { - return "preference_save_video_prefix"; - } + public static final String SaveVideoPrefixPreferenceKey = "preference_save_video_prefix"; - public static String getSaveZuluTimePreferenceKey() { - return "preference_save_zulu_time"; - } + public static final String SaveZuluTimePreferenceKey = "preference_save_zulu_time"; public static final String ShowZoomControlsPreferenceKey = "preference_show_zoom_controls"; @@ -310,19 +288,13 @@ public class PreferenceKeys { public static final String GhostImageAlphaPreferenceKey = "ghost_image_alpha"; - public static String getVideoStabilizationPreferenceKey() { - return "preference_video_stabilization"; - } + public static final String VideoStabilizationPreferenceKey = "preference_video_stabilization"; - public static String getForceVideo4KPreferenceKey() { - return "preference_force_video_4k"; - } + public static final String ForceVideo4KPreferenceKey = "preference_force_video_4k"; public static final String VideoFormatPreferenceKey = "preference_video_output_format"; - public static String getVideoBitratePreferenceKey() { - return "preference_video_bitrate"; - } + public static final String VideoBitratePreferenceKey = "preference_video_bitrate"; public static String getVideoFPSPreferenceKey(int cameraId) { // for cameraId==0, we return preference_video_fps instead of preference_video_fps_0, for @@ -338,83 +310,47 @@ public class PreferenceKeys { public static final String VideoProfileGammaPreferenceKey = "preference_video_profile_gamma"; - public static String getVideoMaxDurationPreferenceKey() { - return "preference_video_max_duration"; - } + public static final String VideoMaxDurationPreferenceKey = "preference_video_max_duration"; - public static String getVideoRestartPreferenceKey() { - return "preference_video_restart"; - } + public static final String VideoRestartPreferenceKey = "preference_video_restart"; - public static String getVideoMaxFileSizePreferenceKey() { - return "preference_video_max_filesize"; - } + public static final String VideoMaxFileSizePreferenceKey = "preference_video_max_filesize"; - public static String getVideoRestartMaxFileSizePreferenceKey() { - return "preference_video_restart_max_filesize"; - } + public static final String VideoRestartMaxFileSizePreferenceKey = "preference_video_restart_max_filesize"; - public static String getVideoFlashPreferenceKey() { - return "preference_video_flash"; - } + public static final String VideoFlashPreferenceKey = "preference_video_flash"; - public static String getVideoLowPowerCheckPreferenceKey() { - return "preference_video_low_power_check"; - } + public static final String VideoLowPowerCheckPreferenceKey = "preference_video_low_power_check"; - public static String getLockVideoPreferenceKey() { - return "preference_lock_video"; - } + public static final String LockVideoPreferenceKey = "preference_lock_video"; - public static String getRecordAudioPreferenceKey() { - return "preference_record_audio"; - } + public static final String RecordAudioPreferenceKey = "preference_record_audio"; - public static String getRecordAudioChannelsPreferenceKey() { - return "preference_record_audio_channels"; - } + public static final String RecordAudioChannelsPreferenceKey = "preference_record_audio_channels"; - public static String getRecordAudioSourcePreferenceKey() { - return "preference_record_audio_src"; - } + public static final String RecordAudioSourcePreferenceKey = "preference_record_audio_src"; public static final String PreviewSizePreferenceKey = "preference_preview_size"; - public static String getRotatePreviewPreferenceKey() { - return "preference_rotate_preview"; - } + public static final String RotatePreviewPreferenceKey = "preference_rotate_preview"; - public static String getLockOrientationPreferenceKey() { - return "preference_lock_orientation"; - } + public static final String LockOrientationPreferenceKey = "preference_lock_orientation"; - public static String getTimerPreferenceKey() { - return "preference_timer"; - } + public static final String TimerPreferenceKey = "preference_timer"; - public static String getTimerBeepPreferenceKey() { - return "preference_timer_beep"; - } + public static final String TimerBeepPreferenceKey = "preference_timer_beep"; - public static String getTimerSpeakPreferenceKey() { - return "preference_timer_speak"; - } + public static final String TimerSpeakPreferenceKey = "preference_timer_speak"; - public static String getRepeatModePreferenceKey() { - // note for historical reasons the preference refers to burst; the feature was renamed to - // "repeat" in v1.43, but we still need to use the old string to avoid changing user settings - // when people upgrade - return "preference_burst_mode"; - } + // note for historical reasons the preference refers to burst; the feature was renamed to + // "repeat" in v1.43, but we still need to use the old string to avoid changing user settings + // when people upgrade + public static final String RepeatModePreferenceKey = "preference_burst_mode"; - public static String getRepeatIntervalPreferenceKey() { - // see note about "repeat" vs "burst" under getRepeatModePreferenceKey() - return "preference_burst_interval"; - } + // see note about "repeat" vs "burst" under RepeatModePreferenceKey + public static final String RepeatIntervalPreferenceKey = "preference_burst_interval"; - public static String getShutterSoundPreferenceKey() { - return "preference_shutter_sound"; - } + public static final String ShutterSoundPreferenceKey = "preference_shutter_sound"; public static final String ImmersiveModePreferenceKey = "preference_immersive_mode"; } diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index 2e38daf98..d2154dd90 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -292,7 +292,7 @@ public class StorageUtils { // check Android version just to be safe if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - if( sharedPreferences.getBoolean(PreferenceKeys.getUsingSAFPreferenceKey(), false) ) { + if( sharedPreferences.getBoolean(PreferenceKeys.UsingSAFPreferenceKey, false) ) { return true; } } @@ -302,13 +302,13 @@ public class StorageUtils { // only valid if !isUsingSAF() String getSaveLocation() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - return sharedPreferences.getString(PreferenceKeys.getSaveLocationPreferenceKey(), "OpenCamera"); + return sharedPreferences.getString(PreferenceKeys.SaveLocationPreferenceKey, "OpenCamera"); } // only valid if isUsingSAF() String getSaveLocationSAF() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - return sharedPreferences.getString(PreferenceKeys.getSaveLocationSAFPreferenceKey(), ""); + return sharedPreferences.getString(PreferenceKeys.SaveLocationSAFPreferenceKey, ""); } // only valid if isUsingSAF() @@ -567,7 +567,7 @@ public class StorageUtils { index = "_" + count; // try to find a unique filename } SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - boolean useZuluTime = sharedPreferences.getString(PreferenceKeys.getSaveZuluTimePreferenceKey(), "local").equals("zulu"); + boolean useZuluTime = sharedPreferences.getString(PreferenceKeys.SaveZuluTimePreferenceKey, "local").equals("zulu"); String timeStamp; if( useZuluTime ) { SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd_HHmmss'Z'", Locale.US); @@ -581,12 +581,12 @@ public class StorageUtils { switch (type) { case MEDIA_TYPE_GYRO_INFO: // gyro info files have same name as the photo (but different extension) case MEDIA_TYPE_IMAGE: { - String prefix = sharedPreferences.getString(PreferenceKeys.getSavePhotoPrefixPreferenceKey(), "IMG_"); + String prefix = sharedPreferences.getString(PreferenceKeys.SavePhotoPrefixPreferenceKey, "IMG_"); mediaFilename = prefix + timeStamp + suffix + index + extension; break; } case MEDIA_TYPE_VIDEO: { - String prefix = sharedPreferences.getString(PreferenceKeys.getSaveVideoPrefixPreferenceKey(), "VID_"); + String prefix = sharedPreferences.getString(PreferenceKeys.SaveVideoPrefixPreferenceKey, "VID_"); mediaFilename = prefix + timeStamp + suffix + index + extension; break; } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java index f993c8919..a4a711739 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/PopupView.java @@ -847,7 +847,7 @@ public class PopupView extends LinearLayout { final String [] timer_values = getResources().getStringArray(R.array.preference_timer_values); String [] timer_entries = getResources().getStringArray(R.array.preference_timer_entries); - String timer_value = sharedPreferences.getString(PreferenceKeys.getTimerPreferenceKey(), "0"); + String timer_value = sharedPreferences.getString(PreferenceKeys.TimerPreferenceKey, "0"); timer_index = Arrays.asList(timer_values).indexOf(timer_value); if( timer_index == -1 ) { if( MyDebug.LOG ) @@ -862,7 +862,7 @@ public class PopupView extends LinearLayout { String new_timer_value = timer_values[timer_index]; SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(main_activity); SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putString(PreferenceKeys.getTimerPreferenceKey(), new_timer_value); + editor.putString(PreferenceKeys.TimerPreferenceKey, new_timer_value); editor.apply(); } @Override @@ -893,7 +893,7 @@ public class PopupView extends LinearLayout { final String [] repeat_mode_values = getResources().getStringArray(R.array.preference_burst_mode_values); String [] repeat_mode_entries = getResources().getStringArray(R.array.preference_burst_mode_entries); - String repeat_mode_value = sharedPreferences.getString(PreferenceKeys.getRepeatModePreferenceKey(), "1"); + String repeat_mode_value = sharedPreferences.getString(PreferenceKeys.RepeatModePreferenceKey, "1"); repeat_mode_index = Arrays.asList(repeat_mode_values).indexOf(repeat_mode_value); if( repeat_mode_index == -1 ) { if( MyDebug.LOG ) @@ -909,7 +909,7 @@ public class PopupView extends LinearLayout { String new_repeat_mode_value = repeat_mode_values[repeat_mode_index]; SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(main_activity); SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putString(PreferenceKeys.getRepeatModePreferenceKey(), new_repeat_mode_value); + editor.putString(PreferenceKeys.RepeatModePreferenceKey, new_repeat_mode_value); editor.apply(); } @Override -- GitLab From 477246c143613cd9d70cc37ab8328e0d31bf8387 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 29 Feb 2020 15:22:40 +0000 Subject: [PATCH 168/243] Simplify assertions (Android warnings). --- .../opencamera/test/MainActivityTest.java | 2542 ++++++++--------- 1 file changed, 1270 insertions(+), 1272 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 16fce10ae..a180e074e 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -70,8 +70,6 @@ import android.widget.SeekBar; import android.widget.TextView; import android.widget.ZoomControls; -import static junit.framework.Assert.fail; - public class MainActivityTest extends ActivityInstrumentationTestCase2 { private static final String TAG = "MainActivityTest"; private MainActivity mActivity = null; @@ -155,7 +153,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ) { switchToCamera(0); @@ -491,10 +489,10 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 sizes = mPreview.getSupportedPreviewSizes(); CameraController.Size best_size = mPreview.getOptimalPreviewSize(sizes); Log.d(TAG, "best size: " + best_size.width + ", " + best_size.height); - assertTrue( best_size.width == mPreview.getCameraController().getPreviewSize().width ); - assertTrue( best_size.height == mPreview.getCameraController().getPreviewSize().height ); + assertEquals(best_size.width, mPreview.getCameraController().getPreviewSize().width); + assertEquals(best_size.height, mPreview.getCameraController().getPreviewSize().height); } private void checkOptimalVideoPictureSize(double targetRatio) { @@ -867,8 +865,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 sizes = mPreview.getSupportedPictureSizes(false); CameraController.Size best_size = mPreview.getOptimalVideoPictureSize(sizes, targetRatio); Log.d(TAG, "best size: " + best_size.width + ", " + best_size.height); - assertTrue( best_size.width == mPreview.getCameraController().getPictureSize().width ); - assertTrue( best_size.height == mPreview.getCameraController().getPictureSize().height ); + assertEquals(best_size.width, mPreview.getCameraController().getPictureSize().width); + assertEquals(best_size.height, mPreview.getCameraController().getPictureSize().height); } private void checkSquareAspectRatio() { @@ -975,15 +973,15 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ) { Log.d(TAG, "switch camera"); @@ -1020,11 +1018,11 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 supported_focus_values = mPreview.getSupportedFocusValues(); - assertTrue( supported_focus_values != null ); + assertNotNull(supported_focus_values); assertTrue( supported_focus_values.size() > 1 ); for(String supported_focus_value : supported_focus_values) { Log.d(TAG, "supported_focus_value: " + supported_focus_value); @@ -1355,19 +1353,19 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ) { int cameraId = mPreview.getCameraId(); @@ -1602,8 +1600,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 0); String next_string = mActivity.getResources().getString(next ? net.sourceforge.opencamera.R.string.next : net.sourceforge.opencamera.R.string.previous); @@ -1802,7 +1800,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ) { @@ -1876,7 +1874,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 saved_count_cameraContinuousFocusMoving ); // switch to video @@ -2001,21 +1999,21 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 saved_count_cameraContinuousFocusMoving ); } @@ -2080,13 +2078,13 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= Build.VERSION_CODES.O ) { assertTrue(mActivity.testHasNotification()); } @@ -2445,7 +2443,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ) { Log.d(TAG, "switch camera"); @@ -2874,16 +2872,16 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 mPreview.getMaximumExposureTime() ) saved_exposure_time = mPreview.getMaximumExposureTime(); - assertTrue( mPreview.getCameraController().getExposureTime() == saved_exposure_time ); + assertEquals(mPreview.getCameraController().getExposureTime(), saved_exposure_time); } clickView(exposureButton); - assertTrue(exposureButton.getVisibility() == View.VISIBLE); - assertTrue(exposureContainer.getVisibility() == View.VISIBLE); - assertTrue(isoSeekBar.getVisibility() == View.VISIBLE); - assertTrue(exposureTimeSeekBar.getVisibility() == (mPreview.supportsExposureTime() ? View.VISIBLE : View.GONE)); + assertEquals(exposureButton.getVisibility(), View.VISIBLE); + assertEquals(exposureContainer.getVisibility(), View.VISIBLE); + assertEquals(isoSeekBar.getVisibility(), View.VISIBLE); + assertEquals(exposureTimeSeekBar.getVisibility(), (mPreview.supportsExposureTime() ? View.VISIBLE : View.GONE)); assertEquals(Math.min(old_max, mPreview.getMaximumISO()), mPreview.getCameraController().getISO()); if( mPreview.supportsExposureTime() ) - assertTrue( mPreview.getCameraController().getExposureTime() == saved_exposure_time ); + assertEquals(mPreview.getCameraController().getExposureTime(), saved_exposure_time); } } @@ -3041,11 +3039,11 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); if( !immersive_mode ) { - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); } - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); } } @@ -3596,15 +3594,15 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); - assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); - assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(switchCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE))); + assertEquals(switchMultiCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); + assertEquals(switchVideoButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); String focus_value = mPreview.getCameraController().getFocusValue(); String focus_value_ui = mPreview.getCurrentFocusValue(); @@ -3689,7 +3687,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // now wait for immersive mode to kick in Thread.sleep(6000); - assertTrue(switchCameraButton.getVisibility() == View.GONE); - assertTrue(switchMultiCameraButton.getVisibility() == View.GONE); - assertTrue(switchVideoButton.getVisibility() == View.GONE); - assertTrue(exposureButton.getVisibility() == View.GONE); - assertTrue(exposureLockButton.getVisibility() == View.GONE); - assertTrue(audioControlButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == View.GONE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.GONE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), View.GONE); + assertEquals(switchMultiCameraButton.getVisibility(), View.GONE); + assertEquals(switchVideoButton.getVisibility(), View.GONE); + assertEquals(exposureButton.getVisibility(), View.GONE); + assertEquals(exposureLockButton.getVisibility(), View.GONE); + assertEquals(audioControlButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), View.GONE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.GONE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); subTestTakePhoto(false, true, true, true, false, false, false, false); // test now exited immersive mode - assertTrue(switchCameraButton.getVisibility() == (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // wait for immersive mode to kick in again Thread.sleep(6000); - assertTrue(switchCameraButton.getVisibility() == View.GONE); - assertTrue(switchMultiCameraButton.getVisibility() == View.GONE); - assertTrue(switchVideoButton.getVisibility() == View.GONE); - assertTrue(exposureButton.getVisibility() == View.GONE); - assertTrue(exposureLockButton.getVisibility() == View.GONE); - assertTrue(audioControlButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == View.GONE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.GONE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), View.GONE); + assertEquals(switchMultiCameraButton.getVisibility(), View.GONE); + assertEquals(switchVideoButton.getVisibility(), View.GONE); + assertEquals(exposureButton.getVisibility(), View.GONE); + assertEquals(exposureLockButton.getVisibility(), View.GONE); + assertEquals(audioControlButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), View.GONE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.GONE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); subTestTakePhotoPreviewPaused(true, false); // test now exited immersive mode - assertTrue(switchCameraButton.getVisibility() == (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // need to switch video before going back to immersive mode if( !mPreview.isVideo() ) { @@ -4767,53 +4765,53 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // wait for immersive mode to kick in again Thread.sleep(6000); - assertTrue(switchCameraButton.getVisibility() == View.GONE); - assertTrue(switchMultiCameraButton.getVisibility() == View.GONE); - assertTrue(switchVideoButton.getVisibility() == View.GONE); - assertTrue(exposureButton.getVisibility() == View.GONE); - assertTrue(exposureLockButton.getVisibility() == View.GONE); - assertTrue(audioControlButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == View.GONE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.GONE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), View.GONE); + assertEquals(switchMultiCameraButton.getVisibility(), View.GONE); + assertEquals(switchVideoButton.getVisibility(), View.GONE); + assertEquals(exposureButton.getVisibility(), View.GONE); + assertEquals(exposureLockButton.getVisibility(), View.GONE); + assertEquals(audioControlButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), View.GONE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.GONE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); subTestTakeVideo(false, false, false, true, null, 5000, false, false); // test touch exits immersive mode TouchUtils.clickView(MainActivityTest.this, mPreview.getView()); - assertTrue(switchCameraButton.getVisibility() == (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // switch back to photo mode if( mPreview.isVideo() ) { @@ -4827,19 +4825,19 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // now wait for immersive mode to kick in Thread.sleep(6000); - assertTrue(switchCameraButton.getVisibility() == View.GONE); - assertTrue(switchMultiCameraButton.getVisibility() == View.GONE); - assertTrue(switchVideoButton.getVisibility() == View.GONE); - assertTrue(exposureButton.getVisibility() == View.GONE); - assertTrue(exposureLockButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == View.GONE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.GONE); - assertTrue(takePhotoButton.getVisibility() == View.GONE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), View.GONE); + assertEquals(switchMultiCameraButton.getVisibility(), View.GONE); + assertEquals(switchVideoButton.getVisibility(), View.GONE); + assertEquals(exposureButton.getVisibility(), View.GONE); + assertEquals(exposureLockButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), View.GONE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.GONE); + assertEquals(takePhotoButton.getVisibility(), View.GONE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); // now touch to exit immersive mode TouchUtils.clickView(MainActivityTest.this, mPreview.getView()); Thread.sleep(500); // test now exited immersive mode - assertTrue(switchCameraButton.getVisibility() == (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(zoomSeekBar.getVisibility() == View.VISIBLE); - assertTrue(takePhotoButton.getVisibility() == View.VISIBLE); - assertTrue(pauseVideoButton.getVisibility() == View.GONE); - assertTrue(takePhotoVideoButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(zoomSeekBar.getVisibility(), View.VISIBLE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); } /** Tests the use of the FLAG_LAYOUT_NO_LIMITS flag introduced in 1.48. @@ -5050,16 +5048,16 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); - assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); - assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(switchCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE))); + assertEquals(switchMultiCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); + assertEquals(switchVideoButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); // store status to compare with later int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); View takePhotoButton = mActivity.findViewById(net.sourceforge.opencamera.R.id.take_photo); Log.d(TAG, "about to click take photo"); @@ -5069,30 +5067,30 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); if( !immersive_mode ) { - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); } - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); // check still same icon even after a delay Log.d(TAG, "thumbnail:" + thumbnail); Log.d(TAG, "mActivity.gallery_bitmap: " + mActivity.gallery_bitmap); - assertTrue(mActivity.gallery_bitmap == thumbnail); + assertSame(mActivity.gallery_bitmap, thumbnail); Thread.sleep(1000); Log.d(TAG, "thumbnail:" + thumbnail); Log.d(TAG, "mActivity.gallery_bitmap: " + mActivity.gallery_bitmap); - assertTrue(mActivity.gallery_bitmap == thumbnail); + assertSame(mActivity.gallery_bitmap, thumbnail); mActivity.waitUntilImageQueueEmpty(); } @@ -5204,19 +5202,19 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); // flash and focus etc default visibility tested in another test // but store status to compare with later //int flashVisibility = flashButton.getVisibility(); //int focusVisibility = focusButton.getVisibility(); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); View takePhotoButton = mActivity.findViewById(net.sourceforge.opencamera.R.id.take_photo); Log.d(TAG, "about to click take photo"); @@ -5227,32 +5225,32 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); // icon may be null, or have been set to another image - only changed after a delay Thread.sleep(2000); Log.d(TAG, "gallery_bitmap: " + mActivity.gallery_bitmap); Log.d(TAG, "thumbnail: " + thumbnail); - assertTrue(mActivity.gallery_bitmap != thumbnail); + assertNotSame(mActivity.gallery_bitmap, thumbnail); } mActivity.waitUntilImageQueueEmpty(); } @@ -5409,12 +5407,12 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); // flash and focus etc default visibility tested in another test // but store status to compare with later //int flashVisibility = flashButton.getVisibility(); //int focusVisibility = focusButton.getVisibility(); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); // autofocus shouldn't be immediately, but after a delay Thread.sleep(2000); @@ -5570,13 +5568,13 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); } private void takePhotoLoop(int count) { @@ -5625,13 +5623,13 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); - assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); - assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(switchCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE))); + assertEquals(switchMultiCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); + assertEquals(switchVideoButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); // but store status to compare with later int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - - assertTrue( (Integer)takePhotoButton.getTag() == net.sourceforge.opencamera.R.drawable.take_video_selector ); - assertTrue( (Integer)switchVideoButton.getTag() == net.sourceforge.opencamera.R.drawable.take_photo ); - assertTrue( takePhotoButton.getContentDescription().equals( mActivity.getResources().getString(net.sourceforge.opencamera.R.string.start_video) ) ); + assertEquals(audioControlButton.getVisibility(), ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + + assertEquals((int) (Integer) takePhotoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_video_selector); + assertEquals((int) (Integer) switchVideoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_photo); + assertEquals(takePhotoButton.getContentDescription(), mActivity.getResources().getString(net.sourceforge.opencamera.R.string.start_video)); Log.d(TAG, "about to click take video"); clickView(takePhotoButton); Log.d(TAG, "done clicking take video"); @@ -5872,28 +5870,28 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= Build.VERSION_CODES.N ) - assertTrue( pauseVideoButton.getVisibility() == View.VISIBLE ); + assertEquals(pauseVideoButton.getVisibility(), View.VISIBLE); else - assertTrue( pauseVideoButton.getVisibility() == View.GONE ); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); if( mPreview.supportsPhotoVideoRecording() ) - assertTrue( takePhotoVideoButton.getVisibility() == View.VISIBLE ); + assertEquals(takePhotoVideoButton.getVisibility(), View.VISIBLE); else - assertTrue( takePhotoVideoButton.getVisibility() == View.GONE ); - assertTrue(switchCameraButton.getVisibility() == View.GONE); - assertTrue(switchMultiCameraButton.getVisibility() == View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); + assertEquals(switchCameraButton.getVisibility(), View.GONE); + assertEquals(switchMultiCameraButton.getVisibility(), View.GONE); //assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); - assertTrue(switchVideoButton.getVisibility() == View.GONE); - assertTrue(audioControlButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == (!immersive_mode && mPreview.supportsFlash() ? View.VISIBLE : View.GONE)); // popup button only visible when recording video if flash supported - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(switchVideoButton.getVisibility(), View.GONE); + assertEquals(audioControlButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), (!immersive_mode && mPreview.supportsFlash() ? View.VISIBLE : View.GONE)); // popup button only visible when recording video if flash supported + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); if( test_cb == null ) { if( !immersive_mode && time_ms > 500 ) { @@ -5904,15 +5902,15 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE))); - assertTrue(switchMultiCameraButton.getVisibility() == (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); - assertTrue(audioControlButton.getVisibility() == ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); + assertEquals(switchCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE))); + assertEquals(switchMultiCameraButton.getVisibility(), (immersive_mode ? View.GONE : (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE))); + assertEquals(audioControlButton.getVisibility(), ((has_audio_control_button && !immersive_mode) ? View.VISIBLE : View.GONE)); } - assertTrue(switchVideoButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(popupButton.getVisibility() == (immersive_mode ? View.GONE : View.VISIBLE)); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(switchVideoButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(popupButton.getVisibility(), (immersive_mode ? View.GONE : View.VISIBLE)); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); assertFalse( mPreview.isVideoRecording() ); - assertTrue( (Integer)takePhotoButton.getTag() == net.sourceforge.opencamera.R.drawable.take_video_selector ); - assertTrue( (Integer)switchVideoButton.getTag() == net.sourceforge.opencamera.R.drawable.take_photo ); + assertEquals((int) (Integer) takePhotoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_video_selector); + assertEquals((int) (Integer) switchVideoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_photo); assertEquals( takePhotoButton.getContentDescription(), mActivity.getResources().getString(net.sourceforge.opencamera.R.string.start_video) ); - assertTrue( pauseVideoButton.getContentDescription().equals( mActivity.getResources().getString(net.sourceforge.opencamera.R.string.pause_video) ) ); + assertEquals(pauseVideoButton.getContentDescription(), mActivity.getResources().getString(net.sourceforge.opencamera.R.string.pause_video)); Log.d(TAG, "pauseVideoButton.getVisibility(): " + pauseVideoButton.getVisibility()); - assertTrue( pauseVideoButton.getVisibility() == View.GONE ); - assertTrue( takePhotoVideoButton.getVisibility() == View.GONE ); + assertEquals(pauseVideoButton.getVisibility(), View.GONE); + assertEquals(takePhotoVideoButton.getVisibility(), View.GONE); Log.d(TAG, "test_n_videos_scanned: " + mActivity.getApplicationInterface().test_n_videos_scanned); if( !allow_failure ) { @@ -6110,11 +6108,11 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 20000 ) { // need to allow long time for testing devices without mobile network; will likely fail altogether if don't even have wifi - assertTrue(false); + fail(); } } getInstrumentation().waitForIdleSync(); - assertTrue(mActivity.getLocationSupplier().getLocation() != null); + assertNotNull(mActivity.getLocationSupplier().getLocation()); Log.d(TAG, "have location"); try { @@ -6122,7 +6120,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= 3000 - time_tol_ms ); @@ -6187,8 +6185,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= 6000 - time_tol_ms ); @@ -6263,7 +6261,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= 3000 - time_tol_ms ); @@ -6295,8 +6293,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); // flash and focus etc default visibility tested in another test // but store status to compare with later //int flashVisibility = flashButton.getVisibility(); //int focusVisibility = focusButton.getVisibility(); int exposureVisibility = exposureButton.getVisibility(); int exposureLockVisibility = exposureLockButton.getVisibility(); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); // workaround for Android 7.1 bug at https://stackoverflow.com/questions/47548317/what-belong-is-badtokenexception-at-classes-of-project // without this, we get a crash due to that problem on Nexus (old API at least) in testTakeVideoMaxDuration @@ -7485,17 +7483,17 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); //assertTrue(flashButton.getVisibility() == flashVisibility); //assertTrue(focusButton.getVisibility() == focusVisibility); - assertTrue(exposureButton.getVisibility() == exposureVisibility); - assertTrue(exposureLockButton.getVisibility() == exposureLockVisibility); - assertTrue(audioControlButton.getVisibility() == (has_audio_control_button ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(exposureButton.getVisibility(), exposureVisibility); + assertEquals(exposureLockButton.getVisibility(), exposureLockVisibility); + assertEquals(audioControlButton.getVisibility(), (has_audio_control_button ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); } public void testTakeVideoMaxDuration() throws InterruptedException { @@ -7597,7 +7595,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 supported_flash_values = mPreview.getSupportedFlashValues(); if( supported_flash_values == null ) { // button shouldn't show at all - assertTrue( popupButton.getVisibility() == View.GONE ); + assertEquals(popupButton.getVisibility(), View.GONE); } else { // now open popup again @@ -8331,13 +8329,13 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == (mPreview.supportsExposures() ? View.VISIBLE : View.GONE)); - assertTrue(exposureLockButton.getVisibility() == (mPreview.supportsExposureLock() ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), (mPreview.supportsExposures() ? View.VISIBLE : View.GONE)); + assertEquals(exposureLockButton.getVisibility(), (mPreview.supportsExposureLock() ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); clickView(takePhotoButton); waitForTakePhoto(); Log.d(TAG, "done taking 1st photo"); this.getInstrumentation().waitForIdleSync(); - assertTrue(mPreview.count_cameraTakePicture==7); + assertEquals(7, mPreview.count_cameraTakePicture); mActivity.waitUntilImageQueueEmpty(); n_new_files = getNFiles(folder) - n_files; Log.d(TAG, "n_new_files: " + n_new_files); - assertTrue(n_new_files == 7); + assertEquals(7, n_new_files); // wait 2s, should still not have taken another photo Thread.sleep(2000); - assertTrue(mPreview.count_cameraTakePicture==7); + assertEquals(7, mPreview.count_cameraTakePicture); n_new_files = getNFiles(folder) - n_files; Log.d(TAG, "n_new_files: " + n_new_files); - assertTrue(n_new_files == 7); + assertEquals(7, n_new_files); // check GUI has returned to correct state - assertTrue(switchCameraButton.getVisibility() == (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == (mPreview.supportsExposures() ? View.VISIBLE : View.GONE)); - assertTrue(exposureLockButton.getVisibility() == (mPreview.supportsExposureLock() ? View.VISIBLE : View.GONE)); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), (mPreview.supportsExposures() ? View.VISIBLE : View.GONE)); + assertEquals(exposureLockButton.getVisibility(), (mPreview.supportsExposureLock() ? View.VISIBLE : View.GONE)); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); // wait another 5s, should have taken another photo (need to allow time for the extra auto-focus) Thread.sleep(5000); - assertTrue(mPreview.count_cameraTakePicture==8); + assertEquals(8, mPreview.count_cameraTakePicture); n_new_files = getNFiles(folder) - n_files; Log.d(TAG, "n_new_files: " + n_new_files); - assertTrue(n_new_files == 8); + assertEquals(8, n_new_files); // wait 4s, should not have taken any more photos Thread.sleep(4000); - assertTrue(mPreview.count_cameraTakePicture==8); + assertEquals(8, mPreview.count_cameraTakePicture); n_new_files = getNFiles(folder) - n_files; Log.d(TAG, "n_new_files: " + n_new_files); - assertTrue(n_new_files == 8); + assertEquals(8, n_new_files); } catch(InterruptedException e) { e.printStackTrace(); - assertTrue(false); + fail(); } } @@ -8777,7 +8775,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 20000 ) { // need to allow long time for testing devices without mobile network; will likely fail altogether if don't even have wifi - assertTrue(false); + fail(); } } Log.d(TAG, "have received location"); this.getInstrumentation().waitForIdleSync(); - assertTrue(mActivity.getLocationSupplier().getLocation() != null); - assertTrue(mPreview.count_cameraTakePicture==0); + assertNotNull(mActivity.getLocationSupplier().getLocation()); + assertEquals(0, mPreview.count_cameraTakePicture); View takePhotoButton = mActivity.findViewById(net.sourceforge.opencamera.R.id.take_photo); mActivity.test_last_saved_image = null; @@ -8907,9 +8905,9 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 20000 ) { // need to allow long time for testing devices without mobile network; will likely fail altogether if don't even have wifi - assertTrue(false); + fail(); } } this.getInstrumentation().waitForIdleSync(); - assertTrue(mActivity.getLocationSupplier().getLocation() != null); + assertNotNull(mActivity.getLocationSupplier().getLocation()); // switch to front camera if( mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ) { @@ -9075,7 +9073,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 20000 ) { // need to allow long time for testing devices without mobile network; will likely fail altogether if don't even have wifi - assertTrue(false); + fail(); } } this.getInstrumentation().waitForIdleSync(); - assertTrue(mActivity.getLocationSupplier().getLocation() != null); + assertNotNull(mActivity.getLocationSupplier().getLocation()); clickView(takePhotoButton); @@ -9171,9 +9169,9 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 zoom); - assertTrue(max_zoom-zoomSeekBar.getProgress() == mPreview.getCameraController().getZoom()); + assertEquals(max_zoom - zoomSeekBar.getProgress(), mPreview.getCameraController().getZoom()); mPreview.scaleZoom(0.5f); this.getInstrumentation().waitForIdleSync(); Log.d(TAG, "compare actual zoom " + mPreview.getCameraController().getZoom() + " to zoom " + zoom); - assertTrue(mPreview.getCameraController().getZoom() == zoom); - assertTrue(max_zoom-zoomSeekBar.getProgress() == mPreview.getCameraController().getZoom()); + assertEquals(mPreview.getCameraController().getZoom(), zoom); + assertEquals(max_zoom - zoomSeekBar.getProgress(), mPreview.getCameraController().getZoom()); // test to max/min mPreview.scaleZoom(10000.0f); this.getInstrumentation().waitForIdleSync(); Log.d(TAG, "compare actual zoom " + mPreview.getCameraController().getZoom() + " to max_zoom " + max_zoom); - assertTrue(mPreview.getCameraController().getZoom() == max_zoom); - assertTrue(max_zoom-zoomSeekBar.getProgress() == mPreview.getCameraController().getZoom()); + assertEquals(mPreview.getCameraController().getZoom(), max_zoom); + assertEquals(max_zoom - zoomSeekBar.getProgress(), mPreview.getCameraController().getZoom()); mPreview.scaleZoom(1.0f/10000.0f); this.getInstrumentation().waitForIdleSync(); Log.d(TAG, "compare actual zoom " + mPreview.getCameraController().getZoom() + " to zero"); - assertTrue(mPreview.getCameraController().getZoom() == 0); - assertTrue(max_zoom-zoomSeekBar.getProgress() == mPreview.getCameraController().getZoom()); + assertEquals(0, mPreview.getCameraController().getZoom()); + assertEquals(max_zoom - zoomSeekBar.getProgress(), mPreview.getCameraController().getZoom()); // use seekbar to zoom Log.d(TAG, "zoom to max"); @@ -9381,13 +9379,13 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 0); assertTrue(save_location_history.contains(save_folder)); - assertTrue(save_location_history.get( save_location_history.size()-1 ).equals(save_folder)); + assertEquals(save_location_history.get(save_location_history.size() - 1), save_folder); File folder = mActivity.getImageFolder(); if( folder.exists() && delete_folder ) { @@ -9801,14 +9799,14 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= CameraController.ISO_FOR_DARK ) assertEquals(CameraController.N_IMAGES_NR_DARK_LOW_LIGHT, mActivity.getPreview().getCameraController().getBurstTotal()); // reset @@ -11095,7 +11093,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == View.VISIBLE); - assertTrue(exposureLockButton.getVisibility() == View.VISIBLE); - assertTrue(audioControlButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(settingsButton.getVisibility() == View.VISIBLE); - assertTrue(cancelPanoramaButton.getVisibility() == View.GONE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), View.VISIBLE); + assertEquals(exposureLockButton.getVisibility(), View.VISIBLE); + assertEquals(audioControlButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(settingsButton.getVisibility(), View.VISIBLE); + assertEquals(cancelPanoramaButton.getVisibility(), View.GONE); Log.d(TAG, "about to click take photo"); clickView(takePhotoButton); @@ -11276,24 +11274,24 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 1 ? View.VISIBLE : View.GONE)); - assertTrue(switchMultiCameraButton.getVisibility() == (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); - assertTrue(switchVideoButton.getVisibility() == View.VISIBLE); - assertTrue(exposureButton.getVisibility() == View.VISIBLE); - assertTrue(exposureLockButton.getVisibility() == View.VISIBLE); - assertTrue(audioControlButton.getVisibility() == View.GONE); - assertTrue(popupButton.getVisibility() == View.VISIBLE); - assertTrue(trashButton.getVisibility() == View.GONE); - assertTrue(shareButton.getVisibility() == View.GONE); - assertTrue(settingsButton.getVisibility() == View.VISIBLE); - assertTrue(cancelPanoramaButton.getVisibility() == View.GONE); + assertEquals(takePhotoButton.getVisibility(), View.VISIBLE); + assertEquals(switchCameraButton.getVisibility(), (mPreview.getCameraControllerManager().getNumberOfCameras() > 1 ? View.VISIBLE : View.GONE)); + assertEquals(switchMultiCameraButton.getVisibility(), (mActivity.showSwitchMultiCamIcon() ? View.VISIBLE : View.GONE)); + assertEquals(switchVideoButton.getVisibility(), View.VISIBLE); + assertEquals(exposureButton.getVisibility(), View.VISIBLE); + assertEquals(exposureLockButton.getVisibility(), View.VISIBLE); + assertEquals(audioControlButton.getVisibility(), View.GONE); + assertEquals(popupButton.getVisibility(), View.VISIBLE); + assertEquals(trashButton.getVisibility(), View.GONE); + assertEquals(shareButton.getVisibility(), View.GONE); + assertEquals(settingsButton.getVisibility(), View.VISIBLE); + assertEquals(cancelPanoramaButton.getVisibility(), View.GONE); if( !cancel && !to_max ) { // test trying to take another photo whilst saving @@ -11378,7 +11376,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Sat, 29 Feb 2020 16:56:30 +0000 Subject: [PATCH 169/243] Extra checks to ensure location listening stopped in background. --- .../net/sourceforge/opencamera/MainActivity.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 7e6373347..6e0dd3061 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -962,6 +962,16 @@ public class MainActivity extends Activity { } } + @Override + protected void onStop() { + if( MyDebug.LOG ) + Log.d(TAG, "onStop"); + super.onStop(); + + // we stop location listening in onPause, but done here again just to be certain! + applicationInterface.getLocationSupplier().freeLocationListeners(); + } + @Override protected void onDestroy() { if( MyDebug.LOG ) { @@ -1014,6 +1024,9 @@ public class MainActivity extends Activity { textToSpeech = null; } + // we stop location listening in onPause, but done here again just to be certain! + applicationInterface.getLocationSupplier().freeLocationListeners(); + super.onDestroy(); if( MyDebug.LOG ) Log.d(TAG, "onDestroy done"); @@ -1292,6 +1305,9 @@ public class MainActivity extends Activity { createImageSavingNotification(); } + // intentionally do this again, just in case something turned location on since - keep this right at the end: + applicationInterface.getLocationSupplier().freeLocationListeners(); + if( MyDebug.LOG ) { Log.d(TAG, "onPause: total time to pause: " + (System.currentTimeMillis() - debug_time)); } -- GitLab From 3fbecf8eb0c89aa54f6c330de3aa8d1902791a6a Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 29 Feb 2020 16:56:57 +0000 Subject: [PATCH 170/243] Restrict max ghost image alpha to 80%. --- .../net/sourceforge/opencamera/MyPreferenceFragment.java | 9 ++++++--- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index 9ad08acea..b4d7d3976 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -287,12 +287,15 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared } { - final int n_ghost_image_alpha = 20; + final int max_ghost_image_alpha = 80; // limit max to 80% for privacy reasons, so it isn't possible to put in a state where camera is on, but no preview is shown + final int ghost_image_alpha_step = 5; // should be exact divisor of max_ghost_image_alpha + final int n_ghost_image_alpha = max_ghost_image_alpha/ghost_image_alpha_step; CharSequence [] entries = new CharSequence[n_ghost_image_alpha]; CharSequence [] values = new CharSequence[n_ghost_image_alpha]; for(int i=0;iHide everything Ghost image opacity - Alpha value to use for ghost images. A lower value means more transparent, 100%% means opaque.\n%s + Alpha value to use for ghost images. A lower value means more transparent, higher means more opaque.\n%s Zebra stripes foreground color Color to use for the foreground stripe when showing zebra stripes.\n%s -- GitLab From c4f5ec93c741883349559ee64843ba47afb6dbea Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 29 Feb 2020 17:10:50 +0000 Subject: [PATCH 171/243] Camera specific hardware keys such as volume keys shouldn't take effect in settings etc. --- _docs/history.html | 1 + .../sourceforge/opencamera/MainActivity.java | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 8c7c73c2e..ae920457d 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -54,6 +54,7 @@ FIXED Taking front camera photos with frontscreen torch was slow. FIXED When using "Pause after taking photo", touching to unpause no longer triggers auto focus, or taking another photo for "Touch to capture". FIXED Take photo widget issue. +FIXED Camera specific hardware keys such as volume keys shouldn't take effect in settings etc. FIXED Don't set optical image stabilization if video digital stabilization is enabled in video mode. FIXED Seamless video restart on maximum filesize (for Android 8+) wasn't broadcasting video files diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 6e0dd3061..a5dd6e8f8 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1120,16 +1120,30 @@ public class MainActivity extends Activity { public boolean onKeyDown(int keyCode, KeyEvent event) { if( MyDebug.LOG ) Log.d(TAG, "onKeyDown: " + keyCode); - boolean handled = mainUI.onKeyDown(keyCode, event); - if( handled ) - return true; + if( camera_in_background ) { + // don't allow keys such as volume keys for taking photo when camera in background! + if( MyDebug.LOG ) + Log.d(TAG, "camera is in background"); + } + else { + boolean handled = mainUI.onKeyDown(keyCode, event); + if( handled ) + return true; + } return super.onKeyDown(keyCode, event); } public boolean onKeyUp(int keyCode, KeyEvent event) { if( MyDebug.LOG ) Log.d(TAG, "onKeyUp: " + keyCode); - mainUI.onKeyUp(keyCode, event); + if( camera_in_background ) { + // don't allow keys such as volume keys for taking photo when camera in background! + if( MyDebug.LOG ) + Log.d(TAG, "camera is in background"); + } + else { + mainUI.onKeyUp(keyCode, event); + } return super.onKeyUp(keyCode, event); } -- GitLab From 2a919a9dd0ac31c48dbcf6a8170f33ac26a0a55b Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 29 Feb 2020 20:07:56 +0000 Subject: [PATCH 172/243] Add comment about pause preview. --- .../main/java/net/sourceforge/opencamera/preview/Preview.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 8002cfc48..a85766552 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -5918,6 +5918,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( pause_preview && success ) { if( is_preview_started ) { // need to manually stop preview on Android L Camera2 + // also note: even though we now draw the last image on top of the screen instead of relying on the + // camera preview being paused, it's still good practice to pause the preview/camera for privacy reasons if( camera_controller != null ) { camera_controller.stopPreview(); } -- GitLab From 5f9294d62fdc669436025861a9d57bc4e00b220d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 13:28:00 +0000 Subject: [PATCH 173/243] Update jt video profiles. --- .../sourceforge/opencamera/MainActivity.java | 19 +- .../opencamera/MyApplicationInterface.java | 21 +- .../cameracontroller/CameraController.java | 7 +- .../cameracontroller/CameraController2.java | 233 ++++++------------ app/src/main/res/values/arrays.xml | 12 +- app/src/main/res/values/strings.xml | 9 +- 6 files changed, 89 insertions(+), 212 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index a5dd6e8f8..a795d1f31 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -4592,23 +4592,14 @@ public class MainActivity extends Activity { case TONEMAPPROFILE_GAMMA: string_id = R.string.preference_video_gamma; break; + case TONEMAPPROFILE_JTVIDEO: + string_id = R.string.preference_video_jtvideo; + break; case TONEMAPPROFILE_JTLOG: string_id = R.string.preference_video_jtlog; break; - case TONEMAPPROFILE_JTLOGV2: - string_id = R.string.preference_video_jtlogv2; - break; - case TONEMAPPROFILE_JTLOGV3: - string_id = R.string.preference_video_jtlogv3; - break; - /*case TONEMAPPROFILE_JTLNP1: - string_id = R.string.preference_video_jtlnp1; - break;*/ - case TONEMAPPROFILE_JTLIN1: - string_id = R.string.preference_video_jtlin1; - break; - case TONEMAPPROFILE_JTLIN2: - string_id = R.string.preference_video_jtlin2; + case TONEMAPPROFILE_JTLOG2: + string_id = R.string.preference_video_jtlog2; break; } if( string_id != 0 ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 3910bb458..63b200781 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -767,18 +767,12 @@ public class MyApplicationInterface extends BasicApplicationInterface { return CameraController.TonemapProfile.TONEMAPPROFILE_LOG; case "gamma": return CameraController.TonemapProfile.TONEMAPPROFILE_GAMMA; + case "jtvideo": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTVIDEO; case "jtlog": return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOG; - case "jtlogv2": - return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOGV2; - case "jtlogv3": - return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOGV3; - /*case "jtlnp1": - return CameraController.TonemapProfile.TONEMAPPROFILE_JTLNP1;*/ - case "jtlin1": - return CameraController.TonemapProfile.TONEMAPPROFILE_JTLIN1; - case "jtlin2": - return CameraController.TonemapProfile.TONEMAPPROFILE_JTLIN2; + case "jtlog2": + return CameraController.TonemapProfile.TONEMAPPROFILE_JTLOG2; } return CameraController.TonemapProfile.TONEMAPPROFILE_OFF; } @@ -792,12 +786,9 @@ public class MyApplicationInterface extends BasicApplicationInterface { case "rec709": case "srgb": case "gamma": + case "jtvideo": case "jtlog": - case "jtlogv2": - case "jtlogv3": - //case "jtlnp1": - case "jtlin1": - case "jtlin2": + case "jtlog2": return 0.0f; /*case "fine": return 1.0f; diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 228f501a8..8fe86d9fb 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -456,12 +456,9 @@ public abstract class CameraController { TONEMAPPROFILE_SRGB, TONEMAPPROFILE_LOG, TONEMAPPROFILE_GAMMA, + TONEMAPPROFILE_JTVIDEO, TONEMAPPROFILE_JTLOG, - TONEMAPPROFILE_JTLOGV2, - TONEMAPPROFILE_JTLOGV3, - //TONEMAPPROFILE_JTLNP1 - TONEMAPPROFILE_JTLIN1, - TONEMAPPROFILE_JTLIN2 + TONEMAPPROFILE_JTLOG2 } /** Sets a tonemap profile. diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 8338c8326..4c1094158 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -82,141 +82,67 @@ public class CameraController2 extends CameraController { private boolean supports_white_balance_temperature; private final static int tonemap_log_max_curve_points_c = 64; + private final static float [] jtvideo_values_base = new float[] { + 0.00f, 0.00f, + 0.01f, 0.055f, + 0.02f, 0.1f, + 0.05f, 0.21f, + 0.09f, 0.31f, + 0.13f, 0.38f, + 0.18f, 0.45f, + 0.28f, 0.57f, + 0.35f, 0.64f, + 0.45f, 0.72f, + 0.51f, 0.76f, + 0.60f, 0.82f, + 0.67f, 0.86f, + 0.77f, 0.91f, + 0.88f, 0.96f, + 0.97f, 0.99f, + 1.00f, 1.00f + }; + private final float [] jtvideo_values; private final static float [] jtlog_values_base = new float[] { - 0.0000f, 0.0000f, 0.0230f, 0.2295f, 0.0280f, 0.2783f, 0.0319f, 0.3049f, 0.0369f, 0.3321f, 0.0430f, 0.3589f, - 0.0500f, 0.3844f, 0.0583f, 0.4098f, 0.0680f, 0.4351f, 0.0800f, 0.4619f, 0.0930f, 0.4870f, 0.1051f, 0.5076f, - 0.1180f, 0.5275f, 0.1430f, 0.5612f, 0.1680f, 0.5904f, 0.1930f, 0.6162f, 0.2180f, 0.6395f, 0.2430f, 0.6608f, - 0.2680f, 0.6804f, 0.2930f, 0.6986f, 0.3180f, 0.7157f, 0.3430f, 0.7318f, 0.3680f, 0.7471f, 0.3930f, 0.7615f, - 0.4180f, 0.7753f, 0.4430f, 0.7885f, 0.4680f, 0.8011f, 0.4930f, 0.8132f, 0.5180f, 0.8249f, 0.5430f, 0.8361f, - 0.5680f, 0.8470f, 0.5930f, 0.8575f, 0.6180f, 0.8677f, 0.6430f, 0.8776f, 0.6680f, 0.8872f, 0.6930f, 0.8966f, - 0.7180f, 0.9057f, 0.7430f, 0.9145f, 1.0000f, 1.0000f + 0.00f, 0.00f, + 0.01f, 0.07f, + 0.03f, 0.17f, + 0.05f, 0.25f, + 0.07f, 0.31f, + 0.09f, 0.36f, + 0.13f, 0.44f, + 0.18f, 0.51f, + 0.24f, 0.57f, + 0.31f, 0.64f, + 0.38f, 0.70f, + 0.46f, 0.76f, + 0.58f, 0.83f, + 0.70f, 0.89f, + 0.86f, 0.95f, + 0.99f, 0.99f, + 1.00f, 1.00f }; private final float [] jtlog_values; - private final static float [] jtlogv2_values_base = new float[] { - 0.0000f, 0.0000f, - 0.0070f, 0.0700f, - 0.0140f, 0.1400f, - 0.0230f, 0.2295f, - 0.0280f, 0.2783f, - 0.0369f, 0.3321f, - 0.0500f, 0.3844f, - 0.0680f, 0.4351f, - 0.0930f, 0.4870f, - 0.1180f, 0.5275f, - 0.1430f, 0.5612f, - 0.1680f, 0.5904f, - 0.1930f, 0.6162f, - 0.2180f, 0.6395f, - 0.2430f, 0.6608f, - 0.2680f, 0.6804f, - 0.2930f, 0.6986f, - 0.3430f, 0.7318f, - 0.3930f, 0.7615f, - 0.4430f, 0.7885f, - 0.4930f, 0.8132f, - 0.5430f, 0.8361f, - 0.5930f, 0.8575f, - 0.6430f, 0.8776f, - 0.6930f, 0.8966f, - 0.7430f, 0.9145f, - 0.8000f, 0.9330f, - 0.8500f, 0.9500f, - 0.9000f, 0.9670f, - 0.9700f, 0.9900f, - 1.00f, 1.00f, - }; - private final float [] jtlogv2_values; - private final static float [] jtlogv3_values_base = new float[] { - 0.0000f, 0.0000f, - 0.0020f, 0.0400f, - 0.0130f, 0.1500f, - 0.0220f, 0.2295f, - 0.0280f, 0.2783f, - 0.0369f, 0.3321f, - 0.0500f, 0.3844f, - 0.0680f, 0.4351f, - 0.0930f, 0.4870f, - 0.1180f, 0.5275f, - 0.1430f, 0.5612f, - 0.1680f, 0.5904f, - 0.1930f, 0.6162f, - 0.2180f, 0.6395f, - 0.2430f, 0.6608f, - 0.2680f, 0.6804f, - 0.2930f, 0.6986f, - 0.3430f, 0.7318f, - 0.3930f, 0.7615f, - 0.4430f, 0.7885f, - 0.4930f, 0.8132f, - 0.5430f, 0.8361f, - 0.5930f, 0.8575f, - 0.6430f, 0.8750f, - 0.6930f, 0.8930f, - 0.740f, 0.908f, - 0.8000f, 0.9230f, - 0.8600f, 0.9380f, - 0.9200f, 0.9535f, - 0.9500f, 0.9600f, - 0.9900f, 0.9700f, - 1.00f, 1.00f, - }; - private final float [] jtlogv3_values; - /*private final static float [] jtlnp1_values_base = new float[] { - 0.0f, 0.0f, 0.01f, 0.06f, 0.02f, 0.1f, 0.03f, 0.13f, 0.1f, 0.27f, 0.73f, 0.9f, 0.79f, 0.93f, - 0.84f, 0.95f, 1.0f, 1.0f - }; - private final float [] jtlnp1_values;*/ - private final static float [] jtlin1_values_base = new float[] { - 0.000f, 0.000f, - 0.010f, 0.070f, - 0.020f, 0.120f, - 0.040f, 0.180f, - 0.080f, 0.260f, - 0.110f, 0.320f, - 0.160f, 0.370f, - 0.210f, 0.420f, - 0.260f, 0.470f, - 0.310f, 0.520f, - 0.360f, 0.570f, - 0.410f, 0.620f, - 0.460f, 0.670f, - 0.510f, 0.720f, - 0.565f, 0.770f, - 0.600f, 0.800f, - 0.660f, 0.840f, - 0.700f, 0.860f, - 0.740f, 0.880f, - 0.780f, 0.900f, - 0.860f, 0.940f, - 0.930f, 0.970f, - 1.000f, 1.000f, + private final static float [] jtlog2_values_base = new float[] { + 0.00f, 0.00f, + 0.01f, 0.09f, + 0.03f, 0.23f, + 0.07f, 0.37f, + 0.12f, 0.48f, + 0.17f, 0.56f, + 0.25f, 0.64f, + 0.32f, 0.70f, + 0.39f, 0.75f, + 0.50f, 0.81f, + 0.59f, 0.85f, + 0.66f, 0.88f, + 0.72f, 0.9f, + 0.78f, 0.92f, + 0.88f, 0.95f, + 0.92f, 0.96f, + 0.99f, 0.98f, + 1.00f, 1.00f }; - private final float [] jtlin1_values; - private final static float [] jtlin2_values_base = new float[] { - 0.000f, 0.000f, - 0.007f, 0.080f, - 0.012f, 0.140f, - 0.040f, 0.260f, - 0.100f, 0.380f, - 0.150f, 0.430f, - 0.200f, 0.480f, - 0.250f, 0.530f, - 0.300f, 0.580f, - 0.350f, 0.630f, - 0.400f, 0.680f, - 0.450f, 0.730f, - 0.490f, 0.770f, - 0.530f, 0.790f, - 0.570f, 0.810f, - 0.610f, 0.830f, - 0.680f, 0.860f, - 0.750f, 0.890f, - 0.800f, 0.910f, - 0.900f, 0.950f, - 0.990f, 0.980f, - 1.000f, 1.000f, - }; - private final float [] jtlin2_values; + private final float [] jtlog2_values; private final ErrorCallback preview_error_cb; private final ErrorCallback camera_error_cb; @@ -1126,35 +1052,20 @@ public class CameraController2 extends CameraController { } } break; + case TONEMAPPROFILE_JTVIDEO: + values = jtvideo_values; + if( MyDebug.LOG ) + Log.d(TAG, "setting JTVideo profile"); + break; case TONEMAPPROFILE_JTLOG: values = jtlog_values; if( MyDebug.LOG ) Log.d(TAG, "setting JTLog profile"); break; - case TONEMAPPROFILE_JTLOGV2: - values = jtlogv2_values; - if( MyDebug.LOG ) - Log.d(TAG, "setting JTLogv2 profile"); - break; - case TONEMAPPROFILE_JTLOGV3: - values = jtlogv3_values; - if( MyDebug.LOG ) - Log.d(TAG, "setting JTLogv3 profile"); - break; - /*case TONEMAPPROFILE_JTLNP1: - values = jtlnp1_values; - if( MyDebug.LOG ) - Log.d(TAG, "setting JTLNP1 profile"); - break;*/ - case TONEMAPPROFILE_JTLIN1: - values = jtlin1_values; - if( MyDebug.LOG ) - Log.d(TAG, "setting JTLin1 profile"); - break; - case TONEMAPPROFILE_JTLIN2: - values = jtlin2_values; + case TONEMAPPROFILE_JTLOG2: + values = jtlog2_values; if( MyDebug.LOG ) - Log.d(TAG, "setting JTLin2 profile"); + Log.d(TAG, "setting JTLog2 profile"); break; } @@ -2111,12 +2022,9 @@ public class CameraController2 extends CameraController { media_action_sound.load(MediaActionSound.SHUTTER_CLICK); // expand tonemap curves + jtvideo_values = enforceMinTonemapCurvePoints(jtvideo_values_base); jtlog_values = enforceMinTonemapCurvePoints(jtlog_values_base); - jtlogv2_values = enforceMinTonemapCurvePoints(jtlogv2_values_base); - jtlogv3_values = enforceMinTonemapCurvePoints(jtlogv3_values_base); - //jtlnp1_values = enforceMinTonemapCurvePoints(jtlnp1_values_base); - jtlin1_values = enforceMinTonemapCurvePoints(jtlin1_values_base); - jtlin2_values = enforceMinTonemapCurvePoints(jtlin2_values_base); + jtlog2_values = enforceMinTonemapCurvePoints(jtlog2_values_base); } @Override @@ -2766,12 +2674,9 @@ public class CameraController2 extends CameraController { // profiles we support camera_features.supports_tonemap_curve = tonemap_max_curve_points >= tonemap_log_max_curve_points_c && + tonemap_max_curve_points >= jtvideo_values.length && tonemap_max_curve_points >= jtlog_values.length && - tonemap_max_curve_points >= jtlogv2_values.length && - tonemap_max_curve_points >= jtlogv3_values.length && - //tonemap_max_curve_points >= jtlnp1_values.length; - tonemap_max_curve_points >= jtlin1_values.length && - tonemap_max_curve_points >= jtlin2_values.length; + tonemap_max_curve_points >= jtlog2_values.length; } else { if( MyDebug.LOG ) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 6957af508..f222edd12 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -555,11 +555,9 @@ @string/preference_video_log_strong @string/preference_video_log_extra_strong @string/preference_video_gamma + @string/preference_video_jtvideo @string/preference_video_jtlog - @string/preference_video_jtlogv2 - @string/preference_video_jtlogv3 - @string/preference_video_jtlin1 - @string/preference_video_jtlin2 + @string/preference_video_jtlog2 off @@ -571,11 +569,9 @@ strong extra_strong gamma + jtvideo jtlog - jtlogv2 - jtlogv3 - jtlin1 - jtlin2 + jtlog2 @string/preference_video_profile_gamma_1.0 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 118fb2a9f..7b0f13efb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -918,12 +918,9 @@ REC709 sRGB Gamma - JTLog - JTLogv2 - JTLogv3 - JTLNP1 - JTLin1 - JTLin2 + JTVideo + JTLog + JTLog2 Video gamma value Gamma value to use for video if video picture profile is set to Gamma\n%s 1.0 -- GitLab From 2f46b35218c9107330546ebb86ecda45d2d4f1c6 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 13:28:18 +0000 Subject: [PATCH 174/243] Update allowed gamma values. --- app/src/main/res/values/arrays.xml | 24 ++++++------------------ app/src/main/res/values/strings.xml | 12 +++--------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index f222edd12..83efcbdff 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -574,40 +574,28 @@ jtlog2 - @string/preference_video_profile_gamma_1.0 - @string/preference_video_profile_gamma_1.5 + @string/preference_video_profile_gamma_1.6 @string/preference_video_profile_gamma_1.8 + @string/preference_video_profile_gamma_1.9 @string/preference_video_profile_gamma_2.0 + @string/preference_video_profile_gamma_2.1 @string/preference_video_profile_gamma_2.2 @string/preference_video_profile_gamma_2.3 @string/preference_video_profile_gamma_2.4 - @string/preference_video_profile_gamma_2.5 @string/preference_video_profile_gamma_2.6 - @string/preference_video_profile_gamma_2.7 @string/preference_video_profile_gamma_2.8 - @string/preference_video_profile_gamma_2.9 - @string/preference_video_profile_gamma_3.0 - @string/preference_video_profile_gamma_3.1 - @string/preference_video_profile_gamma_3.2 - @string/preference_video_profile_gamma_4.0 - 1.0 - 1.5 + 1.6 1.8 + 1.9 2.0 + 2.1 2.2 2.3 2.4 - 2.5 2.6 - 2.7 2.8 - 2.9 - 3.0 - 3.1 - 3.2 - 4.0 @string/preference_record_audio_src_camcorder diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7b0f13efb..e08a317b7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -923,22 +923,16 @@ JTLog2 Video gamma value Gamma value to use for video if video picture profile is set to Gamma\n%s - 1.0 - 1.5 + 1.6 1.8 + 1.9 2.0 + 2.1 2.2 2.3 2.4 - 2.5 2.6 - 2.7 2.8 - 2.9 - 3.0 - 3.1 - 3.2 - 4.0 Off Only dim on-screen virtual navigation buttons -- GitLab From 66ef8d0b076e1f251ce2155af4d3648d9972a2fd Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 14:01:07 +0000 Subject: [PATCH 175/243] New testIconsAgainstCameras. --- .../opencamera/test/MainActivityTest.java | 47 +++++++++++++++++++ .../opencamera/test/MainTests.java | 1 + 2 files changed, 48 insertions(+) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index a180e074e..f99a9303d 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -3185,6 +3185,53 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Sun, 1 Mar 2020 15:58:03 +0000 Subject: [PATCH 176/243] Add logging. --- .../cameracontroller/CameraController2.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 4c1094158..930edfad4 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -5002,7 +5002,7 @@ public class CameraController2 extends CameraController { if( texture != null ) { // need to set the texture size if( MyDebug.LOG ) - Log.d(TAG, "set size of preview texture"); + Log.d(TAG, "set size of preview texture: " + preview_width + " x " + preview_height); if( preview_width == 0 || preview_height == 0 ) { if( MyDebug.LOG ) Log.e(TAG, "application needs to call setPreviewSize()"); @@ -5032,7 +5032,7 @@ public class CameraController2 extends CameraController { /*if( MyDebug.LOG ) Log.d(TAG, "preview size: " + previewImageReader.getWidth() + " x " + previewImageReader.getHeight());*/ if( MyDebug.LOG ) - Log.d(TAG, "preview size: " + this.preview_width + " x " + this.preview_height); + Log.d(TAG, "set preview size: " + this.preview_width + " x " + this.preview_height); synchronized( background_camera_lock ) { if( video_recorder != null ) @@ -5064,9 +5064,16 @@ public class CameraController2 extends CameraController { synchronized( background_camera_lock ) { captureSession = session; Surface surface = getPreviewSurface(); + if( MyDebug.LOG ) { + Log.d(TAG, "add surface to previewBuilder: " + surface); + } previewBuilder.addTarget(surface); - if( video_recorder != null ) + if( video_recorder != null ) { + if( MyDebug.LOG ) { + Log.d(TAG, "add video recorder surface to previewBuilder: " + video_recorder_surface); + } previewBuilder.addTarget(video_recorder_surface); + } try { setRepeatingRequest(); } -- GitLab From 97ca45d8c3f4d60dacccc7d91aa27c7e25660322 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 15:59:35 +0000 Subject: [PATCH 177/243] Future proofing check on want_video_high_speed. --- .../opencamera/cameracontroller/CameraController2.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 930edfad4..2c52559e3 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -5152,6 +5152,11 @@ public class CameraController2 extends CameraController { } // n.b., raw not supported for photo snapshots while video recording } + else if( want_video_high_speed ) { + // future proofing - at the time of writing want_video_high_speed is only set when recording video, + // but if ever this is changed, can only support the preview_surface as a target + surfaces = Collections.singletonList(preview_surface); + } else if( imageReaderRaw != null ) { surfaces = Arrays.asList(preview_surface, imageReader.getSurface(), imageReaderRaw.getSurface()); } -- GitLab From 66d55fb0918e5c1005007bac22eec434e1e42376 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 16:01:19 +0000 Subject: [PATCH 178/243] Reword comment. --- .../java/net/sourceforge/opencamera/preview/Preview.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index a85766552..c7a2552d0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -1796,9 +1796,9 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu camera_controller.setTonemapProfile(tonemap_profile, video_log_profile_strength, video_gamma); } - // in theory it shouldn't matter if we call setVideoHighSpeed(true) if is_video==false, as it should only have an effect - // in video mode; but don't set high speed mode in photo mode just to be safe - // Setup for high speed - must be done after setupCameraParameters() and switching to video mode, but before setPreviewSize() and startCameraPreview() + // Setup for high speed - must be done after setupCameraParameters() and switching to video mode, but before setPreviewSize() and startCameraPreview(). + // In theory it shouldn't matter if we call setVideoHighSpeed(true) if is_video==false, as it should only have an effect + // when recording video; but don't set high speed mode in photo mode just to be safe. camera_controller.setVideoHighSpeed(is_video && video_high_speed); if( do_startup_focus && using_android_l && camera_controller.supportsAutoFocus() ) { -- GitLab From 6005ce0207c3fd20e6caf67e992fa83cf059f1be Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 16:01:33 +0000 Subject: [PATCH 179/243] Add documentation for setVideoHighSpeed(). --- .../opencamera/cameracontroller/CameraController.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java index 8fe86d9fb..9114e0180 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController.java @@ -424,6 +424,10 @@ public abstract class CameraController { * caught by the callera). */ public abstract void setRaw(boolean want_raw, int max_raw_images); + + /** Request a capture session compatible with high speed frame rates. + * This should be called only when the preview is paused or not yet started. + */ public abstract void setVideoHighSpeed(boolean setVideoHighSpeed); /** * setUseCamera2FakeFlash() should be called after creating the CameraController, and before calling getCameraFeatures() or -- GitLab From 0f33f9a8f5800c0b275e63ab317c18398b1ad768 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 17:24:02 +0000 Subject: [PATCH 180/243] Add logging. --- .../opencamera/cameracontroller/CameraController2.java | 6 ++++-- .../java/net/sourceforge/opencamera/preview/Preview.java | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index 2c52559e3..74f0a7f71 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -4866,8 +4866,10 @@ public class CameraController2 extends CameraController { @Override public void setPreviewTexture(TextureView texture) { - if( MyDebug.LOG ) - Log.d(TAG, "setPreviewTexture"); + if( MyDebug.LOG ) { + Log.d(TAG, "setPreviewTexture: " + texture); + Log.d(TAG, "surface: " + texture.getSurfaceTexture()); + } if( this.texture != null ) { if( MyDebug.LOG ) Log.d(TAG, "preview texture already set"); diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index c7a2552d0..db5cfb330 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -853,8 +853,10 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu @Override public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int width, int height) { - if( MyDebug.LOG ) + if( MyDebug.LOG ) { Log.d(TAG, "onSurfaceTextureSizeChanged " + width + ", " + height); + //Log.d(TAG, "surface texture is now: " + ((TextureView)cameraSurface).getSurfaceTexture()); + } this.set_textureview_size = true; this.textureview_w = width; this.textureview_h = height; -- GitLab From 5e222561093dfee23b641aaa508310e9f93b339d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 1 Mar 2020 22:40:50 +0000 Subject: [PATCH 181/243] Update log profile histogram checks due to recent changes to log video profiles. --- .../opencamera/test/MainActivityTest.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index f99a9303d..3e2887dda 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -15802,7 +15802,8 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Sun, 1 Mar 2020 22:48:20 +0000 Subject: [PATCH 182/243] Fixes due to testing test_n_videos_scanned (for testTakeVideoSnapshot etc). --- .../opencamera/test/MainActivityTest.java | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 3e2887dda..038e15fc7 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -4842,7 +4842,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= Build.VERSION_CODES.O ) { assertTrue( n_new_files >= 2 ); @@ -6774,7 +6773,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Sun, 1 Mar 2020 22:50:29 +0000 Subject: [PATCH 183/243] Preview texture buffer size (for Camera2 API) could be set incorrectly after changing aspect ratios. --- _docs/history.html | 2 ++ .../opencamera/test/MainActivityTest.java | 18 +++++++++++++ .../cameracontroller/CameraController.java | 8 ++++++ .../cameracontroller/CameraController2.java | 27 ++++++++++++++----- .../opencamera/preview/Preview.java | 23 +++++++++++++++- 5 files changed, 71 insertions(+), 7 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index ae920457d..b426428b8 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -74,6 +74,8 @@ FIXED Option on-screen icons (such as flash, RAW) weren't updating correctly i camera that didn't support that feature. FIXED Don't show on-screen flash icon in video mode (since this icon doesn't show torch, and flash auto/on not supported in video mode). +FIXED Preview texture buffer size (for Camera2 API) could be set incorrectly after changing aspect + ratios. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 038e15fc7..a84a261a2 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -5828,6 +5828,10 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2= Build.VERSION_CODES.M ) { + //if( want_video_high_speed && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) { camera.createConstrainedHighSpeedCaptureSession(surfaces, myStateCallback, handler); diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index db5cfb330..4c1229a76 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -852,11 +852,32 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu } @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int width, int height) { + public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { if( MyDebug.LOG ) { Log.d(TAG, "onSurfaceTextureSizeChanged " + width + ", " + height); //Log.d(TAG, "surface texture is now: " + ((TextureView)cameraSurface).getSurfaceTexture()); } + + if( camera_controller != null ) { + camera_controller.test_texture_view_buffer_w = width; + camera_controller.test_texture_view_buffer_h = height; + + if( set_preview_size && (width != preview_w || height != preview_h) ) { + if( MyDebug.LOG ) + Log.d(TAG, "updatePreviewTexture"); + // Needed to fix problem if Open Camera is already running, and the aspect ratio changes (e.g., + // change of resolution, or switching between photo and video mode). When starting up in a "default", + // aspect ratio, the camera is opened via onSurfaceTextureAvailable(), and although we then call setAspectRatio(), + // there are no calls to onSurfaceTextureSizeChanged(). But when already running, or if + // an aspect ratio change for the view is required, changing the aspect ratio causes a call to + // onSurfaceTextureSizeChanged(), which results in the texture view's surface texture's buffer size being reset! + // (This can be seen in the source code of TextureView: onSizeChanged() calls setDefaultBufferSize() before + // calling onSurfaceTextureSizeChanged()!) So we need to call setDefaultBufferSize() again to reset + // to the desired preview buffer size that we already chose! + camera_controller.updatePreviewTexture(); + } + } + this.set_textureview_size = true; this.textureview_w = width; this.textureview_h = height; -- GitLab From 1c868f1aca175ccaa1497d397bb4eaea8f45ec2e Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Mar 2020 21:03:39 +0000 Subject: [PATCH 184/243] Update comments. --- .../java/net/sourceforge/opencamera/LocationSupplier.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java b/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java index 6aa5ff3e5..f398984d9 100644 --- a/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java +++ b/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java @@ -31,7 +31,7 @@ public class LocationSupplier { /** If adding extra calls to this, consider whether explicit user permission is required, and whether * privacy policy needs updating. - * Returns null if location not available. + * @return Returns null if location not available. */ public Location getLocation() { if( locationListeners == null ) @@ -102,7 +102,7 @@ public class LocationSupplier { } /* Best to only call this from MainActivity.initLocation(). - * Returns false if location permission not available for either coarse or fine. + * @return Returns false if location permission not available for either coarse or fine. */ boolean setupLocationListener() { if( MyDebug.LOG ) -- GitLab From da48ae9df62a58ba299bfb896e54ede07a280cbc Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 8 Mar 2020 21:18:10 +0000 Subject: [PATCH 185/243] More repeat mode options (100x, 200x, 500x); also update all translations for repeat mode options. --- _docs/history.html | 1 + app/src/main/res/values-az/strings.xml | 7 +++++++ app/src/main/res/values-be/strings.xml | 7 +++++++ app/src/main/res/values-cs/strings.xml | 7 +++++++ app/src/main/res/values-de/strings.xml | 7 +++++++ app/src/main/res/values-es/strings.xml | 7 +++++++ app/src/main/res/values-fr/strings.xml | 7 +++++++ app/src/main/res/values-hu/strings.xml | 7 +++++++ app/src/main/res/values-it/strings.xml | 7 +++++++ app/src/main/res/values-ja/strings.xml | 7 +++++++ app/src/main/res/values-ko/strings.xml | 7 +++++++ app/src/main/res/values-nb/strings.xml | 7 +++++++ app/src/main/res/values-pl/strings.xml | 7 +++++++ app/src/main/res/values-pt-rBR/strings.xml | 7 +++++++ app/src/main/res/values-pt-rPT/strings.xml | 7 +++++++ app/src/main/res/values-ru/strings.xml | 3 +++ app/src/main/res/values-sl/strings.xml | 7 +++++++ app/src/main/res/values-tr/strings.xml | 7 +++++++ app/src/main/res/values-uk/strings.xml | 7 +++++++ app/src/main/res/values-vi/strings.xml | 3 +++ app/src/main/res/values-zh-rCN/strings.xml | 7 +++++++ app/src/main/res/values-zh-rTW/strings.xml | 7 +++++++ app/src/main/res/values/arrays.xml | 6 ++++++ app/src/main/res/values/strings.xml | 3 +++ 24 files changed, 149 insertions(+) diff --git a/_docs/history.html b/_docs/history.html index b426428b8..8d1452605 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -116,6 +116,7 @@ UPDATED Improved look of on-screen text for manual/exposure sliders. UPDATED Exposure icon now highlights red when exposure UI is open. UPDATED Exposure UI now auto-opens when switching to manual white balance (as exposure UI contains the manual white balance temperature seekbar). +UPDATED More repeat mode options (100x, 200x, 500x). Version 1.47.3 (2019/10/20) diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index a11cb6b33..c7b24b3d3 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -276,6 +276,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Sonsuz Fasiləsiz diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 52f46cd45..e87f2fb1c 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -319,6 +319,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Не абмежавана Без затрымкі diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 416442c93..ac41da77b 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -323,6 +323,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Nekonečno Bez prodlení diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index eefe64dd8..30aa2d265 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -601,6 +601,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Unbegrenzt Keine Verzögerung diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index cae3bb329..ba7138659 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -538,6 +538,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Ilimitado Sin retardo diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f36abbc05..ee8fbedbb 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -386,6 +386,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Illimité Pas de délai diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 2d2132236..856366be0 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -444,6 +444,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Korlátlan Nincs késleltetés diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 786218c0f..29266d47a 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -472,6 +472,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Illimitato Nessun intervallo diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 39eb06eb1..5128ed670 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -318,6 +318,13 @@ 4倍 5倍 10倍 + 20倍 + 30倍 + 40倍 + 50倍 + 100倍 + 200倍 + 500倍 無制限 なし diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index bb5175534..d28009eae 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -288,6 +288,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x 무제한 지연 없음 diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 12d457e70..27e8c324b 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -494,6 +494,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Ubegrenset Ingen forsinkelse diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 3c8e49455..43f872c58 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -420,6 +420,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Bez limitu Bez opóźnienia diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6cd1b9fa1..96073784a 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -288,6 +288,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Ilimitado Nenhum diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index c3e7c95b5..62a373729 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -360,6 +360,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Ilimitado Sem atraso diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 997ce851e..829c3eb9e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -647,6 +647,9 @@ 30x 40x 50x + 100x + 200x + 500x Навсегда Без задержки diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index b8dc63b7f..4d6e02740 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -499,6 +499,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Neomejeno Brez zakasnitve diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 2d4d53076..e0ebf3e33 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -322,6 +322,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Sınırsız Gecikmesiz diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 2f31cfed2..fa975ed3b 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -445,6 +445,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x Постійно Без затримки diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 38ee7f951..eafa34563 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -645,6 +645,9 @@ 30x 40x 50x + 100x + 200x + 500x Không giới hạn Không diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 523966784..c641006b8 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -554,6 +554,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x 无限 无延迟 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 7800204e6..dbc24f984 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -315,6 +315,13 @@ 4x 5x 10x + 20x + 30x + 40x + 50x + 100x + 200x + 500x 無限 無延遲 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 83efcbdff..734146c27 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -713,6 +713,9 @@ @string/preference_burst_mode_30x @string/preference_burst_mode_40x @string/preference_burst_mode_50x + @string/preference_burst_mode_100x + @string/preference_burst_mode_200x + @string/preference_burst_mode_500x @string/preference_burst_mode_unlimited @@ -726,6 +729,9 @@ 30 40 50 + 100 + 200 + 500 unlimited diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e08a317b7..437bbf91d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -648,6 +648,9 @@ 30x 40x 50x + 100x + 200x + 500x Unlimited No delay -- GitLab From b188d2742f8c3b3b9737f3655c09af75640f08c9 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 13 Mar 2020 23:20:09 +0000 Subject: [PATCH 186/243] Don't listen for location when camera in background; use cached location; new testLocationSettings(). --- _docs/help.html | 4 +- .../opencamera/test/MainActivityTest.java | 100 ++++++++++++++++++ .../opencamera/test/MainTests.java | 1 + .../opencamera/LocationSupplier.java | 57 +++++++++- .../sourceforge/opencamera/MainActivity.java | 28 ++++- .../opencamera/MyApplicationInterface.java | 8 ++ .../opencamera/ui/DrawPreview.java | 10 +- 7 files changed, 197 insertions(+), 11 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 7fe58a6f9..575c3750b 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -287,8 +287,8 @@ of the camera. If "Store location data" is enabled (off by default), then a smal Location/GPS icon will appear at the top left when the location is available (you can still take photos when the GPS icon doesn't show, it's just that location data won't be stored in the photo). A dot shows to the top-right of the GPS icon to -indicate the accuracy (green for accurate, yellow for less accurate). If the location isn't available, -a dash will be shown through the gps icon.

    +indicate the accuracy (green for accurate, yellow for less accurate, grey if waiting for location but using a recently +cached location). If the location isn't available, a dash will be shown through the gps icon.

    Auto-level feature

    diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index a84a261a2..7f36645b3 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import net.sourceforge.opencamera.LocationSupplier; import net.sourceforge.opencamera.MyPreferenceFragment; import net.sourceforge.opencamera.PanoramaProcessorException; import net.sourceforge.opencamera.cameracontroller.CameraController2; @@ -229,6 +230,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 20000 ) { + // need to allow long time for testing devices without mobile network; will likely fail altogether if don't even have wifi + fail(); + } + } + Log.d(TAG, "have received location"); + this.getInstrumentation().waitForIdleSync(); + assertNotNull(mActivity.getLocationSupplier().getLocation()); + // check wasn't cached + LocationSupplier.LocationInfo locationInfo = new LocationSupplier.LocationInfo(); + mActivity.getLocationSupplier().getLocation(locationInfo); + assertFalse(locationInfo.LocationWasCached()); + + // now go to settings + assertFalse(mActivity.isCameraInBackground()); + View settingsButton = mActivity.findViewById(net.sourceforge.opencamera.R.id.settings); + Log.d(TAG, "about to click settings"); + clickView(settingsButton); + Log.d(TAG, "done clicking settings"); + this.getInstrumentation().waitForIdleSync(); + Log.d(TAG, "after idle sync"); + assertTrue(mActivity.isCameraInBackground()); + + // now check we're not listening for location + start_t = System.currentTimeMillis(); + int count = 0; + while( System.currentTimeMillis() - start_t <= 15000 ) { + assertFalse(mActivity.getLocationSupplier().hasLocationListeners()); + assertFalse(mActivity.getLocationSupplier().testHasReceivedLocation()); + assertNull(mActivity.getLocationSupplier().getLocation()); + Thread.sleep(10); + if( count++ == 5 ) { + pauseAndResume(); // check we still don't listen for location after pause and resume + } + } + + // now go back + assertTrue(mActivity.isCameraInBackground()); + Log.d(TAG, "go back"); + mActivity.runOnUiThread(new Runnable() { + public void run() { + mActivity.onBackPressed(); + } + }); + this.getInstrumentation().waitForIdleSync(); + Log.d(TAG, "after idle sync"); + assertFalse(mActivity.isCameraInBackground()); + + // check we start listening again + // first should have a cached location + assertTrue(mActivity.getLocationSupplier().hasLocationListeners()); + assertFalse(mActivity.getLocationSupplier().testHasReceivedLocation()); + assertNotNull(mActivity.getLocationSupplier().getLocation()); + locationInfo = new LocationSupplier.LocationInfo(); + mActivity.getLocationSupplier().getLocation(locationInfo); + assertTrue(locationInfo.LocationWasCached()); + + // check we get a non-cached location + while( !mActivity.getLocationSupplier().testHasReceivedLocation() ) { + this.getInstrumentation().waitForIdleSync(); + if( System.currentTimeMillis() - start_t > 20000 ) { + // need to allow long time for testing devices without mobile network; will likely fail altogether if don't even have wifi + fail(); + } + } + Log.d(TAG, "have received location"); + this.getInstrumentation().waitForIdleSync(); + assertNotNull(mActivity.getLocationSupplier().getLocation()); + // check wasn't cached + locationInfo = new LocationSupplier.LocationInfo(); + mActivity.getLocationSupplier().getLocation(locationInfo); + assertFalse(locationInfo.LocationWasCached()); + } + private void subTestPhotoStamp() throws IOException { { assertFalse(mActivity.getApplicationInterface().getDrawPreview().getStoredHasStampPref()); diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java index b093ae42e..863a0915d 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainTests.java @@ -14,6 +14,7 @@ public class MainTests { TestSuite suite = new TestSuite(MainTests.class.getName()); // put these tests first as they require various permissions be allowed, that can only be set by user action suite.addTest(TestSuite.createTest(MainActivityTest.class, "testSwitchVideo")); + suite.addTest(TestSuite.createTest(MainActivityTest.class, "testLocationSettings")); // other tests: suite.addTest(TestSuite.createTest(MainActivityTest.class, "testPause")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testImmediatelyQuit")); diff --git a/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java b/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java index f398984d9..5f4fe3ccc 100644 --- a/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java +++ b/app/src/main/java/net/sourceforge/opencamera/LocationSupplier.java @@ -24,18 +24,61 @@ public class LocationSupplier { private MyLocationListener [] locationListeners; private volatile boolean test_force_no_location; // if true, always return null location; must be volatile for test project setting the state + private Location cached_location; + private long cached_location_ms; + LocationSupplier(Context context) { this.context = context; locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); } + private Location getCachedLocation() { + if( cached_location != null ) { + long time_ms = System.currentTimeMillis(); + if( time_ms <= cached_location_ms + 20000 ) { + return cached_location; + } + else { + cached_location = null; + } + } + return null; + } + + private void cacheLocation() { + if( MyDebug.LOG ) + Log.d(TAG, "cacheLocation"); + cached_location = new Location(getLocation()); + cached_location_ms = System.currentTimeMillis(); + } + + public static class LocationInfo { + private boolean location_was_cached; + + public boolean LocationWasCached() { + return location_was_cached; + } + } + + public Location getLocation() { + return getLocation(null); + } + /** If adding extra calls to this, consider whether explicit user permission is required, and whether * privacy policy needs updating. + * @param locationInfo Optional class to return additional information about the location. * @return Returns null if location not available. */ - public Location getLocation() { - if( locationListeners == null ) + public Location getLocation(LocationInfo locationInfo) { + if( locationInfo != null ) + locationInfo.location_was_cached = false; // init + + if( locationListeners == null ) { + // if we have disabled location listening, then don't return a cached location anyway - + // in theory, callers should have already checked for user permission/setting before calling + // getLocation(), but just in case we didn't, don't want to return a cached location return null; + } if( test_force_no_location ) return null; // location listeners should be stored in order best to worst @@ -44,10 +87,13 @@ public class LocationSupplier { if( location != null ) return location; } - return null; + Location location = getCachedLocation(); + if( location != null && locationInfo != null ) + locationInfo.location_was_cached = true; + return location; } - private static class MyLocationListener implements LocationListener { + private class MyLocationListener implements LocationListener { private Location location; volatile boolean test_has_received_location; // must be volatile for test project reading the state @@ -67,6 +113,7 @@ public class LocationSupplier { Log.d(TAG, "lat " + location.getLatitude() + " long " + location.getLongitude() + " accuracy " + location.getAccuracy()); } this.location = location; + cacheLocation(); } } @@ -83,6 +130,7 @@ public class LocationSupplier { } this.location = null; this.test_has_received_location = false; + cached_location = null; break; } default: @@ -98,6 +146,7 @@ public class LocationSupplier { Log.d(TAG, "onProviderDisabled"); this.location = null; this.test_has_received_location = false; + cached_location = null; } } diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index a795d1f31..52d74f91d 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -1203,7 +1203,7 @@ public class MainActivity extends Activity { debug_time = System.currentTimeMillis(); } super.onResume(); - this.app_is_paused = false; + this.app_is_paused = false; // must be set before initLocation() at least cancelImageSavingNotification(); @@ -2441,7 +2441,13 @@ public class MainActivity extends Activity { } speechControl.initSpeechRecognizer(); // in case we've enabled or disabled speech recognizer - initLocation(); // in case we've enabled or disabled GPS + + // we no longer call initLocation() here (for having enabled or disabled geotagging), as that's + // done in setWindowFlagsForCamera() - important not to call it here as well, otherwise if + // permission wasn't granted, we'll ask for permission twice in a row (on Android 9 or earlier + // at least) + //initLocation(); // in case we've enabled or disabled GPS + initGyroSensors(); // in case we've entered or left panorama if( MyDebug.LOG ) { Log.d(TAG, "updateForSettings: time after init speech and location: " + (System.currentTimeMillis() - debug_time)); @@ -2821,6 +2827,14 @@ public class MainActivity extends Activity { camera_in_background = false; magneticSensor.clearDialog(); // if the magnetic accuracy was opened, it must have been closed now + if( !app_is_paused ) { + // Needs to be called after camera_in_background is set to false. + // Note that the app_is_paused guard is in some sense unnecessary, as initLocation tests for that too, + // but useful for error tracking - ideally we want to make sure that initLocation is never called when + // app is paused. It can happen here because setWindowFlagsForCamera() is called from + // onCreate() + initLocation(); + } } private void setWindowFlagsForSettings() { @@ -2861,6 +2875,9 @@ public class MainActivity extends Activity { setImmersiveMode(false); camera_in_background = true; + + // we disable location listening when showing settings or a dialog etc - saves battery life, also better for privacy + applicationInterface.getLocationSupplier().freeLocationListeners(); } private void showWhenLocked(boolean show) { @@ -4878,13 +4895,18 @@ public class MainActivity extends Activity { } } - void initLocation() { + public void initLocation() { if( MyDebug.LOG ) Log.d(TAG, "initLocation"); if( app_is_paused ) { Log.e(TAG, "initLocation: app is paused!"); // we shouldn't need this (as we only call initLocation() when active), but just in case we end up here after onPause... } + else if( camera_in_background ) { + if( MyDebug.LOG ) + Log.d(TAG, "initLocation: camera in background!"); + // we will end up here if app is pause/resumed when camera in background (settings, dialog, etc) + } else if( !applicationInterface.getLocationSupplier().setupLocationListener() ) { if( MyDebug.LOG ) Log.d(TAG, "location permission not available, so request permission"); diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 63b200781..3ac3dd834 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -261,6 +261,14 @@ public class MyApplicationInterface extends BasicApplicationInterface { return locationSupplier.getLocation(); } + /** If adding extra calls to this, consider whether explicit user permission is required, and whether + * privacy policy needs updating. + * Returns null if location not available. + */ + public Location getLocation(LocationSupplier.LocationInfo locationInfo) { + return locationSupplier.getLocation(locationInfo); + } + @Override public int createOutputVideoMethod() { String action = main_activity.getIntent().getAction(); diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 741bd69d8..61e945801 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Locale; import net.sourceforge.opencamera.GyroSensor; +import net.sourceforge.opencamera.LocationSupplier; import net.sourceforge.opencamera.MainActivity; import net.sourceforge.opencamera.MyApplicationInterface; import net.sourceforge.opencamera.MyDebug; @@ -38,6 +39,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; +import android.location.Location; import android.media.ExifInterface; import android.net.Uri; import android.os.BatteryManager; @@ -112,6 +114,7 @@ public class DrawPreview { private final DateFormat dateFormatTimeInstance = DateFormat.getTimeInstance(); private final String ybounds_text; private final int [] temp_histogram_channel = new int[256]; + private final LocationSupplier.LocationInfo locationInfo = new LocationSupplier.LocationInfo(); //private final DecimalFormat decimal_format_1dp_force0 = new DecimalFormat("0.0"); // cached Rects for drawTextWithBackground() calls private Rect text_bounds_time; @@ -1292,12 +1295,15 @@ public class DrawPreview { canvas.drawRect(icon_dest, p); p.setAlpha(255); - if( applicationInterface.getLocation() != null ) { + Location location = applicationInterface.getLocation(locationInfo); + if( location != null ) { canvas.drawBitmap(location_bitmap, null, icon_dest, p); int location_radius = icon_size / 10; int indicator_x = location_x2 + icon_size - (int)(location_radius*1.5); int indicator_y = location_y + (int)(location_radius*1.5); - p.setColor(applicationInterface.getLocation().getAccuracy() < 25.01f ? Color.rgb(37, 155, 36) : Color.rgb(255, 235, 59)); // Green 500 or Yellow 500 + p.setColor(locationInfo.LocationWasCached() ? Color.rgb(127, 127, 127) : + location.getAccuracy() < 25.01f ? Color.rgb(37, 155, 36) : + Color.rgb(255, 235, 59)); // Green 500 or Yellow 500 canvas.drawCircle(indicator_x, indicator_y, location_radius, p); } else { -- GitLab From 05b47fc39c9ed977b26a5fc063e10e55989f8622 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 14 Mar 2020 16:14:15 +0000 Subject: [PATCH 187/243] Update documentation for new custom video profiles. --- _docs/credits.html | 2 +- _docs/help.html | 14 +++++++++----- _docs/history.html | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index 2e77cd00a..0db14b468 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -51,7 +51,7 @@
    • App icon by Adam Lapinski.
    • Improvements/help for video frame rates (including high speed) by George Joseph.
    • -
    • Support for the video picture profiles implementation and custom Log profile JTLog design by JT Haapala.
    • +
    • Support for the video picture profiles implementation and custom Log profiles JTVideo, JTLog and JTLog2 design by JT Haapala.
    • Smart Housing Bluetooth LE support by Edouard Lafargue
    • Improved selfie stick button support by Lau Keat Hwa.
    • Option for filenames to be based on UTC (Zulu) time by David Pletcher ( lpm_sourceforge AT cathedralcanyon DOT net , https://www.cathedralcanyon.net ).
    • diff --git a/_docs/help.html b/_docs/help.html index 575c3750b..afedafef4 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -964,11 +964,15 @@ not work properly on all devices! Also note:

      • If using 3GPP, then restarting video when hitting maximum filesize will not be seamless (even on Android 8).
      -

      Video flat (log) profile - Enables a "flat" or "log" color profile for recording video. Only available if Camera2 - API is used. This is intended to create videos for further editing in post production. Note that it may be necessary to - increase the video bitrate when shooting with a log profile. This feature is currently experimental, - please test if it fits your need before shooting your masterpiece! -

      +

      Video picture profiles - Enables different color profiles for recording video. Only available if Camera2 + API is used, and only supported on some devices. Additional notes:

        +
      • The various "log" profiles enable a "flat" color profile, and are intended to create videos + for further editing in post production.
      • +
      • Note that it may be necessary to increase the video bitrate when shooting with a "log" profile + or with high custom gamma.
      • +
      • When "Gamma" is selected, you can specify the gamma value used with the next option "Video gamma value".
      • +
      • This feature is somewhat experimental, please test if it fits your need before shooting your masterpiece!
      • +

      Max duration of video - This option can be used to set a maximum duration of the video. If set, video recording will stop after the specified time (unless already stopped earlier).

      diff --git a/_docs/history.html b/_docs/history.html index 8d1452605..be1744238 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -87,6 +87,7 @@ ADDED Aperture control, for devices that support this. (Camera2 API only.) ADDED Flash on and torch now supported for manual ISO/exposure. ADDED Option to specify REC709 or sRGB profile for video recording. ADDED New custom gamma profile option for video recording. +ADDED New video profiles JJTVideo, JTLog and JTLog2 (thanks to JT Haapala). ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. ADDED Options to control zebra stripe colours. -- GitLab From cc921927a98d7b8c01dc2552e230d86e91c2f1ab Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 14 Mar 2020 16:14:28 +0000 Subject: [PATCH 188/243] Update licences. --- _docs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/index.html b/_docs/index.html index 9c95b0850..6f5829bd1 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -255,7 +255,7 @@ Also see "Can I use the Open Camera source code in my app?" under the Modified versions of some of these icons are also used on this website. -
      Open Camera's app icon/logo also makes use of ic_photo_camera_white_48dp by Google (also Apache license version 2.0). +
      Open Camera's app icon/logo also makes use of ic_photo_camera by Google (also Apache license version 2.0).

    Note that old versions of Open Camera also used the following:

    -- GitLab From cdb674b8281879ed5d2ec47caf72d8fafae0769d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 14 Mar 2020 16:14:45 +0000 Subject: [PATCH 189/243] Reword. --- _docs/privacy_oc.html | 2 +- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/privacy_oc.html b/_docs/privacy_oc.html index 975846988..6e3e26a1d 100644 --- a/_docs/privacy_oc.html +++ b/_docs/privacy_oc.html @@ -55,7 +55,7 @@ of taking photos and recording videos, to fulfil its purpose as a camera. Microphone permission is also used for the optional "Audio control" options.

    Open Camera requires permission to "access photos, media and files on your devices", as this permission is required for Android to -save resultant photos and videos to your device.

    +save resultant files such as photos and videos to your device.

    Location permission is required for geotagging options (for photos and videos, including stamp and subtitles options). Geotagging is disabled by default, but if enabled, your location is encoded into saved image and video files. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 437bbf91d..6d3345fe7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -982,7 +982,7 @@ Open Camera accesses camera sensor and microphone data to fulfil its purpose as a camera. Microphone is also used for the optional \"Audio control\". - \nAccess to files is needed to save resultant photos and videos to your device. + \nAccess to files is needed to save resultant files such as photos and videos to your device. \nLocation permission is required for the optional geotagging/stamp/subtitles and Bluetooth features. \nSince Open Camera also uses operating system APIs, you should review relevant privacy policies such as for your device, manufacturer, operating system and/or Google accounts. For example: -- GitLab From 9a9e44e75c9606da4007f18fa89f5f0e0a91048d Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 14 Mar 2020 16:15:07 +0000 Subject: [PATCH 190/243] New tests testVideoJTLogProfile, testVideoGammaProfile. --- .../opencamera/test/MainActivityTest.java | 47 +++++++++++++++++++ .../opencamera/test/VideoTests.java | 2 + 2 files changed, 49 insertions(+) diff --git a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java index 7f36645b3..32313e771 100644 --- a/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +++ b/app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java @@ -7430,6 +7430,53 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2 Date: Sat, 14 Mar 2020 19:50:43 +0000 Subject: [PATCH 191/243] Reword. --- _docs/privacy_oc.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/privacy_oc.html b/_docs/privacy_oc.html index 6e3e26a1d..b6143c7b6 100644 --- a/_docs/privacy_oc.html +++ b/_docs/privacy_oc.html @@ -80,7 +80,7 @@ save resultant files such as photos and videos to your device.

    -

    Although Open Camera is ad-free, this website has ads via Google Adsense: Third party vendors, including Google, use cookies to +

    Although Open Camera is ad-free, the Open Camera website has ads via Google Adsense: Third party vendors, including Google, use cookies to serve ads based on a user's previous visits to this website or other websites. Google's use of advertising cookies enables it and its partners to serve ads based on people's visit to this sites and/or other sites on the Internet. You may opt out of personalised advertising by visiting Google's Ads Settings. Alternatively, you can @@ -89,7 +89,7 @@ opt out of some third-party vendors' uses of cookies for personalised advertisin

    Update: I have instructed Google to not display personalised ads to users in the EEA.

    -

    This website also uses Google Analytics which uses cookies, please see their +

    The Open Camera website also uses Google Analytics which uses cookies, please see their Privacy Policy for more details.

    Also see "How Google uses information from sites or apps -- GitLab From 66f7168004cec67454a33bbc5dd2b7722c3bce46 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 15 Mar 2020 20:47:54 +0000 Subject: [PATCH 192/243] Update on-screen time format more when changing device settings; also fix text_bounds_time for 12 hour format. --- _docs/history.html | 1 + .../sourceforge/opencamera/ui/DrawPreview.java | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index be1744238..088b9dce3 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -76,6 +76,7 @@ FIXED Don't show on-screen flash icon in video mode (since this icon doesn't s auto/on not supported in video mode). FIXED Preview texture buffer size (for Camera2 API) could be set incorrectly after changing aspect ratios. +FIXED Update on-screen time format more when changing device settings. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 61e945801..6e902c472 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -7,6 +7,7 @@ import java.text.DateFormat; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Date; import java.util.List; import java.util.Locale; @@ -111,7 +112,7 @@ public class DrawPreview { private final float scale; private final float stroke_width; // stroke_width used for various UI elements private Calendar calendar; - private final DateFormat dateFormatTimeInstance = DateFormat.getTimeInstance(); + private DateFormat dateFormatTimeInstance; private final String ybounds_text; private final int [] temp_histogram_channel = new int[256]; private final LocationSupplier.LocationInfo locationInfo = new LocationSupplier.LocationInfo(); @@ -519,7 +520,14 @@ public class DrawPreview { Log.d(TAG, "photoMode: " + photoMode); show_time_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowTimePreferenceKey, true); + // reset in case user changes the preference: + dateFormatTimeInstance = DateFormat.getTimeInstance(); + current_time_string = null; + last_current_time_time = 0; + text_bounds_time = null; + show_camera_id_pref = main_activity.isMultiCam() && sharedPreferences.getBoolean(PreferenceKeys.ShowCameraIDPreferenceKey, true); + //show_camera_id_pref = true; // test show_free_memory_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowFreeMemoryPreferenceKey, true); show_iso_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowISOPreferenceKey, true); show_video_max_amp_pref = sharedPreferences.getBoolean(PreferenceKeys.ShowVideoMaxAmpPreferenceKey, false); @@ -1112,13 +1120,17 @@ public class DrawPreview { // http://stackoverflow.com/questions/15981516/simpledateformat-gettimeinstance-ignores-24-hour-format // http://daniel-codes.blogspot.co.uk/2013/06/how-to-correctly-format-datetime.html // http://code.google.com/p/android/issues/detail?id=42104 + // update: now seems to be fixed // also possibly related https://code.google.com/p/android/issues/detail?id=181201 //int height = applicationInterface.drawTextWithBackground(canvas, p, current_time_string, Color.WHITE, Color.BLACK, location_x, location_y, MyApplicationInterface.Alignment.ALIGNMENT_TOP); if( text_bounds_time == null ) { if( MyDebug.LOG ) Log.d(TAG, "compute text_bounds_time"); text_bounds_time = new Rect(); - String bounds_time_string = "00:00:00"; + // better to not use a fixed string like "00:00:00" as don't want to make assumptions - e.g., in 12 hour format we'll have the appended am/pm to account for! + String bounds_time_string = dateFormatTimeInstance.format(new Date(100, 0, 1, 10, 59, 59)); + if( MyDebug.LOG ) + Log.d(TAG, "bounds_time_string:" + bounds_time_string); p.getTextBounds(bounds_time_string, 0, bounds_time_string.length(), text_bounds_time); } first_line_xshift += text_bounds_time.width() + gap_x; -- GitLab From 7c6c12bf5579c0a87082561c169081cadf23a0b9 Mon Sep 17 00:00:00 2001 From: tenteru Date: Sat, 21 Mar 2020 09:01:06 +0900 Subject: [PATCH 193/243] localize of getErrorFeatures() function. --- .../opencamera/preview/Preview.java | 21 ++++++++++++------- app/src/main/res/values/strings.xml | 4 ++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 219942f59..3d7a9801f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -4375,25 +4375,32 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu String features = ""; if( was_4k || was_bitrate || was_fps || was_slow_motion ) { if( was_4k ) { - features = "4K UHD"; +// features = "4K UHD"; + features = getContext().getResources().getString(R.string.error_features_4k); } if( was_bitrate ) { if( features.length() == 0 ) - features = "Bitrate"; +// features = "Bitrate"; + features = getContext().getResources().getString(R.string.error_features_bitrate); else - features += "/Bitrate"; +// features += "/Bitrate"; + features += "/" + getContext().getResources().getString(R.string.error_features_bitrate); } if( was_fps ) { if( features.length() == 0 ) - features = "Frame rate"; +// features = "Frame rate"; + features = getContext().getResources().getString(R.string.error_features_frame_rate); else - features += "/Frame rate"; +// features += "/Frame rate"; + features += "/" + getContext().getResources().getString(R.string.error_features_frame_rate); } if( was_slow_motion ) { if( features.length() == 0 ) - features = "Slow motion"; +// features = "Slow motion"; + features = getContext().getResources().getString(R.string.error_features_slow_motion); else - features += "/Slow motion"; +// features += "/Slow motion"; + features += "/" + getContext().getResources().getString(R.string.error_features_slow_motion); } } return features; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 55f1f0b75..5384d0291 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -961,4 +961,8 @@

  • Updated appearance of some icons.\n
  • + 4K UHD + Bitrate + Frame rate + Slow motion -- GitLab From ea79c7e5aa593387c80cced599fb831d463b3c1b Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 21 Mar 2020 17:43:45 +0000 Subject: [PATCH 194/243] Update comment. --- app/src/main/java/net/sourceforge/opencamera/StorageUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index d2154dd90..e286987f1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -367,7 +367,7 @@ public class StorageUtils { * See: http://stackoverflow.com/questions/21605493/storage-access-framework-does-not-update-mediascanner-mtp http://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-framework/ - Also note that this will always return null with Android Q's scoped storage: https://developer.android.com/preview/privacy/scoped-storage + Also note that this will return null for media store Uris with Android Q's scoped storage: https://developer.android.com/preview/privacy/scoped-storage "The DATA column is redacted for each file in the media store." */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) -- GitLab From c2a29cbfba2463ebb3163da3301e7bf136f83a15 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 21 Mar 2020 19:00:36 +0000 Subject: [PATCH 195/243] Use DISPLAY_NAME instead of DATA from mediastore for checking if RAW/DNG. --- .../sourceforge/opencamera/MainActivity.java | 2 +- .../sourceforge/opencamera/StorageUtils.java | 80 +++++++++++-------- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 52d74f91d..9b64186ac 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -3222,7 +3222,7 @@ public class MainActivity extends Activity { StorageUtils.Media media = applicationInterface.getStorageUtils().getLatestMedia(); if( media != null ) { uri = media.uri; - is_raw = media.path != null && media.path.toLowerCase(Locale.US).endsWith(".dng"); + is_raw = media.filename != null && media.filename.toLowerCase(Locale.US).endsWith(".dng"); } } diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index e286987f1..e8318a1d0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -770,15 +770,15 @@ public class StorageUtils { final Uri uri; final long date; final int orientation; - final String path; + final String filename; // this should correspond to DISPLAY_NAME (so available with scoped storage) - so this includes file extension, but not full path - Media(long id, boolean video, Uri uri, long date, int orientation, String path) { + Media(long id, boolean video, Uri uri, long date, int orientation, String filename) { this.id = id; this.video = video; this.uri = uri; this.date = date; this.orientation = orientation; - this.path = path; + this.filename = filename; } } @@ -799,8 +799,11 @@ public class StorageUtils { final int column_id_c = 0; final int column_date_taken_c = 1; final int column_data_c = 2; // full path and filename, including extension - final int column_orientation_c = 3; // for images only - String [] projection = video ? new String[] {VideoColumns._ID, VideoColumns.DATE_TAKEN, VideoColumns.DATA} : new String[] {ImageColumns._ID, ImageColumns.DATE_TAKEN, ImageColumns.DATA, ImageColumns.ORIENTATION}; + final int column_name_c = 3; // filename (without path), including extension + final int column_orientation_c = 4; // for images only + String [] projection = video ? + new String[] {VideoColumns._ID, VideoColumns.DATE_TAKEN, VideoColumns.DATA, VideoColumns.DISPLAY_NAME} : + new String[] {ImageColumns._ID, ImageColumns.DATE_TAKEN, ImageColumns.DATA, ImageColumns.DISPLAY_NAME, ImageColumns.ORIENTATION}; // for images, we need to search for JPEG/etc and RAW, to support RAW only mode (even if we're not currently in that mode, it may be that previously the user did take photos in RAW only mode) String selection = video ? "" : ImageColumns.MIME_TYPE + "='image/jpeg' OR " + ImageColumns.MIME_TYPE + "='image/webp' OR " + @@ -842,50 +845,65 @@ public class StorageUtils { } } while( cursor.moveToNext() ); - if( found ) { + + if( !found ) { + if( MyDebug.LOG ) + Log.d(TAG, "can't find suitable in Open Camera folder, so just go with most recent"); + cursor.moveToFirst(); + } + + { // make sure we prefer JPEG/etc (non RAW) if there's a JPEG/etc version of this image // this is because we want to support RAW only and JPEG+RAW modes - String path = cursor.getString(column_data_c); - if( MyDebug.LOG ) - Log.d(TAG, "path: " + path); - // path may be null on Android 4.4, see above! - if( path != null && path.toLowerCase(Locale.US).endsWith(".dng") ) { + String filename = cursor.getString(column_name_c); + if( MyDebug.LOG ) { + Log.d(TAG, "filename: " + filename); + } + // in theory now that we use DISPLAY_NAME instead of DATA (for path), this should always be non-null, but check just in case + if( filename != null && filename.toLowerCase(Locale.US).endsWith(".dng") ) { if( MyDebug.LOG ) Log.d(TAG, "try to find a non-RAW version of the DNG"); int dng_pos = cursor.getPosition(); boolean found_non_raw = false; - String path_without_ext = path.toLowerCase(Locale.US); - if( path_without_ext.indexOf(".") > 0 ) - path_without_ext = path_without_ext.substring(0, path_without_ext.lastIndexOf(".")); + String filename_without_ext = filename.toLowerCase(Locale.US); + if( filename_without_ext.indexOf(".") > 0 ) + filename_without_ext = filename_without_ext.substring(0, filename_without_ext.lastIndexOf(".")); if( MyDebug.LOG ) - Log.d(TAG, "path_without_ext: " + path_without_ext); + Log.d(TAG, "filename_without_ext: " + filename_without_ext); while( cursor.moveToNext() ) { - String next_path = cursor.getString(column_data_c); + String next_filename = cursor.getString(column_name_c); if( MyDebug.LOG ) - Log.d(TAG, "next_path: " + next_path); - if( next_path == null ) + Log.d(TAG, "next_filename: " + next_filename); + if( next_filename == null ) { + if( MyDebug.LOG ) + Log.d(TAG, "done scanning, couldn't find filename"); break; - String next_path_without_ext = next_path.toLowerCase(Locale.US); - if( next_path_without_ext.indexOf(".") > 0 ) - next_path_without_ext = next_path_without_ext.substring(0, next_path_without_ext.lastIndexOf(".")); + } + String next_filename_without_ext = next_filename.toLowerCase(Locale.US); + if( next_filename_without_ext.indexOf(".") > 0 ) + next_filename_without_ext = next_filename_without_ext.substring(0, next_filename_without_ext.lastIndexOf(".")); if( MyDebug.LOG ) - Log.d(TAG, "next_path_without_ext: " + next_path_without_ext); - if( !path_without_ext.equals(next_path_without_ext) ) + Log.d(TAG, "next_filename_without_ext: " + next_filename_without_ext); + if( !filename_without_ext.equals(next_filename_without_ext) ) { + // no point scanning any further as sorted by date - and we don't want to read through the entire set! + if( MyDebug.LOG ) + Log.d(TAG, "done scanning"); break; + } // so we've found another file with matching filename - is it a JPEG/etc? - if( next_path.toLowerCase(Locale.US).endsWith(".jpg") ) { + if( next_filename.toLowerCase(Locale.US).endsWith(".jpg") ) { if( MyDebug.LOG ) Log.d(TAG, "found equivalent jpeg"); found_non_raw = true; break; } - else if( next_path.toLowerCase(Locale.US).endsWith(".webp") ) { + else if( next_filename.toLowerCase(Locale.US).endsWith(".webp") ) { if( MyDebug.LOG ) Log.d(TAG, "found equivalent webp"); found_non_raw = true; break; } - else if( next_path.toLowerCase(Locale.US).endsWith(".png") ) { + else if( next_filename.toLowerCase(Locale.US).endsWith(".png") ) { if( MyDebug.LOG ) Log.d(TAG, "found equivalent png"); found_non_raw = true; @@ -899,19 +917,15 @@ public class StorageUtils { } } } - if( !found ) { - if( MyDebug.LOG ) - Log.d(TAG, "can't find suitable in Open Camera folder, so just go with most recent"); - cursor.moveToFirst(); - } + long id = cursor.getLong(column_id_c); long date = cursor.getLong(column_date_taken_c); int orientation = video ? 0 : cursor.getInt(column_orientation_c); Uri uri = ContentUris.withAppendedId(baseUri, id); - String path = cursor.getString(column_data_c); + String filename = cursor.getString(column_name_c); if( MyDebug.LOG ) Log.d(TAG, "found most recent uri for " + (video ? "video" : "images") + ": " + uri); - media = new Media(id, video, uri, date, orientation, path); + media = new Media(id, video, uri, date, orientation, filename); } } catch(Exception e) { -- GitLab From 25af0ae27c5fa5b5e4152124e0dbb66271093332 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 21 Mar 2020 19:24:12 +0000 Subject: [PATCH 196/243] Refactor, add comment. --- .../java/net/sourceforge/opencamera/StorageUtils.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index e8318a1d0..987acf675 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -794,6 +794,11 @@ public class StorageUtils { Log.e(TAG, "don't have READ_EXTERNAL_STORAGE permission"); return null; } + + File save_folder = getImageFolder(); // may be null if using SAF + if( MyDebug.LOG ) + Log.d(TAG, "save_folder: " + save_folder); + Media media = null; Uri baseUri = video ? Video.Media.EXTERNAL_CONTENT_URI : MediaStore.Images.Media.EXTERNAL_CONTENT_URI; final int column_id_c = 0; @@ -818,7 +823,7 @@ public class StorageUtils { Log.d(TAG, "found: " + cursor.getCount()); // now sorted in order of date - scan to most recent one in the Open Camera save folder boolean found = false; - File save_folder = getImageFolder(); // may be null if using SAF + //File save_folder = getImageFolder(); // may be null if using SAF String save_folder_string = save_folder == null ? null : save_folder.getAbsolutePath() + File.separator; if( MyDebug.LOG ) Log.d(TAG, "save_folder_string: " + save_folder_string); @@ -927,6 +932,10 @@ public class StorageUtils { Log.d(TAG, "found most recent uri for " + (video ? "video" : "images") + ": " + uri); media = new Media(id, video, uri, date, orientation, filename); } + else { + if( MyDebug.LOG ) + Log.d(TAG, "mediastore returned no media"); + } } catch(Exception e) { // have had exceptions such as SQLiteException, NullPointerException reported on Google Play from within getContentResolver().query() call -- GitLab From 5f0477b229748c349c128969843aaf30f8364ad8 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 21 Mar 2020 19:28:30 +0000 Subject: [PATCH 197/243] Refactor code to new getLatestMediaCore. --- .../sourceforge/opencamera/StorageUtils.java | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index 987acf675..14c809a79 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -782,25 +782,9 @@ public class StorageUtils { } } - private Media getLatestMedia(boolean video) { - if( MyDebug.LOG ) - Log.d(TAG, "getLatestMedia: " + (video ? "video" : "images")); - if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { - // needed for Android 6, in case users deny storage permission, otherwise we get java.lang.SecurityException from ContentResolver.query() - // see https://developer.android.com/training/permissions/requesting.html - // we now request storage permission before opening the camera, but keep this here just in case - // we restrict check to Android 6 or later just in case, see note in LocationSupplier.setupLocationListener() - if( MyDebug.LOG ) - Log.e(TAG, "don't have READ_EXTERNAL_STORAGE permission"); - return null; - } - - File save_folder = getImageFolder(); // may be null if using SAF - if( MyDebug.LOG ) - Log.d(TAG, "save_folder: " + save_folder); - + private Media getLatestMediaCore(Uri baseUri, File save_folder, boolean video) { Media media = null; - Uri baseUri = video ? Video.Media.EXTERNAL_CONTENT_URI : MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + final int column_id_c = 0; final int column_date_taken_c = 1; final int column_data_c = 2; // full path and filename, including extension @@ -948,6 +932,30 @@ public class StorageUtils { cursor.close(); } } + + return media; + } + + private Media getLatestMedia(boolean video) { + if( MyDebug.LOG ) + Log.d(TAG, "getLatestMedia: " + (video ? "video" : "images")); + if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { + // needed for Android 6, in case users deny storage permission, otherwise we get java.lang.SecurityException from ContentResolver.query() + // see https://developer.android.com/training/permissions/requesting.html + // we now request storage permission before opening the camera, but keep this here just in case + // we restrict check to Android 6 or later just in case, see note in LocationSupplier.setupLocationListener() + if( MyDebug.LOG ) + Log.e(TAG, "don't have READ_EXTERNAL_STORAGE permission"); + return null; + } + + File save_folder = getImageFolder(); // may be null if using SAF + if( MyDebug.LOG ) + Log.d(TAG, "save_folder: " + save_folder); + + Uri baseUri = video ? Video.Media.EXTERNAL_CONTENT_URI : MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + Media media = getLatestMediaCore(baseUri, save_folder, video); + return media; } -- GitLab From 547361905ffdd37facf5a75b7d685e8bb0f37366 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 22 Mar 2020 17:03:29 +0000 Subject: [PATCH 198/243] Comment out some comments. --- .../cameracontroller/CameraController2.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java index d2b4e76d4..17c5dfe47 100644 --- a/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java +++ b/app/src/main/java/net/sourceforge/opencamera/cameracontroller/CameraController2.java @@ -2111,14 +2111,14 @@ public class CameraController2 extends CameraController { largest_dist = dist; } } - if( MyDebug.LOG ) - Log.d(TAG, "largest indx " + largest_indx + " dist: " + largest_dist); + /*if( MyDebug.LOG ) + Log.d(TAG, "largest indx " + largest_indx + " dist: " + largest_dist);*/ Pair p0 = points.get(largest_indx); Pair p1 = points.get(largest_indx+1); float mid_x = 0.5f*(p0.first + p1.first); float mid_y = 0.5f*(p0.second + p1.second); - if( MyDebug.LOG ) - Log.d(TAG, " insert: " + mid_x + " , " + mid_y); + /*if( MyDebug.LOG ) + Log.d(TAG, " insert: " + mid_x + " , " + mid_y);*/ points.add(largest_indx+1, new Pair<>(mid_x, mid_y)); } @@ -2127,8 +2127,8 @@ public class CameraController2 extends CameraController { Pair point = points.get(i); out_values[2*i] = point.first; out_values[2*i+1] = point.second; - if( MyDebug.LOG ) - Log.d(TAG, "out point[" + i + "]: " + point.first + " , " + point.second); + /*if( MyDebug.LOG ) + Log.d(TAG, "out point[" + i + "]: " + point.first + " , " + point.second);*/ } return out_values; } -- GitLab From 0a1f5d803fd9ccfa7fc3ec675ee0a95efdb0925a Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 22 Mar 2020 17:05:15 +0000 Subject: [PATCH 199/243] Don't attempt to show toasts in background, just in case. --- .../sourceforge/opencamera/preview/Preview.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 4c1229a76..00bf7c6d3 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -7424,12 +7424,28 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( MyDebug.LOG ) Log.d(TAG, "showToast: " + message); + + if( this.app_is_paused ) { + if( MyDebug.LOG ) + Log.e(TAG, "don't show toast as application is paused: " + message); + // when targeting Android 11+, toasts with custom views won't be shown in background anyway - in theory we + // shouldn't be making toasts when in background, but check just in case + return; + } + final Activity activity = (Activity)this.getContext(); // We get a crash on emulator at least if Toast constructor isn't run on main thread (e.g., the toast for taking a photo when on timer). // Also see http://stackoverflow.com/questions/13267239/toast-from-a-non-ui-thread // Also for the use_fake_toast code, running the creation code, and the postDelayed code (and the code in clearActiveFakeToast()), on the UI thread avoids threading issues activity.runOnUiThread(new Runnable() { public void run() { + if( Preview.this.app_is_paused ) { + if( MyDebug.LOG ) + Log.e(TAG, "don't show toast as application is paused: " + message); + // see note above + return; + } + final float scale = Preview.this.getResources().getDisplayMetrics().density; final int offset_y = (int) (offset_y_dp * scale + 0.5f); // convert dps to pixels -- GitLab From f82f64bd53ecf905a1476f5c04d5e38e0476adab Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 26 Mar 2020 00:02:37 +0000 Subject: [PATCH 200/243] Update russian translation. --- _docs/credits.html | 2 +- app/src/main/res/values-ru/strings.xml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index 0db14b468..46f04a61d 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -73,7 +73,7 @@
  • Norwegian Bokmål translation by Imre Kristoffer Eilertsen ( imreeil42 AT gmail DOT com ).
  • Polish translation by Jacek Buczyński.
  • -
  • Russian translation by maksnogin ( maksnogin AT gmail DOT com ), Grigorii Chirkov and Dmitry Vahnin aka JSBmanD.
  • +
  • Russian translation by maksnogin ( maksnogin AT gmail DOT com ), Grigorii Chirkov, Dmitry Vahnin aka JSBmanD, Aleksey Khlybov.
  • Slovenian translation by Peter Klofutar.
  • Spanish translation by Mario Sanoguera ( sanogueralorenzo AT gmail DOT com , https://play.google.com/store/apps/developer?id=Mario+Sanoguera ; Sebastian05067, https://forum.xda-developers.com/member.php?u=6302705 ) and Gonzalo Prieto Vega.
  • Turkish translation by Serdar Erkoc ( serdarerkoc2004 AT yahoo DOT com ).
  • diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 829c3eb9e..14a3397dd 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -158,7 +158,7 @@ Руководство по обрезке Отображение прямоугольника, показывающего соотношение сторон - полезно, если вы планируете обрезать фото/видео. Требуется режим фотосъемки WYSIWYG или режим видео\n%s Всплывающие сообщения - Показывать всплыващие уведомления при работе + Показывать всплывающие уведомления при работе Показать эскиз анимации Отображение перемещения эскиза анимации при съемке фотографии Показывать рамку во время фотосъемки @@ -302,7 +302,7 @@ РАЗРЕШЕНИЯ НЕ ДОСТУПНЫ Требуется разрешение - Требуется разрешение на доступ к камере для ее сключения + Требуется разрешение на доступ к камере для ее включения Требуется разрешение на чтение/запись для сохранения фото Требуется разрешение на доступ к микрофону для записи видео со звуком Требуется разрешение на определение местоположения для геотеггинга (хранение информации о местоположении @@ -705,7 +705,7 @@ -3 (низкая чувствительность) Улучшение контрастности HDR - Использовать алгоритм улучшения контрастности для HDR. Может улучшить качество при очень высоком динамическом диапазоне в кадре, в результате чего изображение станосится "похожим на HDR".\n%s + Использовать алгоритм улучшения контрастности для HDR. Может улучшить качество при очень высоком динамическом диапазоне в кадре, в результате чего изображение становится "похожим на HDR".\n%s Выкл. Умный Всегда @@ -851,10 +851,10 @@ Показывать на экране ярлык для задания цикла вспышки вместо отображения настроек вспышки во всплывающем меню Разрешать RAW для брэкетинга экспозиции - Настройка также прездназначена для применения RAW для режима брэкетинга экспозиции фото (или для режима HDR, когда включена настройка \"Сохранять все изображения для режима HDR\"). Если данная настройка отключена, в данных режимах фото будут сохранены только в формате JPEG. + Настройка также предназначена для применения RAW для режима брэкетинга экспозиции фото (или для режима HDR, когда включена настройка \"Сохранять все изображения для режима HDR\"). Если данная настройка отключена, в данных режимах фото будут сохранены только в формате JPEG. Разрешать RAW для фокус-брэкетинга - Настройка также прездназначена для применения RAW для режима фокус-брэкетинга фото. Если данная настройка отключена, в режиме фокус-брэкетинга фото будут сохранены только в формате JPEG. + Настройка также предназначена для применения RAW для режима фокус-брэкетинга фото. Если данная настройка отключена, в режиме фокус-брэкетинга фото будут сохранены только в формате JPEG. Переключать режимы RAW Показывать ярлык RAW -- GitLab From b43aa518dda0561239525d71f1bd2084df4fc9a2 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 26 Mar 2020 23:24:04 +0000 Subject: [PATCH 201/243] Optimisation for reading most recent photo/video for thumbnail. --- _docs/history.html | 1 + .../sourceforge/opencamera/StorageUtils.java | 70 ++++++++++++++++--- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 088b9dce3..8542b830c 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -119,6 +119,7 @@ UPDATED Exposure icon now highlights red when exposure UI is open. UPDATED Exposure UI now auto-opens when switching to manual white balance (as exposure UI contains the manual white balance temperature seekbar). UPDATED More repeat mode options (100x, 200x, 500x). +UPDATED Optimisation for reading most recent photo/video for thumbnail. Version 1.47.3 (2019/10/20) diff --git a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java index 14c809a79..70529cac2 100644 --- a/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java +++ b/app/src/main/java/net/sourceforge/opencamera/StorageUtils.java @@ -390,9 +390,9 @@ public class StorageUtils { if( MyDebug.LOG ) Log.d(TAG, "id: " + id); String [] split = id.split(":"); - if( split.length >= 2 ) { + if( split.length >= 1 ) { String type = split[0]; - String path = split[1]; + String path = split.length >= 2 ? split[1] : ""; /*if( MyDebug.LOG ) { Log.d(TAG, "type: " + type); Log.d(TAG, "path: " + path); @@ -782,29 +782,65 @@ public class StorageUtils { } } - private Media getLatestMediaCore(Uri baseUri, File save_folder, boolean video) { + private Media getLatestMediaCore(Uri baseUri, String bucket_id, boolean video) { + if( MyDebug.LOG ) { + Log.d(TAG, "getLatestMediaCore"); + Log.d(TAG, "baseUri: " + baseUri); + Log.d(TAG, "bucket_id: " + bucket_id); + Log.d(TAG, "video: " + video); + } Media media = null; final int column_id_c = 0; final int column_date_taken_c = 1; - final int column_data_c = 2; // full path and filename, including extension + /*final int column_data_c = 2; // full path and filename, including extension final int column_name_c = 3; // filename (without path), including extension - final int column_orientation_c = 4; // for images only + final int column_orientation_c = 4; // for images only*/ + final int column_name_c = 2; // filename (without path), including extension + final int column_orientation_c = 3; // for images only String [] projection = video ? - new String[] {VideoColumns._ID, VideoColumns.DATE_TAKEN, VideoColumns.DATA, VideoColumns.DISPLAY_NAME} : - new String[] {ImageColumns._ID, ImageColumns.DATE_TAKEN, ImageColumns.DATA, ImageColumns.DISPLAY_NAME, ImageColumns.ORIENTATION}; + new String[] {VideoColumns._ID, VideoColumns.DATE_TAKEN, VideoColumns.DISPLAY_NAME} : + new String[] {ImageColumns._ID, ImageColumns.DATE_TAKEN, ImageColumns.DISPLAY_NAME, ImageColumns.ORIENTATION}; // for images, we need to search for JPEG/etc and RAW, to support RAW only mode (even if we're not currently in that mode, it may be that previously the user did take photos in RAW only mode) - String selection = video ? "" : ImageColumns.MIME_TYPE + "='image/jpeg' OR " + + /*String selection = video ? "" : ImageColumns.MIME_TYPE + "='image/jpeg' OR " + ImageColumns.MIME_TYPE + "='image/webp' OR " + ImageColumns.MIME_TYPE + "='image/png' OR " + - ImageColumns.MIME_TYPE + "='image/x-adobe-dng'"; + ImageColumns.MIME_TYPE + "='image/x-adobe-dng'";*/ + String selection = ""; + if( bucket_id != null ) + selection = (video ? VideoColumns.BUCKET_ID : ImageColumns.BUCKET_ID) + " = " + bucket_id; + if( !video ) { + boolean and = selection.length() > 0; + if( and ) + selection += " AND ( "; + selection += ImageColumns.MIME_TYPE + "='image/jpeg' OR " + + ImageColumns.MIME_TYPE + "='image/webp' OR " + + ImageColumns.MIME_TYPE + "='image/png' OR " + + ImageColumns.MIME_TYPE + "='image/x-adobe-dng'"; + if( and ) + selection += " )"; + } + if( MyDebug.LOG ) + Log.d(TAG, "selection: " + selection); String order = video ? VideoColumns.DATE_TAKEN + " DESC," + VideoColumns._ID + " DESC" : ImageColumns.DATE_TAKEN + " DESC," + ImageColumns._ID + " DESC"; Cursor cursor = null; + + // we know we only want the most recent image - however we may need to scan forward if we find a RAW, to see if there's + // an equivalent non-RAW image + // request 3, just in case + Uri queryUri = baseUri.buildUpon().appendQueryParameter("limit", "3").build(); + if( MyDebug.LOG ) + Log.d(TAG, "queryUri: " + queryUri); + try { - cursor = context.getContentResolver().query(baseUri, projection, selection, null, order); + cursor = context.getContentResolver().query(queryUri, projection, selection, null, order); if( cursor != null && cursor.moveToFirst() ) { if( MyDebug.LOG ) Log.d(TAG, "found: " + cursor.getCount()); + + // now sorted in order of date - so just pick the most recent one + + /* // now sorted in order of date - scan to most recent one in the Open Camera save folder boolean found = false; //File save_folder = getImageFolder(); // may be null if using SAF @@ -840,6 +876,7 @@ public class StorageUtils { Log.d(TAG, "can't find suitable in Open Camera folder, so just go with most recent"); cursor.moveToFirst(); } + */ { // make sure we prefer JPEG/etc (non RAW) if there's a JPEG/etc version of this image @@ -952,9 +989,20 @@ public class StorageUtils { File save_folder = getImageFolder(); // may be null if using SAF if( MyDebug.LOG ) Log.d(TAG, "save_folder: " + save_folder); + String bucket_id = null; + if( save_folder != null ) { + bucket_id = String.valueOf(save_folder.getAbsolutePath().toLowerCase().hashCode()); + } + if( MyDebug.LOG ) + Log.d(TAG, "bucket_id: " + bucket_id); Uri baseUri = video ? Video.Media.EXTERNAL_CONTENT_URI : MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - Media media = getLatestMediaCore(baseUri, save_folder, video); + Media media = getLatestMediaCore(baseUri, bucket_id, video); + if( media == null && bucket_id != null ) { + if( MyDebug.LOG ) + Log.d(TAG, "fall back to checking any folder"); + media = getLatestMediaCore(baseUri, null, video); + } return media; } -- GitLab From 1fe6184547ce0d72250972a031c1adc1584de4fd Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Thu, 26 Mar 2020 23:33:09 +0000 Subject: [PATCH 202/243] Tweak last merge - don't need commented out code; move new strings above untranslated strings. --- .../java/net/sourceforge/opencamera/preview/Preview.java | 7 ------- app/src/main/res/values/strings.xml | 9 +++++---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index fffddfa04..a747e0111 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -4517,31 +4517,24 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu String features = ""; if( was_4k || was_bitrate || was_fps || was_slow_motion ) { if( was_4k ) { -// features = "4K UHD"; features = getContext().getResources().getString(R.string.error_features_4k); } if( was_bitrate ) { if( features.length() == 0 ) -// features = "Bitrate"; features = getContext().getResources().getString(R.string.error_features_bitrate); else -// features += "/Bitrate"; features += "/" + getContext().getResources().getString(R.string.error_features_bitrate); } if( was_fps ) { if( features.length() == 0 ) -// features = "Frame rate"; features = getContext().getResources().getString(R.string.error_features_frame_rate); else -// features += "/Frame rate"; features += "/" + getContext().getResources().getString(R.string.error_features_frame_rate); } if( was_slow_motion ) { if( features.length() == 0 ) -// features = "Slow motion"; features = getContext().getResources().getString(R.string.error_features_slow_motion); else -// features += "/Slow motion"; features += "/" + getContext().getResources().getString(R.string.error_features_slow_motion); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 463001ebd..938fa8bbc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -974,6 +974,11 @@ Aperture + 4K UHD + Bitrate + Frame rate + Slow motion + Privacy policy @@ -1025,8 +1030,4 @@
  • Updated appearance of some icons.\n
  • - 4K UHD - Bitrate - Frame rate - Slow motion -- GitLab From 353dfd95621224a57e964ebed09e4b3686c934ba Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 28 Mar 2020 21:39:20 +0000 Subject: [PATCH 203/243] Update Japanese translation. --- _docs/credits.html | 2 +- app/src/main/res/values-ja/arrays.xml | 77 ++- app/src/main/res/values-ja/strings.xml | 674 +++++++++++++++++++++---- 3 files changed, 651 insertions(+), 102 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index 46f04a61d..b9d0b3e99 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -68,7 +68,7 @@
  • Greek translation by Wasilis Mandratzis-Walz.
  • Hungarian translation by Báthory Péter.
  • Italian tranlation by Valerio Bozzolan, Stefano Gualmo ( s DOT gualmo AT gmail DOT com ).
  • -
  • Japanese translation by Mitsuse.
  • +
  • Japanese translation by Mitsuse and Yanagimoto Yoshiaki.
  • Korean translation by Halcyonest.
  • Norwegian Bokmål translation by Imre Kristoffer Eilertsen ( imreeil42 AT gmail DOT com ).
  • Polish translation by Jacek Buczyński.
  • diff --git a/app/src/main/res/values-ja/arrays.xml b/app/src/main/res/values-ja/arrays.xml index 44fb33c61..296b7ef75 100644 --- a/app/src/main/res/values-ja/arrays.xml +++ b/app/src/main/res/values-ja/arrays.xml @@ -1,15 +1,15 @@ - 自動 + オートフォーカス 無限遠 マクロ + 固定(タッチAF) + マニュアルフォーカス 固定 - マニュアル - Fixed EDOF - コンティニュアス - コンティニュアス + コンティニュアスAF + コンティニュアスAF focus_mode_auto @@ -61,8 +61,8 @@ 300 - 最大サイズ - マッチしたサイズ (WYSIWYG) + ディスプレイに合わせる + 撮影範囲に合わせる(WYSIWYG) preference_preview_size_display @@ -70,8 +70,8 @@ なし - 1回押し - 2回押し + タッチ + ダブルタップ none @@ -81,9 +81,9 @@ 写真を撮る (ビデオ録画の開始/終了) フォーカス - ズームの拡大/縮小 + ズームイン/ズームアウト 露出補正 - 自動手振れ防止のオン/オフ + 傾き補正のオン/オフ 音量の変更 なし @@ -242,4 +242,59 @@ audio_mono audio_stereo + + なし + 音に反応 + 音声コマンド: \"チーズ\" + + + none + noise + voice + + + ローカルタイム + UTC協定世界時 + + + local + zulu + + + 3枚 + 5枚 + + + 3 + 5 + + + ±1/2EV + ±1EV + ±2EV + ±3EV + + + 0.5 + 1 + 2 + 3 + + + 反転しない + 反転する + + + preference_front_camera_mirror_no + preference_front_camera_mirror_photo + + + 記録しない + 記録する + + + preference_video_subtitle_no + preference_video_subtitle_yes + + diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 5128ed670..0a9e99a7a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,13 +1,13 @@ - Open Camera + Open Camera 設定 ポップアップ設定 了解しました (この内容を再度表示しない) - 有効 - 無効 + オン + オフ 保存場所を選択する: フォルダの履歴を消去する @@ -18,7 +18,7 @@ 繰り返します カメラへの接続に失敗しました ビデオファイルが壊れている可能性があります - この機械はサポートできません + が無効です 不明なエラーです、ビデオを停止します サーバーが反応しません、ビデオを停止します 最大撮影時間に達しました @@ -31,8 +31,8 @@ リアカメラ 写真 ビデオ - 露出を設定しました - 露出を解除しました + 露出を固定しました + 露出の固定を解除しました タイマーを解除しました 高速撮影を解除しました タイマーを開始しました @@ -41,7 +41,8 @@ 録画を開始しました すみません 保存に失敗しました - 回転に失敗しました + RAWファイルの保存に失敗しました + 傾き補正に失敗しました プレビューに失敗しました 写真を撮ります 撮影に失敗しました @@ -50,7 +51,7 @@ ギャラリーアプリがありません 画面を固定しました。スワイプで解除します。 解除 - すみませんがこの機械では自動回転が使えません + すみませんがこの端末では傾き補正が使えません 音声は無効です 最大撮影時間 カラーエフェクト @@ -68,12 +69,12 @@ [固定: スワイプで解除] - 情報の貼り付けに失敗しました + スタンプの貼り付けに失敗しました m カメラエフェクト - 自動回転 - 水平を(写真のみ)自動的に修正します(撮影後の処理に時間がかかります。メモリの少ない機械では失敗する事があります) + 傾き補正 + 水平を(写真のみ)自動的に修正します(撮影後の処理に時間がかかります。メモリの少ない端末では失敗する事があります) カラーエフェクト 選択した色による効果を適用します シーンモード @@ -81,66 +82,71 @@ ホワイトバランス ホワイトバランスを選択します ISO感度 - 高い感度を設定すると僅かな光でも撮影できます (一部動作しない機械もあります) + 高い感度を設定すると僅かな光でも撮影できます (一部動作しない端末もあります) 露出補正 0に設定するとデフォルトの露出補正になります 写真/ビデオの向き - 設定すると機械上の向きよりも設定された向きを優先して保存します\n%s - 顔検出 - フォーカスの設定に顔検出を利用します + 設定すると端末の向きよりも設定された向きを優先して保存します\n%s + 顔認識 + フォーカスエリアの代わりに顔認識を利用します カメラ制御 タイマー タイマー音 - タイマーの計測もしくは高速撮影時の間隔の計測で音を鳴らします + タイマー撮影やインターバル撮影のカウントダウンで音を鳴らします 音声タイマー - タイマーの計測もしくは高速撮影時の間隔の計測で(残り1分から)音声を流します - 高速撮影 - 撮影間隔 + タイマー撮影やインターバル撮影のカウントダウンで(残り1分から)音声を流します + 連続撮影 + インターバル カメラ制御の詳細設定… - タッチして保存する - タッチもしくはプレビューを2回タップして写真を保存します + 画面タッチで撮影する + 画面をタッチまたはダブルタップして写真を撮影します 撮影の後に一時停止する 一時停止した画面上で写真の共有もしくは削除ができます シャッター音 - 撮影時に音を再生する + 撮影時に音を再生します 音量キー - + 音声コントロール設定 + + 音声コントロール感度 + 音に対する感度の設定 保存場所 写真/ビデオを保存するフォルダを決めます ストレージへのフレームワークを使用する - 写真やビデオを保存する際にStorage Accessフレームワークを使用するかどうかを選択します + 写真やビデオを保存する際にStorage Accessフレームワークを使用するかどうかを選択します。外付けのSDカードに保存する場合はこの設定が必要となります。 保存する写真の命名ルール 保存する写真のファイル名の手前につける内容を設定します 保存するビデオの命名ルール 保存するビデオのファイル名の手前につける内容を設定します + ファイル名に使用する時刻フォーマット ロック画面上でもカメラを表示する - 有効にするとOpen Cameraがロック画面上でも表示されます(ギャラリーを規定のアプリにしているなど、ロックの解除が必要になる場合もあります) - + 有効にするとOpen Cameraがロック画面上でも表示されます(ギャラリーを既定のアプリにしているなど、ロックの解除が必要になる場合もあります) + 起動時にオートフォーカスを行う + Open Camera の起動時にオートフォーカスを行います。もし起動時にライトが点灯する問題が起こる場合は設定をオフにしてください。 録画中は画面を固定する 録画が停止しないように画面を固定します。固定は画面をスワイプすると解除されます。アプリをバックグラウンドに移すか画面を消灯しても録画は停止します。 - 回転をプレビュー - プレビューを回転して表示します(写真/ビデオの保存には影響しません)\n%s - 画面上での表示設定… + プレビューを回転 + プレビューを180度回転して表示します(写真/ビデオの保存には影響しません)\n%s + 画面表示設定… プレビューサイズ - 操作位置 + ボタン配置 全画面表示モード - ズームを表示する - 画面上にズームレベルを表示します(ズームインする場合) - ズーム制御を表示する + ズーム倍率を表示する + 画面上にズーム倍率を表示します(ズームインする場合) + ズームボタンを表示する 画面上にズーム制御の -/+ ボタンを表示します ズーム制御のスライダーを表示する 画面上にズーム制御のスライダーを表示します ISOを表示する - 画面上にISO感度の状態を表示します (Camera2 APIが必要です) + 画面上にISO感度を表示します。自動発光モードの場合は発光するかどうかも表示します。 (Camera2 APIが必要です) 空きメモリを表示する 画面上に空きメモリを表示します 角度を表示する 画面上に角度を表示します 角度を線で表示する 画面上に線を表示します - 角度を色で表示する - 角度の具合を色で表示します + 角度のハイライトカラー + カメラがほぼ水平になった時のハイライトカラーを指定します 方角を表示する 画面上に方角を表示します 時間を表示する @@ -155,6 +161,8 @@ 画面上のメッセージをトースト形式で表示します サムネイルをアニメにする 撮影時のサムネイルをアニメにして表示します + 写真撮影中に枠線を表示する + 写真の撮影中に枠線を表示します 表示を維持する 有効にすると使用している間は画面が消えなくなります 明るさを常に最大にする @@ -166,51 +174,56 @@ 位置情報の設定… 写真の解像度 写真の品質 - 保存する写真の品質を決めます (90%%の圧縮率を提案します)\n%s + JPEG形式とWebP形式の保存品質を設定します(初期値は90%%)。PNG形式には影響しません。\n%s + RAW 位置情報を使用する - 写真/ビデオにジオタグを埋め込みます + 写真/ビデオにジオタグを埋め込みます(写真の場合、JPEGまたはDNGの場合のみ埋め込み可能) 方角情報を使用する - 写真にコンパスを埋め込みます + 写真にコンパスを埋め込みます(JPEG形式のみ) 位置情報を要求する 有効にすると位置情報を取得可能な場合のみ写真/ビデオの撮影が動作します - 情報を貼り付ける + スタンプを貼り付ける 写真に日付と時刻を貼り付けます。GPSが有効であれば位置情報も埋め込みます。\n%s 日付の形式 時刻の形式 GPSの形式 文字の内容 - 写真に貼り付ける文字の内容を決めます + 写真に貼り付けるスタンプ文字の内容を決めます 文字のサイズ - 写真に貼り付ける文字の大きさを決めます + 写真に貼り付けるスタンプ文字の大きさを決めます 文字の色 - 写真に貼り付ける文字の色を決めます - 文字の形状 - 写真に貼り付ける文字の形状を決めます\n%s + 写真に貼り付けるスタンプ文字の色を決めます + 文字の装飾 + 写真に貼り付けるスタンプ文字の装飾方法を決めます\n%s ビデオの解像度 - 4K UHDビデオ (実験中) - 3840x2160での撮影を有効にします - サポートしていない機械ではクラッシュする事もあります! - 自動回転を有効にする - ビデオ撮影時の自動回転を設定します - ビデオのビットレート - ビデオのビットレートを設定します(設定を高くするとより多くの保存スペースが必要になり、サポートしていないレートを設定すると録画に失敗する事があります)\n%s + 4K UHD ビデオ(一部端末のみ) + リアカメラによる3840x2160での撮影を有効にします - これは端末メーカーが公開していない4Kサポート機能を使って4K撮影を可能にします。動作保証はありませんので、利用する前に必ずテストを行ってください。 + 手ぶれ補正を有効にする + ビデオ撮影時の手ぶれ補正を設定します + ビデオのビットレート(目安) + ビデオのビットレートを設定します(設定を高くすると品質は良くなりますが、より多くの保存スペースが必要になります。サポートしていないレートを設定すると録画に失敗する事があります)\n%s ビデオのフレームレート - ビデオのフレームレート(FPS)を設定します(サポートしていないレートを設定すると録画に失敗する事があります)\n%s + ビデオのフレームレート(FPS)を設定します(あくまで目安のため、保証はされません。サポートしていないレートを設定すると録画に失敗する事があります。)\n%s ビデオの最大撮影時間 指定した時間が経過するとビデオ撮影が自動的に停止します\n%s ビデオの最大撮影回数 - 最大撮影時間の経過後に指定した回数だけ撮影を繰り返します(有効時のみ)\n%s - + 最大撮影時間が経過すると録画は停止しますが、このオプションでは指定した回数まで撮影を自動で再開します。\n%s + ビデオの最大ファイルサイズ + ビデオ撮影は最大ファイルサイズに到達すると停止または停止&再開(以下のオプションを参照)します。注意:多くのAndroid端末には端末自体に最大ファイルサイズ制限(2GBや4GBなど)が設定されていますが、このオプションでは任意の値を設定できます。注意:このオプションでは端末自体の最大ファイルサイズ制限を増やすことはできません。\n%s + 最大ファイルサイズで停止&再開 + 最大ファイルサイズに到達したら自動的に録画の停止と再開をします。(端末のファイルサイズ制限かユーザーが指定した任意のサイズのどちらか小さい方) 音声録音 ビデオの撮影時に音声も録音します オーディオソース - 音声の録音にマイクを使用します\n%s + 録音に使用するマイク\n%s オーディオチャンネル - モノラルもしくはステレオを指定します (ステレオはサポートしている機械でのみ有効です) - 録画中にフラッシュを使用する - 有効にすると撮影中にフラッシュを使う事ができます (撮影中である事を相手に伝えます) + モノラルもしくはステレオを指定します (ステレオはサポートしている端末でのみ有効です) + 録画中にライトを点滅する + 有効にすると撮影中にライトが点滅します (撮影中である事を相手に伝えることができます) その他の内容 オンラインヘルプ + Open Camera のWEBサイトをブラウザで開きます サポートのために寄付をする このアプリが気に入りましたら寄付をお願いします。この項目を押すと寄付への窓口が開きます。寄付権を購入する事で寄付ができます。寄付してくれたらありがとう! Camera2 APIを使う @@ -231,6 +244,10 @@ 露出を固定する フォーカス切替 フラッシュ切替 + フロントカメラ切替 + リアカメラ切替 + ビデオモードに切り替える + 写真モードに切り替える さっきの写真を削除する この写真を共有する @@ -244,11 +261,100 @@ 保存先を選択する ストレージへのアクセスがキャンセルされました - + このフォルダには保存できません + マイクの使用が許可されていません 位置情報の使用が許可されていません + ビデオ撮影を開始する + ビデオ撮影を停止する + + MB + GB + + 音声コントロールのリスニングを開始する + 音声コントロールのリスニングを停止する + \"チーズ\"と言ってください + 何か大きな音を立ててください + + 傾き補正は写真が水平になるよう自動的に角度を調整します。\n\n注意:これには回転と切り抜きの処理が必要になるため、解像度と画角(写る範囲)が小さくなります。 + HDR(ハイダイナミックレンジ)は被写体の輝度差が大きな場面で役立ちます。異なる露出で複数の撮影を行い、それらを合成して画像を生成します。\n\n注意:HDRは動きの速い場面には適さないため、色が正しく表現されない可能性があります。\n\nHDRモードは通常の撮影と比べて時間がかかります。 + + 再度表示しない + + 撮影モード + 標準 + 標準 + HDR + 露出BKT + 露出ブラケット + HS連写 + ハイスピード連写 + NR + ノイズリダクション撮影 + スタンプ + HDR撮影時すべての写真を保存する + これを有効にするとHDR撮影時に3つの異なる露出の写真がHDR写真と共に保存されます。注意:スタンプや傾き補正のようなオプションを使用している場合は保存が遅くなります。 + + カメラの権限がありません + 権限が必要です + カメラを有効にするにはカメラの権限が必要です + 写真を保存するにはストレージの読み書き権限が必要です + 音声付き動画の撮影と音声コントロールを使用するにはマイクの権限が必要です + ジオタギング(位置情報を写真やビデオに付加する)には位置情報の権限が必要です。 + 位置情報の権限はBluetooth LE リモートコントロールデバイスの接続にも必要です。 + + デバッグ用オプション + デバッグ用オプション + 代替のフラッシュ方式を使用 + Camera2 API 使用中に端末のフラッシュの挙動が不安定な場合は有効にしてください。 + + 露出ブラケット + 露出ブラケットモードで撮影する枚数を指定します。\n%s + 露出ブラケット幅 + 変化させる露出の幅を指定します\n%s + + ノイズリダクション 元画像保存 + ノイズリダクション撮影時、元の画像を保存します。注意:写真の保存には時間がかかります。\n%s + + 元画像を保存しない + 単一の元画像を保存する + 全ての元画像を保存する(遅い) + + + + ビデオを記録するための充分な空きスペースがありません + ビデオ撮影を停止しました\nバッテリー残量が非常に少なくなりました + バッテリー残量チェック + バッテリー残量が非常に少なくなった場合に録画を停止します。これにより、端末の電源が落ちてファイルが破損するリスクを軽減します。 + + 高速なHDR/露出BKT撮影 + 高速なHDR/露出ブラケット撮影を行います。 もしHDR/露出ブラケット撮影で問題が起こる場合はこの設定を無効にしてください。 + + ビデオ撮影 + セルフィー + + フロントカメラを反転 + フロントカメラ撮影時に左右反転した画像を保存します。\n%s + + 加速度センサーの校正 + このオプションは端末の加速度センサーを校正します。これにより傾き補正と角度表示が正確に動作するようになります。 + 端末を縦向きまたは横向きに平らな場所へ置いて水平になった状態で校正を選択します。\n\n設定を初期値に戻すにはリセットを選択します。\n\nキャンセルするには戻るボタンを押します。 + 校正 + リセット + 加速度センサーを校正しました + 加速度センサーを初期値に戻しました + + DRO + + 仰角/俯角を線で表示する + 仰角/俯角を水平な線で表示します + 方角を線で表示する + 方角を線で表示します + ビデオサブタイトル + 日付情報と時刻情報、もしGPSが有効であればGPS情報も格納されたサブタイトル(.SRT)が作成されます。\n%s + 制限なし 3秒 5秒 @@ -273,19 +379,156 @@ 30分 45分 1時間 + + シャッターボタンを表示する + 撮影と録画のボタンを表示します。他の方法で撮影したい場合はチェックを外します(シャッター専用ボタンが付いている、音量ボタンを使用するなど) + + 撮影中… + + リスニングの初期化に失敗しました + HDR画像の作成に失敗しました + + オート + 曇り + 太陽光 + 蛍光灯 + 白熱電球 + 日陰 + トワイライト + 温白色 + マニュアル + + アクション + バーコード + 砂浜 + ろうそく + オート + 花火 + 風景 + 夜景 + 人物(夜) + パーティー + 人物 + 雪景色 + スポーツ + 夕焼け + シアター + + 水中 + 黒板 + モノクロ + 反転 + なし + ポスタリゼーション + セピア + ソラリゼーション + ホワイトボード + + 新着情報: + 寄付 + + + 人の顔 + 人の顔 + が画面の左側にあります + が画面の右側にあります + が画面の上部にあります + が画面の下部にあります + が画面の中央にあります + デフォルト + カスタムEXIFタグ + アーティスト + EXIFデータ内の\"Artist\"タグに記録されます。(JPEG形式のみ)(使用しない場合は空にします) + 著作権表記 + EXIFデータ内の\"Copyright\"タグに記録されます。(JPEG形式のみ)(使用しない場合は空にします) + + 処理中…あと + デフォルト 年-月-日 日/月/年 月/日/年 なし - オフ - 自動 - オン - 懐中電灯 + HS撮影枚数 + 2枚 + 3枚 + 4枚 + 5枚 + 6枚 + 8枚 + 10枚 + 12枚 + 15枚 + 20枚 + + BKT撮影枚数 + 2枚 + 3枚 + 4枚 + 5枚 + 6枚 + 8枚 + 10枚 + 12枚 + 15枚 + 20枚 + 25枚 + 30枚 + 40枚 + 50枚 + 100枚 + 150枚 + 200枚 + + タイムラプス + なし + + 発光禁止 + 自動発光 + 強制発光 + 常時発光 赤目軽減 + 画面発光 自動 + 画面発光 オン + 画面発光 常時 + + フリッカー軽減 + 照明器具のフリッカー(ちらつき)を軽減します。\n%s + 自動 + 50Hz(東日本) + 60Hz(西日本) + オフ + + ゴーストを表示 + 撮影の位置合わせを容易にするために画像を重ねて表示します。\n%s + 表示しない + 最後に撮った写真を使用 + 選択された画像を使用 + + この端末にはファイル選択ダイアログが無いため、ゴーストの表示には非対応です + この画像は開けません + + ビデオ撮影中の写真撮影 + ビデオ撮影中の写真撮影を許可します。もし端末の Camera2 API の録画が不安定な場合はこの設定を無効にしてください。 + + ビデオのフラットプロファイル(Log) + ビデオのフラットプロファイル(Log)を有効にします\n%s + オフ + ファイン + + + + 最強 + + ビデオカメラ + 外部マイク(接続されている場合) + デフォルトのオーディオソース + 通話用に最適化 + 音声認識用に最適化 + 音声処理を行わない デフォルト 100kbps @@ -311,23 +554,71 @@ 80Mbps 90Mbps 100Mbps + 150Mbps + 200Mbps + + オーディオレベルを表示する + 動画撮影中にオーディオレベルを表示します + + フォーカスBKT + フォーカスブラケット + + フォーカスブラケット 手前側距離 + フォーカスブラケット 奥側距離 + + 無限遠を追加 + + コンパスの向き + 端末のコンパス精度を改善するためにキャリブレーションが必要です。これは端末を8の字に動かすことで実行できます。\n\n現在の精度: + + 距離の単位 + スタンプとビデオサブタイトルのGPS高度に使用されます。\n%s + メートル + フィート + ft + + お知らせを表示する + このアプリが更新された時に新機能や改良点のお知らせを表示する + + 輪郭強調アルゴリズム + カメラが輪郭強調に使用するアルゴリズムを選択します。輪郭強調は写真の精細さを向上させます。(この設定はNR撮影時は無視されます)\n%s + + プロセッシング設定… + + ノイズリダクションアルゴリズム + カメラがノイズリダクションに使用するアルゴリズムを選択します。ノイズリダクションは特に暗い場所での撮影時に発生する多くのノイズを除去することで写真の品質を向上させます。(これはNR撮影モードとは独立しています。この設定はNR撮影モードでは無視されます。)\n%s + デフォルト + オフ + 最小限 + 高速 + 高品質 + + フォーカス補助 + マニュアルフォーカス操作中に画面を拡大表示します\n%s + オフ + 2倍 + 4倍 + + 前の値に変更 + 次の値に変更 なし - 2倍 - 3倍 - 4倍 - 5倍 - 10倍 - 20倍 - 30倍 - 40倍 - 50倍 - 100倍 - 200倍 - 500倍 + 2枚 + 3枚 + 4枚 + 5枚 + 10枚 + 20枚 + 30枚 + 40枚 + 50枚 + 100枚 + 200枚 + 500枚 無制限 なし + 0.5秒 1秒 2秒 3秒 @@ -345,27 +636,230 @@ 1時間 2時間 + 端末のデフォルト + 100MB + 200MB + 300MB + 500MB + 1GB + 2GB + 5GB + 9GB + なし - 1.00 (1対1) - 1.25 (5対4) - 1.33 (4対3) - 1.4 (7対4) - 1.5 (3対2) - 1.78 (16対9) - 1.85 (37対20) - 2.00 (2対1) - 2.33 (21対9) - 2.35 (47対20) - 2.4 (12対5) + 1 (1:1) + 1.25 (5:4) + 1.33 (4:3) + 1.4 (7:4) + 1.5 (3:2) + 1.78 (16:9) + 1.85 (37:20) + 2 (2:1) + 2.33 (21:9) + 2.35 (47:20) + 2.4 (12:5) + + +3 (高感度) + +2 + +1 + 0 (初期値) + -1 + -2 + -3 (低感度) + + HDRコントラスト強調 + HDR撮影時にコントラスト強調アルゴリズムを使用します。大きな輝度差があるようなシーンでの見た目を改善し、いわゆる「HDRルック」な写真が撮影されます。\n%s + オフ + スマート + 常時 + + ビデオの保存形式 + ビデオとオーディオの形式\n%s + + デフォルト + MPEG4 H264 + MPEG4 HEVC + 3GPP + WebM (オーディオには非対応) + + 設定マネージャー + + 設定を保存 + Open Camera のすべての設定をファイルに保存します + 保存する設定の名前 + + 設定を復元 + 以前保存した設定を復元します。この操作を行うと現在の全ての設定が上書きされます! + このオプションは以前保存した設定ファイルのうち1つを選択できます。復元するファイルを選択すると現在の設定は全て上書きされます! + + 設定を保存しました + 設定の保存に失敗しました + 設定の復元に失敗しました + + 写真の保存形式 + JPEG + WebP + PNG + + NRモード + 標準 + ローライト 左利き用 右利き用 + 画面上部 (縦表示時) + + 顔認識アイコンを表示する + 顔認識のオンオフを切り替えるアイコンを表示します + 顔認識を有効にする + 顔認識を無効にする + 顔認識オン + 顔認識オフ + + 傾き補正アイコンを表示する + 傾き補正のオンオフを切り替えるアイコンを表示します。傾き補正を有効にすると写真は水平になるよう自動的に補正されます。 + 傾き補正オン + 傾き補正オフ + + スタンプアイコンを表示する + スタンプのオンオフを切り替えるアイコンを表示します + スタンプを有効にする + スタンプを無効にする + スタンプ オン + スタンプ オフ + + カスタムテキストスタンプアイコンを表示する + カスタムテキストスタンプを入力するためのアイコンを表示します + + ホワイトバランス固定アイコンを表示する + ホワイトバランスを固定/固定解除するアイコンを表示します + ホワイトバランスを固定する + ホワイトバランスの固定を解除する + ホワイトバランスを固定しました + ホワイトバランスの固定を解除しました + + 露出固定アイコンを表示する + 露出を固定/固定解除するアイコンを表示します + 露出の固定を解除する + + ローライトモード: 端末をしっかりと押さえてください + + パノラマ + パノラマ - 影付き文字 + Bluetooth LE リモートコントロール… + Bluetooth LE リモートコントロールを有効にする + Bluetooth LE (BLE) リモートコントロールデバイスを有効にする + リモートデバイスタイプ + + BLE をサポートしていません。 + BLE デバイススキャン + Bluetooth をサポートしていません。 + 不明なデバイス + 接続先から切断された場合は画面を暗くする + ヒント: Open Camera の起動時にデフォルトの輝度を最小輝度に設定します。 + 深度計算のために海水を使用する + 水中ハウジングの場合、正しい水のタイプを選択すると精度が向上します。 + 接続されています + + 住所の使用 + + もし可能であればGPS座標だけでなく住所も表示する。 + 住所を優先して表示する(取得できない場合はGPS座標) + 住所を表示しない + + 位置情報記録アイコンを表示する + 位置情報記録のオンオフを切り替えるアイコンを表示します(ジオタギング) + 位置情報を記録する + 位置情報を記録しない + + ヒストグラムを表示 + 色のヒストグラムを表示します。\n%s + オフ + RGB表示 + 輝度(RGBの加重平均) + Value(RGBのうち最大値) + Intensity(RGBの平均) + Lightness(RGBのうち最大値と最小値の平均) + + ゼブラ模様を表示 + このオプションを有効にすると、露出オーバーになっている部分に縞模様が表示されます。\n%s + Off + 70% + 80% + 90% + 100% + + フォーカスピーキング + このオプションを有効にするとピントの合った輪郭部分がハイライト表示されます。 これは主にマニュアルフォーカス時どこにピントが合っているのか判断するのに役立ちます。\n%s + オフ + オン + フォーカスピーキングの色 + ピントの合った輪郭部分のハイライト色を設定します\n%s + + + + プレビュー画面設定… + + フラッシュ切替 + フラッシュアイコンを表示する + フラッシュの切り替えをするボタンをポップアップメニューの代わりに表示します + + 現在の接続先: + スキャン + + 文字を縁取りする 普通の文字 + 文字の背景を少し暗くする + + パノラマ撮影を終了する + パノラマ撮影をキャンセルする + + パノラマ 自動切り抜き + パノラマ撮影時、波打っている端の部分を切り落とします\n%s + + パノラマ撮影をする場合、端末を縦に構えて撮影ボタンを押します。そして白い円が青い点と重なるように端末を左または右に動かします。新しく撮影されるたび青い点と重なるよう端末を回転させ続けます。\n\n保存するにはチェックマーク、キャンセルするには×マークを押します。\n\n注意:パノラマ撮影は処理と保存に時間がかかります。 + + パノラマ 元画像保存 + パノラマ撮影時、元の画像を保存します。注意:パノラマ写真の保存には時間がかかります。問題を報告するのに役立つXMLファイルを保存することもできます。\n%s + + 元画像を保存しない + 元画像を保存する + 元画像とデバッグ用XMLを保存する + + ID + + 露出補正値変更 + + 写真を保存する形式を指定します。これはRAW以外の写真に適用されます。注意:ここで指定可能なPNG形式は品質設定100%%のJPEGから変換されたもので、本当の意味で可逆ではありません。\n%s + + カメラ用API + Camera2 API を使用すると、露出、フォーカス、ホワイトバランス、RAW(対応している場合)が利用可能になります。APIを変更するとアプリは再起動します。\n%s + 従来のカメラ用API + Camera2 API + + 音または音声コマンドに反応して撮影/録画を行います。 + この機能をオンにした場合、画面上に表示されるマイクボタンを使用してリスニングをスタート/ストップします。 + 注意:音声コマンドにはAndroidの音声認識サービスを使用します。このオプションを使用する場合、音声データは + 音声認識のためリモートサーバーへ送信されます。 + \n%s + + もし可能であれば、GPS座標と一緒に住所もスタンプします。 + この機能にはインターネット接続が必要です。 + 注意:住所の使用が有効になっている場合、GPS座標から住所への変換をするため端末の位置情報を含むリクエストが第三者へ送信されます。 + 詳しくはこちら https://developer.android.com/reference/android/location/Geocoder + \n%s + + フォーカスするには画面をタッチ、そして写真を撮るには青いカメラボタンを押します。 + \n\n画面の輝度が最大になるのを無効にする場合は、[設定]->[画面表示設定]->[明るさを常に最大にする]をオフにします。 + Android5以降の端末でSDカードに保存するには、[設定]->[カメラ制御の詳細設定]->[ストレージへのフレームワークを使う]を設定します。 + 詳しくは、[設定]->[オンラインヘルプ]をご覧ください。 + + + リモートデバイスの選択 オフ - スクリーンボタンのみ除外 - GUIを除外 - すべてを除外 + スクリーンボタンのみ隠す + GUIを隠す + すべてを隠す -- GitLab From 754b20bc9ff4688117b78e0358dd96176dd3c639 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 28 Mar 2020 22:15:16 +0000 Subject: [PATCH 204/243] Don't use period in string names, seems to confuse Android lint warnings. --- app/src/main/res/values/arrays.xml | 20 ++++++++++---------- app/src/main/res/values/strings.xml | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 734146c27..29a5ea272 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -574,16 +574,16 @@ jtlog2 - @string/preference_video_profile_gamma_1.6 - @string/preference_video_profile_gamma_1.8 - @string/preference_video_profile_gamma_1.9 - @string/preference_video_profile_gamma_2.0 - @string/preference_video_profile_gamma_2.1 - @string/preference_video_profile_gamma_2.2 - @string/preference_video_profile_gamma_2.3 - @string/preference_video_profile_gamma_2.4 - @string/preference_video_profile_gamma_2.6 - @string/preference_video_profile_gamma_2.8 + @string/preference_video_profile_gamma_1_6 + @string/preference_video_profile_gamma_1_8 + @string/preference_video_profile_gamma_1_9 + @string/preference_video_profile_gamma_2_0 + @string/preference_video_profile_gamma_2_1 + @string/preference_video_profile_gamma_2_2 + @string/preference_video_profile_gamma_2_3 + @string/preference_video_profile_gamma_2_4 + @string/preference_video_profile_gamma_2_6 + @string/preference_video_profile_gamma_2_8 1.6 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 938fa8bbc..7bb546461 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -926,16 +926,16 @@ JTLog2 Video gamma value Gamma value to use for video if video picture profile is set to Gamma\n%s - 1.6 - 1.8 - 1.9 - 2.0 - 2.1 - 2.2 - 2.3 - 2.4 - 2.6 - 2.8 + 1.6 + 1.8 + 1.9 + 2.0 + 2.1 + 2.2 + 2.3 + 2.4 + 2.6 + 2.8 Off Only dim on-screen virtual navigation buttons -- GitLab From bcae916374e7f73028e907480ba44136bcd47ff2 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 30 Mar 2020 23:06:43 +0100 Subject: [PATCH 205/243] Suppress warning about unused repeated parameter. --- .../main/java/net/sourceforge/opencamera/preview/Preview.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index a747e0111..b367eb005 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -4982,7 +4982,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu Log.d(TAG, "takePicturePressed exit"); } - private void takePictureOnTimer(final long timer_delay, boolean repeated) { + private void takePictureOnTimer(final long timer_delay, @SuppressWarnings("unused") boolean repeated) { if( MyDebug.LOG ) { Log.d(TAG, "takePictureOnTimer"); Log.d(TAG, "timer_delay: " + timer_delay); -- GitLab From c22a28e662954114aedad27e51ce4391a2a59f49 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Mon, 30 Mar 2020 23:08:21 +0100 Subject: [PATCH 206/243] Add comments. --- .../sourceforge/opencamera/ImageSaver.java | 4 ++-- .../opencamera/preview/Preview.java | 20 ++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java index e1ce193cc..94a1ce93f 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java +++ b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java @@ -138,7 +138,7 @@ public class ImageSaver extends Thread { ImageFormat image_format; int image_quality; boolean do_auto_stabilise; - final double level_angle; + final double level_angle; // in degrees final List gyro_rotation_matrix; // used for panorama (one 3x3 matrix per jpeg_images entry), otherwise can be null boolean panorama_dir_left_to_right; // used for panorama float camera_view_angle_x; // used for panorama @@ -164,7 +164,7 @@ public class ImageSaver extends Thread { final boolean store_location; final Location location; final boolean store_geo_direction; - final double geo_direction; + final double geo_direction; // in radians final String custom_tag_artist; final String custom_tag_copyright; final int sample_factor; // sampling factor for thumbnail, higher means lower quality diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index b367eb005..56a0229bf 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -223,11 +223,11 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private int current_orientation; // orientation received by onOrientationChanged private int current_rotation; // orientation relative to camera's orientation (used for parameters.setRotation()) private boolean has_level_angle; - private double natural_level_angle; // "level" angle of device, before applying any calibration and without accounting for screen orientation - private double level_angle; // "level" angle of device, including calibration - private double orig_level_angle; // "level" angle of device, including calibration, but without accounting for screen orientation + private double natural_level_angle; // "level" angle of device in degrees, before applying any calibration and without accounting for screen orientation + private double level_angle; // "level" angle of device in degrees, including calibration + private double orig_level_angle; // "level" angle of device in degrees, including calibration, but without accounting for screen orientation private boolean has_pitch_angle; - private double pitch_angle; + private double pitch_angle; // pitch angle of device in degrees // if applicationInterface.allowZoom() returns false, then has_zoom will be false, but camera_controller_supports_zoom // supports whether the camera controller supported zoom @@ -342,7 +342,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu private final float [] cameraRotation = new float[9]; private final float [] deviceInclination = new float[9]; private boolean has_geo_direction; - private final float [] geo_direction = new float[3]; + private final float [] geo_direction = new float[3]; // geo direction in radians private final float [] new_geo_direction = new float[3]; private final DecimalFormat decimal_format_1dp = new DecimalFormat("#.#"); @@ -6490,14 +6490,20 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return this.has_level_angle; } + /** Returns the uncalibrated level angle in degrees. + */ public double getLevelAngleUncalibrated() { return this.natural_level_angle - this.current_orientation; } + /** Returns the level angle in degrees. + */ public double getLevelAngle() { return this.level_angle; } + /** Returns the original level angle in degrees. + */ public double getOrigLevelAngle() { return this.orig_level_angle; } @@ -6506,6 +6512,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return this.has_pitch_angle; } + /** Returns the pitch angle in degrees. + */ public double getPitchAngle() { return this.pitch_angle; } @@ -6593,6 +6601,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu return has_geo_direction; } + /** Returns the geo direction in radians. + */ public double getGeoDirection() { return geo_direction[0]; } -- GitLab From 0ac41e1268a0cf69a41446839c6c605b9a3e1d1a Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 31 Mar 2020 23:26:13 +0100 Subject: [PATCH 207/243] Update Traditional Chinese translation. --- _docs/credits.html | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 661 +++++++++++++++++++-- 2 files changed, 609 insertions(+), 54 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index b9d0b3e99..b50298e78 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -60,7 +60,7 @@
  • Azerbaijani translation by Eldost ( l-dost AT mail DOT ru ).
  • Brazilian tranlation by Kaio Duarte.
  • Chinese Simplified translation by Michael Lu ( yeskky AT gmail DOT com ) and tumuyan ( tumuyan AT gmail DOT com ).
  • -
  • Chinese Traditional translation by You-Cheng Hsieh ( yochenhsieh AT gmail DOT com ).
  • +
  • Chinese Traditional translation by You-Cheng Hsieh ( yochenhsieh AT gmail DOT com ) and Hsiu-Ming Chang.
  • Belarusian translation by Zmicer Turok.
  • Czech translation by Jaroslav Svoboda ( multi DOT flexi AT gmail DOT com , http://jaroslavsvoboda.eu ).
  • French translation by Olivier Seiler ( oseiler AT nebuka DOT net ) and Eric Lassauge ( lassauge AT users DOT sf DOT net ).
  • diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index dbc24f984..83dd367e5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,22 +1,22 @@ - Open Camera - 設定 + Open Camera + 設定 彈出設定 好 (此訊息將不再顯示) - 開啟 - 關閉 + 開啟 + 關閉 - 選擇儲存位置: + 選擇儲存位置: 清除資料夾歷史 清除資料夾歷史? 選擇另一個資料夾 已更改儲存位置到: 已停止錄製影片 - repeats to go - 連結到相機失敗 + 次剩餘重複次數 + 重新連結到相機失敗 錯誤,影片檔可能已經損壞 在您的裝置上不支援 未知錯誤,影片中斷 @@ -41,7 +41,8 @@ 已開始錄製影片 抱歉 儲存照片失敗 - 防手震失敗 + 儲存 RAW 照片失敗 + 自動水平失敗 啟動相機預覽失敗 拍照 拍照失敗 @@ -50,7 +51,7 @@ 沒有可用的相簿程式 螢幕被鎖定\n滑動螢幕來解鎖 已解鎖 - 對不起,防手震在此裝置上\n不支援 + 對不起,自動水平在此裝置上\n不支援 停用音訊 最大持續時間 顏色效果 @@ -62,19 +63,20 @@ 打開相機失敗。 相機可能正被 其它程式使用? + ISO 縮放 可用記憶體 - [鎖定: + [已鎖定: 滑動以解鎖] 在照片上標記失敗 - m + 公尺 相機特效 - 防手震 - 圖像將被旋轉,使它們自動對準(僅照片) (拍照更慢,且可能在記憶體過低的裝置上失敗) + 自動水平 + 圖片將被旋轉,使它們自動對準(僅照片) (拍照更慢,且可能在記憶體過低的裝置上失敗) 套用一個顏色效果 - 套用選定的顏色效果到照片 + 套用選取的顏色效果到照片 套用一個場景模式 為各種場景優化照片 設定白平衡 @@ -82,11 +84,11 @@ 設定 ISO 越高的值意味著對光越敏感(在某些裝置上可能無法作用) 設定曝光補償 - 設為 0 使用預設曝光補償。 + 設為 0 使用預設曝光補償 鎖定照片/影片方向 - 如果設定,裝置的方向將被忽略,且照片/影片的方向將相對於指定的方向。\n%s + 如果設定,裝置的方向將被忽略,且照片/影片的方向將相對於指定的方向\n%s 臉部偵測 - 用臉部偵測代替對焦區。 + 用臉部偵測代替對焦區 相機控制 定時器 @@ -94,31 +96,38 @@ 當定時器倒數或連拍模式延遲時提示 語音倒數計時 定時或連拍模式時使用語音倒數計時 (從 60 秒開始) - 連拍模式 + 連拍模式 連拍模式間隔 更多相機控制… - 快門設定 + 點擊拍照 在預覽畫面按一次或兩次來拍照 拍照後暫停 拍照後暫停螢幕,顯示分享或刪除照片選項 快門聲音 拍照時播放聲音 音量鍵 + 音訊控制選項 + + 音訊控制敏感度 + 音訊(大的聲音)選項的聲音等級敏感度 儲存位置 用來儲存照片/影片檔的資料夾 - 使用 Storage Access Framework - 是否使用 Storage Access Framework 來儲存照片和影片 + 使用 Storage Access Framework + 是否使用 Storage Access Framework 來儲存照片和影片。這個選項應該被啟用來允許儲存到外部 SD 卡。 照片檔名前綴 用於儲存照片檔名的前置字串 影片檔名前綴 用於儲存影片檔名的前置字串 + 檔案名稱的時間格式 鎖定時顯示相機 如果開啟,Open Camera 將在任何鎖定畫面上顯示 (您仍然必須解鎖來存取設定、相簿等) + 啟動時自動對焦 + Open Camera 啟動時是否要自動對焦。如果您有啟動時閃光燈開啟的問題,請停用此選項 錄影時鎖定螢幕 - 當錄製影片時,圖形化使用者介面將被鎖定以防止意外的停止錄影。滑動螢幕以解鎖。注意,如果程式轉到背景或螢幕是空白,影片錄製會停止。 + 當錄製影片時,圖形化使用者介面將被鎖定以防止意外的停止錄影。滑動螢幕以解鎖。注意,如果程式進入背景或螢幕關閉,影片錄製會停止。 旋轉預覽 旋轉預覽選項 (不會影響最終的照片/影片)\n%s - 螢幕GUI… + 螢幕 GUI… 預覽大小 UI 佈局 全螢幕模式 @@ -126,17 +135,17 @@ 在螢幕上顯示目前的相機縮放等級 (當放大時) 顯示縮放 -/+ 控制 顯示縮放控制的 -/+ 按鈕 - 顯示縮放滑條控制 - 顯示縮放控制的滑條 - 顯示 ISO - 顯示目前的 ISO 等級 (需要 Camera2 API) + 顯示縮放滑桿控制 + 顯示縮放控制的滑桿 + 顯示 ISO + 顯示目前的 ISO 等級。在自動閃光模式,閃光符號也會指示閃光燈何時閃光。(需要 Camera2 API。) 顯示可用記憶體 在螢幕上顯示剩餘的裝置儲存空間 顯示角度 在螢幕上顯示目前的裝置角度 顯示角度線 顯示水平線 - 角度標示顏色 + 角度標示顏色 相機接近水平時的標示顏色 顯示羅盤方向 在螢幕上顯示裝置的羅盤方向 @@ -145,15 +154,17 @@ 顯示電池 在螢幕上顯示目前電池電量 顯示格線 - + 格線 顯示裁切輔助 - 裁切輔助顯示一個矩形來表示指定的長寬比看起來如何 - 如果您計畫以後裁切照片/影片為不同的解析度很有用。需要所見即所得拍照模式,或處於錄影模式中。\n%s + 裁切輔助顯示一個矩形來表示指定的長寬比看起來如何 - 如果您計畫以後裁切照片/影片為不同的長寬比很有用。需要所見即所得拍照模式,或處於錄影模式中。\n%s 顯示拍照前提示訊息 是否要在拍照快門前顯示彈出訊息提示 顯示縮圖動畫 當拍照時顯示移動縮圖動畫 + 拍照時顯示邊緣 + 在螢幕上顯示邊緣來表示拍照 保持螢幕常亮 - 如果開啟,當 Open Camera 的主介面啟動時,螢幕將不會關閉。 + 如果開啟,當 Open Camera 的使用者介面啟動時,螢幕將不會關閉。 強制最大亮度 強制螢幕以最大亮度顯示,而不是裝置預設值 @@ -162,16 +173,17 @@ 影片設定… 位置設定… 相機解析度 - 圖像品質 - 設定儲存的照片圖像的圖像品質(建議值是90%%)\n%s + 圖片品質 + 設定儲存的 JPEG 或 WebP 照片的圖片品質(預設值是 90%%)。對於 PNG 圖片格式沒有作用。\n%s + RAW 儲存位置資料 (地理標記) - 在照片/影片中儲存 GPS 位置資料 + 在照片/影片中儲存 GPS 位置資料(對於照片,位置資料只能儲存在 JPEG 和 DNG 格式) 儲存羅盤方向 - 在照片中儲存 GPS 羅盤方向 + 在照片中儲存 GPS 羅盤方向(只有 JPEG 格式) 需要位置資料 如果啟用位置資料,只拍照/錄影如果位置資料可用。 標記照片 - 用日期和時間標記照片;如果啟用了位置/方向資料也標記 GPS 資訊\n%s + 用日期和時間標記照片;如果啟用了位置/方向資料,也標記 GPS 資訊\n%s 日期標記格式 時間標記格式 GPS 標記格式 @@ -181,40 +193,47 @@ 當在照片上標記文字時使用的字型大小 字型顏色 當在照片上標記文字時使用的字型顏色 - 文字風格 - 當在照片上標記文字時使用的字型風格\n%s + 文字樣式 + 當在照片上標記文字時使用的樣式\n%s + 使用背景執行緒 + 是否要在背景執行緒儲存照片(操作較快) 影片解析度 - 強制 4K UHD 影片 (實驗中) + 強制 4K UHD 影片(只能在某些裝置上運作) 為後置相機錄影啟用 3840x2160 解析度 - 僅當您的裝置支援時才能作用,且如果不支援可能當機! - 啟用影片穩定 - 影片穩定減少在預覽和錄影中由於相機移動引起的晃動。 + 啟用影片防震 + 影片防震減少在預覽和錄影中由於相機移動引起的晃動。 影片位元率 (大約) 設定影片的大致位元率 (越高表示越好的品質,但佔用更多磁碟空間;如果位元率不支援可能造成錄影失敗)\n%s - 影片FPS (大約) - 設定影片的 FPS(大約值,不能保證有用,且如果不支援可能造成錄影失敗)\n%s + 影片影格率 (大約) + 設定影片的影格率 (FPS)(大約值,不能保證有用,且如果不支援可能造成錄影失敗)。注意這個設定在慢動作影片會被忽略。\n%s 影片最長持續時間 - 在指定的時間後錄影將停止。\n%s + 在指定的時間後錄影將停止\n%s 在最大持續時間後重啟錄影 - 如果在達到最大持續時間(如果有設定)後影片停止,此選項將使錄影重啟,最多為指定的次數。\n%s + 如果在達到最大持續時間(如果有設定)後影片停止,此選項將使錄影重新開始,最多為指定的次數\n%s + 最大影片檔案大小 + 當到達(大約)最大檔案大小,錄影會停止和/或重新開始(見下面選項)。注意許多 Android 裝置對影片有最大檔案大小(通常約為 2GB 或 4GB),但是這個選項允許設定特定值。注意這個選項無法用於增加裝置內建的最大大小。\n%s + 到達最大檔案大小時重新開始 + 當到達最大檔案大小時,是否要自動重新開始(無論是裝置預設最大檔案大小或使用者指定) 錄音 錄影時錄音 音源 - 麥克風用於錄製音訊\n%s - 音源頻道 + 用於錄製音訊的麥克風\n%s + 音源頻道 指定使用單聲道或立體聲來錄音 (立體聲只支援某些裝置) 錄影時閃光 - 如果啟用,錄影時閃光將開啟/關閉 (在一段距離外可以用來判斷相機仍然在錄製)。 + 如果啟用,錄影時閃光將開啟/關閉 (在一段距離外可以用來判斷相機仍然在錄製) 其他 線上說明 + 在瀏覽器中開啟 Open Camera 網站 捐贈以支援開發 如果您喜歡這個程式,請考慮捐助。您可以透過購買我的“捐助 app”來進行捐助 - 點擊此選項將打開我的捐助 app 頁面。謝謝! 使用 Camera2 API - 啟用 Camera2 API - 提供更多功能,但仍在實驗中 (會造成重新啟動) + 啟用額外的功能,例如手動曝光模式、對焦、白平衡和 RAW(如果裝置支援),但是無法在所有裝置上正確運作 (會造成重新啟動) 關於 應用程式和除錯資訊 - 復原設定 - 重設所有 Open Camera 設定為預設 + 重設設定 + 重設所有 Open Camera 設定為預設值 您確定要重設所有 Open Camera 設定為預設值嗎? 可用 @@ -227,8 +246,12 @@ 曝光鎖定 對焦模式 閃光模式 + 切換到前置相機 + 切換到後置相機 + 切換到影片模式 + 切換到照片模式 刪除上一張照片 - 共用照片 + 分享照片 上層資料夾 新資料夾 @@ -240,6 +263,108 @@ 選擇儲存位置 Storage Access Framework 已取消 + 無法儲存到這個資料夾 + + + 麥克風權限不可用 + 位置權限不可用 + + 開始錄製影片 + 停止錄製影片 + + 最大檔案大小 + MB + GB + + 開始音訊監聽 + 停止音訊監聽 + 說「cheese」 + 發出大的聲音 + + 自動水平會自動旋轉照片,使它們顯得水平。\n\n注意這意味著圖片解析度會較低(因為需要旋轉和裁切)。 + DNG 檔案包含來自相機的全部未壓縮和未處理的資訊。\n\n注意有些圖庫無法識別 DNG 檔案。DNG 圖片可以使用專用編輯器(例如 Snapseed 和 Lightroom)處理。\n\n注意「標記照片」和「自動水平」等處理選項僅適用於非-DNG (JPEG/etc) 圖片 ,不適用於 DNG 圖片。 + HDR 模式在亮度變化範圍大的環境中非常有用。它的工作原理是在不同曝光下拍攝多張照片,並將它們組合在一起以建立最終圖片。\n\n注意 HDR 不適合用於快速移動的場景,而且可能造成顏色較不精確。\n\nHDR 模式拍照比較慢。 + + 不要再次顯示 + + 照片模式 + 標準 + 標準 + HDR + Expo {} + 包圍曝光 + []]] + 快速連拍 + NR + 雜訊抑制 + 照片標記 + HDR 模式儲存所有圖片 + 如果啟用,使用 HDR 模式拍照會儲存三個基本曝光圖片以及最終的 HDR 照片。注意這會使儲存速度變慢,尤其是啟用了「照片標記」或自動水平等選項時。 + + 權限不可用 + 需要權限 + 需要相機權限來啟用相機 + 需要讀/寫儲存空間權限來儲存照片 + 錄製具有音訊的影片和語音控制需要麥克風權限 + 地理標記需要位置權限(在照片和影片中儲存位置資訊)。 + 連線到藍牙低功耗遠端控制裝置也需要位置權限。 + + 除錯選項 + 除錯選項 + 使用替代閃光燈方法 + 如果您的裝置使用 Camera2 API 時閃光燈有異常,請啟用此功能 + + 包圍曝光 + 包圍曝光的圖片數\n%s + 包圍曝光光圈 (Stops) + 最暗/最亮圖片要減少/增加多少光圈 (Stops)\n%s + + 雜訊抑制原圖 + 是否在雜訊抑制模式中儲存原圖。注意這會讓儲存照片慢很多。\n%s + + 不儲存原圖 + 儲存一張原圖 + 儲存所有原圖(慢) + + + + 沒有足夠的儲存空間錄製影片了 + 停止錄影\n電量嚴重不足 + 電量不足檢查 + 如果電池電量嚴重不足,則停止錄影。這會降低由於電力不足突然關機造成影片損壞的風險。 + + + + 快門速度 + + 相機發生了嚴重錯誤 + + 啟用快速 HDR/expo 連拍 + 允許更快地完成 HDR/expo 拍照。如果您的裝置在使用 HDR/expo 模式拍照時出現了問題,請停用此功能。 + + 相機 + 錄影 + 自拍 + + 前置相機鏡像 + 是否在使用前置相機時反轉左右方向\n%s + + 校正水平角度 + 此選項可以校正裝置的加速計,使自動水平和螢幕顯示的水平/角度正常運作 + 請將您的裝置放在平坦的水平面上(直向或橫向),然後按下「校正」\n\n按下「重置」可以從裝置中刪除校正資料。\n\n按返回按鈕以取消。 + 校正 + 重置 + 水平校正 + 重置水平校正 + + DRO + + 顯示傾斜線 + 顯示水平傾斜線 + 顯示羅盤方向線 + 顯示羅盤方向線 + 影片字幕 + 建立儲存日期和時間的字幕檔案 (.SRT)。如果啟用了位置/方向資料,也會記錄 GPS 資訊\n%s 無限 3 秒 @@ -265,24 +390,171 @@ 30 分 45 分 1 小時 + + 顯示拍照按鈕 + 顯示拍照、錄影按鈕。如果您要使用其他方法拍照(例如硬體快門、使用音量鍵),請取消勾選。 + + 已暫停錄影 + 已繼續錄影 + 暫停錄影 + 繼續錄影 + + 錄影中… + + 初始化音訊監聽失敗 + HDR 照片建立失敗 + + 自動 + 多雲 + 日光 + 螢光燈 + 白熾燈 + 陰翳 + 星光 + 溫暖 + 手動 + + 動作 + 條碼 + 沙灘 + 燭光 + 自動 + 煙火 + 橫向 + 夜晚 + 夜間人像 + 聚會 + 人像 + 雪景 + 運動 + 穩定拍照 + 日落 + 劇院 + + 湖藍 + 黑板 + 黑白 + 負片 + + 色調分離 + 棕褐色 + 過曝 + 白板 + + 新功能: + 捐贈 + + + + + 在螢幕左側 + 在螢幕右側 + 在螢幕頂端 + 在螢幕底端 + 在中央 + + 高速 + 預設 + 自訂 EXIF 標籤 + 藝術家 + 儲存在圖片詮釋資料藝術家標籤的文字(只有 JPEG 格式)。(留空代表不儲存) + 版權 + 儲存在圖片詮釋資料版權標籤的文字(只有 JPEG 格式)。(留空代表不儲存) + + 處理中… + + + 標準和 DNG(RAW) + 僅 DNG(RAW) + 預設 - 年-月-日 + 年-月-日 (ISO 8601) 日/月/年 月/日/年 + 照片數量 + 2 + 3 + 4 + 5 + 6 + 8 + 10 + 12 + 15 + 20 + + 照片數量 + 2 + 3 + 4 + 5 + 6 + 8 + 10 + 12 + 15 + 20 + 25 + 30 + 40 + 50 + 100 + 150 + 200 + + 速度 + 正常 + 啟用慢動作 + 關閉慢動作 + 關閉閃光 自動閃光 開啟閃光 手電筒 紅眼 + 自動螢幕閃光 + 開啟螢幕閃光 + 螢幕手電筒 + + 去除條紋 + 消除燈光閃爍造成的條紋使用的演算法。\n%s + 自動 + 50Hz + 60Hz + 關閉 + + 輔助圖片 + 在取景框內顯示一張半透明的圖片,輔助你對正鏡頭。\n%s + 關閉 + 上次拍攝的照片 + 選擇一張圖片 + + 在裝置上找不到檔案選擇器,所以不能使用輔助圖片功能 + 無法開啟圖片 + + 允許在錄影時拍照 + 允許在錄影時拍照。如果您啟用了 Camera2 API 後發現錄製影片有問題,請停用此功能。 + + 影片 flat (log) profile + 影片模式啟用 flat (log) profile\n%s + 關閉 + 細微 + + + + 超強 + Log profile 攝影機 外部麥克風(如果存在) 預設的音源 優化語音 + 針對語音辨識最佳化 + 未處理 預設 100kbps @@ -308,6 +580,63 @@ 80Mbps 90Mbps 100Mbps + 150Mbps + 200Mbps + + 沒有連拍 + + 顯示音量計 + 錄影時是否在螢幕上顯示音量等級 + + 對焦 {} + 包圍對焦 + + 包圍對焦來源距離 + 包圍對焦目標距離 + + 加入無限遠距離 + + 羅盤方向 + 您裝置的羅盤需要校正以提高準確度。這可以通過以8的形狀的動作移動手機來完成。\n\n目前準確度: + + 不可靠 + + + + 未知 + + 距離單位 + 在照片標記和影片字幕中使用的 GPS 高度的單位\n%s + 公尺 + 英尺 + 英尺 + + 顯示新功能對話框 + 是否在應用程式更新後顯示新功能和改進資訊 + + 邊緣銳化演算法 + 相機驅動程序套用邊緣銳化應該使用的演算法。邊緣銳化可以提高拍攝圖片的銳度和細節。(在 NR 拍照模式下這個設定會被忽略。)\n%s + + 處理設定… + + 雜訊抑制演算法 + 相機驅動程式套用雜訊抑制應該使用的演算法。雜訊抑制演算法會試圖去除相機拍攝的噪點(特別是在黑暗環境),改善圖片品質。(注意這與雜訊抑制照片模式無關,實際上在 NR 照片模式下此設定會被忽略。)\n%s + 預設 + 關閉 + 最小 + 快速 + 高品質 + + 輔助對焦 + 調整手動對焦距離時是否放大顯示\n%s + 關閉 + 2倍 + 4倍 + + 增加或減少曝光補償 + + 上一步 + 下一步 關閉 2x @@ -325,6 +654,7 @@ 無限 無延遲 + 0.5秒 1秒 2秒 3秒 @@ -342,6 +672,18 @@ 1小時 2小時 + 裝置預設值 + 100MB + 200MB + 300MB + 500MB + 1GB + 2GB + 5GB + 9GB + + 取消包圍對焦 + 1 (1:1) 1.25 (5:4) @@ -350,12 +692,225 @@ 1.5 (3:2) 1.78 (16:9) 1.85 (37:20) + 2 (2:1) 2.33 (21:9) 2.35 (47:20) 2.4 (12:5) + +3 (高靈敏度) + +2 + +1 + 0 (預設) + -1 + -2 + -3 (低靈敏度) + + HDR 對比度增強 + HDR 何時使用對比度增強演算法。在動態範圍非常大的場景中能夠提高成像品質。這也會讓照片多出一種 HDR 的味道。\n%s + 關閉 + 自動 + 總是 + + 影片格式 + 影片和音訊檔案格式和編解碼器\n%s + + 預設 + MPEG4 H264 + MPEG4 HEVC + 3GPP + WebM(不支援音訊) + + 設定管理員 + + 儲存設定 + 將所有 Open Camera 的設定儲存在一個檔案中 + 儲存的檔案名稱 + + 還原設定 + 還原之前儲存的設定。注意這會覆寫現在的所有設定值! + 這個選項會讓你選擇一個之前儲存的設定檔案。需要注意選擇載入檔案後會覆寫現在所有的設定! + + 儲存的設定 + 儲存設定失敗 + 還原設定失敗 + 這個裝置沒有可用的檔案對話框,不支援這個選項 + + 圖片格式 + JPEG + WebP + PNG + + 雜訊抑制模式 + 正常 + 低照度 + 左手使用者介面 右手使用者介面 + 圖示在頂部(直向) + + 顯示臉部偵測圖示 + 是否在螢幕上顯示圖示來啟用或停用臉部偵測 + 啟用臉部偵測 + 停用臉部偵測 + 臉部偵測已啟用 + 臉部偵測已停用 + + 顯示自動水平圖示 + 是否在螢幕上顯示圖示來啟用或停用自動水平。當自動水平啟用時,照片會被旋轉,對齊地平線。 + 啟用自動水平 + 停用自動水平 + + 顯示標記照片圖示 + 是否在螢幕上顯示圖示來啟用或停用照片標記 + 啟用照片標記 + 停用照片標記 + 已啟用照片標記 + 已停用照片標記 + + 顯示自訂文字照片標記圖示 + 是否在螢幕上顯示圖示來指定照片標示的自訂文字 + + 顯示自動白平衡鎖定圖示 + 是否在螢幕上顯示圖示來啟用或停用自動白平衡 + 鎖定白平衡 + 解鎖白平衡 + 白平衡已鎖定 + 白平衡已解鎖 + + 顯示自動曝光鎖定圖示 + 是否在螢幕上顯示圖示來鎖定或解鎖曝光 + 解鎖曝光 + + 低照度模式:請保持相機穩定 + + 全景 + 全景 + + 藍牙低功耗遠端控制… + 啟用藍牙低功耗遠端控制 + 啟用藍牙低功耗 (BLE) 遠端控制 + 遠端裝置類型 + + 不支援 BLE + 掃描 BLE 裝置 + 不支援藍牙。 + 未知裝置 + 遠端中斷連線時螢幕變暗 + 提示:啟動 Open Camera 前,請把預設亮度調到最低。 + 使用鹽水計算深度 + 使用水下防水盒時,如果選擇正確的水的類型,可以提高拍攝的準確性。 + 遠端已連線 + + Kraken Smart Housing + + 使用地址 + + 可以的話,除了 GPS 座標之外也顯示地址 + 地址優先於 GPS 座標 + 不顯示地址 + + 顯示儲存位置資訊圖示 + 是否在螢幕上顯示圖示來啟用或停用位置資訊(地理標記) + 儲存位置資訊 + 停止儲存位置資訊 + + 顯示色階分佈圖 + 是否要顯示色彩的色階分佈圖\n%s + 關閉 + RGB 色彩 + 亮度 (Luminance) + 明度 (Value)(最大) + 強度 (Intensity)(平均) + 亮度 (Lightness)(最小-最大的平均) + + 顯示斑馬條紋 + 如果啟用此選項,螢幕上會顯示斑馬條紋,顯示哪裡相機預覽曝光過度。\n%s + 關閉 + 70% + 80% + 90% + 100% + + 峰值對焦 + 如果啟用此選項,會標明對焦的邊緣(輪廓)。這主要用於手動對焦,可用於幫助確定圖片的哪些區域處於焦點。\n%s + 關閉 + 開啟 + 峰值對焦顏色 + 標明對焦的邊緣要使用的顏色\n%s + + 剩餘 + + 相機預覽… + + 循環切換閃光燈 + 顯示閃光燈圖示 + 是否在螢幕上顯示圖示來循環切換閃光燈選項,而不是在彈出式選單顯示閃光燈選項 + + 允許 RAW 包圍曝光 + RAW 選項是否也要適用於包圍曝光照片模式(或啟用了「HDR 模式儲存所有圖片」的 HDR 模式)。如果停用此選項,在那些照片模式中只會儲存 JPEG。 + + 允許 RAW 包圍對焦 + RAW 選項是否也要適用於包圍對焦照片模式。如果停用此選項,在包圍對焦照片模式中只會儲存 JPEG。 + + 循環切換 RAW 模式 + 顯示 RAW 圖示 + 是否在螢幕上顯示圖示來循環切換 RAW 模式 + + 目前遠端: + 掃描 + + 陰影文字 + 普通文字 + 带背景色的文字 + + 正在儲存圖片… + + 完成全景 + 取消全景 + 已取消全景 + 無法建立全景圖片 + + 自動裁剪全景照片 + 在全景模式,是否裁剪照片沒有對齊的邊緣 + + 拍攝全景照片時,請將裝置保持直向。點擊拍照按鈕後,向左或向右旋轉裝置,將居中的白色圓圈移到藍點上。拍攝新圖片後,繼續旋轉裝置以覆蓋依次顯示的每個新藍點。\n\n點擊打勾圖示來儲存全景照片,或者點擊打叉圖示取消全景照片。\n\n注意處理和儲存全景照片需要耗費一些時間。 + + 全景照片原圖 + 在全景模式是否儲存原圖。注意這會耗費更多的時間。也有選項可以儲存有助於回報全景問題的 XML 檔案。\n%s + + 不儲存原圖 + 儲存原圖 + 儲存原圖和除錯 XML + + ID + + 變更曝光補償的搜尋欄 + + 選擇照片的檔案格式。這會影響「標準」(非 RAW)的照片。注意 PNG 格式不是真的無損,而是以 100%% 品質從 JPEG 轉換過來。 + + Camera API + 選擇 Camera2 API 來啟用額外的功能,例如手動曝光模式、對焦、白平衡和 RAW(如果裝置支援)。變更 API 會造成重新啟動\n%s + 原本的 camera API + Camera2 API + + 當偵測到聲音或是或音訊指令時拍照/錄影。 + 當啟用時,使用螢幕上的麥克風按鈕來開始/停止監聽。 + 注意音訊指令選項會使用 Android 語音辨識服務:當使用這個選項時, +音訊資料可能會可能會被傳送到遠端伺服器來進行語音辨識。 + \n%s + + 可以的話,當標記 GPS 位置時使用地址。 + 這個選項需要網路連線。 + 注意如果啟用這個選項,您的裝置需要透過網路將位置資訊到第三方 + 以將 GPS 座標轉換為地址。請參閱 https://developer.android.com/reference/android/location/Geocoder . + \n%s + + 點擊以對焦,按下藍色相機按鈕來拍照。 + \n\n要停用最大螢幕亮度,請到設定/螢幕 GUI/「強制最大亮度」。 + 要在 Android 5+ 儲存到 SD 卡,請到設定/更多相機控制/「使用 Storage Access Framework」。 + 請從設定點選「線上說明」取得更多說明。 + + 選擇遠端裝置 關閉 只隱藏螢幕上的虛擬按鈕 -- GitLab From b78262fc0a2642a8068fa1d8074498772ee0f297 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 3 Apr 2020 22:36:17 +0100 Subject: [PATCH 208/243] Document things only supported for JPEG format. --- _docs/help.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index afedafef4..6ffb54bf8 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -893,10 +893,10 @@ photos will still be as the camera (or other people) view the scene. This option resultant photo, so the resultant photo matches the mirrored image you see on the screen.

    Artist - If text is entered in this setting, then the text will be stored in the image's Exif metadata as the - "Artist" tag. Not supported for RAW photos (DNG format). (Requires Android 7.)

    + "Artist" tag. Only supported for JPEG format. Not supported for RAW photos (DNG format). (Requires Android 7.)

    Copyright - If text is entered in this setting, then the text will be stored in the image's Exif metadata as the - "Copyright" tag. Not supported for RAW photos (DNG format). (Requires Android 7.)

    + "Copyright" tag. Only supported for JPEG format. Not supported for RAW photos (DNG format). (Requires Android 7.)

    Stamp photos - Option to add a date and timestamp to the resultant photos. If "Store location data" is enabled (see "Location settings" below), then the current location latitude @@ -1075,7 +1075,7 @@ location. Location data will also be stored in videos (though only for devices t 3GPP formats).

    Store compass direction - If selected, then photos will be tagged with the compass direction. -Not supported for RAW photos (DNG format) or videos.

    +Only supported for JPEG format. Not supported for RAW photos (DNG format) or videos.

    Require location data - If "Store location data" is enabled, then also enabling this option means that photos and videos can only be taken if location data is present (this can be useful if you need pictures/videos to -- GitLab From ddc3625c2143747f376bcc353cf4ab140c3649a9 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 3 Apr 2020 22:50:59 +0100 Subject: [PATCH 209/243] Fix typo. --- _docs/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 8542b830c..01f6ba410 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -70,7 +70,7 @@ FIXED Focus seekbars overlapped with histogram in widescreen aspect ratio when FIXED Was incorrectly offering manual white balance even if camera didn't support this (inconsistency that the manual white balance option showed, even though the manual white balance temperature seekbar wasn't shown). -FIXED Option on-screen icons (such as flash, RAW) weren't updating correctly if switching to a +FIXED Optional on-screen icons (such as flash, RAW) weren't updating correctly if switching to a camera that didn't support that feature. FIXED Don't show on-screen flash icon in video mode (since this icon doesn't show torch, and flash auto/on not supported in video mode). -- GitLab From 2cb61039d33b882a002b2f5c89783e3497b49059 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 3 Apr 2020 22:52:12 +0100 Subject: [PATCH 210/243] Fix typo. --- _docs/history.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index 01f6ba410..4c5a0e4ac 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -72,8 +72,8 @@ FIXED Was incorrectly offering manual white balance even if camera didn't supp balance temperature seekbar wasn't shown). FIXED Optional on-screen icons (such as flash, RAW) weren't updating correctly if switching to a camera that didn't support that feature. -FIXED Don't show on-screen flash icon in video mode (since this icon doesn't show torch, and flash - auto/on not supported in video mode). +FIXED Don't show on-screen flash icon in video mode (since this icon doesn't support torch, and + flash auto/on not supported in video mode). FIXED Preview texture buffer size (for Camera2 API) could be set incorrectly after changing aspect ratios. FIXED Update on-screen time format more when changing device settings. -- GitLab From de2272da7a3d35d0c830cd6f550a71ba9e6fd716 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 3 Apr 2020 22:52:35 +0100 Subject: [PATCH 211/243] Clarify. --- _docs/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 4c5a0e4ac..35ac83672 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -76,7 +76,7 @@ FIXED Don't show on-screen flash icon in video mode (since this icon doesn't s flash auto/on not supported in video mode). FIXED Preview texture buffer size (for Camera2 API) could be set incorrectly after changing aspect ratios. -FIXED Update on-screen time format more when changing device settings. +FIXED Update on-screen time format more often when changing device settings. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front and back camera; the new icon will instead cycle between the multiple front or back cameras. -- GitLab From 5a2cb6ad5275e936a757c628072f79e009eb09de Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 3 Apr 2020 22:58:16 +0100 Subject: [PATCH 212/243] Fix typo. --- _docs/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/history.html b/_docs/history.html index 35ac83672..b068037ec 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -88,7 +88,7 @@ ADDED Aperture control, for devices that support this. (Camera2 API only.) ADDED Flash on and torch now supported for manual ISO/exposure. ADDED Option to specify REC709 or sRGB profile for video recording. ADDED New custom gamma profile option for video recording. -ADDED New video profiles JJTVideo, JTLog and JTLog2 (thanks to JT Haapala). +ADDED New video profiles JTVideo, JTLog and JTLog2 (thanks to JT Haapala). ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. ADDED Options to control zebra stripe colours. -- GitLab From fd2415ba59f5c22e36313d3732a43565725c5b25 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 3 Apr 2020 22:58:24 +0100 Subject: [PATCH 213/243] Clarify. --- _docs/history.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/history.html b/_docs/history.html index b068037ec..f650f11ba 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -108,8 +108,8 @@ UPDATED Improved performance when displaying ghost image larger than device's re UPDATED Popup menu now displays extra information for resolutions (MP for photos, descriptive name like FullHD, VGA etc for video). UPDATED Don't set video digital stabilization when in photo mode. -UPDATED Disable some preferences if only relevant for another nearby option that isn't currently - enabled. +UPDATED Some preferences are now showed disabled if only relevant for another nearby option that + isn't currently enabled. UPDATED Moved video bitrate and frame rate options to debugging section. UPDATED Improved UI support for "external" cameras (if detected/supported with Camera2 API). UPDATED Improved placement of on-screen text (zoom, video recording time etc) to avoid focus -- GitLab From 8a58df79a4c6e0174941ebcc7b23f9c2dc278f5c Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sun, 5 Apr 2020 14:22:17 +0100 Subject: [PATCH 214/243] Option to storing yaw/pitch/roll in Exif user comment. --- _docs/credits.html | 1 + _docs/help.html | 4 ++ _docs/history.html | 2 + .../sourceforge/opencamera/ImageSaver.java | 37 ++++++++++++++++--- .../opencamera/MagneticSensor.java | 1 + .../opencamera/MyApplicationInterface.java | 17 ++++++++- .../opencamera/MyPreferenceFragment.java | 4 ++ .../opencamera/PreferenceKeys.java | 1 + app/src/main/res/values/strings.xml | 3 ++ app/src/main/res/xml/preferences.xml | 10 ++++- 10 files changed, 71 insertions(+), 9 deletions(-) diff --git a/_docs/credits.html b/_docs/credits.html index b50298e78..82f8745e8 100644 --- a/_docs/credits.html +++ b/_docs/credits.html @@ -54,6 +54,7 @@

  • Support for the video picture profiles implementation and custom Log profiles JTVideo, JTLog and JTLog2 design by JT Haapala.
  • Smart Housing Bluetooth LE support by Edouard Lafargue
  • Improved selfie stick button support by Lau Keat Hwa.
  • +
  • Option to storing yaw/pitch/roll in Exif user comment by Joshua.
  • Option for filenames to be based on UTC (Zulu) time by David Pletcher ( lpm_sourceforge AT cathedralcanyon DOT net , https://www.cathedralcanyon.net ).
  • Support for manual ISO for old camera API on Asus Zenphone 2 Z00A and Z008 by Flávio Keglevich ( fkeglevich AT gmail DOT com ).
  • Changing icons for pause/resume video by Johan Ejdemark ( johanejdemark AT hotmail DOT com).
  • diff --git a/_docs/help.html b/_docs/help.html index 6ffb54bf8..80d8ad630 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -1077,6 +1077,10 @@ location. Location data will also be stored in videos (though only for devices t

    Store compass direction - If selected, then photos will be tagged with the compass direction. Only supported for JPEG format. Not supported for RAW photos (DNG format) or videos.

    +

    Store compass direction - If selected, then photos will be tagged with the device's yaw, pitch and roll. + Note that Exif data does not have direct support for this, instead it will be written as a string in the Exif data's + User Comment for the image. Only supported for JPEG format. Not supported for RAW photos (DNG format) or videos.

    +

    Require location data - If "Store location data" is enabled, then also enabling this option means that photos and videos can only be taken if location data is present (this can be useful if you need pictures/videos to have location data in them).

    diff --git a/_docs/history.html b/_docs/history.html index f650f11ba..a6bd7c41d 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -92,6 +92,8 @@ ADDED New video profiles JTVideo, JTLog and JTLog2 (thanks to JT Haapala). ADDED New option for alpha value to use for ghost image option. ADDED More zebra stripe values 93-99%. ADDED Options to control zebra stripe colours. +ADDED Option for storing device's current yaw/pitch/roll in Exif user comment for photos (thanks + to Joshua). ADDED New option Settings/More camera controls/"Allow long press actions" to disable long press actions. UPDATED Improvements for log profiles for video recording. Please note that this means the behaviour diff --git a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java index 94a1ce93f..5d812f352 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java +++ b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java @@ -165,6 +165,8 @@ public class ImageSaver extends Thread { final Location location; final boolean store_geo_direction; final double geo_direction; // in radians + final boolean store_ypr; // whether to store geo_angle, pitch_angle, level_angle in USER_COMMENT if exif (for JPEGs) + final double pitch_angle; // the pitch that the phone is at, in degrees final String custom_tag_artist; final String custom_tag_copyright; final int sample_factor; // sampling factor for thumbnail, higher means lower quality @@ -190,6 +192,7 @@ public class ImageSaver extends Thread { String preference_stamp, String preference_textstamp, int font_size, int color, String pref_style, String preference_stamp_dateformat, String preference_stamp_timeformat, String preference_stamp_gpsformat, String preference_stamp_geo_address, String preference_units_distance, boolean panorama_crop, boolean store_location, Location location, boolean store_geo_direction, double geo_direction, + double pitch_angle, boolean store_ypr, String custom_tag_artist, String custom_tag_copyright, int sample_factor) { @@ -230,6 +233,8 @@ public class ImageSaver extends Thread { this.location = location; this.store_geo_direction = store_geo_direction; this.geo_direction = geo_direction; + this.pitch_angle = pitch_angle; + this.store_ypr = store_ypr; this.custom_tag_artist = custom_tag_artist; this.custom_tag_copyright = custom_tag_copyright; this.sample_factor = sample_factor; @@ -259,6 +264,7 @@ public class ImageSaver extends Thread { this.zoom_factor, this.preference_stamp, this.preference_textstamp, this.font_size, this.color, this.pref_style, this.preference_stamp_dateformat, this.preference_stamp_timeformat, this.preference_stamp_gpsformat, this.preference_stamp_geo_address, this.preference_units_distance, this.panorama_crop, this.store_location, this.location, this.store_geo_direction, this.geo_direction, + this.pitch_angle, this.store_ypr, this.custom_tag_artist, this.custom_tag_copyright, this.sample_factor); @@ -550,6 +556,7 @@ public class ImageSaver extends Thread { String preference_stamp, String preference_textstamp, int font_size, int color, String pref_style, String preference_stamp_dateformat, String preference_stamp_timeformat, String preference_stamp_gpsformat, String preference_stamp_geo_address, String preference_units_distance, boolean panorama_crop, boolean store_location, Location location, boolean store_geo_direction, double geo_direction, + double pitch_angle, boolean store_ypr, String custom_tag_artist, String custom_tag_copyright, int sample_factor) { @@ -579,6 +586,7 @@ public class ImageSaver extends Thread { zoom_factor, preference_stamp, preference_textstamp, font_size, color, pref_style, preference_stamp_dateformat, preference_stamp_timeformat, preference_stamp_gpsformat, preference_stamp_geo_address, preference_units_distance, panorama_crop, store_location, location, store_geo_direction, geo_direction, + pitch_angle, store_ypr, custom_tag_artist, custom_tag_copyright, sample_factor); @@ -620,6 +628,7 @@ public class ImageSaver extends Thread { 1.0f, null, null, 0, 0, null, null, null, null, null, null, false, false, null, false, 0.0, + 0.0, false, null, null, 1); } @@ -645,6 +654,7 @@ public class ImageSaver extends Thread { String preference_stamp, String preference_textstamp, int font_size, int color, String pref_style, String preference_stamp_dateformat, String preference_stamp_timeformat, String preference_stamp_gpsformat, String preference_stamp_geo_address, String preference_units_distance, boolean panorama_crop, boolean store_location, Location location, boolean store_geo_direction, double geo_direction, + double pitch_angle, boolean store_ypr, String custom_tag_artist, String custom_tag_copyright, int sample_factor) { @@ -672,6 +682,7 @@ public class ImageSaver extends Thread { zoom_factor, preference_stamp, preference_textstamp, font_size, color, pref_style, preference_stamp_dateformat, preference_stamp_timeformat, preference_stamp_gpsformat, preference_stamp_geo_address, preference_units_distance, panorama_crop, store_location, location, store_geo_direction, geo_direction, + pitch_angle, store_ypr, custom_tag_artist, custom_tag_copyright, sample_factor); @@ -751,6 +762,7 @@ public class ImageSaver extends Thread { String preference_stamp, String preference_textstamp, int font_size, int color, String pref_style, String preference_stamp_dateformat, String preference_stamp_timeformat, String preference_stamp_gpsformat, String preference_stamp_geo_address, String preference_units_distance, boolean panorama_crop, boolean store_location, Location location, boolean store_geo_direction, double geo_direction, + double pitch_angle, boolean store_ypr, String custom_tag_artist, String custom_tag_copyright, int sample_factor) { @@ -782,6 +794,7 @@ public class ImageSaver extends Thread { zoom_factor, preference_stamp, preference_textstamp, font_size, color, pref_style, preference_stamp_dateformat, preference_stamp_timeformat, preference_stamp_gpsformat, preference_stamp_geo_address, preference_units_distance, panorama_crop, store_location, location, store_geo_direction, geo_direction, + pitch_angle, store_ypr, custom_tag_artist, custom_tag_copyright, sample_factor); @@ -892,6 +905,7 @@ public class ImageSaver extends Thread { 1.0f, null, null, 0, 0, null, null, null, null, null, null, false, false, null, false, 0.0, + 0.0, false, null, null, 1); if( MyDebug.LOG ) @@ -3051,7 +3065,7 @@ public class ImageSaver extends Thread { exif_new.setAttribute(ExifInterface.TAG_USER_COMMENT, exif_user_comment); } - modifyExif(exif_new, request.type == Request.Type.JPEG, request.using_camera2, request.current_date, request.store_location, request.store_geo_direction, request.geo_direction, request.custom_tag_artist, request.custom_tag_copyright); + modifyExif(exif_new, request.type == Request.Type.JPEG, request.using_camera2, request.current_date, request.store_location, request.store_geo_direction, request.geo_direction, request.custom_tag_artist, request.custom_tag_copyright, request.level_angle, request.pitch_angle, request.store_ypr); setDateTimeExif(exif_new); exif_new.saveAttributes(); } @@ -3323,14 +3337,14 @@ public class ImageSaver extends Thread { private void updateExif(Request request, File picFile, Uri saveUri) throws IOException { if( MyDebug.LOG ) Log.d(TAG, "updateExif: " + picFile); - if( request.store_geo_direction || hasCustomExif(request.custom_tag_artist, request.custom_tag_copyright) ) { + if( request.store_geo_direction || request.store_ypr || hasCustomExif(request.custom_tag_artist, request.custom_tag_copyright) ) { long time_s = System.currentTimeMillis(); if( MyDebug.LOG ) Log.d(TAG, "add additional exif info"); try { ExifInterface exif = createExifInterface(picFile, saveUri); if( exif != null ) { - modifyExif(exif, request.type == Request.Type.JPEG, request.using_camera2, request.current_date, request.store_location, request.store_geo_direction, request.geo_direction, request.custom_tag_artist, request.custom_tag_copyright); + modifyExif(exif, request.type == Request.Type.JPEG, request.using_camera2, request.current_date, request.store_location, request.store_geo_direction, request.geo_direction, request.custom_tag_artist, request.custom_tag_copyright, request.level_angle, request.pitch_angle, request.store_ypr); exif.saveAttributes(); } } @@ -3368,17 +3382,28 @@ public class ImageSaver extends Thread { /** Makes various modifications to the exif data, if necessary. */ - private void modifyExif(ExifInterface exif, boolean is_jpeg, boolean using_camera2, Date current_date, boolean store_location, boolean store_geo_direction, double geo_direction, String custom_tag_artist, String custom_tag_copyright) { + private void modifyExif(ExifInterface exif, boolean is_jpeg, boolean using_camera2, Date current_date, boolean store_location, boolean store_geo_direction, double geo_direction, String custom_tag_artist, String custom_tag_copyright, double level_angle, double pitch_angle, boolean store_ypr) { if( MyDebug.LOG ) Log.d(TAG, "modifyExif"); - setGPSDirectionExif(exif, store_geo_direction, geo_direction); + setGPSDirectionExif(exif, store_geo_direction, geo_direction, level_angle, pitch_angle, store_ypr); + if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && store_ypr ){ + float geo_angle = (float)Math.toDegrees(geo_direction); + if( geo_angle < 0.0f ) { + geo_angle += 360.0f; + } + String encoding = "ASCII\0\0\0"; + //exif.setAttribute(ExifInterface.TAG_USER_COMMENT,"Yaw:" + geo_angle + ",Pitch:" + pitch_angle + ",Roll:" + level_angle); + exif.setAttribute(ExifInterface.TAG_USER_COMMENT,encoding + "Yaw:" + geo_angle + ",Pitch:" + pitch_angle + ",Roll:" + level_angle); + if( MyDebug.LOG ) + Log.d(TAG, "UserComment: " + exif.getAttribute(ExifInterface.TAG_USER_COMMENT)); + } setCustomExif(exif, custom_tag_artist, custom_tag_copyright); if( needGPSTimestampHack(is_jpeg, using_camera2, store_location) ) { fixGPSTimestamp(exif, current_date); } } - private void setGPSDirectionExif(ExifInterface exif, boolean store_geo_direction, double geo_direction) { + private void setGPSDirectionExif(ExifInterface exif, boolean store_geo_direction, double geo_direction, double level_angle, double pitch_angle, boolean store_ypr) { if( MyDebug.LOG ) Log.d(TAG, "setGPSDirectionExif"); if( store_geo_direction ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/MagneticSensor.java b/app/src/main/java/net/sourceforge/opencamera/MagneticSensor.java index 87f7790c2..c2853bd46 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MagneticSensor.java +++ b/app/src/main/java/net/sourceforge/opencamera/MagneticSensor.java @@ -198,6 +198,7 @@ class MagneticSensor { */ private boolean needsMagneticSensor(SharedPreferences sharedPreferences) { if( main_activity.getApplicationInterface().getGeodirectionPref() || + sharedPreferences.getBoolean(PreferenceKeys.AddYPRToComments, false) || sharedPreferences.getBoolean(PreferenceKeys.ShowGeoDirectionLinesPreferenceKey, false) || sharedPreferences.getBoolean(PreferenceKeys.ShowGeoDirectionPreferenceKey, false) ) { return true; diff --git a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java index 3ac3dd834..fa58cc9f1 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyApplicationInterface.java @@ -2927,11 +2927,22 @@ public class MyApplicationInterface extends BasicApplicationInterface { boolean using_camera2 = main_activity.getPreview().usingCamera2API(); ImageSaver.Request.ImageFormat image_format = getImageFormatPref(); + boolean store_ypr = sharedPreferences.getBoolean(PreferenceKeys.AddYPRToComments, false) && + main_activity.getPreview().hasLevelAngle() && + main_activity.getPreview().hasPitchAngle() && + main_activity.getPreview().hasGeoDirection(); + if( MyDebug.LOG ) { + Log.d(TAG, "store_ypr: " + store_ypr); + Log.d(TAG, "has level angle: " + main_activity.getPreview().hasLevelAngle()); + Log.d(TAG, "has pitch angle: " + main_activity.getPreview().hasPitchAngle()); + Log.d(TAG, "has geo direction: " + main_activity.getPreview().hasGeoDirection()); + } int image_quality = getSaveImageQualityPref(); if( MyDebug.LOG ) Log.d(TAG, "image_quality: " + image_quality); boolean do_auto_stabilise = getAutoStabilisePref() && main_activity.getPreview().hasLevelAngleStable(); - double level_angle = do_auto_stabilise ? main_activity.getPreview().getLevelAngle() : 0.0; + double level_angle = (main_activity.getPreview().hasLevelAngle()) ? main_activity.getPreview().getLevelAngle() : 0.0; + double pitch_angle = (main_activity.getPreview().hasPitchAngle()) ? main_activity.getPreview().getPitchAngle() : 0.0; if( do_auto_stabilise && main_activity.test_have_angle ) level_angle = main_activity.test_angle; if( do_auto_stabilise && main_activity.test_low_memory ) @@ -2953,7 +2964,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { boolean store_location = getGeotaggingPref() && getLocation() != null; Location location = store_location ? getLocation() : null; boolean store_geo_direction = main_activity.getPreview().hasGeoDirection() && getGeodirectionPref(); - double geo_direction = store_geo_direction ? main_activity.getPreview().getGeoDirection() : 0.0; + double geo_direction = main_activity.getPreview().hasGeoDirection() ? main_activity.getPreview().getGeoDirection() : 0.0; String custom_tag_artist = sharedPreferences.getString(PreferenceKeys.ExifArtistPreferenceKey, ""); String custom_tag_copyright = sharedPreferences.getString(PreferenceKeys.ExifCopyrightPreferenceKey, ""); String preference_hdr_contrast_enhancement = sharedPreferences.getString(PreferenceKeys.HDRContrastEnhancementPreferenceKey, "preference_hdr_contrast_enhancement_smart"); @@ -3061,6 +3072,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { preference_stamp, preference_textstamp, font_size, color, pref_style, preference_stamp_dateformat, preference_stamp_timeformat, preference_stamp_gpsformat, preference_stamp_geo_address, preference_units_distance, panorama_crop, store_location, location, store_geo_direction, geo_direction, + pitch_angle, store_ypr, custom_tag_artist, custom_tag_copyright, sample_factor); @@ -3103,6 +3115,7 @@ public class MyApplicationInterface extends BasicApplicationInterface { preference_stamp, preference_textstamp, font_size, color, pref_style, preference_stamp_dateformat, preference_stamp_timeformat, preference_stamp_gpsformat, preference_stamp_geo_address, preference_units_distance, false, // panorama doesn't use this codepath store_location, location, store_geo_direction, geo_direction, + pitch_angle, store_ypr, custom_tag_artist, custom_tag_copyright, sample_factor); } diff --git a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java index b4d7d3976..aaf8c35dc 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java +++ b/app/src/main/java/net/sourceforge/opencamera/MyPreferenceFragment.java @@ -646,6 +646,10 @@ public class MyPreferenceFragment extends PreferenceFragment implements OnShared Preference pref = findPreference("preference_category_exif_tags"); PreferenceGroup pg = (PreferenceGroup)this.findPreference("preference_screen_photo_settings"); pg.removePreference(pref); + + pref = findPreference("preference_comment_ypr"); + pg = (PreferenceGroup)this.findPreference("preference_screen_location_settings"); + pg.removePreference(pref); } else { setSummary("preference_exif_artist"); diff --git a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java index 3d87662ee..cc8732db0 100644 --- a/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +++ b/app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java @@ -353,4 +353,5 @@ public class PreferenceKeys { public static final String ShutterSoundPreferenceKey = "preference_shutter_sound"; public static final String ImmersiveModePreferenceKey = "preference_immersive_mode"; + public static final String AddYPRToComments="preference_comment_ypr"; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7bb546461..6f0dff68b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -979,6 +979,9 @@ Frame rate Slow motion + Store yaw, pitch and roll + Store the yaw, pitch and roll of the device in the photo\'s Exif user comment (JPEG format only) + Privacy policy diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 5373f8b50..f3221109d 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1226,7 +1226,15 @@ android:summary="@string/preference_gps_direction_summary" android:defaultValue="false" /> - + + + + Date: Tue, 7 Apr 2020 00:14:28 +0100 Subject: [PATCH 215/243] Explicitly set abortOnError to false. --- app/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/app/build.gradle b/app/build.gradle index 33b771a80..5863fc9fd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,6 +26,7 @@ android { } lintOptions { + abortOnError false checkReleaseBuilds false } -- GitLab From 0aa9dcdcc27cbd9d1222c7b61ce7b35e57bc36e9 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Tue, 7 Apr 2020 23:05:22 +0100 Subject: [PATCH 216/243] Bump version to 75 / 1.48. --- app/src/main/AndroidManifest.xml | 4 ++-- .../sourceforge/opencamera/MainActivity.java | 2 +- app/src/main/res/values/strings.xml | 21 +++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 316bd8911..57780202a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,8 @@ diff --git a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java index 9b64186ac..db94546bb 100644 --- a/app/src/main/java/net/sourceforge/opencamera/MainActivity.java +++ b/app/src/main/java/net/sourceforge/opencamera/MainActivity.java @@ -595,7 +595,7 @@ public class MainActivity extends Activity { // E.g., we have a "What's New" for 1.44 (64), but then push out a quick fix for 1.44.1 (65). We don't want to // show the dialog again to people who already received 1.44 (64), but we still want to show the dialog to people // upgrading from earlier versions. - int whats_new_version = 74; // 1.47.3 + int whats_new_version = 75; // 1.48 whats_new_version = Math.min(whats_new_version, version_code); // whats_new_version should always be <= version_code, but just in case! if( MyDebug.LOG ) { Log.d(TAG, "whats_new_version: " + whats_new_version); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6f0dff68b..94bfb5b52 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1024,13 +1024,22 @@ [This dialog is shown when Open Camera is updated. You can disable it under Settings/On screen GUI/Show What\'s New dialog.] - \n\nv1.47.3:\n + \n\nv1.48:\n
      -
    • Camera2 API option is now a \"list\" selection rather than a toggle switch. This option - should be copied over, but just in case, if you had enabled Camera2 API and Camera2 features - are no longer available, please check Settings/\"Camera API\".\n
    • -
    • Grids were being drawing too faintly.\n
    • -
    • Updated appearance of some icons.\n
    • +
    • New icon for multiple cameras. If your device has multiple front/back cameras, then + the existing icon to switch cameras will switch between front + and back camera; the new icon will instead cycle between the multiple front or back cameras. + If you prefer the old behaviour, disable + Settings/On screen GUI/\"Multiple cameras icon\". (Note, only supported for devices that expose + multiple cameras to third party applications.)\n
    • +
    • Aperture control, for devices that support this. (Camera2 API only.)\n
    • +
    • More custom video profiles.\n
    • +
    • New option for alpha value for ghost image option.\n
    • +
    • Options for zebra stripe colours.\n
    • +
    • Option for storing device\'s current yaw/pitch/roll in Exif user comment.\n
    • +
    • Option to disable long press actions.\n
    • +
    • Better use of full screen with wide aspect ratios on devices with on-screen navigation buttons.\n
    • +
    • Bug fixes and UI improvements.\n
    -- GitLab From 5221b7e1fd5b0c5eaae7e35ebc2167cffb004749 Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Fri, 10 Apr 2020 20:06:10 +0100 Subject: [PATCH 217/243] Auto-level feature now shows on-screen rectangle to show the frame of the resultant photo; also fix auto-level bug where photos could never be full resolution (for angle 0). --- _docs/help.html | 11 +- _docs/history.html | 2 + .../sourceforge/opencamera/ImageSaver.java | 103 +++++++++++------- .../opencamera/preview/Preview.java | 1 + .../opencamera/ui/DrawPreview.java | 50 ++++++++- app/src/main/res/values/strings.xml | 1 + 6 files changed, 127 insertions(+), 41 deletions(-) diff --git a/_docs/help.html b/_docs/help.html index 80d8ad630..f46d54d6f 100644 --- a/_docs/help.html +++ b/_docs/help.html @@ -308,9 +308,14 @@ on devices with low memory. Even where it is available, the performance of takin slower, and there is a risk it may cause the app to fail on devices I haven't been able to test. If you do have problems, you'll have to disable the feature again.

    -

    Also note that the feature reduces the available space in the image - because rotating an image makes it no longer fit into a -rectangular image, so we have to crop it. So it's still advisable to try to hold the camera reasonably level when using this -feature.

    +

    Also note that the feature reduces the available space in the image - because rotating an image + makes it no longer fit into a rectangular image, so we have to crop it. So it's still advisable + to try to hold the camera reasonably level when using this feature. + When auto-level is enabled, an on-screen rectangle will display the frame of the resultant + rotated photo (note that this won't necessarily be 100% accurate depending on device/resolution, + in the same way that normally the preview frame may not perfectly match the resultant photo - + this will especially be true if Settings/Camera preview/"Preview size" is set to + "Maximise preview size".

    Note that auto-stabilising will not occur if the device is pointing up or down.

    diff --git a/_docs/history.html b/_docs/history.html index a6bd7c41d..6a50e41ef 100644 --- a/_docs/history.html +++ b/_docs/history.html @@ -76,6 +76,7 @@ FIXED Don't show on-screen flash icon in video mode (since this icon doesn't s flash auto/on not supported in video mode). FIXED Preview texture buffer size (for Camera2 API) could be set incorrectly after changing aspect ratios. +FIXED Auto-level photos could never be full resolution (for when angle was 0). FIXED Update on-screen time format more often when changing device settings. ADDED New icon for switching between multiple cameras. If your device has multiple front and/or back cameras, then the existing icon to switch cameras will switch between the first front @@ -96,6 +97,7 @@ ADDED Option for storing device's current yaw/pitch/roll in Exif user comment to Joshua). ADDED New option Settings/More camera controls/"Allow long press actions" to disable long press actions. +UPDATED Auto-level feature now shows on-screen rectangle to show the frame of the resultant photo. UPDATED Improvements for log profiles for video recording. Please note that this means the behaviour of these profiles has changed! UPDATED On devices with on-screen navigation buttons, camera preview can now display under these diff --git a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java index 5d812f352..722706653 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java +++ b/app/src/main/java/net/sourceforge/opencamera/ImageSaver.java @@ -1815,6 +1815,67 @@ public class ImageSaver extends Thread { } } + /** Computes the width and height of a centred crop region after having rotated an image. + * @param result - Array of length 2 which will be filled with the returned width and height. + * @param level_angle_rad_abs - Absolute value of angle of rotation, in radians. + * @param w0 - Rotated width. + * @param h0 - Rotated height. + * @param w1 - Original width. + * @param h1 - Original height. + * @param max_width - Maximum width to return. + * @param max_height - Maximum height to return. + * @return - Whether a crop region could be successfully calculated. + */ + public static boolean autoStabiliseCrop(int [] result, double level_angle_rad_abs, double w0, double h0, int w1, int h1, int max_width, int max_height) { + boolean ok = false; + result[0] = 0; + result[1] = 0; + + double tan_theta = Math.tan(level_angle_rad_abs); + double sin_theta = Math.sin(level_angle_rad_abs); + double denom = ( h0/w0 + tan_theta ); + double alt_denom = ( w0/h0 + tan_theta ); + if( denom == 0.0 || denom < 1.0e-14 ) { + if( MyDebug.LOG ) + Log.d(TAG, "zero denominator?!"); + } + else if( alt_denom == 0.0 || alt_denom < 1.0e-14 ) { + if( MyDebug.LOG ) + Log.d(TAG, "zero alt denominator?!"); + } + else { + int w2 = (int)(( h0 + 2.0*h1*sin_theta*tan_theta - w0*tan_theta ) / denom); + int h2 = (int)(w2*h0/w0); + int alt_h2 = (int)(( w0 + 2.0*w1*sin_theta*tan_theta - h0*tan_theta ) / alt_denom); + int alt_w2 = (int)(alt_h2*w0/h0); + if( MyDebug.LOG ) { + //Log.d(TAG, "h0 " + h0 + " 2.0*h1*sin_theta*tan_theta " + 2.0*h1*sin_theta*tan_theta + " w0*tan_theta " + w0*tan_theta + " / h0/w0 " + h0/w0 + " tan_theta " + tan_theta); + Log.d(TAG, "w2 = " + w2 + " , h2 = " + h2); + Log.d(TAG, "alt_w2 = " + alt_w2 + " , alt_h2 = " + alt_h2); + } + if( alt_w2 < w2 ) { + if( MyDebug.LOG ) { + Log.d(TAG, "chose alt!"); + } + w2 = alt_w2; + h2 = alt_h2; + } + if( w2 <= 0 ) + w2 = 1; + else if( w2 > max_width ) + w2 = max_width; + if( h2 <= 0 ) + h2 = 1; + else if( h2 > max_height ) + h2 = max_height; + + ok = true; + result[0] = w2; + result[1] = h2; + } + return ok; + } + /** Performs the auto-stabilise algorithm on the image. * @param data The jpeg data. * @param bitmap Optional argument - the bitmap if already unpacked from the jpeg data. @@ -1911,43 +1972,11 @@ public class ImageSaver extends Thread { Log.d(TAG, "rotated and scaled bitmap size " + bitmap.getWidth() + ", " + bitmap.getHeight()); Log.d(TAG, "rotated and scaled bitmap size: " + bitmap.getWidth()*bitmap.getHeight()*4); } - double tan_theta = Math.tan(level_angle_rad_abs); - double sin_theta = Math.sin(level_angle_rad_abs); - double denom = ( h0/w0 + tan_theta ); - double alt_denom = ( w0/h0 + tan_theta ); - if( denom == 0.0 || denom < 1.0e-14 ) { - if( MyDebug.LOG ) - Log.d(TAG, "zero denominator?!"); - } - else if( alt_denom == 0.0 || alt_denom < 1.0e-14 ) { - if( MyDebug.LOG ) - Log.d(TAG, "zero alt denominator?!"); - } - else { - int w2 = (int)(( h0 + 2.0*h1*sin_theta*tan_theta - w0*tan_theta ) / denom); - int h2 = (int)(w2*h0/w0); - int alt_h2 = (int)(( w0 + 2.0*w1*sin_theta*tan_theta - h0*tan_theta ) / alt_denom); - int alt_w2 = (int)(alt_h2*w0/h0); - if( MyDebug.LOG ) { - //Log.d(TAG, "h0 " + h0 + " 2.0*h1*sin_theta*tan_theta " + 2.0*h1*sin_theta*tan_theta + " w0*tan_theta " + w0*tan_theta + " / h0/w0 " + h0/w0 + " tan_theta " + tan_theta); - Log.d(TAG, "w2 = " + w2 + " , h2 = " + h2); - Log.d(TAG, "alt_w2 = " + alt_w2 + " , alt_h2 = " + alt_h2); - } - if( alt_w2 < w2 ) { - if( MyDebug.LOG ) { - Log.d(TAG, "chose alt!"); - } - w2 = alt_w2; - h2 = alt_h2; - } - if( w2 <= 0 ) - w2 = 1; - else if( w2 >= bitmap.getWidth() ) - w2 = bitmap.getWidth()-1; - if( h2 <= 0 ) - h2 = 1; - else if( h2 >= bitmap.getHeight() ) - h2 = bitmap.getHeight()-1; + + int [] crop = new int [2]; + if( autoStabiliseCrop(crop, level_angle_rad_abs, w0, h0, w1, h1, bitmap.getWidth(), bitmap.getHeight()) ) { + int w2 = crop[0]; + int h2 = crop[1]; int x0 = (bitmap.getWidth()-w2)/2; int y0 = (bitmap.getHeight()-h2)/2; if( MyDebug.LOG ) { diff --git a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java index 56a0229bf..1603122b4 100644 --- a/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +++ b/app/src/main/java/net/sourceforge/opencamera/preview/Preview.java @@ -6444,6 +6444,7 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu if( this.natural_level_angle < -0.0 ) { this.natural_level_angle += 360.0; } + //natural_level_angle = 0.0f; // test zero angle updateLevelAngles(); } diff --git a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java index 6e902c472..c194e6abd 100644 --- a/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java +++ b/app/src/main/java/net/sourceforge/opencamera/ui/DrawPreview.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Locale; import net.sourceforge.opencamera.GyroSensor; +import net.sourceforge.opencamera.ImageSaver; import net.sourceforge.opencamera.LocationSupplier; import net.sourceforge.opencamera.MainActivity; import net.sourceforge.opencamera.MyApplicationInterface; @@ -116,6 +117,7 @@ public class DrawPreview { private final String ybounds_text; private final int [] temp_histogram_channel = new int[256]; private final LocationSupplier.LocationInfo locationInfo = new LocationSupplier.LocationInfo(); + private final int [] auto_stabilise_crop = new int [2]; //private final DecimalFormat decimal_format_1dp_force0 = new DecimalFormat("0.0"); // cached Rects for drawTextWithBackground() calls private Rect text_bounds_time; @@ -2155,7 +2157,10 @@ public class DrawPreview { } else actual_show_angle_line_pref = show_angle_line_pref; - if( camera_controller != null && !preview.isPreviewPaused() && has_level_angle && ( actual_show_angle_line_pref || show_pitch_lines_pref || show_geo_direction_lines_pref ) ) { + + boolean allow_angle_lines = camera_controller != null && !preview.isPreviewPaused(); + + if( allow_angle_lines && has_level_angle && ( actual_show_angle_line_pref || show_pitch_lines_pref || show_geo_direction_lines_pref ) ) { int ui_rotation = preview.getUIRotation(); double level_angle = preview.getLevelAngle(); boolean has_pitch_angle = preview.hasPitchAngle(); @@ -2351,6 +2356,49 @@ public class DrawPreview { canvas.restore(); } + + if( allow_angle_lines && auto_stabilise_pref && preview.hasLevelAngleStable() && !preview.isVideo() ) { + // although auto-level is supported for photos taken in video mode, there's the risk that it's misleading to display + // the guide when in video mode! + double level_angle = preview.getLevelAngle(); + double auto_stabilise_level_angle = level_angle; + //double auto_stabilise_level_angle = angle; + while( auto_stabilise_level_angle < -90 ) + auto_stabilise_level_angle += 180; + while( auto_stabilise_level_angle > 90 ) + auto_stabilise_level_angle -= 180; + double level_angle_rad_abs = Math.abs( Math.toRadians(auto_stabilise_level_angle) ); + + int w1 = canvas.getWidth(); + int h1 = canvas.getHeight(); + double w0 = (w1 * Math.cos(level_angle_rad_abs) + h1 * Math.sin(level_angle_rad_abs)); + double h0 = (w1 * Math.sin(level_angle_rad_abs) + h1 * Math.cos(level_angle_rad_abs)); + + if( ImageSaver.autoStabiliseCrop(auto_stabilise_crop, level_angle_rad_abs, w0, h0, w1, h1, canvas.getWidth(), canvas.getHeight()) ) { + int w2 = auto_stabilise_crop[0]; + int h2 = auto_stabilise_crop[1]; + int cx = canvas.getWidth()/2; + int cy = canvas.getHeight()/2; + + canvas.save(); + canvas.rotate((float)-level_angle, cx, cy); + + if( has_level_angle && Math.abs(level_angle) <= close_level_angle ) { // n.b., use level_angle, not angle or orig_level_angle + p.setColor(angle_highlight_color_pref); + } + else { + p.setColor(Color.WHITE); + } + p.setStyle(Paint.Style.STROKE); + p.setStrokeWidth(stroke_width); + + canvas.drawRect((canvas.getWidth() - w2)/2, (canvas.getHeight() - h2)/2, (canvas.getWidth() + w2)/2, (canvas.getHeight() + h2)/2, p); + + canvas.restore(); + + p.setStyle(Paint.Style.FILL); // reset + } + } } private void doThumbnailAnimation(Canvas canvas, long time_ms) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 94bfb5b52..a3a1d38d5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1032,6 +1032,7 @@ If you prefer the old behaviour, disable Settings/On screen GUI/\"Multiple cameras icon\". (Note, only supported for devices that expose multiple cameras to third party applications.)\n +
  • Auto-level feature now shows on-screen rectangle to show the frame of the resultant photo.\n
  • Aperture control, for devices that support this. (Camera2 API only.)\n
  • More custom video profiles.\n
  • New option for alpha value for ghost image option.\n
  • -- GitLab From f096acaf1a4affc4a3a976544995dd19d4a6510b Mon Sep 17 00:00:00 2001 From: Mark Harman Date: Sat, 11 Apr 2020 14:28:01 +0100 Subject: [PATCH 218/243] Ignore orientation lint errors for now. --- .idea/inspectionProfiles/Project_Default.xml | 2 ++ opencamera_source.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index fbe320a41..ebc9e598e 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,6 +1,8 @@