How to divide an image to some parts in android eclipse? - android

I'm designing a puzzle game in android eclipse. I have a picture in resources drawable file named "puzzle_image01". i want to divide this image to 9 parts and put it to some variables. then using them for the puzzle pieces. Now, how can i divide the image to 9 parts?
thank you for your advice.

for(int i = 0; i < 9; ++i) {
int indexY = 0;
if(i < 3) {
imageStartY = 0;
imageFinishY = sourceBitmap.height() / 3;
}
else if(i < 6) {
imageStartY = sourceBitmap.height() / 3;
imageFinishY = (sourceBitmap-height() / 3) * 2;
}
else if(i < 9) {
imageStartY = (sourceBitmap.height() / 3) * 2;
imageFinishY = sourceBitmap.height();
}
Bitmap resizedbitmap = Bitmap.createBitmap(sourceBitmap
, ((sourceBitmap.width()) / 3) * i
, imageStartY
,((sourceBitmap.width()) / 3) * i + sourceBitmap.width()
, imageFinishY)
}

Interesting challenge. Didn't test this, but it should work for any row/column combination where the image's dimensions divided by their respective value is greater than zero:
private Bitmap[][] split(Bitmap bitmap, int rows, int columns){
int[] dimens = new int[]{ bitmap.getWidth() / rows, bitmap.getHeight() / columns };
Bitmap[][] splitMap = new Bitmap[rows][columns];
for(int i = 0; i < rows; i++){
for(int j = 0; j < columns; j++){
splitMap[i][j] = Bitmap.createBitmap(bitmap, i * dimens[0], j * dimens[1], dimens[0], dimens[1]);
}
}
return splitMap;
}

Related

UWP - Changing Alpha on specific pixel in uwp

im struggeling for a long while now. Im trying to change the alpha channel on a specific pixel of a image. I want to convert an image to a 2D array with only alpha channels. I got this working in Android, but don't know how in UWP.
Android version
short[][] dotMapArray;
short[][] heatMapArray;
int[] scolorGradiant;
void init() {
Bitmap dotBitmap = loadImageFromResources(DOT);
Bitmap gradiantBitmap = loadImageFromResources(SPECTRUMPIC);
// initializing the 'dot' for the points on the heatmap
dotMapArray = new short[dotBitmap.getWidth()][dotBitmap.getHeight()];
print(true, "Converting Dot image to black image");
for (int x = 0; x < dotBitmap.getWidth(); x++) {
for (int y = 0; y < dotBitmap.getHeight(); y++) {
dotMapArray[x][y] = (short) (Color.alpha(dotBitmap.getPixel(x, y)));
if (dotMapArray[x][y] > 255)
dotMapArray[x][y] = 255;
}
}
// initializing the color gradiant
scolorGradiant = new int[gradiantBitmap.getHeight()];
int gradiant, pixelColor;
for (int y = 0; y < scolorGradiant.length; y++) {
gradiant = gradiantBitmap.getPixel(0, y); // color
pixelColor = Color.argb(90, Color.red(gradiant), Color.green(gradiant), Color.blue(gradiant));
scolorGradiant[y] = pixelColor;
}
}
How do I do this in UWP?
Can anybody help me?
Here's a loop that checks 1st channel (BGRA) if blue = 255 then all channels go to 0
var pixels = yourWriteableBitmap.PixelBuffer.ToArray();
for (int i = 0; i < pixels.Length; i += 4)
{
if (pixels[i] == 255)
{
pixels[i] = 0;
pixels[i + 1] = 0;
pixels[i + 2] = 0;
pixels[i + 3] = 0;
}
}
using (var stream = yourWriteableBitmap.PixelBuffer.AsStream())
{
await stream.WriteAsync(pixels, 0, pixels.Length);
}

Drawing a Moving Grid on Android Canvas?

Is it possible to create and draw a Moving Grid on a canvas that recycles its points? I want to create a Grid on an android canvas that moves downwards and recycles its points when a point reaches the bottom of the screen.
The First part of the question is: How do I draw a grid with lines on an Android Canvas?
The Second part: How do I make it scroll and repeat?
The grid should look something like this:
I have tried doing this with a Bitmap , but I am not sure if that is as efficient as doing it By using the Draw Line feature. Plus, I cannot access the girds points when using a bitmap, so it is not very useful when trying to draw a graph for example.
I am developing a drawing app, and I encountered the same problem. I searched everywhere, but I could not found a direct solution. That is why I developed a library that do exactly that. It creates a infinite grid that can be transformed, include transformations are: Translate, Rotate and Scale. The library generates only the visible lines, that are shown on the View and are generated in real time using simple math. Here is a direct link to the library
The explanation is pretty simple, if you want to learn more about how it works your can check the Wiki page.
Here is a link to the library source code, if you are interested.
To tag onto Balha's answer:
the android/java equivalent looks something like this:
int canvasWidth = 0;
int canvasHeight = 0;
float gridSize = 20f;
float ecart = Math.max(mCanvasHeight, mCanvasWidth) / gridSize;
//last j index value
int lj= 0;
//last i index value
int li = 0;
canvasWidth = canvas.getWidth();
canvasHeight = canvas.getHeight();
for (int j = 0; j <= Math.min(canvasWidth, canvasHeight); j += (int)ecart)
{
for (int i = 0; i <= Math.max(canvasWidth, canvasHeight); i += (int)ecart)
{
li = i;
}
lj = j;
}
canvas.clipRect(0, 0, lj, canvas.getHeight());
for (int j = 0; j <= Math.min(canvasWidth, canvasHeight); j += (int)ecart)
{
for (int i = 0; i <= Math.max(canvasWidth, canvasHeight); i += (int)ecart)
{
//horizontal lines
canvas.drawLine(j, i, i, i, paint);
//vertical lines
canvas.drawLine(j, i, j, j, paint);
}
}
I know its too late but It can help someone else;
This Draws a perfect grid mesh
Note: This is a c# code
float gridSize = 20f;
var ecart = Math.Max(MaxHeight, MaxWidth) / gridSize;
//last j index value
int lj= 0;
//last i index value
int li = 0;
for (int j = 0; j <= Math.Min(canvas.Width, canvas.Height); j += (int)ecart)
{
for (int i = 0; i <= Math.Max(canvas.Width, canvas.Height); i += (int)ecart)
{
li = i;
}
lj = j;
}
canvas.ClipRect(0, 0, lj, canvas.Height);
for (int j = 0; j <= Math.Min(canvas.Width, canvas.Height); j += (int)ecart)
{
for (int i = 0; i <= Math.Max(canvas.Width, canvas.Height); i += (int)ecart)
{
//horizontal lines
canvas.DrawLine(j, i, i, i, paint);
//vertical lines
canvas.DrawLine(j, i, j, j, paint);
}
}

Linear Color Gradient in openCV

i am trying to create gradient of two colors like Photoshop.
r,g,b of two colors is input and result will be the Mat of gradient. I tried it like for 5 hours at least and i could not find exact effect as of the Photoshop.
I tried to create my own formula (as i could not find any on the web), by changing RGB to HSV and then adding the difference of hue, with respect to the total number of rows, to each row of Mat with and also decreasing intensity to the center of image and then increasing it again. The code is self explanatory.
Additionally if anyone can tell me the exact formula for creating a gradient it will be really helpful.
here is how Photoshop gradient looks like
and this is what i get from my code
int r1, g1, b1, r2, g2, b2;
r1 = 255;
g1 = 0;
b1 = 0;
r2 = 0;
g2 = 255;
b2 = 0;
Mat input = imread("img.jpg");
Mat color1(input.size(), input.type());
Mat color2(input.size(), input.type());
vector<Mat> bgr1;
vector<Mat> bgr2;
split(color1, bgr1);
bgr1[0] = b1;
bgr1[1] = g1;
bgr1[2] = r1;
merge(bgr1, color1);
split(color2, bgr2);
bgr2[0] = b2;
bgr2[1] = g2;
bgr2[2] = r2;
merge(bgr2, color2);
vector<Mat> hls1;
vector<Mat> hls2;
cvtColor(color1, color1, CV_BGRA2BGR);
cvtColor(color1, color1, CV_BGR2HSV);
split(color1, hls1);
cvtColor(color2, color2, CV_BGRA2BGR);
cvtColor(color2, color2, CV_BGR2HSV);
split(color2, hls2);
double h1 = hls1[0].at<uchar>(0, 0);
double h2 = hls2[0].at<uchar>(0, 0);
double dif = (h2 - h1) / input.rows;
double h = h1;
double halfL = 255 / 2;
double halfR = input.rows / 2;
double ldif = halfL / halfR;
double l = 255;
bool isHalf = false;
for (int i = 0; i < input.rows; i++)
{
for (int j = 0; j < input.cols; j++)
{
hls1[0].at<uchar>(i, j) = h;
hls1[2].at<uchar>(i, j) = l;
}
if (isHalf == false){
l -= ldif;
}
else{
l += ldif;
}
if (i < input.rows * 0.40)
{
h += dif * 0.40;
}
else if (i < input.rows * 0.60)
{
h += dif * 3;
}
else
{
h += dif * 0.40;
}
if (i >= input.rows / 2)
{
isHalf = true;
}
}
merge(hls1, color1);
merge(hls2, color2);
cvtColor(color1, color1, CV_HSV2BGR);
cvtColor(color1, color1, CV_BGR2BGRA);
cvtColor(color2, color2, CV_HSV2BGR);
cvtColor(color2, color2, CV_BGR2BGRA);
namedWindow("Color1", cv::WINDOW_NORMAL);
resizeWindow("Color1", color1.size().width / 2, color1.size().height / 2);
imshow("Color1", color1);
waitKey(0);
destroyAllWindows();
system("pause");
I corrected my first code
It seems to be a really complex code for something that should be easier.
I would do something like that.
int taille = 500;
Mat image(taille,taille,CV_8UC3);
for(int y = 0; y < taille; y++){
Vec3b val;
val[0] = 0; val[1] = (y*255)/taille; val[2] = (taille-y)*255/taille;
for(int x = 0; x < taille; x++)
image.at<Vec3b>(y,x) = val;
}
On Micka's advice, I add a picture of the result with taille = 400;

How to convert YUV to RGB efficient

``I want to use RGB in the camera's preview.I used JNI to do the YUV to RGB conversion.I changed the data in RGB,then I show RGB on preview by using drawBitmap.But it shows the very slow,how could I improve it
public void onPreviewFrame(final byte[] data, Camera camera) {
Thread showPic = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Canvas c = mHolder.lockCanvas(null);
try {
synchronized (mHolder) {
// TODO Auto-generated method stub
int imageWidth = mCamera.getParameters()
.getPreviewSize().width;
int imageHeight = mCamera.getParameters()
.getPreviewSize().height;
int RGBData[] = new int[imageWidth * imageHeight];
int RGBDataa[] = new int[imageWidth * imageHeight];
int RGBDatab[] = new int[imageWidth * imageHeight];
int center = imageWidth * imageHeight / 2;
Jni.decodeYUV420SP(RGBData, data, imageWidth,
imageHeight); // decode
for (int i = 0; i < center; i++)
RGBDataa[i] = RGBData[i];
for (int i = center; i < imageWidth * imageHeight; i++)
RGBDatab[i - center] = RGBData[i];
for (int i = 0; i < center; i++)
RGBData[i] = RGBDatab[i];
for (int i = center; i < imageWidth * imageHeight; i++)
RGBData[i] = RGBDataa[i - center];
c.drawBitmap(RGBData, 0, imageWidth, 0, 0, imageWidth,
imageHeight, false, new Paint());
// Bitmap bm = Bitmap.createBitmap(RGBData, imageWidth,
// imageHeight, Config.ARGB_8888);
}
} finally {
if (data != null)
mHolder.unlockCanvasAndPost(c);
}
}
});
showPic.run();
}
The following code is Jni
public class Jni {
public native static void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width,
int height);
}
The method decodeYUV420SP is completed by C.
I came across this thread searching for YUV420sp to RGB565 conversion. Using decodeYUV420SP as suggested above works fine, but I want to add some runtime considerations.
My first test using decodeYUV420SP in Java took 74 seconds decoding and converting a 10 second .mp4 FullHD video (using an Nexus 6 Android device). The profiler reported 96% of the overall process has been spent in decodeYUV420SP.
Moving decodeYUV420SP to JNI / C made made overall time spent go down to 32 seconds. Turning on GCC code optimization, it fell to 12 seconds.
Although the OP suggested this already, I wanted to emphasizes it will not be an improvement to move the routine to Java. While it is correct a context change between Java and C comes at a cost, this is a good example an expensive operation performed in the native function will easily compensate this overhead. The statement on overhead costs is valid for very simple JNI functions and in case method and field lookups back and forth are required. Nothing of this applies here.
To improve the performance of the OP's code: get rid of the memory allocation done for each frame and store it globally, get rid of the arithmetic on RGBData* and move that stuff to JNI too. Arrays can be accessed on JNI level at no cost using the Critical functions.
It's not recommended to use jni because of slow speed for compiler to change java code to C++. I think you should use direct method like this
public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;
rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
}
}
}
OR simply use this
Camera.Parameters.setPreviewFormat(ImageFormat.RGB_565);
to change the format output to rgb directly

onDraw() triggered but results don't show

I have the following routine in a subclass of view:
It calculates an array of points that make up a line, then erases the previous lines, then draws the new lines (impact refers to the width in pixels drawn with multiple lines). The line is your basic bell curve, squeezed or stretched by variance and x-factor.
Unfortunately, nothing shows on the screen. A previous version with drawPoint() and no array worked, and I've verified the array contents are being loaded correctly, and I can see that my onDraw() is being triggered.
Any ideas why it might not be drawn? Thanks in advance!
protected void drawNewLine( int maxx, int maxy, Canvas canvas, int impact, double variance, double xFactor, int color) {
// impact = 2 to 8; xFactor between 4 and 20; variance between 0.2 and 5
double x = 0;
double y = 0;
int cx = maxx / 2;
int cy = maxy / 2;
int mu = cx;
int index = 0;
points[maxx<<1][1] = points[maxx<<1][0];
for (x = 0; x < maxx; x++) {
points[index][1] = points[index][0];
points[index][0] = (float) x;
Log.i(DEBUG_TAG, "x: " + x);
index++;
double root = 1.0 / (Math.sqrt(2 * Math.PI * variance));
double exponent = -1.0 * (Math.pow(((x - mu)/maxx*xFactor), 2) / (2 * variance));
double ePow = Math.exp(exponent);
y = Math.round(cy * root * ePow);
points[index][1] = points[index][0];
points[index][0] = (float) (maxy - y - OFFSET);
index++;
}
points[maxx<<1][0] = (float) impact;
for (int line = 0; line < points[maxx<<1][1]; line++) {
for (int pt = 0; pt < (maxx<<1); pt++) {
pointsToPaint[pt] = points[pt][1];
}
for (int skip = 1; skip < (maxx<<1); skip = skip + 2)
pointsToPaint[skip] = pointsToPaint[skip] + line;
myLinePaint.setColor(Color.BLACK);
canvas.drawLines(pointsToPaint, bLinePaint); // draw over old lines w/blk
}
for (int line = 0; line < points[maxx<<1][0]; line++) {
for (int pt = 0; pt < maxx<<1; pt++) {
pointsToPaint[pt] = points[pt][0];
}
for (int skip = 1; skip < maxx<<1; skip = skip + 2)
pointsToPaint[skip] = pointsToPaint[skip] + line;
myLinePaint.setColor(color);
canvas.drawLines(pointsToPaint, myLinePaint); / new color
}
}
update: Replaced the drawLines() with drawPoint() in loop, still no joy
for (int p = 0; p<pointsToPaint.length; p = p + 2) {
Log.i(DEBUG_TAG, "x " + pointsToPaint[p] + " y " + pointsToPaint[p+1]);
canvas.drawPoint(pointsToPaint[p], pointsToPaint[p+1], myLinePaint);
}
/// canvas.drawLines(pointsToPaint, myLinePaint);
I was attempting to write from within onCreate() and onStart(). The View and its Canvas are never actually rendered for the first time until the end of onStart().
aren't you suppose to call invalidate (like a mapview) to force the view to reload?
YourView.invalidate() (or maybe postInvalidate(), depending where you are : main sthread or not)
here is the detail

Categories

Resources