javacv: grabber.getFrameRate() return 0 - javacv

I have used javacv for my project to deal with avi.
The video shows faster than normal, I want to get the fps to set the speed of the video. But grabber.getFrameRate() return 0, as the same with grabber.getLengthInFrames() and grabber.getSampleRate(), can anyone tell me why?
code snippet below:
FrameGrabber grabber = new OpenCVFrameGrabber("sample.avi");
double fps=grabber.getFrameRate();
System.out.println(fps);
//int n=grabber.getLengthInFrames();
//int f=grabber.getSampleRate();
CvMemStorage storage = CvMemStorage.create();
grabber.start();
grabbedImage = grabber.grab();
while (frame.isVisible() && (grabbedImage = grabber.grab()) != null)
{
BufferedImage bfimg = grabbedImage.getBufferedImage();
frame.showImage(bfimg);
frame.waitKey((int)(1000/fps));
cvClearMemStorage(storage);
}
grabber.stop();

you must call after start();
maybe you can
FrameGrabber grabber = new OpenCVFrameGrabber("sample.avi");
grabber.start();
double fps=grabber.getFrameRate();

I use this code to record mp4 video:
public static void main(String[] args) {
IplImage image;
CanvasFrame canvas = new CanvasFrame("Web Cam");
try {
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start();
IplImage grabbedImage = grabber.grab();
canvas.setCanvasSize(grabbedImage.width(), grabbedImage.height());
System.out.println("framerate = " + grabber.getFrameRate());
grabber.setFrameRate(grabber.getFrameRate());
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("c:/demo.mp4", 320, 240);
recorder.setVideoCodec(13);
recorder.setFormat("mp4");
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFrameRate(10);
recorder.setVideoBitrate(5*1024);
recorder.start();
System.out.println("framerate = " + grabber.getFrameRate());
while (canvas.isVisible() && (grabbedImage = grabber.grab()) != null) {
canvas.showImage(grabbedImage);
recorder.record(grabbedImage);
}
recorder.stop();
grabber.stop();
canvas.dispose();
} catch (Exception e) {
e.printStackTrace();
}
}

I tried this in a webcam example and it worked:
double time1,time2;
// your loop
while(....){
time1=System.currentTimeMillis(); // add this first in the loop
//code here
.
.
.
.
time2=System.currentTimeMillis(); // add this at the end of the loop
System.out.println("framerate = " + 1/(((time2-time)/1000)%60))
} //end of loop
In case of webcam example with code for webcam found:
http://opencvlover.blogspot.com/2012/05/accessing-webcam-using-javacv.html
it looks like this :
IplImage img
while (...) {
time1=System.currentTimeMillis(); // add this first in the loop
//inser grabed video fram to IplImage img
img = grabber.grab();
.
.
.
.
//Show video frame in canvas
canvas.showImage(img);
time2=System.currentTimeMillis(); // add this at the end of the loop
System.out.println("framerate = " + 1/(((time2-time)/1000)%60))
} //end of loop
.
.
.

Related

Rgb 565 Pdf to Image

I am trying to convert a PDF page to an image, to create thumbnails. This is the code that I am using:
PdfRenderer pdfRenderer = new PdfRenderer(GetSeekableFileDescriptor(filePath));
var appDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
string directoryPath = System.IO.Path.Combine(appDirectory, "thumbnailsTemp", System.IO.Path.GetFileNameWithoutExtension(fileName));
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
int pageCount = pdfRenderer.PageCount;
for (int i = 0; i < pageCount; i++)
{
Page page = pdfRenderer.OpenPage(i);
Android.Graphics.Bitmap bmp = Android.Graphics.Bitmap.CreateBitmap(page.Width, page.Height, Android.Graphics.Bitmap.Config.Rgb565 or Argb8888);
page.Render(bmp, null, null, PdfRenderMode.ForDisplay);
try
{
using (FileStream output = new FileStream(System.IO.Path.Combine(directoryPath, fileName + "Thumbnails" + i + ".png"), FileMode.Create))
{
bmp.Compress(Android.Graphics.Bitmap.CompressFormat.Png, 100, output);
}
page.Close();
}
catch (Exception ex)
{
//TODO -- GERER CETTE EXPEXPTION
throw new Exception();
}
}
return directoryPath;
}
I tried with ARGB 8888 and that was a success. But the rendering time was too slow for big PDF files. This is why I tried to improve it by changing the format to RGB 565. But my app is crashing with this Execption:
Unsuported pixel format
Any idea to fix this, or how to render a PDF to a bitmap faster? I was looking on google but didn't find a solution related to my code.
UPDATE
I did this but know, my app is crashing at this line of code :
await Task.Run(() =>
{
bytes = page.AsPNG(72);
});
My class :
public async Task<string> GetBitmaps(string filePath)
{
//TODO -- WORK ON THIS
PdfRenderer pdfRenderer = new PdfRenderer(GetSeekableFileDescriptor(filePath));
var appDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
string directoryPath = System.IO.Path.Combine(appDirectory, "thumbnailsTemp", System.IO.Path.GetFileNameWithoutExtension(fileName));
var stream = new MemoryStream();
using (Stream resourceStream = new FileStream(filePath, FileMode.Open))
{
resourceStream.CopyTo(stream);
}
for (int i = 0; i < pdfRenderer.PageCount; i++)
{
TallComponents.PDF.Rasterizer.Page page = new TallComponents.PDF.Rasterizer.Page(stream, i);
byte[] bytes = null;
await Task.Run(() =>
{
bytes = page.AsPNG(72);
});
using (FileStream output = new FileStream(System.IO.Path.Combine(directoryPath, fileName + "Thumbnails" + i + ".png"), FileMode.Create, FileAccess.Write))
{
output.Write(bytes, 0, bytes.Length);
}
}
return directoryPath;
}
you could draw a PDF page in app by converting a PDF page to a bitmap,here the PDF document itself is embedded as a resource.
var assembly = Assembly.GetExecutingAssembly();
var stream = new MemoryStream();
using (Stream resourceStream = assembly.GetManifestResourceStream("DrawPdf.Android.tiger.pdf"))
{
resourceStream.CopyTo(stream);
}
Page page = new Page(stream, 0);
// render PDF Page object to a Bitmap
byte[] bytes = null;
await Task.Run(() =>
{
bytes = page.AsPNG(72);
});
Bitmap bmp = global::Android.Graphics.BitmapFactory.DecodeByteArray(bytes, 0, bytes.Length);

Xamarin.Forms Android save image to gallery

I have a stream which is the result of taking a photo. I want to save that photo to the users Gallery.
I have tried all manner of things but nothing takes... The class I am saving is a plain C# class - it does not inherit form any android types but that could be done if necessary (to fire an intent perhaps - though I tried this and it ended up another rabbit hole)
I have tried this:
try{
using (FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + _name, FileMode.OpenOrCreate))
{
fs.Write(bytes, 0, bytes.Length);
}
} catch (Exception ex) {
Console.WriteLine (ex.Message);
}
and also:
if (_filename.ToLower ().Contains (".jpg") || _filename.ToLower ().Contains (".png")) {
stream.Position = 0;
var bitmap = BitmapFactory.DecodeStream (stream);
var finalStream = new MemoryStream ();
bitmap.Compress (Bitmap.CompressFormat.Jpeg, 25, finalStream);
bitmap = null;
finalStream.Position = 0;
var path2 = Environment.GetFolderPath (Environment.SpecialFolder.MyPictures);
var filename2 = System.IO.Path.Combine (path2, _filename);
using (var fileStream = File.Create (filename2)) {
finalStream.Seek (0, SeekOrigin.Begin);
finalStream.CopyTo (fileStream);
fileStream.Close ();
finalStream.Dispose ();
stream.Dispose ();
fileStream.Dispose ();
GC.Collect ();
}
return;
}
I thought this would be an easy task! meh...
Any help?
Use the MediaStore ContentProvider. MediaStore.Images.Media has several Insert methods you can use to add content to the gallery.

"Parameter is not valid" error when extracting images using iTextSharp from a PDF containing JPXDecode filter

I am trying to extract images from a PDF using the following code. It works well for some filters like DCTDecode , but is not working for JPXDEcode ."Parameter not valid " error occurs at the point image.GetDrawingImage() is called.
using System.Drawing.Imaging;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
...
PdfReader pdf = new PdfReader(currfilename);
PdfReaderContentParser parser = new PdfReaderContentParser(pdf);
ImageRender listener = new ImageRender();
for (int i = 1; i <= pdf.NumberOfPages; i++)
{
try
{
parser.ProcessContent(i, listener);//calls RenderImage() at this point
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public void RenderImage(ImageRenderInfo renderInfo)
{
PdfImageObject image = renderInfo.GetImage();
PdfName filter = image.Get(PdfName.FILTER) as PdfName;
if (renderInfo.GetRef() != null && image != null)
{
using (System.Drawing.Image dotnetImg = image.GetDrawingImage())//exception occurs at this point
{
if (dotnetImg != null)
{
ImageNames.Add(string.Format("{0}.tiff", renderInfo.GetRef().Number));
using (MemoryStream ms = new MemoryStream())
{
dotnetImg.Save(ms, ImageFormat.Tiff);
Images.Add(ms.ToArray());
}
}
}
}
}
I tried these links for a solution
Extract images using iTextSharp
Extract Image from a particular page in PDF
and was able to extract the raw image bytes using PdfReader.GetStreamBytesRaw() function but "Parameter not valid "exception always occurs at the point where System.Drawing.Image.FromStream(memory stream) is called.
I also checked this link "Parameter is not valid" exception from System.Drawing.Image.FromStream() method , but could not find anything helpful.
Please help
The JPXDecode filter corresponds to JPEG 2000 compression, which is not supported by .net framework. This other question in SO may help: JPEG 2000 support in C#.NET
Using FreeImage.dll solved the problem. The code is as follows
using FreeImageAPI;
using System.Drawing.Imaging;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
...
imagecount = 0;
PdfReader pdf = new PdfReader(currfilename);
PdfReaderContentParser parser = new PdfReaderContentParser(pdf);
ImageRender listener = new ImageRender();
for (int i = 1; i <= pdf.NumberOfPages; i++)
{
try
{
parser.ProcessContent(i, listener);//calls RenderImage() at this point
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
if (listener.Images.Count > 0)
{
for (int j = 0; (j < listener.Images.Count); ++j)
{
string imgpath = Environment.CurrentDirectory.ToString() + "\\Image" + imagecount + ".bmp";
// create a memory stream
MemoryStream imageStream = new MemoryStream(listener.Images[j]);
// create a FIBITMAP from that stream
FIBITMAP dib = FreeImage.LoadFromStream(imageStream);
if (dib.IsNull) continue;
//turn it into a normal Bitmap
Bitmap bitmap = FreeImage.GetBitmap(dib);
bitmap.Save(imgpath);
//unload the FIBITMAP
FreeImage.UnloadEx(ref dib);
bitmap.Dispose();
System.Drawing.Image img = System.Drawing.Image.FromFile(imgpath);
}
public void RenderImage(ImageRenderInfo renderInfo)
{
PdfImageObject image = renderInfo.GetImage();
if (renderInfo.GetRef() != null && image != null)
{
byte[] tempImage = image.GetImageAsBytes();
ImageNames.Add(string.Format("0}.bmp",renderInfo.GetRef().Number));
Images.Add(tempImage);
}
}
I followed the instructions given here to add FreeImage .Net to solution

Image overlay with camera captured image in android

I need to take a picture with the camera and at the same time show an overlay image on top of the camera view. After the picture is taken, i need to save what the user saw while taking the picture. Can anyone suggest me? Please.
public void onPictureTaken(byte[] data, Camera camera){
Bitmap cameraBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
wid = cameraBitmap.getWidth();
hgt = cameraBitmap.getHeight();
Bitmap newImage = Bitmap.createBitmap(wid , hgt , Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(cameraBitmap, 0f, 0f, null);
Drawable drawable = getResources().getDrawable(R.drawable.d);
drawable.setBounds(20 ,20, 260, 160);
drawable.draw(canvas);
File storagePath = new File(Environment.getExternalStorageDirectory() + "/Vampire Photos/");
storagePath.mkdirs();
File myImage = new File(storagePath,Long.toString(System.currentTimeMillis()) + ".jpg");
try
{
FileOutputStream out = new FileOutputStream(myImage);
newImage.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
}
catch(FileNotFoundException e)
{
Log.d("In Saving File", e + "");
}
catch(IOException e)
{
Log.d("In Saving File", e + "");
}
camera.startPreview();
drawable = null;
newImage.recycle();
newImage = null;
cameraBitmap.recycle();
cameraBitmap = null;
} };

Why is part of the image cut out when taking a picture with this code on Blackberry?

When I take a picture on the simulator (Haven't tried a device yet) the result is only less than half of the image and the rest is gray. Does anyone know why?
Thanks
listener = new FileSystemJournalListener()
{
private long _lastUSN;
public void fileJournalChanged()
{
long nextUSN = FileSystemJournal.getNextUSN();
FileSystemJournalEntry entry = FileSystemJournal.getEntry(nextUSN - 1);
nextUSN++;
switch (entry.getEvent()) {
case FileSystemJournalEntry.FILE_ADDED:
try
{
FileConnection fconn = (FileConnection)Connector.open("file://" +entry.getPath());
if(fconn.exists())
{
InputStream input = null;
input = fconn.openInputStream();
byte[] data = new byte[(int) fconn.fileSize() + 1000];
input.read(data);
rawImage = data;
pic = Bitmap.createBitmapFromBytes(data, 0, -1, 1);
if(input != null)
{
input.close();
}
Bitmap[] images = new Bitmap[1];
images[0] = pic;
//labels[1] = "Label for image 2";
// tooltips[1] = "Tooltip for image 2";
// labels[2] = "Label for image 2";
// tooltips[2] = "Tooltip for image 2";
ScrollEntry[] entries = new ScrollEntry[images.length];
entries[0] = new ScrollEntry(images[0], "", "");
PictureScrollField pictureScrollField = new PictureScrollField(175, 131);
pictureScrollField.setData(entries, 0);
pictureScrollField.setHighlightStyle(HighlightStyle.ILLUMINATE_WITH_SHRINK_LENS);
// pictureScrollField.setHighlightBorderColor(Color.BLUE);
pictureScrollField.setBackground(BackgroundFactory.createSolidTransparentBackground(Color.BLACK, 150));
insert(pictureScrollField, 1);
picTaken = true;
EventInjector.KeyEvent inject = new EventInjector.KeyEvent(EventInjector.KeyEvent.KEY_DOWN, Characters.ESCAPE, 0, 50);
inject.post();
inject.post();
}
break;
}
catch (Exception e)
{
// TODO Auto-generated catch block
Dialog.alert(e.toString());
}
//either a picture was taken or a picture was added to the BlackBerry device
case FileSystemJournalEntry.FILE_DELETED:
//a picture was removed from the BlackBerry device;
break;
}
input.read(data) only reads some amount of data, not all of it. If you want to read the whole file, use IOUtilities.streamToBytes(input); instead, like this:
byte[] data = IOUtilities.streamToBytes(input);
byte[] data = new byte[(int) fconn.fileSize() + 1000];
...
pic = Bitmap.createBitmapFromBytes(data, 0, -1, 1);
I think data now contains last wrong 1000 bytes, try changing to:
byte[] data = new byte[(int) fconn.fileSize()];
I faced the same problem. Just use:
synchronized(UiApplication.getEventLock()) {
//your code here
}

Resources