Taking photos from camera and gallery

is there any classes written to :

  1. take photo from camera to a sprite.
  2. take photos from camera to a sprite.

regards.

2 Likes

After you get the image data from camera, you can create sprite from this buffer, like this

CCTexture2D texture = new CCTexture2D;
texture->initWithData(data, ......);
CCSprite: sprite = CCSprite::spriteWithTexture(texture, ...)

thanx for the reply…. actually i am asking how to access camera then your method can be used….

Anyone recommend any classes for using the camera? Or the webcam camera?

As far as I know, there is no cocos2d-x class to do that. I have an implementation running on iOS and Android, perhaps I can share some more code if there is an interest.

The gist of it is, on Android :

  • call Java code to start an Intent

    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    instance.startActivityForResult(cameraIntent, 31); //31 is an ID to recognize that intent yourself

  • get the Bitmap returned by the Intent

    Bitmap original = (Bitmap) intent.getExtras().get(“data”);

  • eventually, scale it for your own needs (especially on lower-end device if you also get images from the library)

  • save it in the file format you want (I use png)

    FileOutputStream stream = new FileOutputStream(path);
    /* Write bitmap to file using JPEG or PNG and 80% quality hint for JPEG. */
    bitmap.compress(CompressFormat.PNG, 80, stream);
    bitmap.recycle(); //ensure the image is freed;
    stream.close();

  • notify your native code (optional)

  • create a sprite with the path you used above. You don’t even need to worry about data, since it’s saved in a file.

1 Like

cool. Thanks Francois.

What classes do you suggest for the iPhone side?

On iOS, the similar class is UIImagePickerController. The code is a bit less straightforward, but here are the steps :

  • subclass UIImagePickerControllerDelegate to receive notifications

  • create a UIImagePickerController, setting the sourceType to UIImagePickerControllerSourceTypePhotoLibrary and the delegate to the subclass you just did. Optionaly, you can allow the user to edit the image (I tried it but didn’t like the result, but it’s an option)

  • present the UIImagePickerController using presentModalViewController (warning : if you are on an iPad and want to use the library, you need to use a popover instead)

  • a sample of code for the methods you need to implement (the step to save in library is optional. Keep it if it’s relevant. It can be done on Android too). I left the code to resize too, the idea for Android is the same :

    • (void) imagePickerController:(UIImagePickerController*) picker didFinishPickingMediaWithInfo:(NSDictionary*) info
      {
      NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
      UIImage *originalImage, *editedImage, *imageToSave;

      if (CFStringCompare ((CFStringRef) mediaType, kUTTypeImage, 0) == kCFCompareEqualTo)
      {
      editedImage = (UIImage *) [info objectForKey:UIImagePickerControllerEditedImage];
      originalImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];

        imageToSave = editedImage != nil ? editedImage : originalImage;
      
        // Save the new image (original or edited) to the Camera Roll  if the image have metadata, which means it comes from the library
        if([info objectForKey: UIImagePickerControllerMediaMetadata] != nil)
        {
            NSLog(@"Saving photo in library");
            UIImageWriteToSavedPhotosAlbum (imageToSave, nil, nil , nil);
        }
      
        CGSize targetSize = imageToSave.size;
        UIImage* resultImage = nil;
      
        //Here, width and height are your size limit. The image will fit in those bounds
        float scaleX = width/imageToSave.size.width;
        float scaleY = height/imageToSave.size.height;
        float scale = MIN(scaleX, scaleY);
        if(scale != 1)
        {
            targetSize.width *= scale;
            targetSize.height *= scale;
            //hard resize because the image can be way too heavy (1536x2048 on 3GS ....)
            resultImage = [imageToSave resizedImage:targetSize interpolationQuality:kCGInterpolationHigh]; //see vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/
        }
        else
        {
            resultImage = imageToSave;
        }
        controller.view.hidden = YES;
        NSString* fileName = [NSString stringWithFormat:@"Documents/%@.png", saveName];
        NSString  *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:fileName];
        NSError* error = NULL;
        BOOL result = [UIImagePNGRepresentation(resultImage) writeToFile:pngPath options:NSDataWritingAtomic error:&error];
        //BOOL result = [UIImagePNGRepresentation(resultImage) writeToFile:pngPath atomically:YES];
        NSLog(@"Write result for file %@ : %@, fullPath : %@", fileName, (result ? @"OK" : @"Problem"), pngPath);
        if(result)
        {
            //Save in the Documents directory
            CCString* fullPath = ScreateF("%s/Documents/%s.png", getenv("HOME"), [saveName UTF8String]);
            //Remove the texture from the cache so that if you reuse a name, you'll have the new one next time you create a CCSprite with it
            CCTextureCache::sharedTextureCache()->removeTextureForKey(fullPath->getCString());
            //change that call by your own notification
            notifyImagePicked([saveName UTF8String], [identifier UTF8String]);
        }
        else
        {
            NSLog(@"Write error description: %@, reason: %@", [error localizedDescription], [error localizedFailureReason]);
        }
      
        controller = [[UIImagePickerController alloc] init];
        controller.delegate = self;
      

      }
      else
      {
      NSLog(@“Problem : picked a media which is not an image”);
      }
      [self imagePickerControllerDidCancel:picker];
      }

    • (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
      {
      // Dismiss the image selection and close the program
      [picker dismissModalViewControllerAnimated:YES];
      if(popOver)
      {
      [popOver dismissPopoverAnimated:YES];
      }
      }

That’s quite a bit of code, but with that you get everything covered, as far as I know.

1 Like

Nitesh Purohit wrote:

is there any classes written to :
>

  1. take photo from camera to a sprite.
  2. take photos from camera to a sprite.
    >
    regards.

Should I write a subclass of android.app.Activity which can get the data by override “onActivityResult()”?

Hello :slight_smile:

I’m trying to launch the Android Camera. I have called my java code from c++ but when I try to create an intent my code crash with a FATAL EXCEPTION: GLTHREAD 1656

Only appear if I try to setClassName of the intent.

Intent cameraIntent = new Intent();
cameraIntent.setClassName(getApplicationContext(), CameraActivity.class);

//CameraActivity is my class who has all the camera process.

Anyone has an example of how call Androd camera from cocos2dx?

I have a question about how can to know what the take photo action be done in cocos2dx?

Now, I really can save photo in iOS photo album and file system, but how take to sprite when close the camera view?

@daniewang Once you saved the image to the file system, load the sprite like you would normally do, but use the absolute path (named pngPath on the previous code). Cocos2d-x will load it like any other image.

You may have noticed notice notifyImagePicked([saveName UTF8String], [identifier UTF8String]); : I implement this function in the C++ part, and send a notification that the C++ uses to react to the new image. Note: the identifier is not needed, it’s an easy way for me to identify what they are linked to. You may want to use fullPath instead of saveName if you want to directly use that to load your sprite (on the other hand, if you save the path, use a relative path to save space, and reconstruct full path at runtime).

Sorry for bumping an old post, but: does anyone have a working code example for this?

@ZippoLag since then, I open-sourced my framework. This feature is part of FenneX, take a look: https://github.com/FenneX/FenneX The C++ usage is very simple : call pickImage and add an observer for the “ImagePicked” notification.

There is no usage example yet, but I could do one. I need to get started on samples.

4 Likes

Awesome!

I’m currently just focusing in -JS development, but I’ll probably need to bind native functions soon, so I’ll keep an eye on your project.

Thanks!

@Fradow Have you tested it on Windows? it seem that android.mk find relies on gnu find, when trying to build on windows (with gnu find) the following errors are presented…

In file included from jni/…/…/Classes/FenneX/Core/GesturesHandling/GenericReco
gnizer.cpp:25:
jni/…/…/Classes/FenneX/Core/GesturesHandling/GenericRecognizer.h:28:10: fatal
error:
      ‘Logs.h’ file not found
#include “Logs.h”
         ^
In file included from jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomNode.cp
p:25:
In file included from jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomNode.h:
30:
jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomBaseNode.h:30:10: fatal error
:
      ‘FenneXMacros.h’ file not found
#include “FenneXMacros.h”
         ^
In file included from jni/…/…/Classes/FenneX/Core/CCBIntegration/FenneXCCBLoad
er.cpp:27:
jni/…/…/Classes/FenneX/Core/CCBIntegration/FenneXCCBLoader.h:29:10: fatal erro
r:
      ‘FenneXMacros.h’ file not found
#include “FenneXMacros.h”
         ^
In file included from jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomBaseNod
e.cpp:25:
jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomBaseNode.h:30:10: fatal error
:
      ‘FenneXMacros.h’ file not found
#include “FenneXMacros.h”
         ^
In file included from jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomSprite.
cpp:25:
In file included from jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomSprite.
h:30:
jni/…/…/Classes/FenneX/Core/CCBIntegration/CustomBaseNode.h:30:10: fatal error
:
      ‘FenneXMacros.h’ file not found
#include “FenneXMacros.h”
         ^

@viran No, it’s not tested on Windows, and the Android.mk definitely won’t work on Windows, because it relies on find command.

You need to replace it by dir command with the appropriate parameters, or manually list all the files (like cocos2d-x does). Unfortunately, I don’t work on Windows, so I can’t help you.

Since your library is version 2 compatible, and I dont have the time to port it all,
If all I need is image picker from the Gallery/Camera, can I do it with a selected few files? Which files?

Yes, you can use only the wrapper files.

  • go on branch cocosV2.2
  • take projects / Classes / FenneX / NativeWrappers / ImagePickerWrapper.h
  • take projects / proj.ios / ImagePicker.h and .mm
  • take projects / proj.android / jni / ImagePickerWrapper.cpp
  • take projects / proj.android / src / com / fennex / modules / ImagePicker.java
  • add ImagePickerWrapper.cpp to your Android.mk
  • in ImagePicker.java, you need to replace NativeUtility.getMainActivity by your main Activity. Your Activity must forward onActivityResult to ImagePicker
  • there may be a few shorteners use, you will find the definitions in projects / Classes / FenneX / Core / Utility / Shorteners.h
  • don’t forget about the permissions (Android) and frameworks (iOS). I don’t remember the specific ones.
  • resolve any other problem. It shouldn’t be very hard as there are very few dependencies between the wrappers and the rest ofthe code.

Hey @Fradow

I’ve been trying to do as you suggested for a while, but I’m afraid it’s beyond my abilities.

If you could take the time and upload a sample project I would really appreciate it

Hello @viran

You are in luck, following your question, I decided to start the samples with that feature (it’s a recurring question in cocos2d-x forum to be honest). Have a look: https://github.com/FenneX/FenneXTestProject The last commit from October 19th is the most interesting for you. It is for V3.2, but FenneX interface didn’t change yet from V2.X

What are you struggling with? An error message, another problem?

2 Likes