ColorMatrix.setConcat() to combine ColorMatrixes

The exercise "Set the rotation on a color axis of Bitmap with ColorMatrix" create rotated ColorMatrix for one color only, not all. We can create ColorMatrix from more than one by calling ColorMatrix.setConcat().

ColorMatrix.setConcat() to combine ColorMatrixs


package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

Button btnLoadImage;
ImageView imageResult;
SeekBar rotBarRed, rotBarGreen, rotBarBlue;
TextView rotText;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button) findViewById(R.id.loadimage);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

rotText = (TextView) findViewById(R.id.textRot);
rotBarRed = (SeekBar) findViewById(R.id.rotbarred);
rotBarGreen = (SeekBar) findViewById(R.id.rotbargreen);
rotBarBlue = (SeekBar) findViewById(R.id.rotbarblue);
rotBarRed.setOnSeekBarChangeListener(seekBarChangeListener);
rotBarGreen.setOnSeekBarChangeListener(seekBarChangeListener);
rotBarBlue.setOnSeekBarChangeListener(seekBarChangeListener);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();

try {
bitmapMaster = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
source));

rotBarRed.setProgress(0);
rotBarGreen.setProgress(0);
rotBarBlue.setProgress(0);

loadBitmapRotate();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
loadBitmapRotate();
}
};

private void loadBitmapRotate() {
if (bitmapMaster != null) {

float rotRed = (float) rotBarRed.getProgress();
float rotGreen = (float) rotBarGreen.getProgress();
float rotBlue = (float) rotBarBlue.getProgress();

rotText.setText("setRotate: " + String.valueOf(rotRed) + ", "
+ String.valueOf(rotGreen) + ", " + String.valueOf(rotBlue));

Bitmap bitmapColorScaled = updateRot(bitmapMaster, rotRed,
rotGreen, rotBlue);

imageResult.setImageBitmap(bitmapColorScaled);
}
}

private Bitmap updateRot(Bitmap src, float degreesRed, float degreesGreen,
float degreesBlue) {

int w = src.getWidth();
int h = src.getHeight();

Bitmap bitmapResult = Bitmap
.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();

ColorMatrix colorMatrixRed = new ColorMatrix();
colorMatrixRed.setRotate(0, degreesRed);
ColorMatrix colorMatrixGreen = new ColorMatrix();
colorMatrixGreen.setRotate(1, degreesGreen);
ColorMatrix colorMatrixBlue = new ColorMatrix();
colorMatrixBlue.setRotate(2, degreesBlue);
ColorMatrix colorMatrixConcat = new ColorMatrix();
colorMatrixConcat.setConcat(colorMatrixRed, colorMatrixGreen);
colorMatrixConcat.setConcat(colorMatrixConcat, colorMatrixBlue);

ColorMatrixColorFilter filter = new ColorMatrixColorFilter(
colorMatrixConcat);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);

return bitmapResult;
}
}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@android:color/background_dark"
android:scaleType="centerInside" />

<TextView
android:id="@+id/textRot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ColorMatrix Rotate" />

<SeekBar
android:id="@+id/rotbarred"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="360"
android:progress="0" />
<SeekBar
android:id="@+id/rotbargreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="360"
android:progress="0" />
<SeekBar
android:id="@+id/rotbarblue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="360"
android:progress="0" />
</LinearLayout>
</ScrollView>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



more: Something about processing images in Android

Scale color and alpha of colormatrix with setScale()

Example of using ColorMatrix.setScale(float rScale, float gScale, float bScale, float aScale).

Example of using ColorMatrix.setScale()

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

Button btnLoadImage;
ImageView imageResult;
SeekBar scaleBarRed, scaleBarGreen, scaleBarBlue, scaleBarAlpha;
TextView cmScaleText;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button) findViewById(R.id.loadimage);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

cmScaleText = (TextView) findViewById(R.id.textCMScale);
scaleBarRed = (SeekBar) findViewById(R.id.scalebarred);
scaleBarGreen = (SeekBar) findViewById(R.id.scalebargreen);
scaleBarBlue = (SeekBar) findViewById(R.id.scalebarblue);
scaleBarAlpha = (SeekBar) findViewById(R.id.scalebaralpha);
scaleBarRed.setOnSeekBarChangeListener(seekBarChangeListener);
scaleBarGreen.setOnSeekBarChangeListener(seekBarChangeListener);
scaleBarBlue.setOnSeekBarChangeListener(seekBarChangeListener);
scaleBarAlpha.setOnSeekBarChangeListener(seekBarChangeListener);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();

try {
bitmapMaster = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
source));

scaleBarRed.setProgress(100);
scaleBarGreen.setProgress(100);
scaleBarBlue.setProgress(100);
scaleBarAlpha.setProgress(100);

loadBitmapScaleColor();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

OnSeekBarChangeListener seekBarChangeListener =
new OnSeekBarChangeListener() {

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
loadBitmapScaleColor();
}
};

private void loadBitmapScaleColor() {
if (bitmapMaster != null) {

int progressScaleRed = scaleBarRed.getProgress();
int progressScaleGreen = scaleBarGreen.getProgress();
int progressScaleBlue = scaleBarBlue.getProgress();
int progressScaleAlpha = scaleBarAlpha.getProgress();

float scaleRed = (float) progressScaleRed/100;
float scaleGreen = (float) progressScaleGreen/100;
float scaleBlue = (float) progressScaleBlue/100;
float scaleAlpha = (float) progressScaleAlpha/100;

cmScaleText.setText("setScale: "
+ String.valueOf(scaleRed) + ", "
+ String.valueOf(scaleGreen) + ", "
+ String.valueOf(scaleBlue) + ", "
+ String.valueOf(scaleAlpha));

Bitmap bitmapColorScaled = updateScale(
bitmapMaster,
scaleRed,
scaleGreen,
scaleBlue,
scaleAlpha);

imageResult.setImageBitmap(bitmapColorScaled);
}
}

private Bitmap updateScale(Bitmap src, float rScale, float gScale,
float bScale, float aScale) {

int w = src.getWidth();
int h = src.getHeight();

Bitmap bitmapResult = Bitmap
.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setScale(rScale, gScale, bScale, aScale);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);

return bitmapResult;
}
}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@drawable/ic_launcher"
android:scaleType="centerInside" />

<TextView
android:id="@+id/textCMScale"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ColorMatrix Scale" />

<SeekBar
android:id="@+id/scalebarred"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100" />
<SeekBar
android:id="@+id/scalebargreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100" />
<SeekBar
android:id="@+id/scalebarblue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100" />
<SeekBar
android:id="@+id/scalebaralpha"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100" />
</LinearLayout>
</ScrollView>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



more: Something about processing images in Android

Using the Hardware Scaler for Performance and Efficiency

Posted by Hak Matsuda and Dirk Dougherty, Android Developer Relations team



If you develop a performance-intensive 3D game, you’re always looking for ways to give users richer graphics, higher frame rates, and better responsiveness. You also want to conserve the user’s battery and keep the device from getting too warm during play. To help you optimize in all of these areas, consider taking advantage of the hardware scaler that’s available on almost all Android devices in the market today.



How it works and why you should use it



Virtually all modern Android devices use a CPU/GPU chipset that includes a hardware video scaler. Android provides the higher-level integration and makes the scaler available to apps through standard Android APIs, from Java or native (C++) code. To take advantage of the hardware scaler, all you have to do is render to a fixed-size graphics buffer, rather than using the system-provided default buffers, which are sized to the device's full screen resolution.



When you render to a fixed-size buffer, the device hardware does the work of scaling your scene up (or down) to match the device's screen resolution, including making any adjustments to aspect ratio. Typically, you would create a fixed-size buffer that's smaller than the device's full screen resolution, which lets you render more efficiently — especially on today's high-resolution screens.



Using the hardware scaler is more efficient for several reasons. First, hardware scalers are extremely fast and can produce great visual results through multi-tap and other algorithms that reduce artifacts. Second, because your app is rendering to a smaller buffer, the computation load on the GPU is reduced and performance improves. Third, with less computation work to do, the GPU runs cooler and uses less battery. And finally, you can choose what size rendering buffer you want to use, and that buffer can be the same on all devices, regardless of the actual screen resolution.



Optimizing the fill rate



In a mobile GPU, the pixel fill rate is one of the major sources of performance bottlenecks for performance game applications. With newer phones and tablets offering higher and higher screen resolutions, rendering your 2D or 3D graphics on those those devices can significantly reduce your frame rate. The GPU hits its maximum fill rate, and with so many pixels to fill, your frame rate drops.





style="border-radius: 6px;padding:0;margin:0;" />

Power consumed in the GPU at different rendering resolutions, across several popular chipsets in use on Android devices. (Data provided by Qualcomm).



To avoid these bottlenecks, you need to reduce the number of pixels that your game is drawing in each frame. There are several techniques for achieving that, such as using depth-prepass optimizations and others, but a really simple and effective way is making use of the hardware scaler.



Instead of rendering to a full-size buffer that could be as large as 2560x1600, your game can instead render to a smaller buffer — for example 1280x720 or 1920x1080 — and let the hardware scaler expand your scene without any additional cost and minimal loss in visual quality.



Reducing power consumption and thermal effects



A performance-intensive game can tend to consume too much battery and generate too much heat. The game’s power consumption and thermal conditions are important to users, and they are important considerations to developers as well.



As shown in the diagram, the power consumed in the device GPU increases significantly as rendering resolution rises. In most cases, any heavy use of power in GPU will end up reducing battery life in the device.



In addition, as CPU/GPU rendering load increases, heat is generated that can make the device uncomfortable to hold. The heat can even trigger CPU/GPU speed adjustments designed to cool the CPU/GPU, and these in turn can throttle the processing power that’s available to your game.



For both minimizing power consumption and thermal effects, using the hardware scaler can be very useful. Because you are rendering to a smaller buffer, the GPU spends less energy rendering and generates less heat.



Accessing the hardware scaler from Android APIs



Android gives you easy access to the hardware scaler through standard APIs, available from your Java code or from your native (C++) code through the Android NDK.



All you need to do is use the APIs to create a fixed-size buffer and render into it. You don’t need to consider the actual size of the device screen, however in cases where you want to preserve the original aspect ratio, you can either match the aspect ratio of the buffer to that of the screen, or you can adjust your rendering into the buffer.



From your Java code, you access the scaler through SurfaceView, introduced in API level 1. Here’s how you would create a fixed-size buffer at 1280x720 resolution:




surfaceView = new GLSurfaceView(this);
surfaceView.getHolder().setFixedSize(1280, 720);


If you want to use the scaler from native code, you can do so through the NativeActivity class, introduced in Android 2.3 (API level 9). Here’s how you would create a fixed-size buffer at 1280x720 resolution using NativeActivity:




int32_t ret = ANativeWindow_setBuffersGeometry(window, 1280, 720, 0);


By specifying a size for the buffer, the hardware scaler is enabled and you benefit in your rendering to the specified window.



Choosing a size for your graphics buffer



If you will use a fixed-size graphics buffer, it's important to choose a size that balances visual quality across targeted devices with performance and efficiency gains.



For most performance 3D games that use the hardware scaler, the recommended size for rendering is 1080p. As illustrated in the diagram, 1080p is a sweet spot that balances a visual quality, frame rate, and power consumption. If you are satisfied with 720p, of course you can use that size for even more efficient operations.



More information



If you’d like to take advantage of the hardware scaler in your app, take a look at the class documentation for SurfaceView or NativeActivity, depending on whether you are rendering through the Android framework or native APIs.

Watch for sample code on using the hardware scaler coming soon!

Set the rotation on a color axis of Bitmap with ColorMatrix

Example to set the rotation on a color axis by the specified values. axis=0 correspond to a rotation around the RED color axis=1 correspond to a rotation around the GREEN color axis=2 correspond to a rotation around the BLUE color.

rotation on a color axis of Bitmap with ColorMatrix

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

Button btnLoadImage;
ImageView imageResult;
SeekBar rotBar;
TextView rotText;

RadioGroup groupAxis;
RadioButton optAxisRed, optAxisGreen, optAxisBlue;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button) findViewById(R.id.loadimage);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

rotText = (TextView) findViewById(R.id.textRot);
rotBar = (SeekBar) findViewById(R.id.rotbar);
rotBar.setOnSeekBarChangeListener(seekBarChangeListener);

groupAxis = (RadioGroup) findViewById(R.id.axisgroup);
optAxisRed = (RadioButton) findViewById(R.id.axisred);
optAxisGreen = (RadioButton) findViewById(R.id.axisgreen);
optAxisBlue = (RadioButton) findViewById(R.id.axisblue);
groupAxis.setOnCheckedChangeListener(groupAxisOnCheckedChangeListener);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();

try {
bitmapMaster = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
source));

optAxisRed.setChecked(true);
rotBar.setProgress(0);

loadBitmapSat();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

OnSeekBarChangeListener seekBarChangeListener =
new OnSeekBarChangeListener() {

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
loadBitmapSat();
}
};

OnCheckedChangeListener groupAxisOnCheckedChangeListener =
new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
loadBitmapSat();
}
};

private void loadBitmapSat() {
if (bitmapMaster != null) {

int progressRot = rotBar.getProgress();

float rotDegree = (float) progressRot;

if (optAxisRed.isChecked()) {
rotText.setText("setRotate: " + "Red: "
+ String.valueOf(rotDegree));
imageResult
.setImageBitmap(updateRot(bitmapMaster, 0, rotDegree));
} else if (optAxisGreen.isChecked()) {
rotText.setText("setRotate: " + "Green: "
+ String.valueOf(rotDegree));
imageResult
.setImageBitmap(updateRot(bitmapMaster, 1, rotDegree));
} else if (optAxisBlue.isChecked()) {
rotText.setText("setRotate: " + "Blue: "
+ String.valueOf(rotDegree));
imageResult
.setImageBitmap(updateRot(bitmapMaster, 2, rotDegree));
}
}
}

private Bitmap updateRot(Bitmap src, int axis, float degrees) {

int w = src.getWidth();
int h = src.getHeight();

Bitmap bitmapResult = Bitmap
.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setRotate(axis, degrees);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);

return bitmapResult;
}
}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@android:color/background_dark"
android:scaleType="centerInside" />

<TextView
android:id="@+id/textRot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Rotate Axis" />

<RadioGroup
android:id="@+id/axisgroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<RadioButton
android:id="@+id/axisred"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="Red" />

<RadioButton
android:id="@+id/axisgreen"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Green" />

<RadioButton
android:id="@+id/axisblue"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Blue" />
</RadioGroup>

<SeekBar
android:id="@+id/rotbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="360"
android:progress="0" />
</LinearLayout>
</ScrollView>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.

Related: Combine ColorMatrixes by calling setConcat().


more: Something about processing images in Android

Android Studio 0.2.10 Released

Read it more: http://tools.android.com/recent/androidstudio0210released


Watch video of Surface 2 Launch Event

Watch video the Surface 2 Launch Event in New York City, Sept. 23 HERE.

Surface 2 Launch Event

Adjust saturation of Bitmap with ColorMatrix

android.graphics.ColorMatrix is a 5x4 matrix for transforming the color+alpha components of a Bitmap. The setSaturation(float sat) method of ColorMatrix set the matrix to affect the saturation of colors. A value of 0 maps the color to gray-scale. 1 is identity.

This example demonstrate how to generate a bitmap with adjusted saturation using ColorMatrix.setSaturation().

Adjust saturation of Bitmap with ColorMatrix

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

Button btnLoadImage;
TextView textSource;
ImageView imageResult;
SeekBar satBar;
TextView satText;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button) findViewById(R.id.loadimage);
textSource = (TextView) findViewById(R.id.sourceuri);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

satText = (TextView) findViewById(R.id.textsat);
satBar = (SeekBar) findViewById(R.id.satbar);
satBar.setOnSeekBarChangeListener(seekBarChangeListener);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();

try {
bitmapMaster = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
source));

satBar.setProgress(256);

loadBitmapSat();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
loadBitmapSat();
}
};

private void loadBitmapSat() {
if (bitmapMaster != null) {

int progressSat = satBar.getProgress();

//Saturation, 0=gray-scale. 1=identity
float sat = (float) progressSat / 256;
satText.setText("Saturation: " + String.valueOf(sat));
imageResult.setImageBitmap(updateSat(bitmapMaster, sat));
}
}

private Bitmap updateSat(Bitmap src, float settingSat) {

int w = src.getWidth();
int h = src.getHeight();

Bitmap bitmapResult =
Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(settingSat);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);

return bitmapResult;
}
}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />

<TextView
android:id="@+id/sourceuri"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@android:color/background_dark"
android:scaleType="centerInside" />

<TextView
android:id="@+id/textsat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Saturation" />
<SeekBar
android:id="@+id/satbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="512"
android:progress="256"/>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



more: Something about processing images in Android

New Features in the Google Maps Mobile APIs for Android and iOS

Maps Live: New Features in the Google Maps Mobile APIs for Android and iOS

Google Maps API Team members Daniel Schramm and Chris Broadfoot discuss exciting new cross platform features in the Google Maps Android API v2 (http://goo.gl/5k18Es) and the Google Maps SDK for iOS (http://goo.gl/r2c2e). New to the latest versions are map padding, marker rotation, and flat markers.




The series:
A simple example using Google Maps Android API v2, step by step.

Android SDK and ADT Plugin updated 22.2.1

To update Android SDK in Eclipse, select Window ->Android SDK Manager:

Android SDK 22.2.1

Update Eclipse ADT Plugin, select Help -> Check for Updates:

ADT 22.2.1

Scale bitmap with inDither and inPreferQualityOverSpeed

The exercise "Load scaled bitmap" demonstrate a simple and standard method to scale bitmap. Additionally, we can set inDither and inPreferQualityOverSpeed options to improve quality of the scaled bitmap.
  • inDither:
    If set, the decoder will attempt to dither the decoded image.
    Dithering is a technique used in computer graphics to create the illusion of color depth in images with a limited color palette (color quantization). ~ reference: Wikipedia, Dither in Digital photography and image processing.
  • inPreferQualityOverSpeed (Added in API level 10) : 
    If set, the decoder will try to decode the reconstructed image to a higher quality even at the expense of the decoding speed. Currently the field only affects JPEG decode, in the case of which a more accurate, but slightly slower, IDCT method will be used instead.

In this exercise, we can set options of inDither and inPreferQualityOverSpeed in scaling bitmap. And also display the INACCURACY processing duration of scaling bitmap in millisecond, for reference only.

Scale bitmap with inDither and inPreferQualityOverSpeed

package com.example.androidscalebitmap;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Date;

import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class MainActivity extends Activity {

final int RQS_IMAGE1 = 1;

Button btnLoadImage;
ToggleButton optBtnInDither, optBtnInPreferQualityOverSpeed;
TextView textInfo;
ImageView imageResult;

Uri source1;
Date startTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLoadImage = (Button) findViewById(R.id.loadimage);
optBtnInDither = (ToggleButton) findViewById(R.id.optInDither);
optBtnInPreferQualityOverSpeed = (ToggleButton) findViewById(R.id.optInPreferQualityOverSpeed);
textInfo = (TextView) findViewById(R.id.info);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

optBtnInDither.setOnCheckedChangeListener(
optBtnOnCheckedChangeListener);
optBtnInPreferQualityOverSpeed.setOnCheckedChangeListener(
optBtnOnCheckedChangeListener);
}

OnCheckedChangeListener optBtnOnCheckedChangeListener =
new OnCheckedChangeListener(){

@Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
doScale(source1);
}};

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source1 = data.getData();
optBtnInDither.setChecked(false);
optBtnInPreferQualityOverSpeed.setChecked(false);
doScale(source1);
break;
}
}
}

private void doScale(Uri src){

try {
Bitmap bm = loadScaledBitmap(source1);
imageResult.setImageBitmap(bm);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

private Bitmap loadScaledBitmap(Uri src) throws FileNotFoundException {

// required max width/height
final int REQ_WIDTH = 800;
final int REQ_HEIGHT = 800;

Bitmap bm = null;

if (src != null) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver()
.openInputStream(src), null, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, REQ_WIDTH,
REQ_HEIGHT);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;

//set options according to RadioButton setting
options.inDither = optBtnInDither.isChecked();
//inPreferQualityOverSpeed require API Level 10
options.inPreferQualityOverSpeed = optBtnInPreferQualityOverSpeed.isChecked();

InputStream inputStream = getContentResolver().openInputStream(src);
startTime = new Date();

bm = BitmapFactory.decodeStream(inputStream, null, options);

//INACCURACY processing duration of scaling bitmap in millisecond
long duration = new Date().getTime() - startTime.getTime();
textInfo.setText("duration in ms: " + duration);
}

return bm;
}

public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);

// Choose the smallest ratio as inSampleSize value, this will
// guarantee a final image with both dimensions larger than or
// equal to the requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}

return inSampleSize;
}
}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />
<ToggleButton
android:id="@+id/optInDither"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:textOn="inDither ON"
android:textOff="inDither OFF"/>
<ToggleButton
android:id="@+id/optInPreferQualityOverSpeed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:textOn="inPreferQualityOverSpeed ON"
android:textOff="inPreferQualityOverSpeed OFF"/>
<TextView
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@android:color/background_dark"
android:scaleType="center" />

</LinearLayout>


download filesDownload the files.


download filesDownload and try the APK.



more: Something about processing images in Android

Android Developer Tools Essentials: Android Studio to Zipalign


Android development can be challenging, but through the effective use of Android Developer Tools (ADT), you can make the process easier and improve the quality of your code. This concise guide demonstrates how to build apps with ADT for a device family that features several screen sizes, different hardware capabilities, and a varying number of resources.
With examples in Windows, Linux, and Mac OS X, you’ll learn how to set up an Android development environment and use ADT with the Eclipse IDE. Also, contributor Donn Felker introduces Android Studio, a Google IDE that will eventually replace Eclipse.
  • Learn how to use Eclipse and ADT together to develop Android code
  • Create emulators of various sizes and configurations to test your code
  • Master Eclipse tools, or explore the new Android Studio
  • Use Logcat, Lint, and other ADT tools to test and debug your code
  • Simulate real-world events, including location, sensors, and telephony
  • Create dynamic and efficient UIs, using Graphical Layout tools
  • Monitor and optimize you application performance using DDMS, HierarchyViewer, and the Android Monitor tool
  • Use Wizards and shortcuts to generate code and image assets
  • Compile and package Android code with Ant and Gradle

RenderScript in the Android Support Library



Renderscript Support library on devicesstyle="border-radius: 6px;padding:0;margin:0;" />


The RenderScript Support Library lets you take advantage of the latest RenderScript features on devices running Android 2.2 and later.



Posted by Tim Murray, Android RenderScript team

One of the requests we hear most commonly from developers is to enable more devices to run the latest features of RenderScript. Over the past several releases of Android, we’ve added a ton of functionality to the RenderScript runtime, but the runtime's dependence on the core Android platform version has limited the range of devices that can support that new functionality. We’ve been working on a solution to this since last year, and we’re now ready to share it with all Android developers.



Today we're announcing a new RenderScript Support Library and updated SDK tools that together let you take advantage of RenderScript on plaform versions all the way back to Android 2.2 (Froyo).

With ADT v22.2, SDK Tools v22.2, and Android Build Tools v18.1.0, apps targeting Android 2.2 and later can now make use of almost all of the functionality available natively in RenderScript with Android 4.3. This includes access to the newest RenderScript features such as high-performance intrinsics and the new performance optimizations available to scripts.



Using the RenderScript Support Library


Using the RenderScript Support Library is straightforward. Once you've updated ADT and your SDK tools, there are only two things that you have to do to start using Renderscript in your apps:




  1. In your classes that use RenderScript, import the RenderScript Support Library from android.support.v8.renderscript. If you are already using native RenderScript, you can change your import from android.renderscript to android.support.v8.renderscript.

    import android.support.v8.renderscript.*;


  2. In your project.properties, make sure you’re targeting android-18 and add the following lines:

    renderscript.target=18
    renderscript.support.mode=true
    sdk.buildtools=18.1.0



That’s it! With the RenderScript Support Library, you can continue to use the same APIs from your app as with the native RenderScript package (with a few minor exceptions that we’ll talk about below), and you can use the same features in your own scripts as you would with the latest RenderScript toolchain.

For complete details on how to set up the RenderScript Support Library, see Accessing RenderScript Java APIs.



API and Implementation details


If you'd like to use RenderScript Support Library in your app, there are few things you should know:




  • First, the RenderScript Support Library supports almost all of the RenderScript API functions as the native API that's available in API level and higher. The one notable exception is that Allocation.USAGE_IO_INPUT and Allocation.USAGE_IO_OUTPUT are not currently available in the RenderScript Support Library.


  • Second, devices running Android 4.2 and earlier will always run their RenderScript applications on the CPU, while devices running Android 4.3 or later will run their RenderScript applications on whatever processors are available on that particular device. Because the Support Library versions of the scripts have to be precompiled to support all possible platforms, there is a performance hit when running the precompiled scripts compared to runtime compilation on Android 4.3 due to more restrictions on compiler optimizations.



We’re really pleased with how the RenderScript Support Library has turned out. We've already seen how it performs in a shipping app — it's been part of the photo editor in the Google+ Android app since May 2013, and it’s definitely proven itself in a large and widely used application. We hope you’ll be happy with it too.


Adjust HSV(Hue, Saturation and Value) of bitmap

android.graphics.Color class provide colorToHSV() and HSVToColor() methods to convert between ARGB color and HSV components. Such that we can adjust HSV of bitmap.

Adjust HSV(Hue, Saturation and Value) of bitmap

package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity {

Button btnLoadImage;
TextView textSource;
ImageView imageResult;
SeekBar hueBar, satBar, valBar;
TextView hueText, satText, valText;
Button btnResetHSV;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button) findViewById(R.id.loadimage);
textSource = (TextView) findViewById(R.id.sourceuri);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

hueText = (TextView) findViewById(R.id.texthue);
satText = (TextView) findViewById(R.id.textsat);
valText = (TextView) findViewById(R.id.textval);
hueBar = (SeekBar) findViewById(R.id.huebar);
satBar = (SeekBar) findViewById(R.id.satbar);
valBar = (SeekBar) findViewById(R.id.valbar);
hueBar.setOnSeekBarChangeListener(seekBarChangeListener);
satBar.setOnSeekBarChangeListener(seekBarChangeListener);
valBar.setOnSeekBarChangeListener(seekBarChangeListener);
btnResetHSV = (Button)findViewById(R.id.resethsv);
btnResetHSV.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
// reset SeekBars
hueBar.setProgress(256);
satBar.setProgress(256);
valBar.setProgress(256);

loadBitmapHSV();
}});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();

try {
bitmapMaster = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
source));

// reset SeekBars
hueBar.setProgress(256);
satBar.setProgress(256);
valBar.setProgress(256);

loadBitmapHSV();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
loadBitmapHSV();
}

};

private void loadBitmapHSV() {
if (bitmapMaster != null) {

int progressHue = hueBar.getProgress() - 256;
int progressSat = satBar.getProgress() - 256;
int progressVal = valBar.getProgress() - 256;

/*
* Hue (0 .. 360) Saturation (0...1) Value (0...1)
*/

float hue = (float) progressHue * 360 / 256;
float sat = (float) progressSat / 256;
float val = (float) progressVal / 256;

hueText.setText("Hue: " + String.valueOf(hue));
satText.setText("Saturation: " + String.valueOf(sat));
valText.setText("Value: " + String.valueOf(val));

imageResult.setImageBitmap(updateHSV(bitmapMaster, hue, sat, val));

}
}

private Bitmap updateHSV(Bitmap src, float settingHue, float settingSat,
float settingVal) {

int w = src.getWidth();
int h = src.getHeight();
int[] mapSrcColor = new int[w * h];
int[] mapDestColor = new int[w * h];

float[] pixelHSV = new float[3];

src.getPixels(mapSrcColor, 0, w, 0, 0, w, h);

int index = 0;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {

// Convert from Color to HSV
Color.colorToHSV(mapSrcColor[index], pixelHSV);

// Adjust HSV
pixelHSV[0] = pixelHSV[0] + settingHue;
if (pixelHSV[0] < 0.0f) {
pixelHSV[0] = 0.0f;
} else if (pixelHSV[0] > 360.0f) {
pixelHSV[0] = 360.0f;
}

pixelHSV[1] = pixelHSV[1] + settingSat;
if (pixelHSV[1] < 0.0f) {
pixelHSV[1] = 0.0f;
} else if (pixelHSV[1] > 1.0f) {
pixelHSV[1] = 1.0f;
}

pixelHSV[2] = pixelHSV[2] + settingVal;
if (pixelHSV[2] < 0.0f) {
pixelHSV[2] = 0.0f;
} else if (pixelHSV[2] > 1.0f) {
pixelHSV[2] = 1.0f;
}

// Convert back from HSV to Color
mapDestColor[index] = Color.HSVToColor(pixelHSV);

index++;
}
}

return Bitmap.createBitmap(mapDestColor, w, h, Config.ARGB_8888);

}

}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />

<TextView
android:id="@+id/sourceuri"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@android:color/background_dark"
android:scaleType="centerInside" />

<TextView
android:id="@+id/texthue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hue" />
<SeekBar
android:id="@+id/huebar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="511"
android:progress="256"/>
<TextView
android:id="@+id/textsat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Saturation" />
<SeekBar
android:id="@+id/satbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="511"
android:progress="256"/>
<TextView
android:id="@+id/textval"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Value" />
<SeekBar
android:id="@+id/valbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="511"
android:progress="256"/>
<Button
android:id="@+id/resethsv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reset HSV" />
</LinearLayout>


download filesDownload the files.

download filesDownload and try APK.



more: Something about processing images in Android

Create SimpleDateFormat for specified Locale

Example of creating SimpleDateFormat with specified Locale from previous exercise "Get default Locale and available Locales".

Create SimpleDateFormat with specified Locale


package com.example.androidlocale;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView textViewDefaultLocale = (TextView)findViewById(R.id.defaultlocale);
TextView textViewNoOfLocale = (TextView)findViewById(R.id.numberoflocale);
ListView listViewAvailableLocale = (ListView)findViewById(R.id.listviewlocale);

Locale defaultLocale = Locale.getDefault();
textViewDefaultLocale.setText("Default Locale: " + defaultLocale.toString());

final Locale[] availableLocales = Locale.getAvailableLocales();
textViewNoOfLocale.setText("Number of available Locale: " + availableLocales.length);
String[] availableLocalesString = new String[availableLocales.length];

for (int i=0; i<availableLocales.length; i++){
availableLocalesString[i] = availableLocales[i].toString();
}

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, availableLocalesString);
listViewAvailableLocale.setAdapter(adapter);

listViewAvailableLocale.setOnItemClickListener(
new OnItemClickListener(){

@Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
Locale item = availableLocales[position];

String format = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, item);
Date now = new Date();
Toast.makeText(getApplicationContext(),
"Locale: " + item.toString() + "\n"
+ simpleDateFormat.format(now),
Toast.LENGTH_LONG).show();

}});

}

}

Get details of Locale

Last exercise list available Locale of the system. It's modified to display details of the clicked Locale.

Get details of Locale


package com.example.androidlocale;

import java.util.Locale;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView textViewDefaultLocale = (TextView)findViewById(R.id.defaultlocale);
TextView textViewNoOfLocale = (TextView)findViewById(R.id.numberoflocale);
ListView listViewAvailableLocale = (ListView)findViewById(R.id.listviewlocale);

Locale defaultLocale = Locale.getDefault();
textViewDefaultLocale.setText("Default Locale: " + defaultLocale.toString());

final Locale[] availableLocales = Locale.getAvailableLocales();
textViewNoOfLocale.setText("Number of available Locale: " + availableLocales.length);
String[] availableLocalesString = new String[availableLocales.length];

for (int i=0; i<availableLocales.length; i++){
availableLocalesString[i] = availableLocales[i].toString();
}

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, availableLocalesString);
listViewAvailableLocale.setAdapter(adapter);

listViewAvailableLocale.setOnItemClickListener(
new OnItemClickListener(){

@Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
Locale item = availableLocales[position];

Toast.makeText(getApplicationContext(),
"Language: " + item.getLanguage() + "\n"
+ "Country: " + item.getCountry() + "\n"
+ "DisplayName: " + item.getDisplayName() + "\n"
+ "DisplayLanguage: " + item.getDisplayLanguage() + "\n"
+ "DisplayCountry: " + item.getDisplayCountry(),
Toast.LENGTH_LONG).show();
}});

}

}


Keep using the layout in last exercise.

Next: Create SimpleDateFormat for specified Locale

Get default Locale and available Locales

Example to get default Locale and available Locales:

Get default Locale and available Locales


package com.example.androidlocale;

import java.util.Locale;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView textViewDefaultLocale = (TextView)findViewById(R.id.defaultlocale);
TextView textViewNoOfLocale = (TextView)findViewById(R.id.numberoflocale);
ListView listViewAvailableLocale = (ListView)findViewById(R.id.listviewlocale);

Locale defaultLocale = Locale.getDefault();
textViewDefaultLocale.setText("Default Locale: " + defaultLocale.toString());

Locale[] availableLocales = Locale.getAvailableLocales();
textViewNoOfLocale.setText("Number of available Locale: " + availableLocales.length);
String[] availableLocalesString = new String[availableLocales.length];

for (int i=0; i<availableLocales.length; i++){
availableLocalesString[i] = availableLocales[i].toString();
}

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, availableLocalesString);
listViewAvailableLocale.setAdapter(adapter);

}

}


<LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />
<TextView
android:id="@+id/defaultlocale"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/numberoflocale"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ListView
android:id="@+id/listviewlocale"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</LinearLayout>

next: Get details of Locale

Combine bitmap, half/half

This example demonstrate how to combin two bitmap, half from a bitmap, another from the mirror bitmap of the same source.

Combine bitmap, half/half


package com.example.androiddrawbitmap;

import java.io.FileNotFoundException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {

Button btnLoadImage;
TextView textSource;
ImageView imageResult;

final int RQS_IMAGE1 = 1;

Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnLoadImage = (Button) findViewById(R.id.loadimage);
textSource = (TextView) findViewById(R.id.sourceuri);
imageResult = (ImageView) findViewById(R.id.result);

btnLoadImage.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
Intent intent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

Bitmap tempBitmap;

if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();

try {
tempBitmap = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
source));

//create a mirror bitmap
Matrix matrixMirror = new Matrix();
matrixMirror.preScale(-1.0f, 1.0f);
Bitmap bitmapMirror = Bitmap.createBitmap(tempBitmap, 0, 0,
tempBitmap.getWidth(), tempBitmap.getHeight(),
matrixMirror, false);

//define half/half area
Rect rect1Half = new Rect(0, 0, tempBitmap.getWidth() / 2,
tempBitmap.getHeight());
Rect rect2Half = new Rect((tempBitmap.getWidth() / 2) + 1,
0, tempBitmap.getWidth(), tempBitmap.getHeight());

Config config = tempBitmap.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}

//craete the master bitmap
bitmapMaster = Bitmap.createBitmap(
tempBitmap.getWidth(), tempBitmap.getHeight(), config);
canvasMaster = new Canvas(bitmapMaster);

//merge bitmap half/half
canvasMaster.drawBitmap(tempBitmap, rect1Half, rect1Half,
null);
canvasMaster.drawBitmap(bitmapMirror, rect2Half, rect2Half,
null);

imageResult.setImageBitmap(bitmapMaster);

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

break;
}
}
}

}


<LinearLayout 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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/loadimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Image 1" />

<TextView
android:id="@+id/sourceuri"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@android:color/background_dark"
android:scaleType="centerInside" />

</LinearLayout>


download filesDownload the files.



more: Something about processing images in Android