1

I would like to create something similar to this question Can I convert an image into a grid of dots? but I cannot find any answer for my problem. The basic idea is to load a picture from the phone and apply this grid of dots. I would appreciate any suggestions to this.

Community
  • 1
  • 1
chavlord
  • 13
  • 4
  • Edit: I originally misinterpreted the problem. I didn't realize that you needed each dot to be the exact same color. I completely rewrote my solution for you. – Brian Attwell Feb 01 '13 at 19:16

2 Answers2

3

As others may suggest, your problem can also be solved using a fragment shader in OpenGL Shading Language (GLSL). GLSL might require painful setup.

Here is my solution using Android Renderscript (a lot like GLSL, but specifically designed for Android. It isn't used much). First, setup the Renderscript > Hello Compute sample from inside the official Android SDK samples. Next, replace mono.rs with the following:

#pragma version(1)
#pragma rs java_package_name(com.android.example.hellocompute)

rs_allocation gIn;
rs_allocation gOut;
rs_script gScript;

static int mImageWidth;
const uchar4 *gPixels;

const float4 kBlack = {
    0.0f, 0.0f, 0.0f, 1.0f
};

// There are two radius's for each circle for anti-aliasing reasons. 
const static uint32_t radius = 15; 
const static uint32_t smallerRadius = 13;

// Used so that we have smooth circle edges
static float smooth_step(float start_threshold, float end_threshold, float value) {
    if (value < start_threshold) {
        return 0;
    }
    if (value > end_threshold) {
        return 1;
    }
    value = (value - start_threshold)/(end_threshold - start_threshold);
    // As defined at http://en.wikipedia.org/wiki/Smoothstep
    return value*value*(3 - 2*value);
}

void root(const uchar4 *v_in, uchar4 *v_out, uint32_t u_x, uint32_t u_y) {
    int32_t diameter = radius * 2;

    // Compute distance from center of the circle
    int32_t x = u_x % diameter - radius;
    int32_t y = u_y % diameter - radius;
    float dist = hypot((float)x, (float)y);

    // Compute center of the circle
    uint32_t center_x = u_x /diameter*diameter + radius;
    uint32_t center_y = u_y /diameter*diameter + radius;

    float4 centerColor = rsUnpackColor8888(gPixels[center_x + center_y*mImageWidth]);
    float amount = smooth_step(smallerRadius, radius, dist);
    *v_out = rsPackColorTo8888(mix(centerColor, kBlack, amount));
}

void filter() {
    mImageWidth = rsAllocationGetDimX(gIn);
    rsForEach(gScript, gIn, gOut); // You may need a forth parameter, depending on your target SDK.
}

Inside HelloCompute.java, replace createScript() with the following:

private void createScript() {
      mRS = RenderScript.create(this);

        mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
                                                    Allocation.MipmapControl.MIPMAP_NONE,
                                                    Allocation.USAGE_SCRIPT);
        mOutAllocation = Allocation.createTyped(mRS, mInAllocation.getType());

        mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono);

        mScript.bind_gPixels(mInAllocation);

        mScript.set_gIn(mInAllocation);
        mScript.set_gOut(mOutAllocation);
        mScript.set_gScript(mScript);
        mScript.invoke_filter();
        mOutAllocation.copyTo(mBitmapOut);
}

The end result will look like this enter image description here

ALTERNATIVE

If you don't care about having each dot a solid color, you can do the following:

There is a very easy way to do this. You need a BitmapDrawable for the picture and a BitmapDrawable for the overlay tile (lets call it overlayTile). On overlayTile, call

overlayTile.setTileModeX(Shader.TileMode.REPEAT);
overlayTile.setTileModeY(Shader.TileMode.REPEAT);

Next, combine the two Drawable's into a single Drawable using LayerDrawable. You can use the resulting LayerDrawable as src for some ImageView, if you wish. Or, you can convert the Drawable to a Bitmap and save it to disk.

Community
  • 1
  • 1
Brian Attwell
  • 9,239
  • 2
  • 31
  • 26
  • Thanks for the reply, I believe this is close enough to what I am looking for! – chavlord Feb 02 '13 at 03:10
  • Sorry for the question but I am confused when I try to this mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono); I get some errors even with the official Android SDK Sample. I think I am missing something with the type of private ScriptC_mono mScript; I try to declare. – chavlord Feb 02 '13 at 09:28
  • What error did you get. This class should be autogenerated when you have mono.rs in the src directory. Did you create the sample project using New > Project > Android > Android Sample Project? – Brian Attwell Feb 02 '13 at 14:51
  • So the error I got was "No mapping for the Unicode character exists in the target multibyte code page." and eclipse couldn't open the file and as a result the class did not autogenerate. I believe it has to do something with the encoding of the file mono.rs . – chavlord Feb 02 '13 at 18:44
  • You get the same problem when you first create [New > Project > Android > Android Sample Project] without modifying mono.rs? If not, then you can probably fix this by avoiding copying and pasting. Otherwise, I don't know your problem. – Brian Attwell Feb 02 '13 at 19:05
  • Unfortunately I get the same same error when I try to create a new Android Sample Project without modifying the mono.rs . Anyway,I will figure out the problem and I appreciate your help and thanks again for the solution it really saved my day. Cheers! – chavlord Feb 02 '13 at 22:08
  • 1
    Just an update solution for anyone that might have similar problem, I found that my workspace where I had my projects for eclipse was in a path with non-english words so the file could not be loaded properly. For example I had to move my project folder to something like c:\myworks\HelloCompute – chavlord Feb 03 '13 at 01:56
1

I think studying OpenGL might help in what you want to achieve.

You may want to go through the basics of Displaying Graphics with OpenGL ES

Hope that helps. :)

kdroider
  • 731
  • 5
  • 20
  • Thanks for your reply, I was hoping to avoid anything related to opengl so I was thinking to create a mask to my image using some circles drawn on. Not sure if I can achieve what I want though. – chavlord Feb 01 '13 at 04:41