How to set an Image border on BlackBerry Screen - blackberry

I have a List Items(an Image and text)on BB Screen,
My requirement is to set an image border(So that Image Separation will be done on List Items) to image on BB Screen
Could any one help?
Here My Code:
public void drawListRow(ListField list, Graphics g, int index, int y,
int width) {
String title = (String) listElements.elementAt(index);
Bitmap image = (Bitmap) listImage.elementAt(index);
int LEFT_OFFSET = 2;
int TOP_OFFSET = 8;
int xpos = LEFT_OFFSET;
int ypos = TOP_OFFSET + y;
int w = image.getWidth();
int h = image.getHeight();
g.drawBitmap(xpos, ypos, w, h, image, 4, 6);
xpos = w + 20;
g.setFont(myFont);
g.setColor(Color.BLACK);
g.drawText(title, xpos, ypos);
}

i hope i got your question right and would suggest you drawing a rectangle around the image like that:
g.setColor(Color.RED);
g.drawRect(xpos - 1, ypos - 1, w + 1, h + 1);
This would draw the rectangle around your image without overlapping it. For more details on why you need these adjustments of the position and the size of the rectangle you can check on the documentation of Graphics class here http://www.it.uc3m.es/florina/docencia/j2me/midp/docs/api/javax/microedition/lcdui/Graphics.html

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

Scrolling Image using PixelWriter / Reader

I'm trying to create a scrolling image that wraps around a canvas to follow its own tail. I've been trying to use PixelWriters and Readers to save off the vertical pixel lines that are scrolling off the screen to the West, and append these to a new image which, should grow on the RHS (East) of the screen.
It scrolls, but that's all that's happening. I don't understand how to calculate the scanlines, so apologies for this part.
Any help appreciated.
package controller;
import javafx.animation.AnimationTimer;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import util.GraphicsUtils;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
class ImageContainer extends HBox {
int w, h;
int translatedAmount = 0;
Image image;
Canvas canvas;
long startNanoTime = System.nanoTime();
WritableImage eastImage = null;
public ImageContainer() {
setVisible(true);
load();
w = (int) image.getWidth();
h = (int) image.getHeight();
canvas = new Canvas(w, h);
int edgeX = (int) canvas.getWidth(); //You can set this a little west for visibility sake...whilst debugging
getChildren().addAll(canvas);
GraphicsContext gc = canvas.getGraphicsContext2D();
canvas.setVisible(true);
gc.drawImage(image, 0, 0, w, h);
setPrefSize(w, h);
eastImage = new WritableImage(translatedAmount+1, h); //create a new eastImage
new AnimationTimer() {
public void handle(long currentNanoTime) {
if (((System.nanoTime() - startNanoTime) / 1000000000.0) < 0.05) {
return;
} else {
startNanoTime = System.nanoTime();
}
translatedAmount++;
Image westLine = getSubImageRectangle(image, 1, 0, 1, h); //get a 1 pixel strip from west of main image
PixelReader westLinepixelReader = westLine.getPixelReader(); //create a pixel reader for this image
byte[] westLinePixelBuffer = new byte[1 * h * 4]; //create a buffer to store the pixels collected from the about to vanish westLine
westLinepixelReader.getPixels(0, 0, 1, h, PixelFormat.getByteBgraInstance(), westLinePixelBuffer, 0, 4); //collect the pixels from westLine strip
Image tempImg = eastImage; //save away the current east side image
byte[] tempBuffer = new byte[(int)tempImg.getWidth() * h * 4];
PixelReader tempImagePixelReader = tempImg.getPixelReader(); //create a pixel reader for our temp copy of the east side image
tempImagePixelReader.getPixels(0, 0, (int)tempImg.getWidth(), h, PixelFormat.getByteBgraInstance(), tempBuffer, 0, 4); //save the tempImage into the tempBuffer
eastImage = new WritableImage(translatedAmount+1, h); //create a new eastImage, but one size larger
PixelWriter eastImagePixelWriter = eastImage.getPixelWriter(); //create a pixel writer for this new east side image
eastImagePixelWriter.setPixels(1, 0, (int)tempImg.getWidth(), h, PixelFormat.getByteBgraInstance(), tempBuffer, 0, 4); //copy the temp image in at x=1
eastImagePixelWriter.setPixels((int)tempImg.getWidth(), 0, 1, h, PixelFormat.getByteBgraInstance(), westLinePixelBuffer, 0, 4); //copy the westLine at x=tempImg.width
image = getSubImageRectangle(image, 1, 0, (int) image.getWidth() - 1, h);
gc.drawImage(image, 0, 0); //draw main image
System.out.println(edgeX-eastImage.getWidth());
gc.drawImage(eastImage, edgeX-eastImage.getWidth(), 0); //add lost image lines
}
}.start();
}
public void load() {
Path imagePath = Paths.get("./src/main/resources/ribbonImages/clouds.png");
File f = imagePath.toFile();
assert f.exists();
image = new Image(f.toURI().toString());
}
public Image getSubImageRectangle(Image image, int x, int y, int w, int h) {
PixelReader pixelReader = image.getPixelReader();
WritableImage newImage = new WritableImage(pixelReader, x, y, w, h);
ImageView imageView = new ImageView();
imageView.setImage(newImage);
return newImage;
}
}
Why make this more difficult than necessary? Simply draw the image to the Canvas twice:
public static void drawImage(Canvas canvas, Image sourceImage, double offset, double wrapWidth) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
// make |offset| < wrapWidth
offset %= wrapWidth;
if (offset < 0) {
// make sure positive offsets do not result in the previous version
// of the image not being drawn
offset += wrapWidth;
}
gc.drawImage(sourceImage, -offset, 0);
gc.drawImage(sourceImage, wrapWidth - offset, 0);
}
#Override
public void start(Stage primaryStage) {
Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/402px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg");
Canvas canvas = new Canvas(image.getWidth(), image.getHeight());
primaryStage.setResizable(false);
Scene scene = new Scene(new Group(canvas));
DoubleProperty offset = new SimpleDoubleProperty();
offset.addListener((observable, oldOffset, newOffset) -> drawImage(canvas, image, newOffset.doubleValue(), canvas.getWidth()));
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(offset, 0, Interpolator.LINEAR)),
new KeyFrame(Duration.seconds(10), new KeyValue(offset, image.getWidth()*2, Interpolator.LINEAR))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
}

Advanced denoise Image using Opencv

I am trying denoise this image to get better edges
I've tried bilaterFilter, GaussianBlur, morphological close and several threshold but every time I get an image like:
and when I do the HoughLinesP with dilatation of edges is really bad result.
Can some one help me to improve this? Is there a some way to take out those noise?
Frist try: using GaussianBlur, in this case, I must use equalizeHist or I cant get edges even if I use a really low threshold
public class TesteNormal {
static {
System.loadLibrary("opencv_java310");
}
public static void main(String args[]) {
Mat imgGrayscale = new Mat();
Mat imgBlurred = new Mat();
Mat imgCanny = new Mat();
Mat image = Imgcodecs.imread("c:\\cordova\\imagens\\teste.jpg", 1);
int imageWidth = image.width();
int imageHeight = image.height();
Imgproc.cvtColor(image, imgGrayscale, Imgproc.COLOR_BGR2GRAY);
Imgproc.equalizeHist(imgGrayscale, imgGrayscale);
Imgproc.GaussianBlur(imgGrayscale, imgBlurred, new Size(5, 5), 1.8);
Photo.fastNlMeansDenoising(imgBlurred, imgBlurred);
Imshow.show(imgBlurred);
Mat imgKernel = Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3));
Imgproc.Canny(imgBlurred, imgCanny, 0, 80);
Imshow.show(imgCanny);
Imgproc.dilate(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 2);
Imgproc.erode(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 1);
Imshow.show(imgCanny);
Mat lines = new Mat();
int threshold = 100;
int minLineSize = imageWidth < imageHeight ? imageWidth / 3 : imageHeight / 3;
int lineGap = 5;
Imgproc.HoughLinesP(imgCanny, lines, 1, Math.PI / 360, threshold, minLineSize, lineGap);
System.out.println(lines.rows());
for(int x = 0; x < lines.rows(); x++) {
double[] vec = lines.get(x, 0);
double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
Point start = new Point(x1, y1);
Point end = new Point(x2, y2);
Imgproc.line(image, start, end, new Scalar(255, 0, 0), 1);
}
Imshow.show(image);
}
}
Second try: using bilateral filter:
public class TesteNormal {
static {
System.loadLibrary("opencv_java310");
}
public static void main(String args[]) {
Mat imgBlurred = new Mat();
Mat imgCanny = new Mat();
Mat image = Imgcodecs.imread("c:\\cordova\\imagens\\teste.jpg", 1);
int imageWidth = image.width();
int imageHeight = image.height();
Imgproc.bilateralFilter(image, imgBlurred, 10, 35, 35);
Imshow.show(imgBlurred);
Mat imgKernel = Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3));
Imgproc.Canny(imgBlurred, imgCanny, 0, 120);
Imshow.show(imgCanny);
Imgproc.dilate(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 2);
Imgproc.erode(imgCanny, imgCanny, imgKernel, new Point(-1, -1), 1);
Imshow.show(imgCanny);
Mat lines = new Mat();
int threshold = 100;
int minLineSize = imageWidth < imageHeight ? imageWidth / 3 : imageHeight / 3;
int lineGap = 5;
Imgproc.HoughLinesP(imgCanny, lines, 1, Math.PI / 360, threshold, minLineSize, lineGap);
System.out.println(lines.rows());
for(int x = 0; x < lines.rows(); x++) {
double[] vec = lines.get(x, 0);
double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
Point start = new Point(x1, y1);
Point end = new Point(x2, y2);
Imgproc.line(image, start, end, new Scalar(255, 0, 0), 1);
}
Imshow.show(image);
}
}
As suggested, I am trying use opencv contrib, using StructuredEdgeDetection. I am testing using a fixed image.
Frist I compile opencv with contrib
Segund I wrote the C++ code:
JNIEXPORT jobject JNICALL Java_vi_pdfscanner_main_ScannerEngine_getRandomFlorest(JNIEnv *env, jobject thiz) {
Mat mbgra = imread("/storage/emulated/0/Resp/coco.jpg", 1);
Mat3f fsrc;
mbgra.convertTo(fsrc, CV_32F, 1.0 / 255.0); // when I run those convertTo, I got all back image, that way I got no edges.
const String model = "/storage/emulated/0/Resp/model.yml.gz";
Ptr<cv::ximgproc::StructuredEdgeDetection> pDollar = cv::ximgproc::createStructuredEdgeDetection(model);
Mat edges;
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "chamando edges");
pDollar->detectEdges(fsrc, edges);
imwrite( "/storage/emulated/0/Resp/edges.jpg", edges);
jclass java_bitmap_class = (jclass)env->FindClass("android/graphics/Bitmap");
jmethodID mid = env->GetMethodID(java_bitmap_class, "getConfig", "()Landroid/graphics/Bitmap$Config;");
jobject bitmap_config = env->CallObjectMethod(bitmap, mid);
jobject _bitmap = mat_to_bitmap(env,edges,false,bitmap_config);
return _bitmap;
}
and I wrote this java wapper
public class ScannerEngine {
private static ScannerEngine ourInstance = new ScannerEngine();
public static ScannerEngine getInstance() {
return ourInstance;
}
private ScannerEngine() {
}
public native Bitmap getRandomFlorest(Bitmap bitmap);
static {
System.loadLibrary("opencv_java3");
System.loadLibrary("Scanner");
}
}
this point is, when I run those lines
Mat mbgra = imread("/storage/emulated/0/Resp/coco.jpg", 1); //image is ok
Mat3f fsrc;
mbgra.convertTo(fsrc, CV_32F, 1.0 / 255.0); //now image got all back, someone have some ideia why?
Thanks very much!
The Result about are strong, like this
Original Image:
http://prntscr.com/cyd8qi
Edges Image:
http://prntscr.com/cyd9ax
Its run on android 4.4 (api lvl 19) in a really old device.
That's all,
Thanks you very much

Improve javaFx processing performance

I'm working on Image processing with javaFx. I think that my code is not enouth efficient (With HD images, refresh is very slow). Because I do a for on each pixel of my image everytime I have to refresh it. But I don't know how to do differently.
So I need help to improve the performance of my processing.
This is my code :
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Example extends Application {
private Image src;
private WritableImage dest;
private int width;
private int height;
int value = 0;
#Override
public void start(Stage stage) {
AnchorPane root = new AnchorPane();
initImage(root);
Scene scene = new Scene(root);
stage.setTitle("Demo processing");
stage.setResizable(false);
stage.setScene(scene);
stage.show();
}
private void initImage(AnchorPane root) {
src = new Image(
"http://mikecann.co.uk/wp-content/uploads/2009/12/ScreenHunter_02-Dec.-10-19.41-1024x484.jpg");
width = (int) src.getWidth();
height = (int) src.getHeight();
root.setPrefSize(800, 800 + 50);
ScrollPane scrollPane = new ScrollPane();
scrollPane.setPrefHeight(600);
scrollPane.setPrefWidth(1000);
dest = new WritableImage(width, height);
ImageView destView = new ImageView(dest);
scrollPane.setContent(destView);
root.getChildren().add(scrollPane);
AnchorPane.setTopAnchor(scrollPane, 0.0);
Slider slider = new Slider(0, 255, 1);
slider.setPrefSize(800, 50);
slider.setShowTickLabels(true);
slider.setShowTickMarks(true);
slider.setSnapToTicks(true);
slider.setMajorTickUnit(1.0);
slider.setMinorTickCount(0);
slider.setLayoutY(700);
slider.valueProperty().addListener(new InvalidationListener() {
#Override
public void invalidated(Observable o) {
value = (int) ((DoubleProperty) o).get();
color();
}
});
root.getChildren().add(slider);
color();
}
private void color() {
PixelReader reader = src.getPixelReader();
PixelWriter writer = dest.getPixelWriter();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
Color color = reader.getColor(x, y);
double red = (double) value * x * y / (width * height) / 255;
double green = color.getGreen();
double blue = (double) value * ((width * height) - x * y)
/ (width * height) / 255;
writer.setColor(x, y, Color.color(red, green, blue));
}
}
}
public static void main(String[] args) {
launch(args);
}
}
And this is with a full HD image :
src = new Image(
"http://www.freedomwallpaper.com//nature-wallpaper-hd/hd_sunshine_hd.jpg");
Getitng color of each pixel in loop is too slow. So, get entire pixels first, and change colors, finally wirte changed colors with PixelWriter.
Like this
private void color() {
PixelReader reader = src.getPixelReader();
WritablePixelFormat<IntBuffer> format = WritablePixelFormat.getIntArgbInstance();
int[] pixels = new int[width * height]; // Buffer for all pixels
reader.getPixels(0, 0, width, height, format, pixels, 0, width); // get all pixels by argb format
int alpha = 0xFF << 24;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int index = x + y * width;
int argb = pixels[index];
int red = value * x * y / (width * height);
int green = (argb >> 8) & 0xFF;
int blue = value * ((width * height) - x * y)
/ (width * height);
int newArgb = alpha | (red << 16) | (green << 8) | blue;
pixels[index] = newArgb;
}
}
PixelWriter writer = dest.getPixelWriter();
writer.setPixels(0, 0, width, height, format, pixels, 0, width); // write entire image
}

Sepia Image effect in 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;
}

Resources