openshot.code team mailing list archive
-
openshot.code team
-
Mailing list archive
-
Message #00022
[Branch ~openshot.code/openshot/main] Rev 517: Applied a patch from Emil for bug #822300, Convert clip on timline to images. This enables you to...
------------------------------------------------------------
revno: 517
committer: Andy Finch <we.rocked.in79@xxxxxxxxx>
branch nick: openshot
timestamp: Sat 2011-08-27 22:53:40 +0100
message:
Applied a patch from Emil for bug #822300, Convert clip on timline to images. This enables you to cut a clip on the timeline and then export the remainder of the clip to an image sequence. Thanks to Emil for the patch.
modified:
openshot/classes/files.py
openshot/classes/thumbnail.py
openshot/windows/MainGTK.py
openshot/windows/ui/Main_clip_properties.ui
--
lp:openshot
https://code.launchpad.net/~openshot.code/openshot/main
Your team OpenShot Code is subscribed to branch lp:openshot.
To unsubscribe from this branch go to https://code.launchpad.net/~openshot.code/openshot/main/+edit-subscription
=== modified file 'openshot/classes/files.py'
--- openshot/classes/files.py 2011-08-27 20:46:36 +0000
+++ openshot/classes/files.py 2011-08-27 21:53:40 +0000
@@ -372,31 +372,89 @@
self.project.form.refresh_files()
#----------------------------------------------------------------------
- def ConvertFileToImages(self, file_name):
+ def ConvertFileToImages(self, file_location, start_time=0.00, end_time=None):
"""Add a new file to the current folder"""
+ """
+ file_location: The location of the file to convert.
+ start_time: The time to grab the first image.
+ end_time: The time to grab the last image. None=last frame
+ """
import urllib
# get a reference to the language translate method
_ = self.project.translate
+
+ # get a reference to the file
+ f = self.project.project_folder.FindFile(file_location)
# clean path to video
- file_name = urllib.unquote(file_name)
+ file_location = urllib.unquote(file_location)
+
+ # True if only a part of the file should be converted.
+ is_part = True
+ if start_time == 0.00 and (end_time == None or end_time == f.length):
+ is_part = False
+
+ # get file name, path, and extension
+ (dirName, filename) = os.path.split(file_location)
+ (fileBaseName, fileExtension)=os.path.splitext(filename)
+ # the folder path if the image sequence is not a part (inside the same folder as the movie file)
+ new_folder_path = os.path.join(dirName, fileBaseName)
+
# check if this file is already in the project
for item in self.items:
- if file_name in item.name and item.file_type == _("Image Sequence").lower():
- return True
-
- # inspect the media file and generate it's thumbnail image (if any)
- newFile = self.project.thumbnailer.GetFile(file_name, all_frames=True)
-
+ if not is_part and item.file_type == _("Image Sequence").lower():
+ (itemBase, itemExt) = os.path.split(item.name)
+ if new_folder_path == itemBase:
+ return True
+
+ # Create folder(s)
+
+ # if file is a video
+ if f.file_type == "video":
+
+ # create thumbnail folder (if it doesn't exist)
+ if os.path.exists(new_folder_path) == False:
+ os.mkdir(new_folder_path)
+
+ # part of the clip will be converted
+ if is_part:
+
+ # counter
+ x = 1
+
+ while(True):
+
+ # add "_x" to the name, so the folder has the name "base_x", and the first image will
+ # have the name "base_x_1"
+ new_file_base_name = fileBaseName + "_" + str(x)
+ # create a new folder for this file (inside the previously created folder)
+ new_folder_path = os.path.join(dirName, fileBaseName, new_file_base_name)
+
+ # create thumbnail folder (if it doesn't exist)
+ # FIXME: (TJ) This doesn't use thumbnail_path - should it?
+ if os.path.exists(new_folder_path) == False:
+ os.mkdir(new_folder_path)
+
+ # if the directory is empty
+ if not os.listdir(new_folder_path):
+
+ # inspect the media file and generate it's thumbnail image (if any)
+ newFile = self.project.thumbnailer.GetFile(file_location, False, new_file_base_name, start_time, end_time)
+
+ break
+
+ x += 1
+ # whole clip
+ else:
+ # get the image sequence
+ newFile = self.project.thumbnailer.GetFile(file_location, False)
+
# update the location
if newFile:
- (dirName, fname) = os.path.split(file_name)
- (fileBaseName, fileExtension)=os.path.splitext(fname)
- newFile.name = os.path.join(dirName, fileBaseName, fileBaseName + "_%d.png")
-
+
# add to internal item collection
self.items.append(newFile)
=== modified file 'openshot/classes/thumbnail.py'
--- openshot/classes/thumbnail.py 2011-08-11 21:59:28 +0000
+++ openshot/classes/thumbnail.py 2011-08-27 21:53:40 +0000
@@ -34,26 +34,32 @@
""" Associate the OpenShot project file with this threaded class. """
self.project = project
- def GetFile(self, file_name, all_frames=False):
+ def GetFile(self, file_location, only_thumbnail=True, new_file_base_name=None, start_time=0.00, end_time=None):
""" Use this method to generate an OpenShotFile object based on the URL (or file location)
of a video or audio file. Each time you call this method, it will lock this thread (and OpenShot's
main thread) until it has finished. """
+ """
+ file_location: The location of the file on the hard drive, including the name and extension.
+ only_thumbnail: True if only a thumbnail should be grabbed from the file, False if image sequence.
+ new_file_base_name: The name of the folder and the base for the image sequence name, not including the path.
+ start_time: The time to start grabbing frames from the file, in seconds.
+ end_time: The time to end grabbing frames from the file, in seconds. None = To the last frame.
+ """
try:
# determine name and location of thumbnail image
- self.file_name = file_name
+ self.file_name = file_location
self.thumbnail_path = ""
self.file_type = "video"
self.label = ""
project_path = self.project.folder
- myPath = self.file_name
- (dirName, fileName) = os.path.split(myPath)
- (fileBaseName, fileExtension)=os.path.splitext(fileName)
+ (dirName, fileName) = os.path.split(file_location)
+ (fileBaseName, fileExtension) = os.path.splitext(fileName)
fileExtension = fileExtension.replace(".", "")
actual_thumbnail_path = project_path + "/thumbnail/" + fileBaseName + "_" + fileExtension + "_1.png"
- if all_frames == False:
+ if only_thumbnail:
# just get 1 thumbnail frame
self.thumbnail_path = project_path + "/thumbnail/" + fileBaseName + "_" + fileExtension + "_%d.png"
@@ -61,17 +67,18 @@
self.profile = mlt.Profile("quarter_ntsc")
else:
- # export all frames of the video
- self.thumbnail_path = dirName + "/" + fileBaseName + "/" + fileBaseName + "_%d.png"
-
- # set the profile
- self.profile = profiles.mlt_profiles(self.project).get_profile(self.project.project_type)
-
+ if new_file_base_name == None or new_file_base_name == fileBaseName:
+ # choose the same folder as the name (without extension) as default
+ self.thumbnail_path = os.path.join(dirName, fileBaseName, fileBaseName + "_%d.png")
+ else:
+ # export a part of the video to a folder under the folder with the same name as the file.
+ self.thumbnail_path = os.path.join(dirName, fileBaseName, new_file_base_name, new_file_base_name + "_%d.png")
+
# re-init the mlt factory
mlt.Factory.init()
# Create the producer
- self.p = mlt.Producer( self.profile, '%s' % self.file_name )
+ self.p = mlt.Producer( self.profile, '%s' % file_location )
# Check if clip is valid (otherwise a seg fault)
if self.p.is_valid() == False:
@@ -85,10 +92,17 @@
self.c.set("vcodec", "png")
# determine length of clip in seconds
- max_frames = float(self.p.get_length()) - 1.0
producer_fps = float(self.p.get_fps())
- calculate_length = max_frames / producer_fps
-
+ first_frame = int(round(producer_fps * start_time))
+ # Whole clip if end_time = None
+ if end_time == None:
+ last_frame = self.p.get_length()
+ else:
+ last_frame = int(round(producer_fps * end_time))
+ max_frames = last_frame - first_frame
+
+ # determine dimensions
+
height = 0
width = 0
if self.p.get("height"):
@@ -132,13 +146,20 @@
# set the max length of the image to 300 seconds (i.e. 5 minutes)
max_frames = producer_fps * 300
+ # get actual height & width of image (since MLT defaults to 1 x 1)
+ width, height = self.get_image_size(file_location)
+
+ # determine length
+ if only_thumbnail:
+ calculate_length = self.p.get_length() / producer_fps
+ else:
+ calculate_length = max_frames / producer_fps
+ if is_image:
+
# set the length to 300 seconds (i.e. 5 minutes)
calculate_length = float(300)
- # get actual height & width of image (since MLT defaults to 1 x 1)
- width, height = self.get_image_size(self.file_name)
-
-
+
# set thumbnail image (if no height & width are detected)
if (height == False or width == False) and (is_image == False):
self.thumbnail_path = ""
@@ -146,9 +167,12 @@
# get the 1st frame (if not exporting all frames)
- if all_frames == False:
+ if only_thumbnail:
+ max_frames = float(self.p.get_length()) - 1.0
self.p = self.p.cut(1, 1)
+ # get the frames in an interval
else:
+ self.p = self.p.cut(first_frame, last_frame)
# mark as image seq
self.label = "Image Sequence"
self.file_type = "image sequence"
@@ -164,7 +188,11 @@
# create an openshot file object
newFile = files.OpenShotFile(self.project)
- newFile.name = self.file_name
+ # thumbnails and image sequences are stored at different locations
+ if only_thumbnail:
+ newFile.name = file_location
+ else:
+ newFile.name = self.thumbnail_path
newFile.length = calculate_length
newFile.thumb_location = actual_thumbnail_path
newFile.videorate = (self.p.get_fps(), 0)
@@ -183,7 +211,7 @@
return newFile
except Exception:
- print "Failed to import file: %s" % file_name
+ print "Failed to import file: %s" % file_location
=== modified file 'openshot/windows/MainGTK.py'
--- openshot/windows/MainGTK.py 2011-08-27 20:46:36 +0000
+++ openshot/windows/MainGTK.py 2011-08-27 21:53:40 +0000
@@ -3563,6 +3563,12 @@
self.form.mnuPositionSubMenu1.selected_clip = object
self.form.mnuPositionSubMenu1.selected_clip_item = canvas_item
+ f = self.selected_clip.file_object
+
+ if not f.file_type == "video":
+ self.mnuConvertPartToImageSequence.hide()
+ self.menuitem2.hide()
+
if ".svg" in self.selected_clip.name:
self.mnuClipEditTitle.show()
else:
@@ -3788,6 +3794,31 @@
# show import file dialog to select replacement file
self.import_files_dialog = AddFiles.frmReplaceFiles(form=self, project=self.project, clip=self.selected_clip)
+ def on_mnuConvertPartToImageSequence_activate (self, event, *args):
+ print "on_mnuConvertPartToImageSequence_activate"
+
+ # change cursor to "please wait"
+ self.form.myTree.window.set_cursor(gtk.gdk.Cursor(150))
+
+ # get the clip
+ clip = self.selected_clip
+ f = clip.file_object
+
+ # When to start and end the image sequence
+ start_time = clip.start_time
+ end_time = clip.end_time
+
+ # make images
+ self.project.project_folder.ConvertFileToImages(f.name, start_time, end_time)
+
+ # mark the project as modified
+ self.project.set_project_modified(is_modified=True, refresh_xml=True)
+
+ # refresh the form (i.e. add new items to the treeview)
+ self.form.refresh()
+
+ # set cursor to normal
+ self.form.myTree.window.set_cursor(None)
def replace_clip(self, selected_clip, new_clip):
#this replaces the selected clip with a new clip
@@ -4333,15 +4364,9 @@
def on_mnuConvertToImages_activate(self, event, *args):
print "on_mnuConvertToImages_activate"
- # FIXME: (TJ) is thumbnail actually used in this method?
- # find the thumbnail folder location
- # FIXME: (TJ) Is this 'thumbnail/' per-project directory supposed to be ~/.openshot/thumbnail ?
- project_path = self.project.folder
- thumbnail_path = os.path.join(project_path, "thumbnail")
# change cursor to "please wait"
self.form.myTree.window.set_cursor(gtk.gdk.Cursor(150))
- self.form.myTree.window.set_cursor(gtk.gdk.Cursor(150))
# loop through all selected files
iters = [self.model.get_iter(path) for path in self.selected]
@@ -4351,24 +4376,9 @@
unique_id = self.model.get_value(iter, 3)
f = self.project.project_folder.FindFileByID(unique_id)
- # get file name, path, and extention
- (dirName, filename) = os.path.split(f.name)
- (fileBaseName, fileExtension)=os.path.splitext(filename)
-
- # if file is a video or image
- if f.file_type == "video":
- # create a new folder for this file (inside the thumbnail folder)
- new_folder_path = os.path.join(dirName, fileBaseName)
-
- # create thumbnail folder (if it doesn't exist)
- # FIXME: (TJ) This doesn't use thumbnail_path - should it?
- if os.path.exists(new_folder_path) == False:
- # create new thumbnail folder
- os.mkdir(new_folder_path)
-
- # convert to image sequence
- self.project.project_folder.ConvertFileToImages(f.name)
-
+ # convert to image sequence
+ self.project.project_folder.ConvertFileToImages(f.name)
+
#mark the project as modified
self.project.set_project_modified(is_modified=True, refresh_xml=True)
=== modified file 'openshot/windows/ui/Main_clip_properties.ui'
--- openshot/windows/ui/Main_clip_properties.ui 2011-07-18 21:39:12 +0000
+++ openshot/windows/ui/Main_clip_properties.ui 2011-08-27 21:53:40 +0000
@@ -53,6 +53,11 @@
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-convert</property>
+ </object>
<object class="GtkMenu" id="mnuClipPopup">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -158,6 +163,24 @@
</object>
</child>
<child>
+ <object class="GtkImageMenuItem" id="mnuConvertPartToImageSequence">
+ <property name="label" translatable="yes">Convert To Image Sequence</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="image">image2</property>
+ <property name="use_stock">False</property>
+ <signal name="activate" handler="on_mnuConvertPartToImageSequence_activate" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="menuitem3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ </object>
+ </child>
+ <child>
<object class="GtkImageMenuItem" id="mnuClipEditTitle">
<property name="label" translatable="yes">Edit Title (Simple)</property>
<property name="can_focus">False</property>