How to write to file (encode) modified camera frames in Windows Phone 8 - opencv

I have custom an camera app in Windows Phone 8. I need add a watermark image to each frame from camera capture and then record to a video.
I can customise each frame from the preview using the following code:
int[] pixelData = new int[(int)(camera.PreviewResolution.Width * camera.PreviewResolution.Height)];
camera.GetPreviewBufferArgb32(pixelData);
return pixelData;
and write it back to the preview.
my problem is that while I can show the frames on the screen while the user is recording a movie using the camera I cant find a working solution for WP8 to encode the frames and audio to save to a file.
I already tried opencv,libav and others without success,
if anyone can point me to the right direction it would be greatly appreciated.

You can do it like this.
private void GetCameraPicture_Click(object sender, RoutedEventArgs e)
{
Microsoft.Phone.Tasks.CameraCaptureTask cameraCaptureTask = new Microsoft.Phone.Tasks.CameraCaptureTask();
cameraCaptureTask.Completed += cct_Completed;
cameraCaptureTask.Show();
}
try
{
if (e.TaskResult == Microsoft.Phone.Tasks.TaskResult.OK)
{
var imageStream = e.ChosenPhoto;
var name = e.OriginalFileName;
using (MemoryStream mem = new MemoryStream())
{
TextBlock tb = new TextBlock() { Text = DateTime.Now.ToString("dd MMM yyyy, HH:mm"), Foreground = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)), FontSize = 40 };
BitmapImage finalImage = new BitmapImage();
finalImage.SetSource(imageStream);
WriteableBitmap wbFinal = new WriteableBitmap(finalImage);
wbFinal.Render(tb, null);
wbFinal.Invalidate();
wbFinal.SaveJpeg(mem, wbFinal.PixelWidth, wbFinal.PixelHeight, 0, 100);
mem.Seek(0, System.IO.SeekOrigin.Begin);
MediaLibrary lib = new MediaLibrary();
lib.SavePictureToCameraRoll("Copy" + name, mem.ToArray());
}
}
}
catch (Exception exp) { MessageBox.Show(exp.Message); }
Hope it may help you.

Related

Media Projection and Image Reader duo not working on Netflix/Youtube on Android TV

Media Projection and Image Reader duo not working on Netflix/Youtube on Android TV.
I am trying to get image from android TV with Media Projection and Image Reader.
On the log side, a warning catches my eye; probably because Image Reader uses OpenGL:
W/libEGL: EGLNativeWindowType 0xd7995a68 disconnect failed
Although it works correctly in the simulator, Image Reader does not work properly in programs such as Youtube, Netflix and so on licensed Android TV. (No problem in simulator)
I tried, works fine on CNBC-e and Android TV User Interface.
I'm starting to think it's due to HDCP. Any guesses about it? Or do you think these programs have Media Projection protection?
Images captured on Netflix and Youtube are always the same. It's like time has stopped.
The heart of my codes is as follows.
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
#Override
public void onImageAvailable(ImageReader reader) {
FileOutputStream fos = null;
Bitmap bitmap = null;
try (Image image = mImageReader.acquireLatestImage()) {
if (image != null) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = (ByteBuffer) planes[0].getBuffer().rewind();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// create bitmap
bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
// write bitmap to a file
fos = new FileOutputStream(mStoreDir + "/myscreen_" + IMAGES_PRODUCED + ".png");
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
IMAGES_PRODUCED++;
Log.e(TAG, "captured image: " + IMAGES_PRODUCED);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bitmap != null) {
bitmap.recycle();
}
}
}
}
#SuppressLint("WrongConstant")
private void createVirtualDisplay() {
// get width and height
mWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
mHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
// start capture reader
mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);
mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight,
mDensity, getVirtualDisplayFlags(), mImageReader.getSurface(), null, mHandler);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);
}

How to EnableShutterSound while taking picture in android xamarin

I have a custom camera implementation which I would like to have have my own sound when the picture is taken how to enable shutter sound in hardware camera, I need to only play my camera sound and not the default one
private async void TakePhotoButtonTapped(object sender, EventArgs e)
{
Android.Hardware.Camera.CameraInfo info = new Android.Hardware.Camera.CameraInfo();
// mCameraFacing is CameraID.
Android.Hardware.Camera.GetCameraInfo(mCameraFacing, info);
if (info.CanDisableShutterSound)
camera.EnableShutterSound(false);
else
camera.EnableShutterSound(true);
Bitmap image = textureView.Bitmap;
using (var imageStream = new MemoryStream())
{
await image.CompressAsync(Bitmap.CompressFormat.Jpeg, 100, imageStream);
image.Recycle();
imageBytes = imageStream.ToArray();
AddImages(imageBytes);
Toast.MakeText(Android.App.Application.Context, _languageCache.Translate("Photo Captured"), ToastLength.Short).Show();
}
await Task.Delay(300);
}
You could use the code below of the sound settings and put it into the code which you used to take photo.
I use the system ShutterClick sound for reference. You could use your own as well.
private void SoundSettings()
{
MediaActionSound sound = new MediaActionSound();
AudioManager meng = (AudioManager)Context.GetSystemService(Context.AudioService);
int volume = meng.GetStreamVolume(Android.Media.Stream.Notification);
if (volume != 0)
sound.Play(MediaActionSoundType.ShutterClick);
}

Images shown rotated in Codename One

I'm developing a Codename One app for iOS.
I gave the user the option to take pictures or to load them from the gallery of the device. After that, the app shows pictures in labels (encapsulated in a BoxLayout).
When I take pictures in portrait mode, everything perfectly works, but when I take pictures in landscape mode, that picture is shown rotated (a 90° rotation).
Here is the code:
String filePath = Capture.capturePhoto();
if (filePath != null) {
try {
Image img = Image.createImage(filePath);
if (img != null){
setImageToContainer(img);
}
}
catch (IOException err) {
ToastBar.showErrorMessage("Problemi con le immagini: " + err.getMessage());
completeImageName = null;
fileImageName = null;
}
}
private void setImageToContainer(Image img){
Label imgLbl = new Label();
Style s = UIManager.getInstance().getComponentStyle("Button");
FontImage p = FontImage.createMaterial(FontImage.MATERIAL_PORTRAIT, s);
EncodedImage placeholder = EncodedImage.createFromImage(p.scaled(p.getWidth() * 3, p.getHeight() * 4), false);
imgLbl.setIcon(placeholder);
list.add(imgLbl);
//Scalo l'immagine
if(img.getWidth() > imgLbl.getParent().getWidth())
img = img.scaledWidth(imgLbl.getParent().getWidth());
if(img.getHeight()> imgLbl.getParent().getHeight())
img = img.scaledHeight(imgLbl.getParent().getHeight());
imgLbl.setIcon(img);
list.repaint();
}
Reading that answer, I understood Image.createImage(filePathToImage) method takes in account EXIF data, in order to properly rotate the image.
How can I solve my problem? Is there a way to get EXIF data?

Xamarin.iOS ZXing.Net.Mobile barcode scanner

I'm trying to add barcode scanner feature to my xamarin.ios app. I'm developing from visual studio and I've added the Zxing.Net.Mobile component from xamarin components store.
I've implemented it as shown in the samples:
ScanButton.TouchUpInside += async (sender, e) => {
//var options = new ZXing.Mobile.MobileBarcodeScanningOptions();
//options.AutoRotate = false;
//options.PossibleFormats = new List<ZXing.BarcodeFormat>() {
// ZXing.BarcodeFormat.EAN_8, ZXing.BarcodeFormat.EAN_13
//};
var scanner = new ZXing.Mobile.MobileBarcodeScanner(this);
//scanner.TopText = "Hold camera up to barcode to scan";
//scanner.BottomText = "Barcode will automatically scan";
//scanner.UseCustomOverlay = false;
scanner.FlashButtonText = "Flash";
scanner.CancelButtonText = "Cancel";
scanner.Torch(true);
scanner.AutoFocus();
var result = await scanner.Scan(true);
HandleScanResult(result);
};
void HandleScanResult(ZXing.Result result)
{
if (result != null && !string.IsNullOrEmpty(result.Text))
TextField.Text = result.Text;
}
The problem is that when I tap the scan button, the capture view is shown correctly but if I try to capture a barcode nothing happens and it seems the scanner doesn't recognize any barcode.
Someone has experienced this issue? How can I made it work?
Thanks in advance for your help!
I answered a similar question here. I couldn't get barcodes to scan because the default camera resolution was set too low. The specific implementation for this case would be:
ScanButton.TouchUpInside += async (sender, e) => {
var options = new ZXing.Mobile.MobileBarcodeScanningOptions {
CameraResolutionSelector = HandleCameraResolutionSelectorDelegate
};
var scanner = new ZXing.Mobile.MobileBarcodeScanner(this);
.
.
.
scanner.AutoFocus();
//call scan with options created above
var result = await scanner.Scan(options, true);
HandleScanResult(result);
};
And then the definition for HandleCameraResolutionSelectorDelegate:
CameraResolution HandleCameraResolutionSelectorDelegate(List<CameraResolution> availableResolutions)
{
//Don't know if this will ever be null or empty
if (availableResolutions == null || availableResolutions.Count < 1)
return new CameraResolution () { Width = 800, Height = 600 };
//Debugging revealed that the last element in the list
//expresses the highest resolution. This could probably be more thorough.
return availableResolutions [availableResolutions.Count - 1];
}

Android Attach Image between text with SpannableStringBuilder

Sory for my english. I want attach image from gallery and show in edit text with SpannableStringBuilder. I have success for get Image Path from Gallery. After picture selected, Picture Show. But, for the second attach image picture not show and first image attach became a text. any one give me solution ? big thanks.
this is my code:
private void IntentPict() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select File"),MY_INTENT_CLICK);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK){
if (requestCode == MY_INTENT_CLICK){
if (null == data) return;
String selectedImagePath;
Uri selectedImageUri = data.getData();
//there is no problem with get path
selectedImagePath = ImageFilePath.getPath(getApplicationContext(), selectedImageUri);
//pathImag is ListArray<String>
pathImg.add(selectedImagePath);
addImageBetweentext(pathImg);
}
}
}
private void addImageBetweentext(ArrayList<String> listPath) {
SpannableStringBuilder ssb = new SpannableStringBuilder();
for(int i=0;i<listPath.size();i++){
String path = listPath.get(i);
Drawable drawable = Drawable.createFromPath(path);
drawable.setBounds(0, 0, 400, 400);
ssb.append(mBodyText+"\n");
ssb.setSpan(new ImageSpan(drawable), ssb.length()-(path.length()+1),
ssb.length()-1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mBodyText.setText(ssb);
}
Here's something that should work. I am loading resource drawables instead, just because it was quicker for me to validate, but I tried to keep as mich as possible for your original flow and variable names:
Drawable[] drawables = new Drawable[2];
drawables[0] = getResources().getDrawable(R.drawable.img1);
drawables[1] = getResources().getDrawable(R.drawable.img2);
SpannableStringBuilder ssb = new SpannableStringBuilder();
for (int i = 0; i < drawables.length; i++) {
Drawable drawable = drawables[i];
drawable.setBounds(0, 0, 400, 400);
String newStr = drawable.toString() + "\n";
ssb.append(newStr);
ssb.setSpan(
new ImageSpan(drawable),
ssb.length() - newStr.length(),
ssb.length() - "\n".length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
mBodyText.setText(ssb);
Long story short: the start position for the incremental builder needs to be set to the current length of it, minus what you just added.

Resources