Sepia Image effect in Blackberry - blackberry

I am trying to apply Sepia effect on an Image in Blackberry.
I have tried it but doesn't get the 100% sepia effect.
This is code that I have tried for sepia effect.
I have used getARGB() and setARGB() methods of bitmap class.
public Bitmap changetoSepiaEffect(Bitmap bitmap) {
int sepiaIntensity=30;//value lies between 0-255. 30 works well
// Play around with this. 20 works well and was recommended
// by another developer. 0 produces black/white image
int sepiaDepth = 20;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
// WritableRaster raster = img.getRaster();
// We need 3 integers (for R,G,B color values) per pixel.
int[] pixels = new int[w*h*3];
// raster.getPixels(0, 0, w, h, pixels);
bitmap.getARGB(pixels, 0, w, x, y, w, h);
// Process 3 ints at a time for each pixel.
// Each pixel has 3 RGB colors in array
for (int i=0;i<pixels.length; i+=3) {
int r = pixels[i];
int g = pixels[i+1];
int b = pixels[i+2];
int gry = (r + g + b) / 3;
r = g = b = gry;
r = r + (sepiaDepth * 2);
g = g + sepiaDepth;
if (r>255) r=255;
if (g>255) g=255;
if (b>255) b=255;
// Darken blue color to increase sepia effect
b-= sepiaIntensity;
// normalize if out of bounds
if (b<0) {
b=0;
}
if (b>255) {
b=255;
}
pixels[i] = r;
pixels[i+1]= g;
pixels[i+2] = b;
}
//raster.setPixels(0, 0, w, h, pixels);
bitmap.setARGB(pixels, 0, w, 0, 0, w, h);
return bitmap;
}

This call:
bitmap.getARGB(pixels, 0, w, x, y, w, h);
returns an int[] array where each int represents a color in the format 0xAARRGGBB. This differs from you previous code using JavaSE's Raster class.
EDIT: The method fixed for BlackBerry:
public static Bitmap changetoSepiaEffect(Bitmap bitmap) {
int sepiaIntensity = 30;// value lies between 0-255. 30 works well
// Play around with this. 20 works well and was recommended
// by another developer. 0 produces black/white image
int sepiaDepth = 20;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
// Unlike JavaSE's Raster, we need an int per pixel
int[] pixels = new int[w * h];
// We get the whole image
bitmap.getARGB(pixels, 0, w, 0, 0, w, h);
// Process each pixel component. A pixel comes in the format 0xAARRGGBB.
for (int i = 0; i < pixels.length; i++) {
int r = (pixels[i] >> 16) & 0xFF;
int g = (pixels[i] >> 8) & 0xFF;
int b = pixels[i] & 0xFF;
int gry = (r + g + b) / 3;
r = g = b = gry;
r = r + (sepiaDepth * 2);
g = g + sepiaDepth;
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
// Darken blue color to increase sepia effect
b -= sepiaIntensity;
// normalize if out of bounds
if (b < 0) {
b = 0;
}
if (b > 255) {
b = 255;
}
// Now we compose a new pixel with the modified channels,
// and an alpha value of 0xFF (full opaque)
pixels[i] = ((r << 16) & 0xFF0000) | ((g << 8) & 0x00FF00) | (b & 0xFF) | 0xFF000000;
}
// We return a new Bitmap. Trying to modify the one passed as parameter
// could throw an exception, since in BlackBerry not all Bitmaps are modifiable.
Bitmap ret = new Bitmap(w, h);
ret.setARGB(pixels, 0, w, 0, 0, w, h);
return ret;
}

Related

How do I convert ByteArray from ImageMetaData() to Bitmap?

I have this code:
Frame frame = mSession.update();
Camera camera = frame.getCamera();
...
bytes=frame.getImageMetadata().getByteArray(0);
System.out.println("Byte Array "+frame.getImageMetadata().getByteArray(0));
Bitmap bmp = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
System.out.println(bmp);
When I print Bitmap, I get a null object. I'm trying to get the image from the camera, that's the reason I'm trying to convert byteArray to Bitmap. If there's an alternative way, it would also be helpful.
Thank You.
The ImageMetaData describes the background image, but does not actually contain the image itself.
If you want to capture the background image as a Bitmap, you should look at the computervision sample which uses a FrameBufferObject to copy the image to a byte array.
I've tried something similar. It works. But I don't recommend anyone to try this way. It takes time because of nested loops.
CameraImageBuffer inputImage;
final Bitmap bmp = Bitmap.createBitmap(inputImage.width, inputImage.height, Bitmap.Config.ARGB_8888);
int width = inputImage.width;
int height = inputImage.height;
int frameSize = width*height;
// Write Bytebuffer to byte[]
byte[] imageBuffer= new byte[inputImage.buffer.remaining()];
inputImage.buffer.get(imageBuffer);
int[] rgba = new int[frameSize];
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++) {
int r =imageBuffer[(i * width + j)*4 + 0];
int g =imageBuffer[(i * width + j)*4 + 1];
int b =imageBuffer[(i * width + j)*4 + 2];
rgba[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r;
}
}
bmp.setPixels(rgba, 0, width , 0, 0, width, height);
Bytebuffer is converted to rgba buffer, and is written to Bitmap. CameraImageBuffer is the class provided in computervision sample app.
You may not able to get bitmap using image metadata. Use below approach.Use onDrawFrame override method of surface view render.
#Override public void onDrawFrame(GL10 gl) {
int w = 1080;
int h = 1080;
int b[] = new int[w * (0 + h)];
int bt[] = new int[w * h];
IntBuffer ib = IntBuffer.wrap(b);
ib.position(0);
GLES20.glReadPixels(0, 0, w, h, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ib);
for (int i = 0, k = 0; i < h; i++, k++) {
for (int j = 0; j < w; j++) {
int pix = b[i * w + j];
int pb = (pix >> 16) & 0xff;
int pr = (pix << 16) & 0x00ff0000;
int pix1 = (pix & 0xff00ff00) | pr | pb;
bt[(h - k - 1) * w + j] = pix1;
}
}
Bitmap mBitmap = Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
runOnUiThread(new Runnable() {
#Override public void run() {
image_test.setImageBitmap(resizedBitmap);
}
});
}

converting RGB to YCbCr in OpenCV

I am currently converting image from RGB to YCrCb format using OpenCV function -cvtColor. I would like perform the conversion on my own with equations similar to
//equations for RGB to YUV conversion
Y' = 0.299 R + 0.587 G + 0.114 B
U = -0.147 R - 0.289 G + 0.436 B
V = 0.615 R - 0.515 G - 0.100 B.
I am not able to understand OpenCV image matrix operation. I would like to access RGB pixel values from image Mat so that I can perform the conversion myself. How can I get R,G,B values from image and then how to apply the transformation ? My current code below.
int main (int argc, char *argv[])
{
// Load in image
cv::Mat src = cv ::imread("C:\\openv2410\\frames\\frame_0.png",1);
// Create a vector for the channels and split the original image into B G R colour channels.
// Keep in mind that OpenCV uses BGR and not RGB images
vector<cv::Mat> spl;
split(src,spl);
// Create an zero pixel image for filling purposes - will become clear later
// Also create container images for B G R channels as colour images
cv::Mat empty_image = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
cv::Mat empty_channel = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
cv::Mat result_blue(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
cv::Mat result_green(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
cv::Mat result_red(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
// Create blue channel
cv::Mat in1[] = { spl[0], empty_image, empty_image };
int from_to1[] = { 0,0, 1,1, 2,2 };
mixChannels( in1, 3, &result_blue, 1, from_to1, 3 );
// Create green channel
cv::Mat in2[] = { empty_channel, spl[1], empty_image };
int from_to2[] = { 0,0, 1,1, 2,2 };
mixChannels( in2, 3, &result_green, 1, from_to2, 3 );
// Create red channel
cv::Mat in3[] = { empty_channel, empty_channel, spl[2]};
int from_to3[] = { 0,0, 1,1, 2,2 };
mixChannels( in3, 3, &result_red, 1, from_to3, 3 );
imshow("blue channel",result_blue);
imshow("green channel",result_green);
imshow("red channel",result_red);
cv::waitKey(0);
return 0;
}
Sample code for conversion from BGR to YCrCb. Source(1).
//sample input and output
float data[3][1] = { 98,76,88 };
Mat input( 1, 1, CV_32FC3, data) ;
Mat output( 1, 1, CV_32FC3 );
//iterate over all pixels
for(int i = 0; i < input.rows; i++) {
for(int j = 0; j < input.cols; j++) {
//get bgr pixel
Vec3f bgrPixel = input.at<Vec3f>(i, j);
float B = bgrPixel[0];
float G = bgrPixel[1];
float R = bgrPixel[2];
//actual conversion from BGR to YCrCb
float delta = 0.5f;
float Y = 0.299f * R + 0.587f * G + 0.114f * B;
float Cb = (B - Y) * 0.564f + delta;
float Cr = (R - Y) * 0.713f + delta;
//store into result image
Vec3f yCrCbPixel( Y, Cr, Cb );
output.at<Vec3f>(i, j) = yCrCbPixel;
}
}

How to draw Optical flow images from ocl::PyrLKOpticalFlow::dense()

How to draw Optical flow images from ocl::PyrLKOpticalFlow::dense() Which actually calculates both horizontal and vertical component of the Optical flow? So I don't know how to draw them. I'm new to opencv . Can anyone help me?
Syntax :
ocl::PyrLKOpticalFlow::dense(oclMat &prevImg, oclMat& nextImg, oclMat& u, oclMat &v,oclMat &err)
A well establische method used in the optical flow community is to display a motion vector field as a color coded image as you can see at one of the various data sets. E.g MPI dataset or the Middlebury dataset.
Therefor you estimate the length and the angle of your motion vector. And use a HSV to RGB colorspace transformation (see OpenCV cvtColor function) to create your color coded image. Use the angle of your motion vector as H (Hue) - channel and the normalized length as the S (Saturation) - channel and set V (Value) to 1. The the color of your image will show you the direction of your motion and the saturation the length ( speed ).
The code will should like this ( Note if use_value == true, the Saturation will be set to 1 and the Value channel is related to the motion vector length):
void FlowToRGB(const cv::Mat & inpFlow,
cv::Mat & rgbFlow,
const float & max_size ,
bool use_value)
{
if(inpFlow.empty()) return;
if( inpFlow.depth() != CV_32F)
throw(std::exception("FlowToRGB: error inpFlow wrong data type ( has be CV_32FC2"));
const float grad2deg = (float)(90/3.141);
cv::Mat pol(inpFlow.size(), CV_32FC2);
float mean_val = 0, min_val = 1000, max_val = 0;
float _dx, _dy;
for(int r = 0; r < inpFlow.rows; r++)
{
for(int c = 0; c < inpFlow.cols; c++)
{
cv::Point2f polar = cvmath::toPolar(inpFlow.at<cv::Point2f>(r,c));
polar.y *= grad2deg;
mean_val +=polar.x;
max_val = MAX(max_val, polar.x);
min_val = MIN(min_val, polar.x);
pol.at<cv::Point2f>(r,c) = cv::Point2f(polar.y,polar.x);
}
}
mean_val /= inpFlow.size().area();
float scale = max_val - min_val;
float shift = -min_val;//-mean_val + scale;
scale = 255.f/scale;
if( max_size > 0)
{
scale = 255.f/max_size;
shift = 0;
}
//calculate the angle, motion value
cv::Mat hsv(inpFlow.size(), CV_8UC3);
uchar * ptrHSV = hsv.ptr<uchar>();
int idx_val = (use_value) ? 2:1;
int idx_sat = (use_value) ? 1:2;
for(int r = 0; r < inpFlow.rows; r++, ptrHSV += hsv.step1())
{
uchar * _ptrHSV = ptrHSV;
for(int c = 0; c < inpFlow.cols; c++, _ptrHSV+=3)
{
cv::Point2f vpol = pol.at<cv::Point2f>(r,c);
_ptrHSV[0] = cv::saturate_cast<uchar>(vpol.x);
_ptrHSV[idx_val] = cv::saturate_cast<uchar>( (vpol.y + shift) * scale);
_ptrHSV[idx_sat] = 255;
}
}
cv::Mat rgbFlow32F;
cv::cvtColor(hsv, rgbFlow32F, CV_HSV2BGR);
rgbFlow32F.convertTo(rgbFlow, CV_8UC3);}
}
Python
Please refer to opt_flow.py#draw_flow
def draw_flow(img, flow, step=16):
h, w = img.shape[:2]
y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
fx, fy = flow[y,x].T
lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
lines = np.int32(lines + 0.5)
vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.polylines(vis, lines, 0, (0, 255, 0))
for (x1, y1), (x2, y2) in lines:
cv2.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
return vis
C++
Please can refer to tvl1_optical_flow.cpp#drawOpticalFlow
static void drawOpticalFlow(const Mat_<Point2f>& flow, Mat& dst, float maxmotion = -1)
{
dst.create(flow.size(), CV_8UC3);
dst.setTo(Scalar::all(0));
// determine motion range:
float maxrad = maxmotion;
if (maxmotion <= 0)
{
maxrad = 1;
for (int y = 0; y < flow.rows; ++y)
{
for (int x = 0; x < flow.cols; ++x)
{
Point2f u = flow(y, x);
if (!isFlowCorrect(u))
continue;
maxrad = max(maxrad, sqrt(u.x * u.x + u.y * u.y));
}
}
}
for (int y = 0; y < flow.rows; ++y)
{
for (int x = 0; x < flow.cols; ++x)
{
Point2f u = flow(y, x);
if (isFlowCorrect(u))
dst.at<Vec3b>(y, x) = computeColor(u.x / maxrad, u.y / maxrad);
}
}
}
I did something like this in my code, a while ago:
calcOpticalFlowPyrLK(frame_prec,frame_cur,v_corners_prec[i],corners_cur,status, err);
for(int j=0; j<corners_cur.size(); j++){
if(status[j]){
line(frame_cur,v_corners_prec[i][j],corners_cur[j],colors[i]);
}
}
Basically I draw a line between the points tracked by the OF in this iteration and the previous ones, this draws the optical flow lines which represent the flow on the image.
Hope this helps..

Monochrome and Negative effect on image for blackberry

I am new for blackberry app development.just a week before I start BB development.I had a project on image effects and controll. Now I am facing problems in converting images to negative and monochrome effetcs.
I have tried the following code for negative effetc. I have got the output for negative image.But I dont get image background right... It shows me blue background.....
final static double GS_RED = 0.299;//globally declared
final static double GS_GREEN = 0.587;
final static double GS_BLUE = 0.114;
public Bitmap changeToNegativeEffect(Bitmap bitmap) {
int[] argbData = new int[bitmap.getWidth() * bitmap.getHeight()];
int[] newargb = new int[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getARGB(argbData, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
for ( int i = argbData.length-1; i >= 0; i--)
{
A= 255 -argbData[i] >> 24;
R= 255 -argbData[i] >> 16 & 0xFF;
G= 255 -argbData[i] >> 8 & 0xFF;
B= 255 -argbData[i] & 0xFF;
//R = G = B = (int)(GS_RED * R + GS_GREEN * G + GS_BLUE * B);
//int composite=(A << 24) | (R << 16) | (G << 8) | B;
argbData[i] = (0xff000000 | R<< 16 | G << 8 | B );
newargb[i] = argbData[i];
}
bitmap.setARGB(newargb, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
return bitmap;
}

Convert a Bitmap image to grayscale within BlackBerry J2Me

I have been trying to use the samples from here:
J2ME: Convert transparent PNG image to grayscale
and here:
http://www.java2s.com/Code/Java/Collections-Data-Structure/intarraytobytearray.htm
to convert an Bitmap image object to grayscale on the fly but I am running into issues when I am trying to re-encode my byte to an image and I get the following error/stack:
(Suspended (exception IllegalArgumentException))
EncodedImage.createEncodedImage(byte[], int, int, String) line: 367
EncodedImage.createEncodedImage(byte[], int, int) line: 279
ScreenTemp.getGrayScaleImage(Bitmap) line: 404
Here is my code I am trying:
Bitmap btemp = getGrayScaleImage(Bitmap.getBitmapResource("add.png"));
BitmapField bftemp = new BitmapField(btemp, BitmapField.FOCUSABLE | BitmapField.FIELD_HCENTER | BitmapField.FIELD_VCENTER);
add(bftemp);
public Bitmap getGrayScaleImage(Bitmap image) {
int width = image.getWidth();
int height = image.getHeight();
int[] rgbData = new int[width * height];
image.getARGB(rgbData, 0, width, 0, 0, width, height);
for (int x = 0; x < width*height ; x++) {
rgbData[x] = getGrayScale(rgbData[x]);
}
byte[] b = int2byte(rgbData);
final EncodedImage jpegPic = EncodedImage.createEncodedImage(b, 0, b.length);
return jpegPic.getBitmap();
}
private int getGrayScale(int c) {
int[] p = new int[4];
p[0] = (int) ((c & 0xFF000000) >>> 24); // Opacity level
p[1] = (int) ((c & 0x00FF0000) >>> 16); // Red level
p[2] = (int) ((c & 0x0000FF00) >>> 8); // Green level
p[3] = (int) (c & 0x000000FF); // Blue level
int nc = p[1] / 3 + p[2] / 3 + p[3] / 3;
// a little bit brighter
nc = nc / 2 + 127;
p[1] = nc;
p[2] = nc;
p[3] = nc;
int gc = (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
return gc;
}
private static byte[] int2byte(int[] src) {
int srcLength = src.length;
byte[]dst = new byte[srcLength << 2];
for (int i=0; i<srcLength; i++) {
int x = src[i];
int j = i << 2;
dst[j++] = (byte) ((x >>> 0) & 0xff);
dst[j++] = (byte) ((x >>> 8) & 0xff);
dst[j++] = (byte) ((x >>> 16) & 0xff);
dst[j++] = (byte) ((x >>> 24) & 0xff);
}
return dst;
}
Any help would be great!
Thanks,
Justin
EDIT:
Thanks to the below information I was able to fix this issue. Here is the code. You no longer need the int2byte and here is the updated the getGrayScaleImage method:
public Bitmap getGrayScaleImage(Bitmap image) {
int width = image.getWidth();
int height = image.getHeight();
int[] rgbData = new int[width * height];
image.getARGB(rgbData, 0, width, 0, 0, width, height);
for (int x = 0; x < width*height ; x++) {
rgbData[x] = getGrayScale(rgbData[x]);
}
byte[] b = int2byte(rgbData);
Bitmap bit = new Bitmap(width, height);
bit.setARGB(rgbData, 0, width, 0, 0, width, height);
return bit;
}
Quoting from the EncodedImage javadoc:
If the image format is not recognized, an IllegalArgumentException is thrown.
Why are you fiddling with EncodedImage? It seems like you ought to be able to just create a second Bitmap and use setARGB().
To extend Scott W answer.
EncodedImage.createEncodedImage(byte[] data, int offset, int length) expects a byte array of a supported image type (TIFF, BMP, JPEG, GIF, WBMP or PNG). For instance, if you opened a JPEG image file, read the file bytes, then it would be possible to use the got bytes to create an EncodedImage (it would be JPEGEncodedImage actually).
So as Scott W says you should use Bitmap.setARGB() for the resulting byte array to have a Bitmap with converted data.
And then if you need to save the image as a JPEG file, you can use smth like this:
JPEGEncodedImage eImage = JPEGEncodedImage.encode(bitmap, 75);
byte[] fileData = eImage.getData();
// open a FileConnection and write the fileData

Resources