Palindrome Number time limit exceeded error dart - dart

First i want to say that i am trying to solve Palindrome Number problem on LeetCode using dart, of course
https://leetcode.com/problems/palindrome-number/
So far I have tried total 6 different method to solve the problem.
And am not very happy to say that all of them leading to time limit exceeded error on LeetCode.. Solutions are perfectly working on terminal because of the less test cases but when submit, and it tried on large number it ends up error.
My 6 solutions based on different classes.each class contain their own implemented solution..
I dont know if the while loop in dart is slow or something wrong with the leetcode
class A {
bool isPalindrome(int x) {
if (x < 0) {
return false;
}
double divisor = 1;
while (x / divisor >= 10) {
divisor *= 10;
}
while (x != 0) {
if ((x / divisor).truncate() != (x % 10).floor()) {
return false;
}
x %= divisor.toInt();
x = (x / 10).floor();
divisor /= 100;
}
return true;
}
}
class B {
bool isPalindrome(int x) {
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revNum = 0;
while (x > revNum) {
revNum = revNum * 10 + x % 10;
x = (x / 10).floor();
}
return (x == revNum || x == revNum / 10);
}
}
class C {
bool isPalindrome(int x) {
if (x < 0) {
return false;
}
int y = 0;
int xx = x;
if (xx > 0) {
y = y * 10 + xx % 10;
xx = (xx / 10).floor();
}
return (y != x);
}
// while (xx > 0) {
// y = y * 10 + xx % 10;
// xx = (xx / 10).floor();
// }
}
class D {
bool isPalindrome(int x) {
if (x.isNegative) return false;
final list = convert(x);
for (var i = 0; i < (list.length ~/ 2); i++) {
if (list[i] != list[list.length - 1 - i]) return false;
}
return true;
}
List convert(int x) {
final List<int> list = <int>[];
while (x > 0) {
list.add(x % 10);
x = x ~/ 10;
}
return list;
}
}
class F {
bool isPalindrome(int x) {
if (x.isNegative) return false;
if (x == 0) return true;
if (x % 10 == 0) return false;
var reverted = 0, iter = x;
while (iter > 0) {
reverted = reverted * 10;
reverted += iter % 10;
iter = iter ~/ 10;
}
return reverted == x;
}
}
class G {
bool isPalindrome(int x) {
if (x.isNegative) return false;
var tens = 10;
while (tens < x) tens *= 10;
tens = tens ~/ 10;
while (x > 10) {
var lastDigit = x % 10;
var firstDigit = x ~/ tens;
if (lastDigit != firstDigit) return false;
x -= firstDigit * tens;
x = x ~/ 10;
tens = tens ~/ 100;
}
return true;
}
}

I'm pretty sure the leetcode site has a problem here.
I don't know what they're using their time on, but it seems impossible to get a correct result without a timeout.
My attempted solutions are:
class Solution2 {
// No intermediate allocations, only number operations.
bool isPalindrome(int x) {
if (x < 0) return false;
if (x < 10) return true;
int r = 0;
do {
var d = x.remainder(10);
x = x ~/ 10;
if (r == x) return true; // Odd length number
r = r * 10 + d;
if (r == x) return true; // Even length number
if (r == 0) return false; // Trailing zero
} while (r < x);
return false;
}
}
class Solution3 {
// Just do toString and check that it's a palindrome.
// Integer.toString is heavily optimized already.
bool isPalindrome(int x) {
if (x < 0) return false;
if (x < 10) return true;
var s = x.toString();
for (var i = 0, j = s.length - 1; i < j; i++, j--) {
if (s.codeUnitAt(i) != s.codeUnitAt(j)) return false;
}
return true;
}
}
If those are not fast enough, I seriously doubt anything will be.
I even considered whether repeatedly dividing by 10 was incredibly slow for some reason, so I switched to dividing by 100 instead, which should halve the divisions.
class Solution {
// Minimize divisions by dividing by 100, and do lookup for the digits.
static const digits =[
0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9,
1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9,
2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9,
3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, 3, 6, 3, 7, 3, 8, 3, 9,
4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4, 5, 4, 6, 4, 7, 4, 8, 4, 9,
5, 0, 5, 1, 5, 2, 5, 3, 5, 4, 5, 5, 5, 6, 5, 7, 5, 8, 5, 9,
6, 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6, 6, 6, 7, 6, 8, 6, 9,
7, 0, 7, 1, 7, 2, 7, 3, 7, 4, 7, 5, 7, 6, 7, 7, 7, 8, 7, 9,
8, 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, 6, 8, 7, 8, 8, 8, 9,
9, 0, 9, 1, 9, 2, 9, 3, 9, 4, 9, 5, 9, 6, 9, 7, 9, 8, 9, 9,
];
bool isPalindrome(int x) {
if (x < 0) return false;
if (x < 10) return true;
int r = 0;
do {
var d = x.remainder(100);
x = x ~/ 100;
var d1 = digits[d * 2];
var d2 = digits[d * 2 + 1];
if (r == x && d1 == d2) return true; // Even length number
if (r == x * 10 + d1) return true; // Odd length number.
r = r * 10 + d2;
if (r == 0) return false; // Trailing zero
if (r == x) return true; // Odd length number
r = r * 10 + d1;
if (r == x) return true; // Even length number
} while (r < x);
return false;
}
}
Still times out.

Related

Dart While Loop usage

i have a logic mistake but i cant figure out, loop not stops when num= returnitemcount ?
void main() {
List<int> listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
List<int> exceptions = [2, 3, 4];
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) {
List<int> returnlist = [];
int num = 0;
while (num < returnitemcount) {
for (var i = 0; i < listfrom.length; i++) {
if (!exceptions.contains(listfrom[i])) {
returnlist.add(listfrom[i]);
num++;
}
}
}
return returnlist;
}
List<int> mylist = exceptedlist(3, exceptions, listAll);
print(mylist);
// expected => 1,5,6
// result => 1, 5, 6, 7, 8, 9
}
Your problem is that your while are only evaluated twice. The first time num is 0 and the second time it is 6. It is not evaluated every time num is updated.
while loops does not mean that the code inside the block are running as long some statement are true. It means the code will loop as long the statement are true.
So what you need to do is to check num every time you update the value. Something like this:
void main() {
List<int> listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
List<int> exceptions = [2, 3, 4];
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) {
List<int> returnlist = [];
int num = 0;
while (num < returnitemcount) {
for (var i = 0; i < listfrom.length; i++) {
if (!exceptions.contains(listfrom[i])) {
returnlist.add(listfrom[i]);
if (++num >= returnitemcount) {
break;
}
}
}
}
return returnlist;
}
List<int> mylist = exceptedlist(3, exceptions, listAll);
print(mylist); // [1, 5, 6]
}
I am not sure what you code are going to do exactly but you should be able to skip the while loop:
void main() {
List<int> listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
List<int> exceptions = [2, 3, 4];
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) {
List<int> returnlist = [];
for (var i = 0; i < listfrom.length; i++) {
if (!exceptions.contains(listfrom[i])) {
returnlist.add(listfrom[i]);
if (returnlist.length >= returnitemcount) {
break;
}
}
}
return returnlist;
}
List<int> mylist = exceptedlist(3, exceptions, listAll);
print(mylist); // [1, 5, 6]
}
And can properly even be shorten into:
void main() {
final listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
final exceptions = [2, 3, 4];
final mylist = exceptedlist(3, exceptions, listAll);
print(mylist); // [1, 5, 6]
}
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) =>
listfrom
.where((element) => !exceptions.contains(element))
.take(returnitemcount)
.toList();

How to get the function to be computed differently for different values of x?

Func support("support");
Expr left_x = clamp(x, 0, left_buffer.width() / 4);
RDom scan_left(0, left_buffer.width() / 4, 0, left_buffer.height());
scan_left.where(scan_left.x != left_x && scan_left.y != y);
support(x, y) = argmin(abs(output_x(left_x, y) - output_x(scan_left.x, scan_left.y)) + abs(output_y(left_x, y) - output_y(scan_left.x, scan_left.y)));
Expr center_x = clamp(x, left_buffer.width() / 4, left_buffer.width() * 3/4);
RDom scan_center(-left_buffer.width() / 4, left_buffer.width() / 2, 0, left_buffer.height());
scan_center.where(scan_center.x != 0 && scan_center.y != 0);
support(x, y) = argmin(abs(output_x(center_x, y) - output_x(center_x + scan_center.x, scan_center.y)) + abs(output_y(center_x, scan_center.y) - output_y(center_x + scan_center.x, scan_center.y)));
Expr right_x = clamp(x, left_buffer.width() * 3/4, left_buffer.width());
RDom scan_right(left_buffer.width() * 3/4, left_buffer.width() / 4, 0, left_buffer.height());
scan_right.where(scan_right.x != right_x && scan_right.y != y);
support(x, y) = argmin(abs(output_x(right_x, y) - output_x(scan_right.x, scan_right.y)) + abs(output_y(right_x, y) - output_y(scan_right.x, scan_right.y)));
support.trace_stores();
Realization r = support.realize(left_buffer.width(), left_buffer.height());
The function "support" should be computed differently depending on the x value. For x = [0, width/4] compute it according to the first definition, for x = [width/4, width * 3/4] compute it according to the second definition, and for x = [width*3/4, width] compute it according the third definition. I would think that putting the boundary conditions with respect to those update definitions and then realizing over the whole buffer would do the trick. Right now though, the previous definitions are being overwritten. Since this doesn't seem to work, I would think of doing three realizations but that seems inelegant since we're talking about just one image. Is it possible to achieve the result in a single realization, or must I break into three realizations?
I tried RDoms too:
Func support("support");
support(x, y) = Tuple(i32(0), i32(0), f32(0));
RDom left_x(0, left_buffer.width() / 4);
RDom scan_left(0, left_buffer.width() / 4, 0, left_buffer.height());
scan_left.where(scan_left.x != left_x && scan_left.y != y);
support(left_x, y) = argmin(scan_left, abs(output_x(left_x, y) - output_x(scan_left.x, scan_left.y)) + abs(output_y(left_x, y) - output_y(scan_left.x, scan_left.y)));
RDom center_x(left_buffer.width() / 4, left_buffer.width() / 2);
RDom scan_center(-left_buffer.width() / 4, left_buffer.width() / 2, 0, left_buffer.height());
scan_center.where(scan_center.x != 0 && scan_center.y != 0);
support(center_x, y) = argmin(scan_center, abs(output_x(center_x, y) - \
output_x(center_x + scan_center.x, scan_center.y)) + abs(output_y(center_x, scan_center.y) - \
output_y(center_x + scan_center.x, scan_center.y)));
RDom right_x(left_buffer.width() * 3/4, left_buffer.width() / 4);
RDom scan_right(left_buffer.width() * 3/4, left_buffer.width() / 4, 0, left_buffer.height());
scan_right.where(scan_right.x != right_x && scan_right.y != y);
support(right_x, y) = argmin(scan_right, abs(output_x(right_x, y) - output_x(scan_right.x, scan_right.y)) + abs(output_y(right_x, y) - output_y(scan_right.x, scan_right.y)));
support.compute_root();
support.trace_stores();
Realization r_left = support.realize(left_buffer.width(), left_buffer.height());
but this code gives errors in the following lines:
scan_left.where(scan_left.x != left_x && scan_left.y != y);
...
scan_right.where(scan_right.x != right_x && scan_right.y != y);
A simple way to solve this problem would be to use Halide's select method (example given here). Something like this should work:
Func support("support");
Expr left_x = clamp(x, 0, left_buffer.width() / 4);
RDom scan_left(0, left_buffer.width() / 4, 0, left_buffer.height());
scan_left.where(scan_left.x != left_x && scan_left.y != y);
Expr first = argmin(abs(output_x(left_x, y) - output_x(scan_left.x, scan_left.y)) + abs(output_y(left_x, y) - output_y(scan_left.x, scan_left.y)));
Expr center_x = clamp(x, left_buffer.width() / 4, left_buffer.width() * 3/4);
RDom scan_center(-left_buffer.width() / 4, left_buffer.width() / 2, 0, left_buffer.height());
scan_center.where(scan_center.x != 0 && scan_center.y != 0);
Expr second = argmin(abs(output_x(center_x, y) - output_x(center_x + scan_center.x, scan_center.y)) + abs(output_y(center_x, scan_center.y) - output_y(center_x + scan_center.x, scan_center.y)));
Expr right_x = clamp(x, left_buffer.width() * 3/4, left_buffer.width());
RDom scan_right(left_buffer.width() * 3/4, left_buffer.width() / 4, 0, left_buffer.height());
scan_right.where(scan_right.x != right_x && scan_right.y != y);
Expr third = argmin(abs(output_x(right_x, y) - output_x(scan_right.x, scan_right.y)) + abs(output_y(right_x, y) - output_y(scan_right.x, scan_right.y)));
int width = left_buffer.width();
# select based on x value
support(x, y) = select(x < width / 4, first, x < width * 3 / 4, second, third);
support.trace_stores();
Realization r = support.realize(left_buffer.width(), left_buffer.height());
`

RenderScript's allocation output returns a black Bitmap

few days ago I've just started learning RenderScript. I managed to create some simple image processing filters e.g. grayscale, color change.
Now I'm working on Canny edge filters with no success.
Question: Why ImageView displays black image and how to solve it?
I'am using implementation of Canny egde filter made by arekolek github
optional: Can I compute it faster?
I ended with all code wrote in on method "runEdgeFilter(...)" which runs when i clicked image on my device, to make sure I'am not messing with imageView in other place. Code that i use so far.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v8.renderscript.*;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private static final float THRESHOLD_MULT_LOW = 0.66f * 0.00390625f;
private static final float THRESHOLD_MULT_HIGH = 1.33f * 0.00390625f;
private ImageView imageView;
private Bitmap img;
private boolean setThresholds = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView);
img = BitmapFactory.decodeResource(getResources(), R.drawable.test_img_no_dpi2);
imageView.setImageBitmap(img);
}
public void imageClicked(View view) {
runEdgeFilter(img, this);
}
private void runEdgeFilter(Bitmap image, Context context) {
int width = image.getWidth();
int height = image.getHeight();
RenderScript rs = RenderScript.create(context);
Allocation allocationIn = Allocation.createFromBitmap(rs, image);
Type.Builder tb;
tb = new Type.Builder(rs, Element.F32(rs)).setX(width).setY(height);
Allocation allocationBlurred = Allocation.createTyped(rs, tb.create());
Allocation allocationMagnitude = Allocation.createTyped(rs, tb.create());
tb = new Type.Builder(rs, Element.I32(rs)).setX(width).setY(height);
Allocation allocationDirection = Allocation.createTyped(rs, tb.create());
Allocation allocationEdge = Allocation.createTyped(rs, tb.create());
tb = new Type.Builder(rs, Element.I32(rs)).setX(256);
Allocation allocationHistogram = Allocation.createTyped(rs, tb.create());
tb = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
Allocation allocationOut = Allocation.createTyped(rs, tb.create());
ScriptC_edge edgeFilter = new ScriptC_edge(rs);
ScriptIntrinsicHistogram histogram = ScriptIntrinsicHistogram.create(rs, Element.U8(rs));
histogram.setOutput(allocationHistogram);
edgeFilter.invoke_set_histogram(allocationHistogram);
edgeFilter.invoke_set_blur_input(allocationIn);
edgeFilter.invoke_set_compute_gradient_input(allocationBlurred);
edgeFilter.invoke_set_suppress_input(allocationMagnitude, allocationDirection);
edgeFilter.invoke_set_hysteresis_input(allocationEdge);
edgeFilter.invoke_set_thresholds(0.2f, 0.6f);
histogram.forEach_Dot(allocationIn);
int[] histogramOutput = new int[256];
allocationHistogram.copyTo(histogramOutput);
if(setThresholds) {
int median = width * height / 2;
for (int i = 0; i < 256; ++i) {
median -= histogramOutput[i];
if (median < 1) {
edgeFilter.invoke_set_thresholds(i * THRESHOLD_MULT_LOW, i * THRESHOLD_MULT_HIGH);
break;
}
}
}
edgeFilter.forEach_blur(allocationBlurred);
edgeFilter.forEach_compute_gradient(allocationMagnitude);
edgeFilter.forEach_suppress(allocationEdge);
edgeFilter.forEach_hysteresis(allocationOut);
allocationOut.copyTo(image);
allocationIn.destroy();
allocationMagnitude.destroy();
allocationBlurred.destroy();
allocationDirection.destroy();
allocationEdge.destroy();
allocationHistogram.destroy();
allocationOut.destroy();
histogram.destroy();
edgeFilter.destroy();
rs.destroy();
imageView.setImageBitmap(image);
}
}
renderscript edge.rs:
#pragma version(1)
#pragma rs java_package_name(com.lukasz.edgeexamplers)
#pragma rs_fp_relaxed
#include "rs_debug.rsh"
static rs_allocation raw, magnitude, blurred, direction, candidates;
static float low, high;
static const uint32_t zero = 0;
void set_blur_input(rs_allocation u8_buf) {
raw = u8_buf;
}
void set_compute_gradient_input(rs_allocation f_buf) {
blurred = f_buf;
}
void set_suppress_input(rs_allocation f_buf, rs_allocation i_buf) {
magnitude = f_buf;
direction = i_buf;
}
void set_hysteresis_input(rs_allocation i_buf) {
candidates = i_buf;
}
void set_thresholds(float l, float h) {
low = l;
high = h;
}
inline static float getElementAt_uchar_to_float(rs_allocation a, uint32_t x,
uint32_t y) {
return rsGetElementAt_uchar(a, x, y) / 255.0f;
}
static rs_allocation histogram;
void set_histogram(rs_allocation h) {
histogram = h;
}
uchar4 __attribute__((kernel)) addhisto(uchar in, uint32_t x, uint32_t y) {
int px = (x - 100) / 2;
if (px > -1 && px < 256) {
int v = log((float) rsGetElementAt_int(histogram, (uint32_t) px)) * 30;
int py = (400 - y);
if (py > -1 && v > py) {
in = 255;
}
if (py == -1) {
in = 255;
}
}
uchar4 out = { in, in, in, 255 };
return out;
}
uchar4 __attribute__((kernel)) copy(uchar in) {
uchar4 out = { in, in, in, 255 };
return out;
}
uchar4 __attribute__((kernel)) blend(uchar4 in, uint32_t x, uint32_t y) {
uchar r = rsGetElementAt_uchar(raw, x, y);
uchar4 out = { r, r, r, 255 };
return max(out, in);
}
float __attribute__((kernel)) blur(uint32_t x, uint32_t y) {
float pixel = 0;
pixel += 2 * getElementAt_uchar_to_float(raw, x - 2, y - 2);
pixel += 4 * getElementAt_uchar_to_float(raw, x - 1, y - 2);
pixel += 5 * getElementAt_uchar_to_float(raw, x, y - 2);
pixel += 4 * getElementAt_uchar_to_float(raw, x + 1, y - 2);
pixel += 2 * getElementAt_uchar_to_float(raw, x + 2, y - 2);
pixel += 4 * getElementAt_uchar_to_float(raw, x - 2, y - 1);
pixel += 9 * getElementAt_uchar_to_float(raw, x - 1, y - 1);
pixel += 12 * getElementAt_uchar_to_float(raw, x, y - 1);
pixel += 9 * getElementAt_uchar_to_float(raw, x + 1, y - 1);
pixel += 4 * getElementAt_uchar_to_float(raw, x + 2, y - 1);
pixel += 5 * getElementAt_uchar_to_float(raw, x - 2, y);
pixel += 12 * getElementAt_uchar_to_float(raw, x - 1, y);
pixel += 15 * getElementAt_uchar_to_float(raw, x, y);
pixel += 12 * getElementAt_uchar_to_float(raw, x + 1, y);
pixel += 5 * getElementAt_uchar_to_float(raw, x + 2, y);
pixel += 4 * getElementAt_uchar_to_float(raw, x - 2, y + 1);
pixel += 9 * getElementAt_uchar_to_float(raw, x - 1, y + 1);
pixel += 12 * getElementAt_uchar_to_float(raw, x, y + 1);
pixel += 9 * getElementAt_uchar_to_float(raw, x + 1, y + 1);
pixel += 4 * getElementAt_uchar_to_float(raw, x + 2, y + 1);
pixel += 2 * getElementAt_uchar_to_float(raw, x - 2, y + 2);
pixel += 4 * getElementAt_uchar_to_float(raw, x - 1, y + 2);
pixel += 5 * getElementAt_uchar_to_float(raw, x, y + 2);
pixel += 4 * getElementAt_uchar_to_float(raw, x + 1, y + 2);
pixel += 2 * getElementAt_uchar_to_float(raw, x + 2, y + 2);
pixel /= 159;
return pixel;
}
float __attribute__((kernel)) compute_gradient(uint32_t x, uint32_t y) {
float gx = 0;
gx -= rsGetElementAt_float(blurred, x - 1, y - 1);
gx -= rsGetElementAt_float(blurred, x - 1, y) * 2;
gx -= rsGetElementAt_float(blurred, x - 1, y + 1);
gx += rsGetElementAt_float(blurred, x + 1, y - 1);
gx += rsGetElementAt_float(blurred, x + 1, y) * 2;
gx += rsGetElementAt_float(blurred, x + 1, y + 1);
float gy = 0;
gy += rsGetElementAt_float(blurred, x - 1, y - 1);
gy += rsGetElementAt_float(blurred, x, y - 1) * 2;
gy += rsGetElementAt_float(blurred, x + 1, y - 1);
gy -= rsGetElementAt_float(blurred, x - 1, y + 1);
gy -= rsGetElementAt_float(blurred, x, y + 1) * 2;
gy -= rsGetElementAt_float(blurred, x + 1, y + 1);
int d = ((int) round(atan2pi(gy, gx) * 4.0f) + 4) % 4;
rsSetElementAt_int(direction, d, x, y);
return hypot(gx, gy);
}
int __attribute__((kernel)) suppress(uint32_t x, uint32_t y) {
int d = rsGetElementAt_int(direction, x, y);
float g = rsGetElementAt_float(magnitude, x, y);
if (d == 0) {
// horizontal, check left and right
float a = rsGetElementAt_float(magnitude, x - 1, y);
float b = rsGetElementAt_float(magnitude, x + 1, y);
return a < g && b < g ? 1 : 0;
} else if (d == 2) {
// vertical, check above and below
float a = rsGetElementAt_float(magnitude, x, y - 1);
float b = rsGetElementAt_float(magnitude, x, y + 1);
return a < g && b < g ? 1 : 0;
} else if (d == 1) {
// NW-SE
float a = rsGetElementAt_float(magnitude, x - 1, y - 1);
float b = rsGetElementAt_float(magnitude, x + 1, y + 1);
return a < g && b < g ? 1 : 0;
} else {
// NE-SW
float a = rsGetElementAt_float(magnitude, x + 1, y - 1);
float b = rsGetElementAt_float(magnitude, x - 1, y + 1);
return a < g && b < g ? 1 : 0;
}
}
static const int NON_EDGE = 0b000;
static const int LOW_EDGE = 0b001;
static const int MED_EDGE = 0b010;
static const int HIG_EDGE = 0b100;
inline static int getEdgeType(uint32_t x, uint32_t y) {
int e = rsGetElementAt_int(candidates, x, y);
float g = rsGetElementAt_float(magnitude, x, y);
if (e == 1) {
if (g < low)
return LOW_EDGE;
if (g > high)
return HIG_EDGE;
return MED_EDGE;
}
return NON_EDGE;
}
uchar4 __attribute__((kernel)) hysteresis(uint32_t x, uint32_t y) {
uchar4 white = { 255, 255, 255, 255 };
uchar4 red = { 255, 0, 0, 255 };
uchar4 black = { 0, 0, 0, 255 };
int type = getEdgeType(x, y);
if (type) {
if (type & LOW_EDGE) {
return black;
}
if (type & HIG_EDGE) {
//rsDebug("wh : x=", x);
//rsDebug("wh : y=", y);
return white;
}
// it's medium, check nearest neighbours
type = getEdgeType(x - 1, y - 1);
type |= getEdgeType(x, y - 1);
type |= getEdgeType(x + 1, y - 1);
type |= getEdgeType(x - 1, y);
type |= getEdgeType(x + 1, y);
type |= getEdgeType(x - 1, y + 1);
type |= getEdgeType(x, y + 1);
type |= getEdgeType(x + 1, y + 1);
if (type & HIG_EDGE) {
//rsDebug("wh : x=", x);
//rsDebug("wh : y=", y);
return white;
}
if (type & MED_EDGE) {
// check further
type = getEdgeType(x - 2, y - 2);
type |= getEdgeType(x - 1, y - 2);
type |= getEdgeType(x, y - 2);
type |= getEdgeType(x + 1, y - 2);
type |= getEdgeType(x + 2, y - 2);
type |= getEdgeType(x - 2, y - 1);
type |= getEdgeType(x + 2, y - 1);
type |= getEdgeType(x - 2, y);
type |= getEdgeType(x + 2, y);
type |= getEdgeType(x - 2, y + 1);
type |= getEdgeType(x + 2, y + 1);
type |= getEdgeType(x - 2, y + 2);
type |= getEdgeType(x - 1, y + 2);
type |= getEdgeType(x, y + 2);
type |= getEdgeType(x + 1, y + 2);
type |= getEdgeType(x + 2, y + 2);
if (type & HIG_EDGE) {
//rsDebug("wh : x=", x);
//rsDebug("wh : y=", y);
return white;
}
}
}
return black;
}
After some debugging I found that:
uchar4 __attribute__((kernel)) hysteresis(uint32_t x, uint32_t y) {...}
returns white and black pixels so renderscript works properly I think.
Output is the same type as my previous renderscript filters (uchar4) which I assign to Bitmap with success.
I have no idea what I've done wrong.
Also my logcat prints:
V/RenderScript_jni: RS compat mode
V/RenderScript_jni: Unable to load libRSSupportIO.so, USAGE_IO not supported
V/RenderScript_jni: Unable to load BLAS lib, ONLY BNNM will be supported: java.lang.UnsatisfiedLinkError: Couldn't load blasV8 from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.lukasz.edgeexamplers-20.apk,libraryPath=/data/app-lib/com.lukasz.edgeexamplers-20]: findLibrary returned null
E/RenderScript: Couldn't load libRSSupportIO.so
in every program which use renderscript, but other programs works even with this warnings.
Update #1
As #Stephen Hines mention, there was issue with reading out of bounds. I think I fixed it for now (without messing with renderscript) by changing those lines:
edgeFilter.forEach_blur(allocationBlurred);
edgeFilter.forEach_compute_gradient(allocationMagnitude);
edgeFilter.forEach_suppress(allocationEdge);
edgeFilter.forEach_hysteresis(allocationOut);
into:
Script.LaunchOptions sLaunchOpt = new Script.LaunchOptions();
sLaunchOpt.setX(2, width - 3);
sLaunchOpt.setY(2, height - 3);
edgeFilter.forEach_blur(allocationBlurred, sLaunchOpt);
edgeFilter.forEach_compute_gradient(allocationMagnitude, sLaunchOpt);
edgeFilter.forEach_suppress(allocationEdge, sLaunchOpt);
edgeFilter.forEach_hysteresis(allocationOut, sLaunchOpt);
But my problem is still not solved. Output is black as earlier.

Can I modify image's pixel value?

I would like to do sth like this in Go:
for x := 0; x < width; x++ {
for y := 0; y < height; y++ {
// something similar to this:
src_img[x, y] = color.Black
}
}
is it possible to do this, importing only "image", "image/jpeg", "image/color"?
For example:
package main
import (
"fmt"
"image"
"image/color"
)
func main() {
const D = 12
img := image.NewGray(image.Rect(1, 1, D, D))
for x := 1; x <= D; x++ {
img.Set(x, x, color.Gray{byte(2 * x)})
}
for x := 1; x < D; x++ {
fmt.Printf("[%2d, %2d]: %5v\n", x, x, img.At(x, x))
}
}
Playground
Output:
[ 1, 1]: { 2}
[ 2, 2]: { 4}
[ 3, 3]: { 6}
[ 4, 4]: { 8}
[ 5, 5]: { 10}
[ 6, 6]: { 12}
[ 7, 7]: { 14}
[ 8, 8]: { 16}
[ 9, 9]: { 18}
[10, 10]: { 20}
[11, 11]: { 22}
Recomended reading The Go image package article (additionally to the godocs).
The image.RGBA type is the preferred way to store images in memory if you want to modify them. It implements the draw.Image interface that has a convenient method for setting pixels:
Set(x, y int, c color.Color)
Unfortunately not all decoders are returning the images in the RGBA format. Some of them are leaving the image in a compressed format where not every single pixel is modifiable. That's much faster and fine for a lot of read-only use-cases. If you want to edit the image however, you might need to copy it. For example:
src, _, err := image.Decode(file)
if err != nil {
log.Fatal(err)
}
rgba, ok := src.(*image.RGBA)
if !ok {
b := src.Bounds()
rgba = image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
draw.Draw(rgba, rgba.Bounds(), src, b.Min, draw.Src)
}
// rgba is now a *image.RGBA and can be modified freely
rgba.Set(0, 0, color.RGBA{255, 0, 0, 255})

How to win break the blocks game when using 2d Array to represent blocks

I am just learning XNA and started off my making a simple Break The Blocks Game. I am using a 2d array to represent the blocks at the top of the screen
bricks = new Bricks[18,16];
for (int y = 0; y < 16; y++)
{
for(int x = 0; x < 18; x++)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.Red);
if (y == 2 || y == 3)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.Blue);
}
if (y == 4 || y == 5)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.Green);
}
if (y == 6 || y == 7)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.White);
}
if (y == 8 || y == 9)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.Pink);
}
if (y == 10 || y == 11)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.Purple);
}
if (y == 12 || y == 13)
{
bricks[x, y] = new Bricks(BrickTexture, new Rectangle(x * BrickTexture.Width, y * BrickTexture.Height, 38, 18), Color.Navy);
}
}
}
Thats how the blocks are built and they are draw with a foreeach loop to the screen.
foreach (Bricks brick in bricks)
{
brick.Draw(spriteBatch);
}
In my Update method I then use another for each loop to go through and check if the ball has collided with any of them and if they have to remove the brick from the screen. for for that and the collision method is as follows.
foreach (Bricks brick in bricks)
{
brick.CheckBrickBallCollision(ball);
}
public void CheckBrickBallCollision(Ball ball)
{
if (isVisible && ball.Ball2.Intersects(position))
{
isVisible = false;
ball.direction.X *= 0.85f;
ball.direction.Y *= -1;
}
}
My problem is how to make it so that once all the bricks are gone the game is won, and then by changing the game state would just come up with a won screen.
Any Ideas would be really helpful
To do this without really changing any code you can just count the number of visible bricks there are.
int visibleCount = 0;
foreach (Bricks brick in bricks)
{
brick.CheckBrickBallCollision(ball);
if (brick.isVisible)
{
visibleCount++;
}
}
//If there are no visible bricks then the player won!
if (visibleCount == 0)
{
//Win the Game!
}
As another alternative, you could manage a list of active bricks versus managing their visibility. When a brick gets hit you could remove it from the list. When the list is empty then you know the player has won.
For some reason looking at the answer above this is what ended up working and thought i would share
foreach (Bricks brick in bricks)
{
brick.CheckBrickBallCollision(ball);
if (brick.isVisible == true)
{
brokenBlocks -= 1;
}
}
if (brokenBlocks == 40)
{
currentGameState = GameState.Won;
}

Resources