Breaking News
Loading...
Wednesday 3 October 2012

What's HSV (hue, saturation, value)?

15:52
HSV is one of the most common cylindrical-coordinate representations of points in an RGB color model. It rearrange the geometry of RGB in an attempt to be more intuitive and perceptually relevant than the cartesian (cube) representation. It is used today in color pickers, in image editing software, and less commonly in image analysis and computer vision. ~ To know more: refer Wikipedia - HSL and HSV.

Last exercise demonstrate "how to convert between HSV and RGB Color". it's modified to represent the hue, saturation, value components of HSV separately in red, green and blue images, such that you can understand it easier.

HSV (hue, saturation, value)

package com.example.androidcolor;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.widget.ImageView;

public class MainActivity extends Activity {

ImageView imgSource, imgTarget;
ImageView imgHue, imgSat, imgVal;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgSource = (ImageView)findViewById(R.id.imgsource);
imgTarget = (ImageView)findViewById(R.id.imgtarget);
imgHue = (ImageView)findViewById(R.id.imghue);
imgSat = (ImageView)findViewById(R.id.imgsat);
imgVal = (ImageView)findViewById(R.id.imgval);

//Load bitmap from internet
String onLineImgSource = "http://goo.gl/yxNeG";
URL urlImgSource;

try {
urlImgSource = new URL(onLineImgSource);
new MyNetworkTask(imgSource, imgTarget, imgHue, imgSat, imgVal)
.execute(urlImgSource);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}

private class MyNetworkTask extends AsyncTask<URL, Void, Bitmap>{

ImageView ivSource, ivTarget;
ImageView ivHue, ivSat, ivVal;

public MyNetworkTask(ImageView iSource, ImageView iTarget,
ImageView iHue, ImageView iSat, ImageView iVal){
ivSource = iSource;
ivTarget = iTarget;
ivHue = iHue;
ivSat = iSat;
ivVal = iVal;
}

@Override
protected Bitmap doInBackground(URL... urls) {
Bitmap networkBitmap = null;

URL networkUrl = urls[0]; //Load the first element
try {
networkBitmap = BitmapFactory.decodeStream(
networkUrl.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}

return networkBitmap;
}

@Override
protected void onPostExecute(Bitmap result) {
ivSource.setImageBitmap(result);

GroupBitmap groupBMResult = convertColorHSVColor(result);

ivTarget.setImageBitmap(groupBMResult.bitmapDest);
ivHue.setImageBitmap(groupBMResult.bitmapHue);
ivSat.setImageBitmap(groupBMResult.bitmapSat);
ivVal.setImageBitmap(groupBMResult.bitmapVal);
}

}

class GroupBitmap {
Bitmap bitmapHue;
Bitmap bitmapSat;
Bitmap bitmapVal;
Bitmap bitmapDest;
};

//Convert Bitmap from Color to HSV, then HSV to Color
private GroupBitmap convertColorHSVColor(Bitmap src){

GroupBitmap convertedGroupBitmap = new GroupBitmap();

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

int[] mapSrcColor = new int[w * h];
int[] mapDestColor= new int[w * h];

int[] mapHue = new int[w * h];
int[] mapSat = new int[w * h];
int[] mapVal = new int[w * h];

float[] pixelHSV = new float[3];
/*
* pixelHSV[0] : Hue (0 .. 360)
* pixelHSV[1] : Saturation (0...1)
* pixelHSV[2] : Value (0...1)
*/

src.getPixels(mapSrcColor, 0, w, 0, 0, w, h);
/*
* getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
* - Returns in pixels[] a copy of the data in the bitmap. Each value is a packed int representing a Color.
*
* pixels: The array to receive the bitmap's colors
* offset: The first index to write into pixels[]
* stride: The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative.
* x: The x coordinate of the first pixel to read from the bitmap
* y: The y coordinate of the first pixel to read from the bitmap
* width: The number of pixels to read from each row
* height: The number of rows to read
*
*/

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);

/*
* Represent Hue, Saturation and Value in separated color
* of R, G, B.
*/
mapHue[index] = Color.rgb((int)(pixelHSV[0] * 255/360), 0, 0);
mapSat[index] = Color.rgb(0, (int)(pixelHSV[1] * 255), 0);
mapVal[index] = Color.rgb(0, 0, (int)(pixelHSV[2] * 255));

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

index++;
}
}

Config destConfig = src.getConfig();
/*
* If the bitmap's internal config is in one of the public formats, return that config,
* otherwise return null.
*/

if (destConfig == null){
destConfig = Config.RGB_565;
}

convertedGroupBitmap.bitmapHue = Bitmap.createBitmap(mapHue, w, h, Config.RGB_565);
convertedGroupBitmap.bitmapSat = Bitmap.createBitmap(mapSat, w, h, Config.RGB_565);
convertedGroupBitmap.bitmapVal = Bitmap.createBitmap(mapVal, w, h, Config.RGB_565);
convertedGroupBitmap.bitmapDest = Bitmap.createBitmap(mapDestColor, w, h, destConfig);

return convertedGroupBitmap;
}

}


<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" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
tools:context=".MainActivity" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/imgsource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/imgtarget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imghue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/imgsat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/imgval"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</ScrollView>

</LinearLayout>


Remark: Permission of "android.permission.INTERNET" is needed in this exercise to load Bitmap from internet.

download filesDownload the files.

Next:
- Adjust hue, saturation, and brightness by changing of HSV


0 comments:

Post a Comment

 
Toggle Footer