← Back to team overview

openshot.code team mailing list archive

[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>