Setting pptx Theme in Java - java

I am trying to merge some pptx documents programmatically using java. I figured out how to do this in essence using Apache POI but the documents I am trying to merge do not work.
After significant searching and trial and error I figured out that the reason for this is that the pptx documents do not have theme information (i.e., if I click into powerpoint and check the slide master view it's blank). If I goto the themes in the Design Ribbon and select 'office theme' or another theme then save. the files will merge charmingly. Otherwise, I run into the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Failed to fetch default style for otherStyle and level=0
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.getDefaultMasterStyle(XSLFTextParagraph.java:1005)
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.fetchParagraphProperty(XSLFTextParagraph.java:1029)
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.isBullet(XSLFTextParagraph.java:654)
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.copy(XSLFTextParagraph.java:1044)
at org.apache.poi.xslf.usermodel.XSLFTextShape.copy(XSLFTextShape.java:631)
at org.apache.poi.xslf.usermodel.XSLFSheet.appendContent(XSLFSheet.java:358)
at com.apsiva.main.Snippet.main(Snippet.java:28)
The following is the code I ran:
package com.apsiva.main;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.xslf.usermodel.SlideLayout;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
public class Snippet {
/** Merge the pptx files in the array <decks> to the desired destination
* chosen in <outputPath> */
public static void main(String[] args) {
try {
FileInputStream empty = new FileInputStream("C:/Users/Alex/workspace/OutputWorker/tmp/base2.pptx");
XMLSlideShow pptx;
pptx = new XMLSlideShow(empty);
XSLFSlideLayout defaultLayout = pptx.getSlideMasters()[0].getLayout(SlideLayout.TITLE_AND_CONTENT);
FileInputStream is = new FileInputStream("C:/Users/Alex/workspace/OutputWorker/tmp/noWork.pptx");
// FileInputStream is = new FileInputStream("C:/Users/Alex/workspace/OutputWorker/tmp/works2.pptx");
XMLSlideShow src = new XMLSlideShow(is);
is.close();
for (XSLFSlide srcSlide: src.getSlides()){
pptx.createSlide(defaultLayout).appendContent(srcSlide);
}
FileOutputStream out = new FileOutputStream("C:/POI-TEST-OUTPUT.pptx");
pptx.write(out);
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I want to get these files to merge and I believe the solution is to programmatically assign the theme to the files. How can it be done?
Thank you for your consideration!

In some cases when you have generated pptx files (ex. JasperReport exports) then some invalid values might be added for different fields. For example line spacing, which can be percent, and special characters, and the apache poi xslf doesn't know how to handle these values. When opening the file, PowerPoint automatically adjusts these values to valid ones. When using apache poi, you have to individually identify these fields and adjust them manually.
I had a similar issue, but with line spacing, and did a workaround, by setting the values for each paragraph like this:
List<XSLFShape> shapes = srcSlide.getShapes();
for (XSLFShape xslfShape: shapes) {
if (xslfShape instanceof XSLFTextShape){
List<XSLFTextParagraph> textParagraphs = ((XSLFTextShape) xslfShape).getTextParagraphs();
for (XSLFTextParagraph textParagraph: textParagraphs) {
textParagraph.setLineSpacing(10d);
}
}
}
This worked like a charm.
A more effective way to do this is to do it directly on the XML object:
List<CTShape> ctShapes = srcSlide.getXmlObject().getCSld().getSpTree().getSpList();
for (CTShape ctShape : ctShapes) {
List<CTTextParagraph> ctTextParagraphs = ctShape.getTxBody().getPList();
for (CTTextParagraph paragraph : ctTextParagraphs) {
if (paragraph.getPPr().getLnSpc() != null) {
paragraph.getPPr().unsetLnSpc();
}
}
}

/ApachePOI/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
CTTextParagraphProperties getDefaultMasterStyle()
add
if( o.length == 0 ) {
return null;
}

Related

Oracle OpenScript "Error reading file" when substituting variable

I'm composing a web script with Oracle OpenScript.
I recorded the actions to be performed
open link
select drop-down menu
select field from drop-down menu
save
and I'm trying to now substitute the link to be opened with a variable from a .csv I created in the assets but I get a "Error reading file" message.
SCREENSHOT
Here's the full code:
import oracle.oats.scripting.modules.basic.api.*;
import oracle.oats.scripting.modules.browser.api.*;
import oracle.oats.scripting.modules.functionalTest.api.*;
import oracle.oats.scripting.modules.utilities.api.*;
import oracle.oats.scripting.modules.utilities.api.sql.*;
import oracle.oats.scripting.modules.utilities.api.xml.*;
import oracle.oats.scripting.modules.utilities.api.file.*;
import oracle.oats.scripting.modules.webdom.api.*;
public class script extends IteratingVUserScript {
#ScriptService oracle.oats.scripting.modules.utilities.api.UtilitiesService
utilities;
#ScriptService oracle.oats.scripting.modules.browser.api.BrowserService
browser;
#ScriptService
oracle.oats.scripting.modules.functionalTest.api.FunctionalTestService ft;
#ScriptService oracle.oats.scripting.modules.webdom.api.WebDomService web;
public void initialize() throws Exception {
browser.launch();
}
/**
* Add code to be executed each iteration for this virtual user.
*/
public void run() throws Exception {
beginStep("[1] No Title (/hotelconfig.html)", 0);
{
web.window(2, "/web:window[#index='0' or #title='about:blank']")
.navigate(
"URL");
{
think(0.093);
}
}
endStep();
beginStep("[2] Working... (/wia)", 0);
{
web.window(4, "/web:window[#index='0' or #title='about:blank']")
.navigate(
"URL");
web.window(
5,
"/web:window[#index='0']")
.waitForPage(null);
{
think(6.198);
}
web.selectBox(
6,
"/web:window[#index='0']/web:document[#index='0']/web:form[#index='0']/web:select[(#id='office_id' or #name='office_id' or #index='10') and multiple mod 'False']")
.selectOptionByText(
"Office");
{
think(2.636);
}
web.button(
7,
"/web:window[#index='0']/web:document[#index='0']/web:form[#index='0']/web:input_submit[#name='save' or #value='Save' or #index='0']")
.click();
}
endStep();
beginStep(
"[3] Intranet - Property info - *Hotel Settings - *Hotel configuration (/hotelconfig.html)",
0);
{
web.window(
8,
"/web:window[#index='0']")
.waitForPage(null);
}
endStep();
}
public void finish() throws Exception {
}
}
I looked online and on Oracle's community but I couldn't find a fix.
I also tried to run the OpenScript Diagnosis Tool but no luck.
Anyone has any idea?
Oracle Application Testing Suite (OATS) best supports csv data sheet reading.
Code you pasted is just recording you performed and not seen any issue there. and Screenshot shows error message, something might have gone wrong while creating csv.
I can suggest external excel reader , which is inbuilt in OATS itself
http://www.testinghive.com/category/oracle-application-testing-suite-tips/
//Define Sheet name to be read, and provide comma seperated to read multiple sheets
String sheetName = "Sheet1";
//Mention excel sheet path
String strFile= "C:\\Demo\\test.xls";
//Defined array list to add Sheets to read
List sheetList = new ArrayList();
sheetList.add(sheetName);
// Iports Sheet1
datatable.importSheets(strFile, sheetList, true, true);
//get rowcount
info("Total rows :"+datatable.getRowCount());
int rowcount=datatable.getRowCount();
//Loop to read all rows
for (int i=0;i<rowcount;i++)
{
//Set current row fromw here you need to start reading, in this case start from first row
datatable.setCurrentRow(sheetName, i);
String strCompany=(String) datatable.getValue(sheetName,i,"Company");
String strEmpFName=(String) datatable.getValue(sheetName,i,"FirstName");
String strEmpLName=(String) datatable.getValue(sheetName,i,"LastName");
String strEmpID=(String) datatable.getValue(sheetName,i,"EmpID");
String strLocation=(String) datatable.getValue(sheetName,i,"Location");
//prints first name and last name
System.out.println("First Name : "+strEmpFName+", Last Name : "+strEmpLName);
//Sets ACTIVE column in excel sheet to Y
String strActive="Y";
datatable.setValue(sheetName, i, datatable.getColumn(sheetName, datatable.getColumnIndex("Active")), strActive);
}
//Updates sheet with updated values ie ACTIVE column sets to Y
datatable.exportToExcel("C:\\Demo\\test1.xlsx");
}
public void finish() throws Exception {
}
}
I find it easier to use a databank as data provider.
By adding a CSV file with the necessary variable, you will be able to do the following substitution:
public void run() throws Exception {
getDatabank("databank").getNextDatabankRecord();
String v_dataFilename = "{{db.databank.filename}}";
}

Opening txt in sub directories with notepad through java

I've been browsing the site since yesterday and I can't see to find anything that answers my question, so I decided to just ask.
I'm making a pretty basic java GUI, it's designed to be run alongside files that wont be included in the actual java package for compatibility and easier customization of those files, I doubt they could be included either way as they have their own .jars and other things.
So, the problem I'm having is that the GUI application is in the main folder and I need it to locate and open txt files a couple sub-folders deep, in notepad without requiring a full file path as I'll be giving this project out to some people when it's done.
Currently I've been using this to open the files, but will only work for files in the main folder and trying to edit in any file paths did not work.
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
Runtime rt=Runtime.getRuntime();
String file;
file = "READTHIS.txt";
try {
Process p=rt.exec("notepad " +file);
} catch (IOException ex) {
Logger.getLogger(NumberAdditionUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
if someone knows a way to do this, that'd be great.
On another note, I'd like to include the file shown above (READTHIS.txt) inside the actual java package, where would I put the file and how should I direct java towards it?
I've been away from java for a long time so I've forgotten pretty much anything, so simpler explanations are greatly appreciated.
Thanks to anyone reading this and any help would be awesome.
Update 2
So I added to the ConfigBox.java source code and made jButton1 open home\doc\READTHIS.txt in Notepad. I created an executable jar and the execution of the jar, via java -jar Racercraft.jar, is shown in the image below. Just take the example of what I did in ConfigBox.java and apply it to NumberAdditionUI.java for each of its JButtons, making sure to change the filePath variable to the corresponding file name that you would like to open.
Note: The contents of the JTextArea in the image below were changed during testing, my code below does not change the contents of the JTextArea.
Directory structure:
\home
Rasercraft.jar
\docs
READTHIS.txt
Code:
// imports and other code left out
public class ConfigBox extends javax.swing.JFrame {
// curDir will hold the absolute path to 'home\'
String curDir; // add this line
/**
* Creates new form ConfigBox
*/
public ConfigBox()
{
// this is where curDir gets set to the absolute path of 'home/'
curDir = new File("").getAbsolutePath(); // add this line
initComponents();
}
/*
* irrelevant code
*/
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
Runtime rt = Runtime.getRuntime();
// filePath is set to 'home\docs\READTHIS.txt'
String filePath = curDir + "\\docs\\READTHIS.txt"; // add this line
try {
Process p = rt.exec("notepad " + filePath); // add filePath
} catch (IOException ex) {
Logger.getLogger(NumberAdditionUI.class.getName()).log(Level.SEVERE, null, ex);
}
// TODO add your handling code here:
}//GEN-LAST:event_jButton1ActionPerformed
/*
* irrelevant code
*/
Update
This is the quick and dirty approach, if you would like me to add a more elegant solution just let me know. Notice that the file names and their relative paths are hard-coded as an array of strings.
Image of the folder hierarchy:
Code:
Note - This will only work on Windows.
import java.io.File;
import java.io.IOException;
public class Driver {
public static void main(String[] args) {
final String[] FILE_NAMES = {"\\files\\READTHIS.txt",
"\\files\\sub-files\\Help.txt",
"\\files\\sub-files\\Config.txt"
};
Runtime rt = Runtime.getRuntime();
// get the absolute path of the directory
File cwd = new File(new File("").getAbsolutePath());
// iterate over the hard-coded file names opening each in notepad
for(String file : FILE_NAMES) {
try {
Process p = rt.exec("notepad " + cwd.getAbsolutePath() + file);
} catch (IOException ex) {
// Logger.getLogger(NumberAdditionUI.class.getName())
// .log(Level.SEVERE, null, ex);
}
}
}
}
Alternative Approach
You could use the javax.swing.JFileChooser class to open a dialog that allows the user to select the location of the file they would like to open in Notepad.
I just coded this quick example using the relevant pieces from your code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Driver extends JFrame implements ActionListener {
JFileChooser fileChooser; // the file chooser
JButton openButton; // button used to open the file chooser
File file; // used to get the absolute path of the file
public Driver() {
this.fileChooser = new JFileChooser();
this.openButton = new JButton("Open");
this.openButton.addActionListener(this);
// add openButton to the JFrame
this.add(openButton);
// pack and display the JFrame
this.pack();
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
// handle open button action.
if (e.getSource() == openButton) {
int returnVal = fileChooser.showOpenDialog(Driver.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
// from your code
Runtime rt = Runtime.getRuntime();
try {
File file = fileChooser.getSelectedFile();
String fileAbsPath = file.getAbsolutePath();
Process p = rt.exec("notepad " + fileAbsPath);
} catch (IOException ex) {
// Logger.getLogger(NumberAdditionUI.class.getName())
// .log(Level.SEVERE, null, ex);
}
} else {
System.exit(1);
}
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Driver driver = new Driver();
}
});
}
}
I've also included a link to some helpful information about the FileChooser API, provided by Oracle: How to use File Choosers. If you need any help figuring out the code just let me know, via a comment, and I'll try my best to help.
As for including READTHIS.txt inside the actual java package, take a gander at these other StackOverflow questions:
Getting file from same package?
Reading a text file from a specific package?
How to include text files with executable jar?
Creating runnable jar with external files included?
Including a text file inside a jar file and reading it?

java.lang.IllegalArgumentException: 'hello' does not contain an equals sign

I am currently using the Apache commons configuration library to write and read data from a file. I am able to save the key value pair colors=hello to the user..properties file, but when i try to read the value is get the below exception.
Exception in thread "main" java.lang.IllegalArgumentException: 'hello' does not contain an equals sign
at org.apache.commons.configuration.AbstractConfiguration.getProperties(AbstractConfiguration.java:625)
at org.apache.commons.configuration.AbstractConfiguration.getProperties(AbstractConfiguration.java:579)
at com.code.prep.CommonsMain.readProperties(CommonsMain.java:21)
at com.code.prep.CommonsMain.main(CommonsMain.java:12)
The code is as below
package com.code.prep;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
public class CommonsMain {
public static void main(String[] args) {
CommonsMain main = new CommonsMain();
main.readProperties();
// main.writeProperties();
}
public void readProperties(){
PropertiesConfiguration config = new PropertiesConfiguration();
try {
config.load("user.properties");
System.out.println(config.getProperties("colors"));
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
public void writeProperties(){
PropertiesConfiguration config = new PropertiesConfiguration();
try {
config.load("user.properties");
config.setProperty("colors", "hello");
config.save("user.properties");
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
}
The Jars in the class path are:
commons-configuration-1.9.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
user.properties contains
colors = hello
user = thejavamonk
You should not be using
config.getProperties("colors")
but
config.getProperty("colors")
"getProperties(code)" is looking for (multiple) lines in your user.properties file of the form:
code key=val
so it's expecting your code as it stands to have lines like :
colors foreground=black
colors background=white
etc.
This does not look like library issue. Open your file and check whether the data is actually available. From you code it looks like you are doing -
main.readProperties();
// main.writeProperties();
Why would there be any data unless you write it? Call writeProperties() method first and then read it back.

Damaged file handling

I would like to know if anyone has any advice on handling damaged files with Apache POI
I am trying to open a file and am receiving this message:
Exception in thread "main" org.apache.poi.hssf.record.RecordInputStream$LeftoverDataException: Initialisation of record 0x1C left 2 bytes remaining still to be read.
at org.apache.poi.hssf.record.RecordInputStream.hasNextRecord(RecordInputStream.java:156)
at org.apache.poi.hssf.record.RecordFactoryInputStream.nextRecord(RecordFactoryInputStream.java:231)
at org.apache.poi.hssf.record.RecordFactory.createRecords(RecordFactory.java:480)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:301)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:95)
at ExcelImporter.EditFileImportDialog.main(EditFileImportDialog.java:409)
Here is an SSCCE
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class EditFileImportDialog {
/* Omitted irrelevent code */
public static void main(String[] args) {
File file = new File("Z:\\Path\\To\\File_causing_the_trouble.xls");
try {
Workbook wb = WorkbookFactory.create(file); // Line 409 for ref to the exception stack trace
System.out.println(wb);
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This happens with this file only, and the exception is not thrown if I open the file in excel and save it, then try to open it with POI. Any suggestion as to how I could handle this?
EDIT:
As a note, my issue may be related to this question, but upgrading POI did not fix my issue and there are dissimilarities with the described file. I have searched around for similar answers but perhaps if someone knows what's wrong with the excel file itself, I can write something to patch the file.
EDIT 2
The file creation is not in my control. Excel fixes the file itself just upon opening and re-saving it. My question though is whether anyone can think of a way to adjust/augment POI to handle this damaged file in the same way that excel is able to fix the issue.
EDIT 3
In response to several comments/answers:
My end goal would be to not use excel at all.
File is sent in.
Program runs.
Handles the error.
Processes data.
You could try using HSSFWorkbook to open .xls files.
You could use the following code to check how POI respond determining xls format.
private boolean isExcel(InputStream i) throws IOException {
return (POIFSFileSystem.hasPOIFSHeader(i) || POIXMLDocument.hasOOXMLHeader(i));
}
I would use :
InputStream input = new FileInputStream(fileName);
Instead of :
File file = new File("Z:\\Path\\To\\File_causing_the_trouble.xls");
Did you check what is wrong with the cell 0x1C in your file ?
The best option would be to create a new file and make it a point to remember that you close the file before executing the program. That would be the simplest solution.
Exception in thread main is not a coding problem. You should replace wrong cell references in Excel-Workbook!
Exception in thread "main" org.apache.poi.hssf.record.RecordInputStream$LeftoverDataException:
Initialisation of record 0x23 left 12 bytes remaining still to be read.
This Exception is thrown when i try to open an Excel-Workbook with POI HSSF, that contains a DDE Cell Reference. I have this problem with a cell reference type of 'Excel.Type.12' e.g.:
=Excel.Sheet.12|'\servername\pathname\Workbook.xlsx'!'!Sheetname!Z23S22'
Workaround: Replace the reference with a reference of type 'Sheet' e.g.:
='Drive:\pathname[Workbook.xlsx]Sheetname'!$V$23
Save your Workbook and try it again.
Try creating an XSSFWorkbook instead from a FileInputStream.
With changes your sample would look like:
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class EditFileImportDialog {
/* Omitted irrelevent code */
public static void main(String[] args) {
String file = "Z:\\Path\\To\\File_causing_the_trouble.xls";
try {
InputStream databaseFile = new FileInputStream(file);
XSSFWorkbook wb = new XSSFWorkbook(databaseFile);
System.out.println(wb);
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You might have already checked, but if not, see https://bz.apache.org/bugzilla/show_bug.cgi?id=47251 if helps. It has similar problem(s) and you may find answer on how to handle it.

How can I get a frame sample (jpeg) from a video (mov)

I want to get a frame sample (jpeg) from a video file (mov) with java. Is there an easy way to do this. When I search in google all I can find is to make mov from multiple jpgs. I dont know maybe I cannot find the right keywords.
I know that the original question is solved, nevertheless, I am posting this answer in case anyone else got stuck like I did.
Since yesterday, I have tried everything, and I mean everything to do this. All available Java libraries are either out of date, not maintained anymore or lack any kind of usable documentation (seriously??!?!)
I tried JFM (old and useless), JCodec (no documentation whatsoever), JJMpeg (looks promising but is very difficult and cumbersome to use due to lack of Java-class documentation), OpenCV auto-Java builds and a few bunch of other libraries that I cannot remember.
Finally, I decided to take a look at JavaCV's (Github link) classes and voila! It contains FFMPEG bindings with detailed documentations.
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.0</version>
</dependency>
Turns out there is a very easy way to extract video frames from a video file to a BufferedImage and by extension a JPEG file. The class FFmpegFrameGrabber could be easily used for grabbing individual frames and converting them to BufferedImage. A code sample is as follows:
FFmpegFrameGrabber g = new FFmpegFrameGrabber("textures/video/anim.mp4");
g.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
for (int i = 0 ; i < 50 ; i++) {
Frame frame = g.grabImage(); // It is important to use grabImage() to get a frame that can be turned into a BufferedImage
BufferedImage bi = converter.convert(frame);
ImageIO.write(bi, "png", new File("frame-dump/video-frame-" + System.currentTimeMillis() + ".png"));
}
g.stop();
Basically, this code dumps the first 50 frames of the video and saves them as a PNG file. The good thing is that the internal seek function, works on actual frames not keyframes (a problem that I had with JCodec)
You can refer to the JavaCV's homepage to find out more about other classes that can be used for capturing frames from WebCams etc. Hope this answer helps :-)
Xuggler does the job. They even give a sample code which does exactly what I need. Link is below
http://xuggle.googlecode.com/svn/trunk/java/xuggle-xuggler/src/com/xuggle/mediatool/demos/DecodeAndCaptureFrames.java
And I've modified the code in this link such that it saves only the first frame of the video.
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.image.BufferedImage;
import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import com.xuggle.xuggler.Global;
/**
* * #author aclarke
* #author trebor
*/
public class DecodeAndCaptureFrames extends MediaListenerAdapter
{
private int mVideoStreamIndex = -1;
private boolean gotFirst = false;
private String saveFile;
private Exception e;
/** Construct a DecodeAndCaptureFrames which reads and captures
* frames from a video file.
*
* #param filename the name of the media file to read
*/
public DecodeAndCaptureFrames(String videoFile, String saveFile)throws Exception
{
// create a media reader for processing video
this.saveFile = saveFile;
this.e = null;
IMediaReader reader = ToolFactory.makeReader(videoFile);
// stipulate that we want BufferedImages created in BGR 24bit color space
reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);
// note that DecodeAndCaptureFrames is derived from
// MediaReader.ListenerAdapter and thus may be added as a listener
// to the MediaReader. DecodeAndCaptureFrames implements
// onVideoPicture().
reader.addListener(this);
// read out the contents of the media file, note that nothing else
// happens here. action happens in the onVideoPicture() method
// which is called when complete video pictures are extracted from
// the media source
while (reader.readPacket() == null && !gotFirst);
if (e != null)
throw e;
}
/**
* Called after a video frame has been decoded from a media stream.
* Optionally a BufferedImage version of the frame may be passed
* if the calling {#link IMediaReader} instance was configured to
* create BufferedImages.
*
* This method blocks, so return quickly.
*/
public void onVideoPicture(IVideoPictureEvent event)
{
try
{
// if the stream index does not match the selected stream index,
// then have a closer look
if (event.getStreamIndex() != mVideoStreamIndex)
{
// if the selected video stream id is not yet set, go ahead an
// select this lucky video stream
if (-1 == mVideoStreamIndex)
mVideoStreamIndex = event.getStreamIndex();
// otherwise return, no need to show frames from this video stream
else
return;
}
ImageIO.write(event.getImage(), "jpg", new File(saveFile));
gotFirst = true;
}
catch (Exception e)
{
this.e = e;
}
}
}
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;
public class Read{
public static void main(String []args) throws IOException, Exception
{
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("C:/Users/Digilog/Downloads/Test.mp4");
frameGrabber.start();
IplImage i;
try {
i = frameGrabber.grab();
BufferedImage bi = i.getBufferedImage();
ImageIO.write(bi,"png", new File("D:/Img.png"));
frameGrabber.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here's how with BoofCV:
String fileName = UtilIO.pathExample("tracking/chipmunk.mjpeg");
MediaManager media = DefaultMediaManager.INSTANCE;
ConfigBackgroundBasic configBasic = new ConfigBackgroundBasic(30, 0.005f);
ImageType imageType = ImageType.single(GrayF32.class);
BackgroundModelMoving background = FactoryBackgroundModel.movingBasic(configBasic, new PointTransformHomography_F32(), imageType);
SimpleImageSequence video = media.openVideo(fileName, background.getImageType());
ImageBase nextFrame;
while(video.hasNext()) {
nextFrame = video.next();
// Now do something with it...
}
maybe this will help you:
Buffer buf = frameGrabber.grabFrame();
// Convert frame to an buffered image so it can be processed and saved
Image img = (new BufferToImage((VideoFormat) buf.getFormat()).createImage(buf));
buffImg = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_RGB);
//TODO saving the buffImg
for more informations:
How to take single snapshots from a webcam?
Below it is shown the essential code to request frames from media files.
For the complete source code and video demo:
"Media File Processing" example using Marvin Framework..
public class MediaFileExample implements Runnable{
private MarvinVideoInterface videoAdapter;
private MarvinImage videoFrame;
public MediaFileExample(){
try{
// Create the VideoAdapter used to load the video file
videoAdapter = new MarvinJavaCVAdapter();
videoAdapter.loadResource("./res/snooker.wmv");
// Start the thread for requesting the video frames
new Thread(this).start();
}
catch(MarvinVideoInterfaceException e){e.printStackTrace();}
}
#Override
public void run() {
try{
while(true){
// Request a video frame
videoFrame = videoAdapter.getFrame();
}
}catch(MarvinVideoInterfaceException e){e.printStackTrace();}
}
public static void main(String[] args) {
MediaFileExample m = new MediaFileExample();
}
}

Categories