(Android) Black sprite loading saved image from gallery

Hi,

I’m trying to create a sprite with an image picked from gallery. The code works for iOS, but I get a black sprite in Android.
The image from gallery is saved into the “app dir”. This is the Java code:

Bitmap original = BitmapFactory.decodeFile(selectedImageFromGalleryPath);
String pngPath = myActivity.getFilesDir() + “/” + imageName + “.png”; // Absolute path
FileOutputStream stream = new FileOutputStream(pngPath);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(original, newWidth, newHeight, false);
resizedBitmap.compress(CompressFormat.PNG, 80,stream);
resizedBitmap.recycle();
original.recycle();
stream.flush();
stream.close();

The absolute path is passed to a native cpp code to create the sprite:
CCSprite *s = CCSprite::create(pngPath);
s->setPosition(whateverposition);
container->addChild(s);

The result is a black sprite. I have debugged the CCTextureCache and seems that the image is found ok in:

bool bRet = pImage->initWithImageFile(fullpath.c_str(), eImageFormat);

but displays a BLACK image!!!

Any ideas?
Tx,
M.

Please go to that the image you created is there and looks ok first.

Hi Minggo. The image is there and looks ok. I attach it.
I have discovered this: After seen the black sprite, if I press the home button, and then, come back to my app, the image is displayed OK.

Could be anything related to gl-thread? I’m trying to mask the image picked from gallery and when I try to create a texture:

CCRenderTexture* rt = CCRenderTexture::create((int)pMaskSprite->getContentSize().width, (int)pMaskSprite->getContentSize().height);

I get the following message:

Assert failed: Could not attach texture to framebuffer
CCRenderTexture.cpp function:initWithWidthAndHeight line:333

Any ideas? Tx,
M.

Yes, it was definitively a thread issue. I’m creating a clippingnode in response to a native call from java to cocos2dx. I’ve moved the code to a callfunc action an now works ok. Do you know if the native code is always called not in the main thread?

On Android, UI thread is different from gl thread. cocos2d-x run on gl thread. If you want to operate UI element, you should use Handler to do. And if an operation comes from UI thread, you should not invoke cocos2d-x codes through JNI directly. You can use Cocos2dxHelper.runOnGLThread() to do the operation on gl thread.

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(requestCode == SELECT_PHOTO){
	        if(resultCode == RESULT_OK){  
	            Uri selectedImage = data.getData();
	            final String path = getRealPathFromURI(selectedImage);
	            Cocos2dxHelper.runOnGLThread(new Runnable() {
					
					@Override
					public void run() {
			            imagePicked(path); //jni callback
					}
				});
	        }
	    }
}

private String getRealPathFromURI(Uri contentUri) {
	    String[] proj = { MediaStore.Images.Media.DATA };
	    CursorLoader loader = new CursorLoader(_appActivity, contentUri, proj, null, null, null);
	    Cursor cursor = loader.loadInBackground();
	    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
	    cursor.moveToFirst();
	    String result = cursor.getString(column_index);
	    cursor.close();
	    return result;
	}

It can find a file, but still black sprite…

just for curiosity,
Did you add permission in manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
AFAIK this contains read permission too

Yes, I did.

I also tried scheduler->performFunctionInCocosThread, but it crashes with singnal 11 (runOnGLThread) or singal 6 (from UI thread).

Anyone solved problem?

runOnGLThread doesn’t work. However you can wrap your callback c++ function in this:

Example:

void InAppScene::gotProductPrice(string product, string price){
	this->runAction(CallFunc::create([&, product, price]() {
		if(product == IN_APP_FULL){
			txtPrice->setString(price);
		}
		else{
			CCLOG("gotProductPrice, wrong product: %s", product.c_str());
		}
	}));
}

did any one get a solution for this?

Yes - it’s a threading problem, use runAction(CallFunc::create([&](){}));

1 Like

Hi, thanks for your reply… but the problem I am facing is different… I am a newby so please bear with me.
I do not know how to pass the ImagePickerDelegate instance to pickImage().
How can I send this instance as parameter instead pickImage()

ImagePicker::getInstance()->pickImage()

Thanks in advance

How do i use this… i am now getting a black sprite…

I am now atleast able to get the image… but nw i have the exact same problem “black sprite”

How do i implement runAction(CallFunc::create(&{})); ??

Are you using this class?: https://github.com/qiankanglai/ImagePicker/blob/master/Cocos2dxImagePicker.java

I’ve never used it, but I’ve found usage sample here: https://github.com/cocos2d/cocos2d-x/tree/3020c65832d4fa7d93467676a39313a09e6fa29f/tests/cpp-tests/Classes/ImagePickerTest

And here’s an overall guide: https://github.com/qiankanglai/ImagePicker

Thank you so much for this… i needed an example to do what i needed… thanks alot man!