Merge "Remove renderscript samples."

This commit is contained in:
Elliott Hughes
2022-11-03 15:32:26 +00:00
committed by Gerrit Code Review
73 changed files with 0 additions and 4221 deletions

View File

@@ -174,7 +174,6 @@ developers/build/prebuilts/gradle/AdvancedImmersiveMode/ sam
developers/build/prebuilts/gradle/ImmersiveMode/ samples/${PLATFORM_NAME}/ui/ImmersiveMode developers/build/prebuilts/gradle/ImmersiveMode/ samples/${PLATFORM_NAME}/ui/ImmersiveMode
developers/build/prebuilts/gradle/RepeatingAlarm/ samples/${PLATFORM_NAME}/background/RepeatingAlarm developers/build/prebuilts/gradle/RepeatingAlarm/ samples/${PLATFORM_NAME}/background/RepeatingAlarm
developers/build/prebuilts/gradle/TextLinkify/ samples/${PLATFORM_NAME}/ui/TextLinkify developers/build/prebuilts/gradle/TextLinkify/ samples/${PLATFORM_NAME}/ui/TextLinkify
developers/build/prebuilts/gradle/BasicRenderScript samples/${PLATFORM_NAME}/renderscript/BasicRenderScript
developers/build/prebuilts/gradle/RenderScriptIntrinsic samples/${PLATFORM_NAME}/renderscript/RenderScriptIntrinsic developers/build/prebuilts/gradle/RenderScriptIntrinsic samples/${PLATFORM_NAME}/renderscript/RenderScriptIntrinsic
developers/build/prebuilts/gradle/SlidingTabsBasic samples/${PLATFORM_NAME}/ui/SlidingTabsBasic developers/build/prebuilts/gradle/SlidingTabsBasic samples/${PLATFORM_NAME}/ui/SlidingTabsBasic
developers/build/prebuilts/gradle/SlidingTabsColors samples/${PLATFORM_NAME}/ui/SlidingTabsColors developers/build/prebuilts/gradle/SlidingTabsColors samples/${PLATFORM_NAME}/ui/SlidingTabsColors
@@ -199,7 +198,6 @@ developers/build/prebuilts/gradle/ElevationBasic sam
developers/build/prebuilts/gradle/ElevationDrag samples/${PLATFORM_NAME}/ui/views/Elevation/ElevationDrag developers/build/prebuilts/gradle/ElevationDrag samples/${PLATFORM_NAME}/ui/views/Elevation/ElevationDrag
developers/build/prebuilts/gradle/ClippingBasic samples/${PLATFORM_NAME}/ui/views/Clipping/ClippingBasic developers/build/prebuilts/gradle/ClippingBasic samples/${PLATFORM_NAME}/ui/views/Clipping/ClippingBasic
developers/build/prebuilts/gradle/JobScheduler samples/${PLATFORM_NAME}/background/JobScheduler developers/build/prebuilts/gradle/JobScheduler samples/${PLATFORM_NAME}/background/JobScheduler
developers/build/prebuilts/gradle/HdrViewfinder samples/${PLATFORM_NAME}/media/HdrViewfinder
developers/build/prebuilts/gradle/DocumentCentricApps samples/${PLATFORM_NAME}/ui/activitytasks/DocumentCentricApps developers/build/prebuilts/gradle/DocumentCentricApps samples/${PLATFORM_NAME}/ui/activitytasks/DocumentCentricApps
developers/build/prebuilts/gradle/DocumentCentricRelinquishIdentity samples/${PLATFORM_NAME}/ui/activitytasks/DocumentCentricRelinquishIdentity developers/build/prebuilts/gradle/DocumentCentricRelinquishIdentity samples/${PLATFORM_NAME}/ui/activitytasks/DocumentCentricRelinquishIdentity
developers/build/prebuilts/gradle/AppRestrictionEnforcer samples/${PLATFORM_NAME}/admin/AppRestrictionEnforcer developers/build/prebuilts/gradle/AppRestrictionEnforcer samples/${PLATFORM_NAME}/admin/AppRestrictionEnforcer
@@ -304,7 +302,6 @@ development/samples/WiFiDirectServiceDiscovery samples/${PLATFORM_NAME}/legacy/W
development/samples/Wiktionary samples/${PLATFORM_NAME}/legacy/Wiktionary development/samples/Wiktionary samples/${PLATFORM_NAME}/legacy/Wiktionary
development/samples/WiktionarySimple samples/${PLATFORM_NAME}/legacy/WiktionarySimple development/samples/WiktionarySimple samples/${PLATFORM_NAME}/legacy/WiktionarySimple
development/samples/XmlAdapters samples/${PLATFORM_NAME}/legacy/XmlAdapters development/samples/XmlAdapters samples/${PLATFORM_NAME}/legacy/XmlAdapters
development/samples/RenderScript/HelloCompute samples/${PLATFORM_NAME}/legacy/RenderScript/HelloCompute
# NOTICE files are copied by build/core/Makefile from sdk.git # NOTICE files are copied by build/core/Makefile from sdk.git
development/sdk/sdk_files_NOTICE.txt samples/${PLATFORM_NAME}/NOTICE.txt development/sdk/sdk_files_NOTICE.txt samples/${PLATFORM_NAME}/NOTICE.txt

View File

@@ -1 +0,0 @@
include $(call all-subdir-makefiles)

View File

@@ -1,65 +0,0 @@
//
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package {
// See: http://go/android-license-faq
default_applicable_licenses: ["Android-Apache-2.0"],
}
// This variable is used to match the 'LOCAL_SDK_VERSION' field in the former Android.mk file.
local_sdk_version = "14"
// This variable is used to set the value of the '-target-api' option for the 'llvm-rs-cc' command.
// Note: it may NOT always be the same as the 'local_sdk_version', due to the existing logic in the Make build system.
// For the Android.mk to Android.bp conversion, it is recommend to run the build before and after
// the conversion, to make sure the value of the '-target-api' option to be the same.
target_api_level = local_sdk_version
android_app {
name: "RsHelloCompute",
srcs: [
"src/**/*.java",
":RsHelloCompute-rscript{RsHelloCompute.srcjar}",
],
resource_zips: [
":RsHelloCompute-rscript{RsHelloCompute.res.zip}",
],
sdk_version: local_sdk_version,
}
genrule {
name: "RsHelloCompute-rscript",
srcs: [
"src/**/*.rscript",
":rs_script_api",
":rs_clang_headers",
],
tools: [
"llvm-rs-cc",
"soong_zip",
],
out: [
"RsHelloCompute.srcjar",
"RsHelloCompute.res.zip",
],
cmd: "for f in $(locations src/**/*.rscript); do " +
" $(location llvm-rs-cc) -target-api " + target_api_level +
" -o $(genDir)/res/raw -p $(genDir)/src " +
" -I $$(dirname $$(echo $(locations :rs_script_api) | awk '{ print $$1 }')) " +
" -I $$(dirname $$(echo $(locations :rs_clang_headers) | awk '{ print $$1 }')) $${f}; " +
"done && " +
"$(location soong_zip) -srcjar -o $(location RsHelloCompute.srcjar) -C $(genDir)/src -D $(genDir)/src &&" +
"$(location soong_zip) -o $(location RsHelloCompute.res.zip) -C $(genDir)/res -D $(genDir)/res",
}

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.rs.hellocompute">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk android:minSdkVersion="14" />
<application android:label="RsHelloCompute">
<activity android:name="HelloCompute">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,2 +0,0 @@
<p>A Renderscript compute sample that filters a bitmap. No Renderscript graphics APIs are used
in this sample.</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/displayin"
android:layout_width="320dip"
android:layout_height="266dip" />
<ImageView
android:id="@+id/displayout"
android:layout_width="320dip"
android:layout_height="266dip" />
</LinearLayout>

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.rs.hellocompute;
import android.app.Activity;
import android.os.Bundle;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.renderscript.RenderScript;
import android.renderscript.Allocation;
import android.widget.ImageView;
public class HelloCompute extends Activity {
private Bitmap mBitmapIn;
private Bitmap mBitmapOut;
private RenderScript mRS;
private Allocation mInAllocation;
private Allocation mOutAllocation;
private ScriptC_mono mScript;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBitmapIn = loadBitmap(R.drawable.data);
mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
mBitmapIn.getConfig());
ImageView in = (ImageView) findViewById(R.id.displayin);
in.setImageBitmap(mBitmapIn);
ImageView out = (ImageView) findViewById(R.id.displayout);
out.setImageBitmap(mBitmapOut);
createScript();
}
private void createScript() {
mRS = RenderScript.create(this);
mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
mOutAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
mScript = new ScriptC_mono(mRS);
mScript.forEach_root(mInAllocation, mOutAllocation);
mOutAllocation.copyTo(mBitmapOut);
}
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeResource(getResources(), resource, options);
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma version(1)
#pragma rs java_package_name(com.example.android.rs.hellocompute)
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
void root(const uchar4 *v_in, uchar4 *v_out) {
float4 f4 = rsUnpackColor8888(*v_in);
float3 mono = dot(f4.rgb, gMonoMult);
*v_out = rsPackColorTo8888(mono);
}

View File

@@ -1,56 +0,0 @@
//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package {
// See: http://go/android-license-faq
default_applicable_licenses: ["Android-Apache-2.0"],
}
android_app {
name: "LevelsRS",
srcs: [
"src/**/*.java",
":LevelsRS-rscript{LevelsRS.srcjar}",
],
resource_zips: [
":LevelsRS-rscript{LevelsRS.res.zip}",
],
sdk_version: "current",
}
genrule {
name: "LevelsRS-rscript",
srcs: [
"src/**/*.rscript",
":rs_script_api",
":rs_clang_headers",
],
tools: [
"llvm-rs-cc",
"soong_zip",
],
out: [
"LevelsRS.srcjar",
"LevelsRS.res.zip",
],
cmd: "for f in $(locations src/**/*.rscript); do " +
" $(location llvm-rs-cc) -o $(genDir)/res/raw -p $(genDir)/src " +
" -I $$(dirname $$(echo $(locations :rs_script_api) | awk '{ print $$1 }')) " +
" -I $$(dirname $$(echo $(locations :rs_clang_headers) | awk '{ print $$1 }')) $${f}; " +
"done && " +
"$(location soong_zip) -srcjar -o $(location LevelsRS.srcjar) -C $(genDir)/src -D $(genDir)/src &&" +
"$(location soong_zip) -o $(location LevelsRS.res.zip) -C $(genDir)/res -D $(genDir)/res",
}

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.rs.levels">
<uses-sdk android:minSdkVersion="14" />
<application android:label="Levels RS"
android:hardwareAccelerated="true">
<activity android:name="LevelsRSActivity"
android:label="Levels RS">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="LevelsDalvikActivity"
android:label="Levels Dalvik">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 KiB

View File

@@ -1,140 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/toplevel">
<SurfaceView
android:id="@+id/surface"
android:layout_width="1dip"
android:layout_height="1dip" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/display"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/benchmark"
android:onClick="benchmark"/>
<TextView
android:id="@+id/benchmarkText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:text="@string/saturation"/>
</LinearLayout>
<TextView
android:id="@+id/inSaturationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/saturation"/>
<SeekBar
android:id="@+id/inSaturation"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/outWhiteText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:textSize="8pt"
android:text="@string/out_white"/>
<SeekBar
android:id="@+id/outWhite"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/inWhiteText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/in_white"/>
<SeekBar
android:id="@+id/inWhite"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/outBlackText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/out_black"/>
<SeekBar
android:id="@+id/outBlack"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/inBlackText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/in_black"/>
<SeekBar
android:id="@+id/inBlack"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/inGammaText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/gamma"/>
<SeekBar
android:id="@+id/inGamma"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -1,140 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/toplevel">
<SurfaceView
android:id="@+id/surface"
android:layout_width="1dip"
android:layout_height="1dip" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextureView
android:id="@+id/display"
android:layout_width="800sp"
android:layout_height="423sp" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/benchmark"
android:onClick="benchmark"/>
<TextView
android:id="@+id/benchmarkText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:text="@string/saturation"/>
</LinearLayout>
<TextView
android:id="@+id/inSaturationText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/saturation"/>
<SeekBar
android:id="@+id/inSaturation"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/outWhiteText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:textSize="8pt"
android:text="@string/out_white"/>
<SeekBar
android:id="@+id/outWhite"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/inWhiteText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/in_white"/>
<SeekBar
android:id="@+id/inWhite"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/outBlackText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/out_black"/>
<SeekBar
android:id="@+id/outBlack"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/inBlackText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/in_black"/>
<SeekBar
android:id="@+id/inBlack"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/inGammaText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="8pt"
android:layout_marginLeft="10sp"
android:layout_marginTop="15sp"
android:text="@string/gamma"/>
<SeekBar
android:id="@+id/inGamma"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- General -->
<skip />
<!--slider label -->
<string name="in_white">In White</string>
<string name="out_white">Out White</string>
<string name="in_black">In Black</string>
<string name="out_black">Out Black</string>
<string name="gamma">Gamma</string>
<string name="saturation">Saturation</string>
<string name="benchmark">Benchmark</string>
</resources>

View File

@@ -1,239 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.rs.levels;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.renderscript.Matrix3f;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
public class LevelsDalvikActivity extends Activity
implements SeekBar.OnSeekBarChangeListener {
private final String TAG = "Img";
private Bitmap mBitmapIn;
private Bitmap mBitmapOut;
private float mInBlack = 0.0f;
private SeekBar mInBlackSeekBar;
private float mOutBlack = 0.0f;
private SeekBar mOutBlackSeekBar;
private float mInWhite = 255.0f;
private SeekBar mInWhiteSeekBar;
private float mOutWhite = 255.0f;
private SeekBar mOutWhiteSeekBar;
private float mGamma = 1.0f;
private SeekBar mGammaSeekBar;
private float mSaturation = 1.0f;
private SeekBar mSaturationSeekBar;
private TextView mBenchmarkResult;
private ImageView mDisplayView;
Matrix3f satMatrix = new Matrix3f();
float mInWMinInB;
float mOutWMinOutB;
float mOverInWMinInB;
int mInPixels[];
int mOutPixels[];
private void setLevels() {
mInWMinInB = mInWhite - mInBlack;
mOutWMinOutB = mOutWhite - mOutBlack;
mOverInWMinInB = 1.f / mInWMinInB;
}
private void setSaturation() {
float rWeight = 0.299f;
float gWeight = 0.587f;
float bWeight = 0.114f;
float oneMinusS = 1.0f - mSaturation;
satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
satMatrix.set(0, 1, oneMinusS * rWeight);
satMatrix.set(0, 2, oneMinusS * rWeight);
satMatrix.set(1, 0, oneMinusS * gWeight);
satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
satMatrix.set(1, 2, oneMinusS * gWeight);
satMatrix.set(2, 0, oneMinusS * bWeight);
satMatrix.set(2, 1, oneMinusS * bWeight);
satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
if (seekBar == mInBlackSeekBar) {
mInBlack = (float)progress;
setLevels();
} else if (seekBar == mOutBlackSeekBar) {
mOutBlack = (float)progress;
setLevels();
} else if (seekBar == mInWhiteSeekBar) {
mInWhite = (float)progress + 127.0f;
setLevels();
} else if (seekBar == mOutWhiteSeekBar) {
mOutWhite = (float)progress + 127.0f;
setLevels();
} else if (seekBar == mGammaSeekBar) {
mGamma = (float)progress/100.0f;
mGamma = Math.max(mGamma, 0.1f);
mGamma = 1.0f / mGamma;
} else if (seekBar == mSaturationSeekBar) {
mSaturation = (float)progress / 50.0f;
setSaturation();
}
filter();
mDisplayView.invalidate();
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBitmapIn = loadBitmap(R.drawable.city);
mBitmapOut = loadBitmap(R.drawable.city);
mDisplayView = (ImageView) findViewById(R.id.display);
mDisplayView.setImageBitmap(mBitmapOut);
mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
mInBlackSeekBar.setOnSeekBarChangeListener(this);
mInBlackSeekBar.setMax(128);
mInBlackSeekBar.setProgress(0);
mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
mOutBlackSeekBar.setOnSeekBarChangeListener(this);
mOutBlackSeekBar.setMax(128);
mOutBlackSeekBar.setProgress(0);
mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
mInWhiteSeekBar.setOnSeekBarChangeListener(this);
mInWhiteSeekBar.setMax(128);
mInWhiteSeekBar.setProgress(128);
mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
mOutWhiteSeekBar.setMax(128);
mOutWhiteSeekBar.setProgress(128);
mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
mGammaSeekBar.setOnSeekBarChangeListener(this);
mGammaSeekBar.setMax(150);
mGammaSeekBar.setProgress(100);
mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
mSaturationSeekBar.setOnSeekBarChangeListener(this);
mSaturationSeekBar.setProgress(50);
mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
mBenchmarkResult.setText("Result: not run");
mInPixels = new int[mBitmapIn.getHeight() * mBitmapIn.getWidth()];
mOutPixels = new int[mBitmapOut.getHeight() * mBitmapOut.getWidth()];
mBitmapIn.getPixels(mInPixels, 0, mBitmapIn.getWidth(), 0, 0,
mBitmapIn.getWidth(), mBitmapIn.getHeight());
setLevels();
setSaturation();
filter();
}
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
Canvas c = new Canvas(b2);
c.drawBitmap(b, 0, 0, null);
b.recycle();
return b2;
}
private void filter() {
final float[] m = satMatrix.getArray();
for (int i=0; i < mInPixels.length; i++) {
float r = (float)(mInPixels[i] & 0xff);
float g = (float)((mInPixels[i] >> 8) & 0xff);
float b = (float)((mInPixels[i] >> 16) & 0xff);
float tr = r * m[0] + g * m[3] + b * m[6];
float tg = r * m[1] + g * m[4] + b * m[7];
float tb = r * m[2] + g * m[5] + b * m[8];
r = tr;
g = tg;
b = tb;
if (r < 0.f) r = 0.f;
if (r > 255.f) r = 255.f;
if (g < 0.f) g = 0.f;
if (g > 255.f) g = 255.f;
if (b < 0.f) b = 0.f;
if (b > 255.f) b = 255.f;
r = (r - mInBlack) * mOverInWMinInB;
g = (g - mInBlack) * mOverInWMinInB;
b = (b - mInBlack) * mOverInWMinInB;
if (mGamma != 1.0f) {
r = (float)java.lang.Math.pow(r, mGamma);
g = (float)java.lang.Math.pow(g, mGamma);
b = (float)java.lang.Math.pow(b, mGamma);
}
r = (r * mOutWMinOutB) + mOutBlack;
g = (g * mOutWMinOutB) + mOutBlack;
b = (b * mOutWMinOutB) + mOutBlack;
if (r < 0.f) r = 0.f;
if (r > 255.f) r = 255.f;
if (g < 0.f) g = 0.f;
if (g > 255.f) g = 255.f;
if (b < 0.f) b = 0.f;
if (b > 255.f) b = 255.f;
mOutPixels[i] = ((int)r) + (((int)g) << 8) + (((int)b) << 16)
+ (mInPixels[i] & 0xff000000);
}
mBitmapOut.setPixels(mOutPixels, 0, mBitmapOut.getWidth(), 0, 0,
mBitmapOut.getWidth(), mBitmapOut.getHeight());
}
public void benchmark(View v) {
filter();
long t = java.lang.System.currentTimeMillis();
filter();
t = java.lang.System.currentTimeMillis() - t;
mDisplayView.invalidate();
mBenchmarkResult.setText("Result: " + t + " ms");
}
}

View File

@@ -1,237 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.rs.levels;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import android.renderscript.Allocation;
import android.renderscript.Matrix3f;
import android.renderscript.RenderScript;
import android.util.Log;
import android.view.TextureView;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
public class LevelsRSActivity extends Activity
implements SeekBar.OnSeekBarChangeListener,
TextureView.SurfaceTextureListener
{
private final String TAG = "Img";
private Bitmap mBitmapIn;
private float mInBlack = 0.0f;
private SeekBar mInBlackSeekBar;
private float mOutBlack = 0.0f;
private SeekBar mOutBlackSeekBar;
private float mInWhite = 255.0f;
private SeekBar mInWhiteSeekBar;
private float mOutWhite = 255.0f;
private SeekBar mOutWhiteSeekBar;
private float mGamma = 1.0f;
private SeekBar mGammaSeekBar;
private float mSaturation = 1.0f;
private SeekBar mSaturationSeekBar;
private TextView mBenchmarkResult;
private TextureView mDisplayView;
Matrix3f satMatrix = new Matrix3f();
float mInWMinInB;
float mOutWMinOutB;
float mOverInWMinInB;
private RenderScript mRS;
private Allocation mInPixelsAllocation;
private Allocation mOutPixelsAllocation;
private ScriptC_levels mScript;
private void setLevels() {
mInWMinInB = mInWhite - mInBlack;
mOutWMinOutB = mOutWhite - mOutBlack;
mOverInWMinInB = 1.f / mInWMinInB;
mScript.set_inBlack(mInBlack);
mScript.set_outBlack(mOutBlack);
mScript.set_inWMinInB(mInWMinInB);
mScript.set_outWMinOutB(mOutWMinOutB);
mScript.set_overInWMinInB(mOverInWMinInB);
}
private void setSaturation() {
float rWeight = 0.299f;
float gWeight = 0.587f;
float bWeight = 0.114f;
float oneMinusS = 1.0f - mSaturation;
satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
satMatrix.set(0, 1, oneMinusS * rWeight);
satMatrix.set(0, 2, oneMinusS * rWeight);
satMatrix.set(1, 0, oneMinusS * gWeight);
satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
satMatrix.set(1, 2, oneMinusS * gWeight);
satMatrix.set(2, 0, oneMinusS * bWeight);
satMatrix.set(2, 1, oneMinusS * bWeight);
satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
mScript.set_colorMat(satMatrix);
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
if (seekBar == mInBlackSeekBar) {
mInBlack = (float)progress;
setLevels();
} else if (seekBar == mOutBlackSeekBar) {
mOutBlack = (float)progress;
setLevels();
} else if (seekBar == mInWhiteSeekBar) {
mInWhite = (float)progress + 127.0f;
setLevels();
} else if (seekBar == mOutWhiteSeekBar) {
mOutWhite = (float)progress + 127.0f;
setLevels();
} else if (seekBar == mGammaSeekBar) {
mGamma = (float)progress/100.0f;
mGamma = Math.max(mGamma, 0.1f);
mGamma = 1.0f / mGamma;
mScript.set_gamma(mGamma);
} else if (seekBar == mSaturationSeekBar) {
mSaturation = (float)progress / 50.0f;
setSaturation();
}
filter();
mDisplayView.invalidate();
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rs);
mBitmapIn = loadBitmap(R.drawable.city);
mDisplayView = (TextureView) findViewById(R.id.display);
mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
mInBlackSeekBar.setOnSeekBarChangeListener(this);
mInBlackSeekBar.setMax(128);
mInBlackSeekBar.setProgress(0);
mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
mOutBlackSeekBar.setOnSeekBarChangeListener(this);
mOutBlackSeekBar.setMax(128);
mOutBlackSeekBar.setProgress(0);
mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
mInWhiteSeekBar.setOnSeekBarChangeListener(this);
mInWhiteSeekBar.setMax(128);
mInWhiteSeekBar.setProgress(128);
mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
mOutWhiteSeekBar.setMax(128);
mOutWhiteSeekBar.setProgress(128);
mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
mGammaSeekBar.setOnSeekBarChangeListener(this);
mGammaSeekBar.setMax(150);
mGammaSeekBar.setProgress(100);
mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
mSaturationSeekBar.setOnSeekBarChangeListener(this);
mSaturationSeekBar.setProgress(50);
mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
mBenchmarkResult.setText("Result: not run");
mRS = RenderScript.create(this);
mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
mOutPixelsAllocation = Allocation.createTyped(mRS, mInPixelsAllocation.getType(),
Allocation.USAGE_SCRIPT |
Allocation.USAGE_IO_OUTPUT);
mDisplayView.setSurfaceTextureListener(this);
mScript = new ScriptC_levels(mRS);
mScript.set_gamma(mGamma);
setSaturation();
setLevels();
}
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
Canvas c = new Canvas(b2);
c.drawBitmap(b, 0, 0, null);
b.recycle();
return b2;
}
private void filter() {
mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
mOutPixelsAllocation.ioSend();
mRS.finish();
}
public void benchmark(View v) {
filter();
long t = java.lang.System.currentTimeMillis();
filter();
t = java.lang.System.currentTimeMillis() - t;
mDisplayView.invalidate();
mBenchmarkResult.setText("Result: " + t + " ms");
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if (surface != null) {
mOutPixelsAllocation.setSurface(new Surface(surface));
}
filter();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
if (surface != null) {
mOutPixelsAllocation.setSurface(new Surface(surface));
}
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mOutPixelsAllocation.setSurface(null);
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma version(1)
#pragma rs java_package_name(com.android.rs.levels)
float inBlack;
float outBlack;
float inWMinInB;
float outWMinOutB;
float overInWMinInB;
float gamma;
rs_matrix3x3 colorMat;
void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
float3 pixel = convert_float4(in[0]).rgb;
pixel = rsMatrixMultiply(&colorMat, pixel);
pixel = clamp(pixel, 0.f, 255.f);
pixel = (pixel - inBlack) * overInWMinInB;
if (gamma != 1.0f)
pixel = pow(pixel, (float3)gamma);
pixel = pixel * outWMinOutB + outBlack;
pixel = clamp(pixel, 0.f, 255.f);
out->xyz = convert_uchar3(pixel);
out->w = 0xff;
}

View File

@@ -1 +0,0 @@
<p>A set of samples that demonstrate how to use various features of the Renderscript APIs.</p>

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?><!--
Copyright 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.basicrenderscript"
android:versionCode="1"
android:versionName="1.0">
<!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/FullscreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,12 +0,0 @@
page.tags="BasicRenderScript"
sample.group=RenderScript
@jd:body
<p>
This sample demonstrates using RenderScript to perform basic image manipulation. Specifically, it allows users
to dynamically adjust the saturation for an image using a slider. A custom RenderScript kernel performs the saturation
adjustment, running the computation on the device\'s GPU or other compute hardware as deemed appropriate by the system.
</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,22 +0,0 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:src="@drawable/data" />
<SeekBar
android:id="@+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="16dp" />
</FrameLayout>

View File

@@ -1,24 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Semantic definitions -->
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
</resources>

View File

@@ -1,25 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<style name="Widget.SampleMessage">
<item name="android:textAppearance">?android:textAppearanceLarge</item>
<item name="android:lineSpacingMultiplier">1.2</item>
<item name="android:shadowDy">-6.5</item>
</style>
</resources>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<!-- API 11 theme customizations can go here. -->
</style>
<style name="FullscreenTheme" parent="android:Theme.Holo">
<item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
<item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
<item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
</style>
<style name="FullscreenActionBarStyle" parent="android:Widget.Holo.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
</resources>

View File

@@ -1,22 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Activity themes -->
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
</resources>

View File

@@ -1,12 +0,0 @@
<resources>
<!--
Base application theme for API 14+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- API 14 theme customizations can go here. -->
</style>
</resources>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
</resources>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Activity themes -->
<style name="Theme.Base" parent="android:Theme.Material.Light">
</style>
</resources>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="app_name">BasicRenderScript</string>
<string name="intro_message">
<![CDATA[
This sample demonstrates using RenderScript to perform basic image manipulation. Specifically, it allows users
to dynamically adjust the saturation for an image using a slider. A custom RenderScript kernel performs the saturation
adjustment, running the computation on the device\'s GPU or other compute hardware as deemed appropriate by the system.
]]>
</string>
</resources>

View File

@@ -1,5 +0,0 @@
<resources>
<color name="black_overlay">#66000000</color>
</resources>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FullscreenTheme" parent="android:Theme.NoTitleBar">
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@null</item>
<item name="buttonBarStyle">@style/ButtonBar</item>
<item name="buttonBarButtonStyle">@style/ButtonBarButton</item>
</style>
<style name="ButtonBar">
<item name="android:paddingLeft">2dp</item>
<item name="android:paddingTop">5dp</item>
<item name="android:paddingRight">2dp</item>
<item name="android:paddingBottom">0dp</item>
<item name="android:background">@android:drawable/bottom_bar</item>
</style>
<style name="ButtonBarButton" />
</resources>

View File

@@ -1,32 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
<dimen name="margin_tiny">4dp</dimen>
<dimen name="margin_small">8dp</dimen>
<dimen name="margin_medium">16dp</dimen>
<dimen name="margin_large">32dp</dimen>
<dimen name="margin_huge">64dp</dimen>
<!-- Semantic definitions -->
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
</resources>

View File

@@ -1,42 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Activity themes -->
<style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
<style name="AppTheme" parent="Theme.Sample" />
<!-- Widget styling -->
<style name="Widget" />
<style name="Widget.SampleMessage">
<item name="android:textAppearance">?android:textAppearanceMedium</item>
<item name="android:lineSpacingMultiplier">1.1</item>
</style>
<style name="Widget.SampleMessageTile">
<item name="android:background">@drawable/tile</item>
<item name="android:shadowColor">#7F000000</item>
<item name="android:shadowDy">-3.5</item>
<item name="android:shadowRadius">2</item>
</style>
</resources>

View File

@@ -1,190 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.basicrenderscript;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.support.v8.renderscript.*;
public class MainActivity extends Activity {
/* Number of bitmaps that is used for renderScript thread and UI thread synchronization.
Ideally, this can be reduced to 2, however in some devices, 2 buffers still showing tierings on UI.
Investigating a root cause.
*/
private final int NUM_BITMAPS = 3;
private int mCurrentBitmap = 0;
private Bitmap mBitmapIn;
private Bitmap[] mBitmapsOut;
private ImageView mImageView;
private RenderScript mRS;
private Allocation mInAllocation;
private Allocation[] mOutAllocations;
private ScriptC_saturation mScript;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
/*
* Initialize UI
*/
mBitmapIn = loadBitmap(R.drawable.data);
mBitmapsOut = new Bitmap[NUM_BITMAPS];
for (int i = 0; i < NUM_BITMAPS; ++i) {
mBitmapsOut[i] = Bitmap.createBitmap(mBitmapIn.getWidth(),
mBitmapIn.getHeight(), mBitmapIn.getConfig());
}
mImageView = (ImageView) findViewById(R.id.imageView);
mImageView.setImageBitmap(mBitmapsOut[mCurrentBitmap]);
mCurrentBitmap += (mCurrentBitmap + 1) % NUM_BITMAPS;
SeekBar seekbar = (SeekBar) findViewById(R.id.seekBar1);
seekbar.setProgress(50);
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
float max = 2.0f;
float min = 0.0f;
float f = (float) ((max - min) * (progress / 100.0) + min);
updateImage(f);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
/*
* Create renderScript
*/
createScript();
/*
* Invoke renderScript kernel and update imageView
*/
updateImage(1.0f);
}
/*
* Initialize RenderScript
* In the sample, it creates RenderScript kernel that performs saturation manipulation.
*/
private void createScript() {
//Initialize RS
mRS = RenderScript.create(this);
//Allocate buffers
mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
mOutAllocations = new Allocation[NUM_BITMAPS];
for (int i = 0; i < NUM_BITMAPS; ++i) {
mOutAllocations[i] = Allocation.createFromBitmap(mRS, mBitmapsOut[i]);
}
//Load script
mScript = new ScriptC_saturation(mRS);
}
/*
* In the AsyncTask, it invokes RenderScript intrinsics to do a filtering.
* After the filtering is done, an operation blocks at Allication.copyTo() in AsyncTask thread.
* Once all operation is finished at onPostExecute() in UI thread, it can invalidate and update ImageView UI.
*/
private class RenderScriptTask extends AsyncTask<Float, Integer, Integer> {
Boolean issued = false;
protected Integer doInBackground(Float... values) {
int index = -1;
if (isCancelled() == false) {
issued = true;
index = mCurrentBitmap;
/*
* Set global variable in RS
*/
mScript.set_saturationValue(values[0]);
/*
* Invoke saturation filter kernel
*/
mScript.forEach_saturation(mInAllocation, mOutAllocations[index]);
/*
* Copy to bitmap and invalidate image view
*/
mOutAllocations[index].copyTo(mBitmapsOut[index]);
mCurrentBitmap = (mCurrentBitmap + 1) % NUM_BITMAPS;
}
return index;
}
void updateView(Integer result) {
if (result != -1) {
// Request UI update
mImageView.setImageBitmap(mBitmapsOut[result]);
mImageView.invalidate();
}
}
protected void onPostExecute(Integer result) {
updateView(result);
}
protected void onCancelled(Integer result) {
if (issued) {
updateView(result);
}
}
}
RenderScriptTask currentTask = null;
/*
Invoke AsynchTask and cancel previous task.
When AsyncTasks are piled up (typically in slow device with heavy kernel),
Only the latest (and already started) task invokes RenderScript operation.
*/
private void updateImage(final float f) {
if (currentTask != null)
currentTask.cancel(false);
currentTask = new RenderScriptTask();
currentTask.execute(f);
}
/*
Helper to load Bitmap from resource
*/
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeResource(getResources(), resource, options);
}
}

View File

@@ -1,190 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.media;
import android.annotation.TargetApi;
import android.hardware.Camera;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* Camera related utilities.
*/
public class CameraHelper {
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/**
* Iterate over supported camera video sizes to see which one best fits the
* dimensions of the given view while maintaining the aspect ratio. If none can,
* be lenient with the aspect ratio.
*
* @param supportedVideoSizes Supported camera video sizes.
* @param previewSizes Supported camera preview sizes.
* @param w The width of the view.
* @param h The height of the view.
* @return Best match camera video size to fit in the view.
*/
public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
List<Camera.Size> previewSizes, int w, int h) {
// Use a very small tolerance because we want an exact match.
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
// Supported video sizes list might be null, it means that we are allowed to use the preview
// sizes
List<Camera.Size> videoSizes;
if (supportedVideoSizes != null) {
videoSizes = supportedVideoSizes;
} else {
videoSizes = previewSizes;
}
Camera.Size optimalSize = null;
// Start with max value and refine as we iterate over available video sizes. This is the
// minimum difference between view and camera height.
double minDiff = Double.MAX_VALUE;
// Target view height
int targetHeight = h;
// Try to find a video size that matches aspect ratio and the target view size.
// Iterate over all available sizes and pick the largest size that can fit in the view and
// still maintain the aspect ratio.
for (Camera.Size size : videoSizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find video size that matches the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : videoSizes) {
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
/**
* @return the default camera on the device. Return null if there is no camera on the device.
*/
public static Camera getDefaultCameraInstance() {
return Camera.open();
}
/**
* @return the default rear/back facing camera on the device. Returns null if camera is not
* available.
*/
public static Camera getDefaultBackFacingCameraInstance() {
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
}
/**
* @return the default front facing camera on the device. Returns null if camera is not
* available.
*/
public static Camera getDefaultFrontFacingCameraInstance() {
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
}
/**
*
* @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT
* or Camera.CameraInfo.CAMERA_FACING_BACK.
* @return the default camera on the device. Returns null if camera is not available.
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
private static Camera getDefaultCamera(int position) {
// Find the total number of cameras available
int mNumberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the back-facing ("default") camera
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < mNumberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == position) {
return Camera.open(i);
}
}
return null;
}
/**
* Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory
* is persistent and available to other applications like gallery.
*
* @param type Media type. Can be video or image.
* @return A file object pointing to the newly created file.
*/
public static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {
return null;
}
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CameraSample");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()) {
Log.d("CameraSample", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}

View File

@@ -1,387 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.media;
import android.media.*;
import android.os.Handler;
import android.os.Looper;
import android.view.Surface;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Queue;
/**
* Simplifies the MediaCodec interface by wrapping around the buffer processing operations.
*/
public class MediaCodecWrapper {
// Handler to use for {@code OutputSampleListener} and {code OutputFormatChangedListener}
// callbacks
private Handler mHandler;
// Callback when media output format changes.
public interface OutputFormatChangedListener {
void outputFormatChanged(MediaCodecWrapper sender, MediaFormat newFormat);
}
private OutputFormatChangedListener mOutputFormatChangedListener = null;
/**
* Callback for decodes frames. Observers can register a listener for optional stream
* of decoded data
*/
public interface OutputSampleListener {
void outputSample(MediaCodecWrapper sender, MediaCodec.BufferInfo info, ByteBuffer buffer);
}
/**
* The {@link MediaCodec} that is managed by this class.
*/
private MediaCodec mDecoder;
// References to the internal buffers managed by the codec. The codec
// refers to these buffers by index, never by reference so it's up to us
// to keep track of which buffer is which.
private ByteBuffer[] mInputBuffers;
private ByteBuffer[] mOutputBuffers;
// Indices of the input buffers that are currently available for writing. We'll
// consume these in the order they were dequeued from the codec.
private Queue<Integer> mAvailableInputBuffers;
// Indices of the output buffers that currently hold valid data, in the order
// they were produced by the codec.
private Queue<Integer> mAvailableOutputBuffers;
// Information about each output buffer, by index. Each entry in this array
// is valid if and only if its index is currently contained in mAvailableOutputBuffers.
private MediaCodec.BufferInfo[] mOutputBufferInfo;
// An (optional) stream that will receive decoded data.
private OutputSampleListener mOutputSampleListener;
private MediaCodecWrapper(MediaCodec codec) {
mDecoder = codec;
codec.start();
mInputBuffers = codec.getInputBuffers();
mOutputBuffers = codec.getOutputBuffers();
mOutputBufferInfo = new MediaCodec.BufferInfo[mOutputBuffers.length];
mAvailableInputBuffers = new ArrayDeque<Integer>(mOutputBuffers.length);
mAvailableOutputBuffers = new ArrayDeque<Integer>(mInputBuffers.length);
}
/**
* Releases resources and ends the encoding/decoding session.
*/
public void stopAndRelease() {
mDecoder.stop();
mDecoder.release();
mDecoder = null;
mHandler = null;
}
/**
* Getter for the registered {@link OutputFormatChangedListener}
*/
public OutputFormatChangedListener getOutputFormatChangedListener() {
return mOutputFormatChangedListener;
}
/**
*
* @param outputFormatChangedListener the listener for callback.
* @param handler message handler for posting the callback.
*/
public void setOutputFormatChangedListener(final OutputFormatChangedListener
outputFormatChangedListener, Handler handler) {
mOutputFormatChangedListener = outputFormatChangedListener;
// Making sure we don't block ourselves due to a bad implementation of the callback by
// using a handler provided by client.
Looper looper;
mHandler = handler;
if (outputFormatChangedListener != null && mHandler == null) {
if ((looper = Looper.myLooper()) != null) {
mHandler = new Handler();
} else {
throw new IllegalArgumentException(
"Looper doesn't exist in the calling thread");
}
}
}
/**
* Constructs the {@link MediaCodecWrapper} wrapper object around the video codec.
* The codec is created using the encapsulated information in the
* {@link MediaFormat} object.
*
* @param trackFormat The format of the media object to be decoded.
* @param surface Surface to render the decoded frames.
* @return
*/
public static MediaCodecWrapper fromVideoFormat(final MediaFormat trackFormat,
Surface surface) throws IOException {
MediaCodecWrapper result = null;
MediaCodec videoCodec = null;
// BEGIN_INCLUDE(create_codec)
final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
// Check to see if this is actually a video mime type. If it is, then create
// a codec that can decode this mime type.
if (mimeType.contains("video/")) {
videoCodec = MediaCodec.createDecoderByType(mimeType);
videoCodec.configure(trackFormat, surface, null, 0);
}
// If codec creation was successful, then create a wrapper object around the
// newly created codec.
if (videoCodec != null) {
result = new MediaCodecWrapper(videoCodec);
}
// END_INCLUDE(create_codec)
return result;
}
/**
* Write a media sample to the decoder.
*
* A "sample" here refers to a single atomic access unit in the media stream. The definition
* of "access unit" is dependent on the type of encoding used, but it typically refers to
* a single frame of video or a few seconds of audio. {@link android.media.MediaExtractor}
* extracts data from a stream one sample at a time.
*
* @param input A ByteBuffer containing the input data for one sample. The buffer must be set
* up for reading, with its position set to the beginning of the sample data and its limit
* set to the end of the sample data.
*
* @param presentationTimeUs The time, relative to the beginning of the media stream,
* at which this buffer should be rendered.
*
* @param flags Flags to pass to the decoder. See {@link MediaCodec#queueInputBuffer(int,
* int, int, long, int)}
*
* @throws MediaCodec.CryptoException
*/
public boolean writeSample(final ByteBuffer input,
final MediaCodec.CryptoInfo crypto,
final long presentationTimeUs,
final int flags) throws MediaCodec.CryptoException, WriteException {
boolean result = false;
int size = input.remaining();
// check if we have dequed input buffers available from the codec
if (size > 0 && !mAvailableInputBuffers.isEmpty()) {
int index = mAvailableInputBuffers.remove();
ByteBuffer buffer = mInputBuffers[index];
// we can't write our sample to a lesser capacity input buffer.
if (size > buffer.capacity()) {
throw new MediaCodecWrapper.WriteException(String.format(
"Insufficient capacity in MediaCodec buffer: "
+ "tried to write %d, buffer capacity is %d.",
input.remaining(),
buffer.capacity()));
}
buffer.clear();
buffer.put(input);
// Submit the buffer to the codec for decoding. The presentationTimeUs
// indicates the position (play time) for the current sample.
if (crypto == null) {
mDecoder.queueInputBuffer(index, 0, size, presentationTimeUs, flags);
} else {
mDecoder.queueSecureInputBuffer(index, 0, crypto, presentationTimeUs, flags);
}
result = true;
}
return result;
}
static MediaCodec.CryptoInfo cryptoInfo= new MediaCodec.CryptoInfo();
/**
* Write a media sample to the decoder.
*
* A "sample" here refers to a single atomic access unit in the media stream. The definition
* of "access unit" is dependent on the type of encoding used, but it typically refers to
* a single frame of video or a few seconds of audio. {@link android.media.MediaExtractor}
* extracts data from a stream one sample at a time.
*
* @param extractor Instance of {@link android.media.MediaExtractor} wrapping the media.
*
* @param presentationTimeUs The time, relative to the beginning of the media stream,
* at which this buffer should be rendered.
*
* @param flags Flags to pass to the decoder. See {@link MediaCodec#queueInputBuffer(int,
* int, int, long, int)}
*
* @throws MediaCodec.CryptoException
*/
public boolean writeSample(final MediaExtractor extractor,
final boolean isSecure,
final long presentationTimeUs,
int flags) {
boolean result = false;
boolean isEos = false;
if (!mAvailableInputBuffers.isEmpty()) {
int index = mAvailableInputBuffers.remove();
ByteBuffer buffer = mInputBuffers[index];
// reads the sample from the file using extractor into the buffer
int size = extractor.readSampleData(buffer, 0);
if (size <= 0) {
flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
}
// Submit the buffer to the codec for decoding. The presentationTimeUs
// indicates the position (play time) for the current sample.
if (!isSecure) {
mDecoder.queueInputBuffer(index, 0, size, presentationTimeUs, flags);
} else {
extractor.getSampleCryptoInfo(cryptoInfo);
mDecoder.queueSecureInputBuffer(index, 0, cryptoInfo, presentationTimeUs, flags);
}
result = true;
}
return result;
}
/**
* Performs a peek() operation in the queue to extract media info for the buffer ready to be
* released i.e. the head element of the queue.
*
* @param out_bufferInfo An output var to hold the buffer info.
*
* @return True, if the peek was successful.
*/
public boolean peekSample(MediaCodec.BufferInfo out_bufferInfo) {
// dequeue available buffers and synchronize our data structures with the codec.
update();
boolean result = false;
if (!mAvailableOutputBuffers.isEmpty()) {
int index = mAvailableOutputBuffers.peek();
MediaCodec.BufferInfo info = mOutputBufferInfo[index];
// metadata of the sample
out_bufferInfo.set(
info.offset,
info.size,
info.presentationTimeUs,
info.flags);
result = true;
}
return result;
}
/**
* Processes, releases and optionally renders the output buffer available at the head of the
* queue. All observers are notified with a callback. See {@link
* OutputSampleListener#outputSample(MediaCodecWrapper, android.media.MediaCodec.BufferInfo,
* java.nio.ByteBuffer)}
*
* @param render True, if the buffer is to be rendered on the {@link Surface} configured
*
*/
public void popSample(boolean render) {
// dequeue available buffers and synchronize our data structures with the codec.
update();
if (!mAvailableOutputBuffers.isEmpty()) {
int index = mAvailableOutputBuffers.remove();
if (render && mOutputSampleListener != null) {
ByteBuffer buffer = mOutputBuffers[index];
MediaCodec.BufferInfo info = mOutputBufferInfo[index];
mOutputSampleListener.outputSample(this, info, buffer);
}
// releases the buffer back to the codec
mDecoder.releaseOutputBuffer(index, render);
}
}
/**
* Synchronize this object's state with the internal state of the wrapped
* MediaCodec.
*/
private void update() {
// BEGIN_INCLUDE(update_codec_state)
int index;
// Get valid input buffers from the codec to fill later in the same order they were
// made available by the codec.
while ((index = mDecoder.dequeueInputBuffer(0)) != MediaCodec.INFO_TRY_AGAIN_LATER) {
mAvailableInputBuffers.add(index);
}
// Likewise with output buffers. If the output buffers have changed, start using the
// new set of output buffers. If the output format has changed, notify listeners.
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
while ((index = mDecoder.dequeueOutputBuffer(info, 0)) != MediaCodec.INFO_TRY_AGAIN_LATER) {
switch (index) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
mOutputBuffers = mDecoder.getOutputBuffers();
mOutputBufferInfo = new MediaCodec.BufferInfo[mOutputBuffers.length];
mAvailableOutputBuffers.clear();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
if (mOutputFormatChangedListener != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
mOutputFormatChangedListener
.outputFormatChanged(MediaCodecWrapper.this,
mDecoder.getOutputFormat());
}
});
}
break;
default:
// Making sure the index is valid before adding to output buffers. We've already
// handled INFO_TRY_AGAIN_LATER, INFO_OUTPUT_FORMAT_CHANGED &
// INFO_OUTPUT_BUFFERS_CHANGED i.e all the other possible return codes but
// asserting index value anyways for future-proofing the code.
if(index >= 0) {
mOutputBufferInfo[index] = info;
mAvailableOutputBuffers.add(index);
} else {
throw new IllegalStateException("Unknown status from dequeueOutputBuffer");
}
break;
}
}
// END_INCLUDE(update_codec_state)
}
private class WriteException extends Throwable {
private WriteException(final String detailMessage) {
super(detailMessage);
}
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma version(1)
#pragma rs java_package_name(com.example.android.basicrenderscript)
#pragma rs_fp_relaxed
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
float saturationValue = 0.f;
/*
RenderScript kernel that performs saturation manipulation.
*/
uchar4 __attribute__((kernel)) saturation(uchar4 in)
{
float4 f4 = rsUnpackColor8888(in);
float3 result = dot(f4.rgb, gMonoMult);
result = mix( result, f4.rgb, saturationValue );
return rsPackColorTo8888(result);
}

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest
package="com.example.android.hdrviewfinder"
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0">
<uses-feature android:name="android.hardware.camera"/>
<uses-feature
android:name="android.hardware.camera.front"
android:required="false"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".HdrViewfinderActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,12 +0,0 @@
page.tags="HdrViewfinder"
sample.group=Media
@jd:body
<p>
This demo implements a real-time high-dynamic-range camera viewfinder, by alternating
the sensor\'s exposure time between two exposure values on even and odd frames, and then
compositing together the latest two frames whenever a new frame is captured.
</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,100 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/panels"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="com.example.android.hdrviewfinder.HdrViewfinderActivity">
<com.example.android.hdrviewfinder.FixedAspectSurfaceView
android:id="@+id/preview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="4"
custom:aspectRatio="1.333"/>
<LinearLayout
android:id="@+id/control_bar_contents"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:layout_margin="5dp">
<Button
android:id="@+id/help_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/help_button"/>
<TextView
android:id="@+id/mode_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
tools:text="MODE: HDR"/>
<TextView
android:id="@+id/auto_exposure_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/auto_exposure_label"/>
<TextView
android:id="@+id/auto_exposure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
tools:text="33.33 ms"/>
<TextView
android:id="@+id/even_exposure_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/even_exposure_label"/>
<TextView
android:id="@+id/even_exposure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
tools:text="30.30 ms"/>
<TextView
android:id="@+id/odd_exposure_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/odd_exposure_label"/>
<TextView
android:id="@+id/odd_exposure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
tools:text="30.30 ms"/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/info"
android:icon="@drawable/ic_action_info"
android:showAsAction="always"
android:title="@string/info"/>
</menu>

View File

@@ -1,24 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Semantic definitions -->
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
</resources>

View File

@@ -1,25 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<style name="Widget.SampleMessage">
<item name="android:textAppearance">?android:textAppearanceLarge</item>
<item name="android:lineSpacingMultiplier">1.2</item>
<item name="android:shadowDy">-6.5</item>
</style>
</resources>

View File

@@ -1,22 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Activity themes -->
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
</resources>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
</resources>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Activity themes -->
<style name="Theme.Base" parent="android:Theme.Material.Light">
</style>
</resources>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<declare-styleable name="FixedAspectSurfaceView">
<attr name="aspectRatio" format="float"/>
</declare-styleable>
</resources>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="app_name">HdrViewfinder</string>
<string name="intro_message">
<![CDATA[
This demo implements a real-time high-dynamic-range camera viewfinder, by alternating
the sensor\'s exposure time between two exposure values on even and odd frames, and then
compositing together the latest two frames whenever a new frame is captured.
]]>
</string>
</resources>

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="help_button">Help</string>
<string-array name="mode_label_array">
<!-- must be in same order as ViewfinderProcessor.MODE_ ints -->
<item>Mode: Normal</item>
<item>Mode: Split</item>
<item>Mode: HDR</item>
</string-array>
<string name="auto_exposure_label">Auto exp. time:</string>
<string name="even_exposure_label">Even exp. time:</string>
<string name="odd_exposure_label">Odd exp. time:</string>
<string name="help_text">
<b>HDR Viewfinder Demo:</b>\n\n
Tap viewfinder to switch modes.\n\n
<b>Normal:</b> Standard camera preview\n
<b>Split:</b> Manual exposure control\n
<b>HDR:</b> Fused HDR viewfinder\n\n
Swipe up/down in Split/HDR modes to change manual exposure
values.\n\n
The left half of the viewfinder controls exposure time for
even-numbered frames, and the right half of the viewfinder
controls exposure time for odd-numbered frames
</string>
<string name="info">Info</string>
<string name="camera_permission_rationale">This sample app requires camera access in order to
demo the API.</string>
<string name="camera_no_good">No back-facing sufficiently capable camera available!</string>
<string name="camera_disabled">Camera is disabled by device policy</string>
<string name="camera_disconnected">Camera was disconnected before it was opened</string>
<string name="camera_error">Camera service reported an error</string>
<string name="camera_unknown">Unknown camera error: %s</string>
<string name="camera_permission_denied_explanation">You\'ve denied a permission that the app
needs for core functionality. If you selected &quot;don\'t ask again&quot; in the past then
you need to use Settings to re-enable the permission.</string>
<string name="ok">OK</string>
<string name="settings">Settings</string>
</resources>

View File

@@ -1,32 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
<dimen name="margin_tiny">4dp</dimen>
<dimen name="margin_small">8dp</dimen>
<dimen name="margin_medium">16dp</dimen>
<dimen name="margin_large">32dp</dimen>
<dimen name="margin_huge">64dp</dimen>
<!-- Semantic definitions -->
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
</resources>

View File

@@ -1,42 +0,0 @@
<!--
Copyright 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Activity themes -->
<style name="Theme.Base" parent="android:Theme.Light" />
<style name="Theme.Sample" parent="Theme.Base" />
<style name="AppTheme" parent="Theme.Sample" />
<!-- Widget styling -->
<style name="Widget" />
<style name="Widget.SampleMessage">
<item name="android:textAppearance">?android:textAppearanceMedium</item>
<item name="android:lineSpacingMultiplier">1.1</item>
</style>
<style name="Widget.SampleMessageTile">
<item name="android:background">@drawable/tile</item>
<item name="android:shadowColor">#7F000000</item>
<item name="android:shadowDy">-3.5</item>
<item name="android:shadowRadius">2</item>
</style>
</resources>

View File

@@ -1,284 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.hdrviewfinder;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;
import java.util.List;
/**
* Simple interface for operating the camera, with major camera operations
* all performed on a background handler thread.
*/
public class CameraOps {
private static final String TAG = "CameraOps";
public static final long CAMERA_CLOSE_TIMEOUT = 2000; // ms
private final CameraManager mCameraManager;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCameraSession;
private List<Surface> mSurfaces;
private final ConditionVariable mCloseWaiter = new ConditionVariable();
private HandlerThread mCameraThread;
private Handler mCameraHandler;
private final ErrorDisplayer mErrorDisplayer;
private final CameraReadyListener mReadyListener;
private final Handler mReadyHandler;
/**
* Create a new camera ops thread.
*
* @param errorDisplayer listener for displaying error messages
* @param readyListener listener for notifying when camera is ready for requests
* @param readyHandler the handler for calling readyListener methods on
*/
CameraOps(CameraManager manager, ErrorDisplayer errorDisplayer,
CameraReadyListener readyListener, Handler readyHandler) {
mCameraThread = new HandlerThread("CameraOpsThread");
mCameraThread.start();
if (manager == null || errorDisplayer == null ||
readyListener == null || readyHandler == null) {
throw new IllegalArgumentException("Need valid displayer, listener, handler");
}
mCameraManager = manager;
mErrorDisplayer = errorDisplayer;
mReadyListener = readyListener;
mReadyHandler = readyHandler;
}
/**
* Open the first back-facing camera listed by the camera manager.
* Displays a dialog if it cannot open a camera.
*/
public void openCamera(final String cameraId) {
mCameraHandler = new Handler(mCameraThread.getLooper());
mCameraHandler.post(new Runnable() {
public void run() {
if (mCameraDevice != null) {
throw new IllegalStateException("Camera already open");
}
try {
mCameraManager.openCamera(cameraId, mCameraDeviceListener, mCameraHandler);
} catch (CameraAccessException e) {
String errorMessage = mErrorDisplayer.getErrorString(e);
mErrorDisplayer.showErrorDialog(errorMessage);
}
}
});
}
/**
* Close the camera and wait for the close callback to be called in the camera thread.
* Times out after @{value CAMERA_CLOSE_TIMEOUT} ms.
*/
public void closeCameraAndWait() {
mCloseWaiter.close();
mCameraHandler.post(mCloseCameraRunnable);
boolean closed = mCloseWaiter.block(CAMERA_CLOSE_TIMEOUT);
if (!closed) {
Log.e(TAG, "Timeout closing camera");
}
}
private Runnable mCloseCameraRunnable = new Runnable() {
public void run() {
if (mCameraDevice != null) {
mCameraDevice.close();
}
mCameraDevice = null;
mCameraSession = null;
mSurfaces = null;
}
};
/**
* Set the output Surfaces, and finish configuration if otherwise ready.
*/
public void setSurfaces(final List<Surface> surfaces) {
mCameraHandler.post(new Runnable() {
public void run() {
mSurfaces = surfaces;
startCameraSession();
}
});
}
/**
* Get a request builder for the current camera.
*/
public CaptureRequest.Builder createCaptureRequest(int template) throws CameraAccessException {
CameraDevice device = mCameraDevice;
if (device == null) {
throw new IllegalStateException("Can't get requests when no camera is open");
}
return device.createCaptureRequest(template);
}
/**
* Set a repeating request.
*/
public void setRepeatingRequest(final CaptureRequest request,
final CameraCaptureSession.CaptureCallback listener,
final Handler handler) {
mCameraHandler.post(new Runnable() {
public void run() {
try {
mCameraSession.setRepeatingRequest(request, listener, handler);
} catch (CameraAccessException e) {
String errorMessage = mErrorDisplayer.getErrorString(e);
mErrorDisplayer.showErrorDialog(errorMessage);
}
}
});
}
/**
* Set a repeating request.
*/
public void setRepeatingBurst(final List<CaptureRequest> requests,
final CameraCaptureSession.CaptureCallback listener,
final Handler handler) {
mCameraHandler.post(new Runnable() {
public void run() {
try {
mCameraSession.setRepeatingBurst(requests, listener, handler);
} catch (CameraAccessException e) {
String errorMessage = mErrorDisplayer.getErrorString(e);
mErrorDisplayer.showErrorDialog(errorMessage);
}
}
});
}
/**
* Configure the camera session.
*/
private void startCameraSession() {
// Wait until both the camera device is open and the SurfaceView is ready
if (mCameraDevice == null || mSurfaces == null) return;
try {
mCameraDevice.createCaptureSession(
mSurfaces, mCameraSessionListener, mCameraHandler);
} catch (CameraAccessException e) {
String errorMessage = mErrorDisplayer.getErrorString(e);
mErrorDisplayer.showErrorDialog(errorMessage);
mCameraDevice.close();
mCameraDevice = null;
}
}
/**
* Main listener for camera session events
* Invoked on mCameraThread
*/
private CameraCaptureSession.StateCallback mCameraSessionListener =
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mCameraSession = session;
mReadyHandler.post(new Runnable() {
public void run() {
// This can happen when the screen is turned off and turned back on.
if (null == mCameraDevice) {
return;
}
mReadyListener.onCameraReady();
}
});
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
mErrorDisplayer.showErrorDialog("Unable to configure the capture session");
mCameraDevice.close();
mCameraDevice = null;
}
};
/**
* Main listener for camera device events.
* Invoked on mCameraThread
*/
private CameraDevice.StateCallback mCameraDeviceListener = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
startCameraSession();
}
@Override
public void onClosed(CameraDevice camera) {
mCloseWaiter.open();
}
@Override
public void onDisconnected(CameraDevice camera) {
mErrorDisplayer.showErrorDialog("The camera device has been disconnected.");
camera.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice camera, int error) {
mErrorDisplayer.showErrorDialog("The camera encountered an error:" + error);
camera.close();
mCameraDevice = null;
}
};
/**
* Simple listener for main code to know the camera is ready for requests, or failed to
* start.
*/
public interface CameraReadyListener {
public void onCameraReady();
}
/**
* Simple listener for displaying error messages
*/
public interface ErrorDisplayer {
public void showErrorDialog(String errorMessage);
public String getErrorString(CameraAccessException e);
}
}

View File

@@ -1,156 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.hdrviewfinder;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
/**
* A SurfaceView that maintains its aspect ratio to be a desired target value.
*
* <p>Depending on the layout, the FixedAspectSurfaceView may not be able to maintain the
* requested aspect ratio. This can happen if both the width and the height are exactly
* determined by the layout. To avoid this, ensure that either the height or the width is
* adjustable by the view; for example, by setting the layout parameters to be WRAP_CONTENT for
* the dimension that is best adjusted to maintain the aspect ratio.</p>
*/
public class FixedAspectSurfaceView extends SurfaceView {
/**
* Desired width/height ratio
*/
private float mAspectRatio;
private GestureDetector mGestureDetector;
public FixedAspectSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
// Get initial aspect ratio from custom attributes
TypedArray a =
context.getTheme().obtainStyledAttributes(attrs,
R.styleable.FixedAspectSurfaceView, 0, 0);
setAspectRatio(a.getFloat(
R.styleable.FixedAspectSurfaceView_aspectRatio, 1.f));
a.recycle();
}
/**
* Set the desired aspect ratio for this view.
*
* @param aspect the desired width/height ratio in the current UI orientation. Must be a
* positive value.
*/
public void setAspectRatio(float aspect) {
if (aspect <= 0) {
throw new IllegalArgumentException("Aspect ratio must be positive");
}
mAspectRatio = aspect;
requestLayout();
}
/**
* Set a gesture listener to listen for touch events
*/
public void setGestureListener(Context context, GestureDetector.OnGestureListener listener) {
if (listener == null) {
mGestureDetector = null;
} else {
mGestureDetector = new GestureDetector(context, listener);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
// General goal: Adjust dimensions to maintain the requested aspect ratio as much
// as possible. Depending on the measure specs handed down, this may not be possible
// Only set one of these to true
boolean scaleWidth = false;
boolean scaleHeight = false;
// Sort out which dimension to scale, if either can be. There are 9 combinations of
// possible measure specs; a few cases below handle multiple combinations
if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
// Can't adjust sizes at all, do nothing
} else if (widthMode == MeasureSpec.EXACTLY) {
// Width is fixed, heightMode either AT_MOST or UNSPECIFIED, so adjust height
scaleHeight = true;
} else if (heightMode == MeasureSpec.EXACTLY) {
// Height is fixed, widthMode either AT_MOST or UNSPECIFIED, so adjust width
scaleWidth = true;
} else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
// Need to fit into box <= [width, height] in size.
// Maximize the View's area while maintaining aspect ratio
// This means keeping one dimension as large as possible and shrinking the other
float boxAspectRatio = width / (float) height;
if (boxAspectRatio > mAspectRatio) {
// Box is wider than requested aspect; pillarbox
scaleWidth = true;
} else {
// Box is narrower than requested aspect; letterbox
scaleHeight = true;
}
} else if (widthMode == MeasureSpec.AT_MOST) {
// Maximize width, heightSpec is UNSPECIFIED
scaleHeight = true;
} else if (heightMode == MeasureSpec.AT_MOST) {
// Maximize height, widthSpec is UNSPECIFIED
scaleWidth = true;
} else {
// Both MeasureSpecs are UNSPECIFIED. This is probably a pathological layout,
// with width == height == 0
// but arbitrarily scale height anyway
scaleHeight = true;
}
// Do the scaling
if (scaleWidth) {
width = (int) (height * mAspectRatio);
} else if (scaleHeight) {
height = (int) (width / mAspectRatio);
}
// Override width/height if needed for EXACTLY and AT_MOST specs
width = View.resolveSizeAndState(width, widthMeasureSpec, 0);
height = View.resolveSizeAndState(height, heightMeasureSpec, 0);
// Finally set the calculated dimensions
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mGestureDetector != null) {
return mGestureDetector.onTouchEvent(event);
}
return false;
}
}

View File

@@ -1,667 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.hdrviewfinder;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.renderscript.RenderScript;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.Size;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* A small demo of advanced camera functionality with the Android camera2 API.
*
* <p>This demo implements a real-time high-dynamic-range camera viewfinder,
* by alternating the sensor's exposure time between two exposure values on even and odd
* frames, and then compositing together the latest two frames whenever a new frame is
* captured.</p>
*
* <p>The demo has three modes: Regular auto-exposure viewfinder, split-screen manual exposure,
* and the fused HDR viewfinder. The latter two use manual exposure controlled by the user,
* by swiping up/down on the right and left halves of the viewfinder. The left half controls
* the exposure time of even frames, and the right half controls the exposure time of odd frames.
* </p>
*
* <p>In split-screen mode, the even frames are shown on the left and the odd frames on the right,
* so the user can see two different exposures of the scene simultaneously. In fused HDR mode,
* the even/odd frames are merged together into a single image. By selecting different exposure
* values for the even/odd frames, the fused image has a higher dynamic range than the regular
* viewfinder.</p>
*
* <p>The HDR fusion and the split-screen viewfinder processing is done with RenderScript; as is the
* necessary YUV->RGB conversion. The camera subsystem outputs YUV images naturally, while the GPU
* and display subsystems generally only accept RGB data. Therefore, after the images are
* fused/composited, a standard YUV->RGB color transform is applied before the the data is written
* to the output Allocation. The HDR fusion algorithm is very simple, and tends to result in
* lower-contrast scenes, but has very few artifacts and can run very fast.</p>
*
* <p>Data is passed between the subsystems (camera, RenderScript, and display) using the
* Android {@link android.view.Surface} class, which allows for zero-copy transport of large
* buffers between processes and subsystems.</p>
*/
public class HdrViewfinderActivity extends AppCompatActivity implements
SurfaceHolder.Callback, CameraOps.ErrorDisplayer, CameraOps.CameraReadyListener {
private static final String TAG = "HdrViewfinderDemo";
private static final String FRAGMENT_DIALOG = "dialog";
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
/**
* View for the camera preview.
*/
private FixedAspectSurfaceView mPreviewView;
/**
* Root view of this activity.
*/
private View rootView;
/**
* This shows the current mode of the app.
*/
private TextView mModeText;
// These show lengths of exposure for even frames, exposure for odd frames, and auto exposure.
private TextView mEvenExposureText, mOddExposureText, mAutoExposureText;
private Handler mUiHandler;
private CameraCharacteristics mCameraInfo;
private Surface mPreviewSurface;
private Surface mProcessingHdrSurface;
private Surface mProcessingNormalSurface;
CaptureRequest.Builder mHdrBuilder;
ArrayList<CaptureRequest> mHdrRequests = new ArrayList<CaptureRequest>(2);
CaptureRequest mPreviewRequest;
RenderScript mRS;
ViewfinderProcessor mProcessor;
CameraManager mCameraManager;
CameraOps mCameraOps;
private int mRenderMode = ViewfinderProcessor.MODE_NORMAL;
// Durations in nanoseconds
private static final long MICRO_SECOND = 1000;
private static final long MILLI_SECOND = MICRO_SECOND * 1000;
private static final long ONE_SECOND = MILLI_SECOND * 1000;
private long mOddExposure = ONE_SECOND / 33;
private long mEvenExposure = ONE_SECOND / 33;
private Object mOddExposureTag = new Object();
private Object mEvenExposureTag = new Object();
private Object mAutoExposureTag = new Object();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
rootView = findViewById(R.id.panels);
mPreviewView = (FixedAspectSurfaceView) findViewById(R.id.preview);
mPreviewView.getHolder().addCallback(this);
mPreviewView.setGestureListener(this, mViewListener);
Button helpButton = (Button) findViewById(R.id.help_button);
helpButton.setOnClickListener(mHelpButtonListener);
mModeText = (TextView) findViewById(R.id.mode_label);
mEvenExposureText = (TextView) findViewById(R.id.even_exposure);
mOddExposureText = (TextView) findViewById(R.id.odd_exposure);
mAutoExposureText = (TextView) findViewById(R.id.auto_exposure);
mUiHandler = new Handler(Looper.getMainLooper());
mRS = RenderScript.create(this);
// When permissions are revoked the app is restarted so onCreate is sufficient to check for
// permissions core to the Activity's functionality.
if (!checkCameraPermissions()) {
requestCameraPermissions();
} else {
findAndOpenCamera();
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
// Wait until camera is closed to ensure the next application can open it
if (mCameraOps != null) {
mCameraOps.closeCameraAndWait();
mCameraOps = null;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.info: {
MessageDialogFragment.newInstance(R.string.intro_message)
.show(getFragmentManager(), FRAGMENT_DIALOG);
break;
}
}
return super.onOptionsItemSelected(item);
}
private GestureDetector.OnGestureListener mViewListener
= new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
switchRenderMode(1);
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (mRenderMode == ViewfinderProcessor.MODE_NORMAL) return false;
float xPosition = e1.getAxisValue(MotionEvent.AXIS_X);
float width = mPreviewView.getWidth();
float height = mPreviewView.getHeight();
float xPosNorm = xPosition / width;
float yDistNorm = distanceY / height;
final float ACCELERATION_FACTOR = 8;
double scaleFactor = Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR);
// Even on left, odd on right
if (xPosNorm > 0.5) {
mOddExposure *= scaleFactor;
} else {
mEvenExposure *= scaleFactor;
}
setHdrBurst();
return true;
}
};
/**
* Show help dialogs.
*/
private View.OnClickListener mHelpButtonListener = new View.OnClickListener() {
public void onClick(View v) {
MessageDialogFragment.newInstance(R.string.help_text)
.show(getFragmentManager(), FRAGMENT_DIALOG);
}
};
/**
* Return the current state of the camera permissions.
*/
private boolean checkCameraPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
// Check if the Camera permission is already available.
if (permissionState != PackageManager.PERMISSION_GRANTED) {
// Camera permission has not been granted.
Log.i(TAG, "CAMERA permission has NOT been granted.");
return false;
} else {
// Camera permissions are available.
Log.i(TAG, "CAMERA permission has already been granted.");
return true;
}
}
/**
* Attempt to initialize the camera.
*/
private void initializeCamera() {
mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
if (mCameraManager != null) {
mCameraOps = new CameraOps(mCameraManager,
/*errorDisplayer*/ this,
/*readyListener*/ this,
/*readyHandler*/ mUiHandler);
mHdrRequests.add(null);
mHdrRequests.add(null);
} else {
Log.e(TAG, "Couldn't initialize the camera");
}
}
private void requestCameraPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA);
// Provide an additional rationale to the user. This would happen if the user denied the
// request previously, but didn't check the "Don't ask again" checkbox.
if (shouldProvideRationale) {
Log.i(TAG, "Displaying camera permission rationale to provide additional context.");
Snackbar.make(rootView, R.string.camera_permission_rationale, Snackbar
.LENGTH_INDEFINITE)
.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Request Camera permission
ActivityCompat.requestPermissions(HdrViewfinderActivity.this,
new String[]{Manifest.permission.CAMERA},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
})
.show();
} else {
Log.i(TAG, "Requesting camera permission");
// Request Camera permission. It's possible this can be auto answered if device policy
// sets the permission in a given state or the user denied the permission
// previously and checked "Never ask again".
ActivityCompat.requestPermissions(HdrViewfinderActivity.this,
new String[]{Manifest.permission.CAMERA},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
}
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission was granted.
findAndOpenCamera();
} else {
// Permission denied.
// In this Activity we've chosen to notify the user that they
// have rejected a core permission for the app since it makes the Activity useless.
// We're communicating this message in a Snackbar since this is a sample app, but
// core permissions would typically be best requested during a welcome-screen flow.
// Additionally, it is important to remember that a permission might have been
// rejected without asking the user for permission (device policy or "Never ask
// again" prompts). Therefore, a user interface affordance is typically implemented
// when permissions are denied. Otherwise, your app could appear unresponsive to
// touches or interactions which have required permissions.
Snackbar.make(rootView, R.string.camera_permission_denied_explanation, Snackbar
.LENGTH_INDEFINITE)
.setAction(R.string.settings, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.show();
}
}
}
private void findAndOpenCamera() {
boolean cameraPermissions = checkCameraPermissions();
if (cameraPermissions) {
String errorMessage = "Unknown error";
boolean foundCamera = false;
initializeCamera();
if (cameraPermissions && mCameraOps != null) {
try {
// Find first back-facing camera that has necessary capability.
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id);
int facing = info.get(CameraCharacteristics.LENS_FACING);
int level = info.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
boolean hasFullLevel
= (level
== CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
int[] capabilities = info
.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
int syncLatency = info.get(CameraCharacteristics.SYNC_MAX_LATENCY);
boolean hasManualControl = hasCapability(capabilities,
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
boolean hasEnoughCapability = hasManualControl &&
syncLatency
== CameraCharacteristics.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
// All these are guaranteed by
// CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, but checking
// for only the things we care about expands range of devices we can run on.
// We want:
// - Back-facing camera
// - Manual sensor control
// - Per-frame synchronization (so that exposure can be changed every frame)
if (facing == CameraCharacteristics.LENS_FACING_BACK &&
(hasFullLevel || hasEnoughCapability)) {
// Found suitable camera - get info, open, and set up outputs
mCameraInfo = info;
mCameraOps.openCamera(id);
configureSurfaces();
foundCamera = true;
break;
}
}
if (!foundCamera) {
errorMessage = getString(R.string.camera_no_good);
}
} catch (CameraAccessException e) {
errorMessage = getErrorString(e);
}
if (!foundCamera) {
showErrorDialog(errorMessage);
}
}
}
}
private boolean hasCapability(int[] capabilities, int capability) {
for (int c : capabilities) {
if (c == capability) return true;
}
return false;
}
private void switchRenderMode(int direction) {
if (mCameraOps != null) {
mRenderMode = (mRenderMode + direction) % 3;
mModeText.setText(getResources().getStringArray(R.array.mode_label_array)[mRenderMode]);
if (mProcessor != null) {
mProcessor.setRenderMode(mRenderMode);
}
if (mRenderMode == ViewfinderProcessor.MODE_NORMAL) {
mCameraOps.setRepeatingRequest(mPreviewRequest,
mCaptureCallback, mUiHandler);
} else {
setHdrBurst();
}
}
}
/**
* Configure the surfaceview and RS processing.
*/
private void configureSurfaces() {
// Find a good size for output - largest 16:9 aspect ratio that's less than 720p
final int MAX_WIDTH = 1280;
final float TARGET_ASPECT = 16.f / 9.f;
final float ASPECT_TOLERANCE = 0.1f;
StreamConfigurationMap configs =
mCameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] outputSizes = configs.getOutputSizes(SurfaceHolder.class);
Size outputSize = outputSizes[0];
float outputAspect = (float) outputSize.getWidth() / outputSize.getHeight();
for (Size candidateSize : outputSizes) {
if (candidateSize.getWidth() > MAX_WIDTH) continue;
float candidateAspect = (float) candidateSize.getWidth() / candidateSize.getHeight();
boolean goodCandidateAspect =
Math.abs(candidateAspect - TARGET_ASPECT) < ASPECT_TOLERANCE;
boolean goodOutputAspect =
Math.abs(outputAspect - TARGET_ASPECT) < ASPECT_TOLERANCE;
if ((goodCandidateAspect && !goodOutputAspect) ||
candidateSize.getWidth() > outputSize.getWidth()) {
outputSize = candidateSize;
outputAspect = candidateAspect;
}
}
Log.i(TAG, "Resolution chosen: " + outputSize);
// Configure processing
mProcessor = new ViewfinderProcessor(mRS, outputSize);
setupProcessor();
// Configure the output view - this will fire surfaceChanged
mPreviewView.setAspectRatio(outputAspect);
mPreviewView.getHolder().setFixedSize(outputSize.getWidth(), outputSize.getHeight());
}
/**
* Once camera is open and output surfaces are ready, configure the RS processing
* and the camera device inputs/outputs.
*/
private void setupProcessor() {
if (mProcessor == null || mPreviewSurface == null) return;
mProcessor.setOutputSurface(mPreviewSurface);
mProcessingHdrSurface = mProcessor.getInputHdrSurface();
mProcessingNormalSurface = mProcessor.getInputNormalSurface();
List<Surface> cameraOutputSurfaces = new ArrayList<Surface>();
cameraOutputSurfaces.add(mProcessingHdrSurface);
cameraOutputSurfaces.add(mProcessingNormalSurface);
mCameraOps.setSurfaces(cameraOutputSurfaces);
}
/**
* Start running an HDR burst on a configured camera session
*/
public void setHdrBurst() {
mHdrBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, 1600);
mHdrBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, ONE_SECOND / 30);
mHdrBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, mEvenExposure);
mHdrBuilder.setTag(mEvenExposureTag);
mHdrRequests.set(0, mHdrBuilder.build());
mHdrBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, mOddExposure);
mHdrBuilder.setTag(mOddExposureTag);
mHdrRequests.set(1, mHdrBuilder.build());
mCameraOps.setRepeatingBurst(mHdrRequests, mCaptureCallback, mUiHandler);
}
/**
* Listener for completed captures
* Invoked on UI thread
*/
private CameraCaptureSession.CaptureCallback mCaptureCallback
= new CameraCaptureSession.CaptureCallback() {
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
// Only update UI every so many frames
// Use an odd number here to ensure both even and odd exposures get an occasional update
long frameNumber = result.getFrameNumber();
if (frameNumber % 3 != 0) return;
long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
// Format exposure time nicely
String exposureText;
if (exposureTime > ONE_SECOND) {
exposureText = String.format("%.2f s", exposureTime / 1e9);
} else if (exposureTime > MILLI_SECOND) {
exposureText = String.format("%.2f ms", exposureTime / 1e6);
} else if (exposureTime > MICRO_SECOND) {
exposureText = String.format("%.2f us", exposureTime / 1e3);
} else {
exposureText = String.format("%d ns", exposureTime);
}
Object tag = request.getTag();
Log.i(TAG, "Exposure: " + exposureText);
if (tag == mEvenExposureTag) {
mEvenExposureText.setText(exposureText);
mEvenExposureText.setEnabled(true);
mOddExposureText.setEnabled(true);
mAutoExposureText.setEnabled(false);
} else if (tag == mOddExposureTag) {
mOddExposureText.setText(exposureText);
mEvenExposureText.setEnabled(true);
mOddExposureText.setEnabled(true);
mAutoExposureText.setEnabled(false);
} else {
mAutoExposureText.setText(exposureText);
mEvenExposureText.setEnabled(false);
mOddExposureText.setEnabled(false);
mAutoExposureText.setEnabled(true);
}
}
};
/**
* Callbacks for the FixedAspectSurfaceView
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mPreviewSurface = holder.getSurface();
setupProcessor();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// ignored
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mPreviewSurface = null;
}
/**
* Callbacks for CameraOps
*/
@Override
public void onCameraReady() {
// Ready to send requests in, so set them up
try {
CaptureRequest.Builder previewBuilder =
mCameraOps.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewBuilder.addTarget(mProcessingNormalSurface);
previewBuilder.setTag(mAutoExposureTag);
mPreviewRequest = previewBuilder.build();
mHdrBuilder =
mCameraOps.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mHdrBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_OFF);
mHdrBuilder.addTarget(mProcessingHdrSurface);
switchRenderMode(0);
} catch (CameraAccessException e) {
String errorMessage = getErrorString(e);
showErrorDialog(errorMessage);
}
}
/**
* Utility methods
*/
@Override
public void showErrorDialog(String errorMessage) {
MessageDialogFragment.newInstance(errorMessage).show(getFragmentManager(), FRAGMENT_DIALOG);
}
@Override
public String getErrorString(CameraAccessException e) {
String errorMessage;
switch (e.getReason()) {
case CameraAccessException.CAMERA_DISABLED:
errorMessage = getString(R.string.camera_disabled);
break;
case CameraAccessException.CAMERA_DISCONNECTED:
errorMessage = getString(R.string.camera_disconnected);
break;
case CameraAccessException.CAMERA_ERROR:
errorMessage = getString(R.string.camera_error);
break;
default:
errorMessage = getString(R.string.camera_unknown, e.getReason());
break;
}
return errorMessage;
}
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.hdrviewfinder;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.os.Bundle;
public class MessageDialogFragment extends DialogFragment {
private static final String ARG_MESSAGE_INT = "message_int";
private static final String ARG_MESSAGE_STRING = "message_string";
public static MessageDialogFragment newInstance(int message) {
MessageDialogFragment fragment = new MessageDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_MESSAGE_INT, message);
fragment.setArguments(args);
return fragment;
}
public static MessageDialogFragment newInstance(String message) {
MessageDialogFragment fragment = new MessageDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_MESSAGE_STRING, message);
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setPositiveButton(android.R.string.ok, null);
Bundle args = getArguments();
if (args.containsKey(ARG_MESSAGE_INT)) {
builder.setMessage(args.getInt(ARG_MESSAGE_INT));
} else if (args.containsKey(ARG_MESSAGE_STRING)) {
builder.setMessage(args.getString(ARG_MESSAGE_STRING));
}
return builder.create();
}
}

View File

@@ -1,165 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.hdrviewfinder;
import android.graphics.ImageFormat;
import android.os.Handler;
import android.os.HandlerThread;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.Type;
import android.util.Size;
import android.view.Surface;
/**
* Renderscript-based merger for an HDR viewfinder
*/
public class ViewfinderProcessor {
private Allocation mInputHdrAllocation;
private Allocation mInputNormalAllocation;
private Allocation mPrevAllocation;
private Allocation mOutputAllocation;
private Surface mOutputSurface;
private HandlerThread mProcessingThread;
private Handler mProcessingHandler;
private ScriptC_hdr_merge mHdrMergeScript;
public ProcessingTask mHdrTask;
public ProcessingTask mNormalTask;
private Size mSize;
private int mMode;
public final static int MODE_NORMAL = 0;
public final static int MODE_SIDE_BY_SIDE = 1;
public final static int MODE_HDR = 2;
public ViewfinderProcessor(RenderScript rs, Size dimensions) {
mSize = dimensions;
Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs));
yuvTypeBuilder.setX(dimensions.getWidth());
yuvTypeBuilder.setY(dimensions.getHeight());
yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
mInputHdrAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
mInputNormalAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
Type.Builder rgbTypeBuilder = new Type.Builder(rs, Element.RGBA_8888(rs));
rgbTypeBuilder.setX(dimensions.getWidth());
rgbTypeBuilder.setY(dimensions.getHeight());
mPrevAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
Allocation.USAGE_SCRIPT);
mOutputAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
mProcessingThread = new HandlerThread("ViewfinderProcessor");
mProcessingThread.start();
mProcessingHandler = new Handler(mProcessingThread.getLooper());
mHdrMergeScript = new ScriptC_hdr_merge(rs);
mHdrMergeScript.set_gPrevFrame(mPrevAllocation);
mHdrTask = new ProcessingTask(mInputHdrAllocation, dimensions.getWidth()/2, true);
mNormalTask = new ProcessingTask(mInputNormalAllocation, 0, false);
setRenderMode(MODE_NORMAL);
}
public Surface getInputHdrSurface() {
return mInputHdrAllocation.getSurface();
}
public Surface getInputNormalSurface() {
return mInputNormalAllocation.getSurface();
}
public void setOutputSurface(Surface output) {
mOutputAllocation.setSurface(output);
}
public void setRenderMode(int mode) {
mMode = mode;
}
/**
* Simple class to keep track of incoming frame count,
* and to process the newest one in the processing thread
*/
class ProcessingTask implements Runnable, Allocation.OnBufferAvailableListener {
private int mPendingFrames = 0;
private int mFrameCounter = 0;
private int mCutPointX;
private boolean mCheckMerge;
private Allocation mInputAllocation;
public ProcessingTask(Allocation input, int cutPointX, boolean checkMerge) {
mInputAllocation = input;
mInputAllocation.setOnBufferAvailableListener(this);
mCutPointX = cutPointX;
mCheckMerge = checkMerge;
}
@Override
public void onBufferAvailable(Allocation a) {
synchronized(this) {
mPendingFrames++;
mProcessingHandler.post(this);
}
}
@Override
public void run() {
// Find out how many frames have arrived
int pendingFrames;
synchronized(this) {
pendingFrames = mPendingFrames;
mPendingFrames = 0;
// Discard extra messages in case processing is slower than frame rate
mProcessingHandler.removeCallbacks(this);
}
// Get to newest input
for (int i = 0; i < pendingFrames; i++) {
mInputAllocation.ioReceive();
}
mHdrMergeScript.set_gFrameCounter(mFrameCounter++);
mHdrMergeScript.set_gCurrentFrame(mInputAllocation);
mHdrMergeScript.set_gCutPointX(mCutPointX);
if (mCheckMerge && mMode == MODE_HDR) {
mHdrMergeScript.set_gDoMerge(1);
} else {
mHdrMergeScript.set_gDoMerge(0);
}
// Run processing pass
mHdrMergeScript.forEach_mergeHdrFrames(mPrevAllocation, mOutputAllocation);
mOutputAllocation.ioSend();
}
}
}

View File

@@ -1,81 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma version(1)
#pragma rs java_package_name(com.example.android.hdrviewfinder)
#pragma rs_fp_relaxed
rs_allocation gCurrentFrame;
rs_allocation gPrevFrame;
int gCutPointX = 0;
int gDoMerge = 0;
int gFrameCounter = 0;
uchar4 __attribute__((kernel)) mergeHdrFrames(uchar4 prevPixel, uint32_t x, uint32_t y) {
// Read in pixel values from latest frame - YUV color space
uchar4 curPixel;
curPixel.r = rsGetElementAtYuv_uchar_Y(gCurrentFrame, x, y);
curPixel.g = rsGetElementAtYuv_uchar_U(gCurrentFrame, x, y);
curPixel.b = rsGetElementAtYuv_uchar_V(gCurrentFrame, x, y);
curPixel.a = 255;
uchar4 mergedPixel;
if (gDoMerge == 1) {
// Complex HDR fusion technique
mergedPixel = curPixel / 2 + prevPixel / 2;
/* Experimental color saturation boosting merge
mergedPixel.r = curPixel.r / 2 + prevPixel.r / 2;
uchar saturationCurrent = abs(curPixel.g - 128) + abs(curPixel.b - 128);
uchar saturationPrev = abs(prevPixel.g - 128) + abs(prevPixel.b - 128);
mergedPixel.g = saturationCurrent > saturationPrev ? curPixel.g : prevPixel.g;
mergedPixel.b = saturationCurrent > saturationPrev ? curPixel.b : prevPixel.b;
*/
} else if (gCutPointX > 0) {
// Composite side by side
mergedPixel = ((x < gCutPointX) ^ (gFrameCounter & 0x1)) ?
curPixel : prevPixel;
} else {
// Straight passthrough
mergedPixel = curPixel;
}
// Convert YUV to RGB, JFIF transform with fixed-point math
// R = Y + 1.402 * (V - 128)
// G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128)
// B = Y + 1.772 * (U - 128)
int4 rgb;
rgb.r = mergedPixel.r +
mergedPixel.b * 1436 / 1024 - 179;
rgb.g = mergedPixel.r -
mergedPixel.g * 46549 / 131072 + 44 -
mergedPixel.b * 93604 / 131072 + 91;
rgb.b = mergedPixel.r +
mergedPixel.g * 1814 / 1024 - 227;
rgb.a = 255;
// Store current pixel for next frame
rsSetElementAt_uchar4(gPrevFrame, curPixel, x, y);
// Write out merged HDR result
uchar4 out = convert_uchar4(clamp(rgb, 0, 255));
return out;
}