Hello,

sometimes a small part of a movie (about 20-30 seconds) is repeated
after a commercial break. In order to find such overlapping regions,
I created this small patch.

First I mark the beginning and end of the commercial, select the last
frame before the commercial and start searching (Menu: View->Search) for
a duplicate picture after the end of the marked commercial. Now I have
an overlapping region to cut out in addition to the commercial.

Unfortunately, the search is pretty slow, so I restrict it to about one
minute (25 frames * 60 seconds). The search range can be set in the
settings file:

search_dups_range=1500

Regards, Olaf
diff --git a/src/dvbcut.cpp b/src/dvbcut.cpp
index fda4c7a..89570d2 100644
--- a/src/dvbcut.cpp
+++ b/src/dvbcut.cpp
@@ -1050,6 +1050,84 @@ void dvbcut::viewDifference()
   updateimagedisplay();
 }
 
+namespace {
+inline int square(int x)
+{
+	return x * x;
+}
+
+unsigned long calc_distance(QImage baseimg, QImage im)
+{
+	if (im.size() != baseimg.size())
+		im = im.scale(baseimg.size());
+
+	unsigned long distance = 0;
+	if (im.depth() == 32 && baseimg.depth() == 32)
+		for (int y = 0; y < baseimg.height(); ++y) {
+			QRgb *imd = (QRgb*) im.scanLine(y);
+			QRgb *bimd = (QRgb*) baseimg.scanLine(y);
+
+			for (int x = im.width(); x > 0; --x) {
+				int dist = square(qRed(*imd) - qRed(*bimd)) + square(qGreen(*imd) - qGreen(*bimd)) + square(qBlue(*imd) - qBlue(*bimd));
+				if (dist > 1000)
+					dist = 1000;
+
+				distance += dist;
+				++imd;
+				++bimd;
+			}
+		}
+
+	return distance;
+}
+
+int getNextEvent(const QListBox *eventlist, int picture)
+{
+	for (QListBoxItem *item = eventlist->firstItem(); item; item = item->next())
+		if (item->rtti() == EventListItem::RTTI()) {
+			EventListItem *eli = (EventListItem*)item;
+			if (eli->getpicture() > picture)
+				return eli->getpicture();
+		}
+
+	return picture + 1;
+}
+};
+
+void dvbcut::searchDuplicate()
+{
+	progressstatusbar psb(statusBar());
+	psb.print("Searching ...");
+	psb.setprogress(0);
+//	dvbcutbusy busy(this);
+//	busy.setbusy(true);
+	imageprovider imgp(*mpg);
+	QImage baseimg = imgp.getimage(curpic);
+	int pic = getNextEvent(eventlist, curpic);
+	gotoFrame(pic);
+	unsigned long min = calc_distance(baseimg, imgp.getimage(pic, true));
+	static const long n = settings().search_dups_range;
+	for (long i = 0; i < n; ++i) {
+		unsigned long d = calc_distance(baseimg, imgp.getimage(++pic, true));
+		if (d < min) {
+			min = d;
+			gotoFrame(pic);
+		}
+
+		psb.setprogress(i * 1000 / n);
+		if (psb.cancelled()) {
+			// FIXME
+			break;
+		}
+	}
+
+//	busy.setbusy(false);
+	if (psb.cancelled()) {
+		// FIXME
+		return;
+	}
+}
+
 
 void dvbcut::viewUnscaled()
 {
@@ -2468,3 +2546,11 @@ void dvbcut::helpContentAction_activated()
       tr("Help file %1 not available").arg(helpFile));
   }
 }
+
+void dvbcut::gotoFrame(int frameno)
+{
+  bool save = fine;
+  fine = true;
+  linslider->setValue(frameno);
+  fine = save;
+}
diff --git a/src/dvbcut.h b/src/dvbcut.h
index dd4aacc..076940e 100644
--- a/src/dvbcut.h
+++ b/src/dvbcut.h
@@ -165,6 +165,7 @@ public slots:
   virtual void editConvert(int);
   virtual void abouttoshoweditconvert();
   virtual void viewDifference();
+  virtual void searchDuplicate();
   virtual void viewUnscaled();
   virtual void viewNormal();
   virtual void zoomIn();
diff --git a/src/dvbcutbase.ui b/src/dvbcutbase.ui
index 2148f44..a08c8f9 100644
--- a/src/dvbcutbase.ui
+++ b/src/dvbcutbase.ui
@@ -470,6 +470,7 @@
         <action name="viewNormalAction"/>
         <action name="viewUnscaledAction"/>
         <action name="viewDifferenceAction"/>
+        <action name="searchDuplicateAction"/>
         <separator/>
         <action name="zoomInAction"/>
         <action name="zoomOutAction"/>
@@ -860,6 +861,14 @@
     </action>
     <action>
         <property name="name">
+            <cstring>searchDuplicateAction</cstring>
+        </property>
+        <property name="text">
+            <string>Search duplicate of current picture</string>
+        </property>
+    </action>
+    <action>
+        <property name="name">
             <cstring>viewFullSizeAction</cstring>
         </property>
         <property name="toggleAction">
@@ -1207,6 +1216,12 @@
         <slot>viewDifference()</slot>
     </connection>
     <connection>
+        <sender>searchDuplicateAction</sender>
+        <signal>activated()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>searchDuplicate()</slot>
+    </connection>
+    <connection>
         <sender>viewNormalAction</sender>
         <signal>activated()</signal>
         <receiver>dvbcutbase</receiver>
@@ -1319,6 +1334,7 @@
     <slot>viewNormal()</slot>
     <slot>viewUnscaled()</slot>
     <slot>viewDifference()</slot>
+    <slot>searchDuplicate()</slot>
     <slot>fileExport()</slot>
     <slot>audiotrackchosen(int)</slot>
     <slot>loadrecentfile(int)</slot>
diff --git a/src/settings.cpp b/src/settings.cpp
index 30d1b9c..328d550 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -58,6 +58,7 @@
 #define DVBCUT_DEFAULT_PIPE_LABEL \
         "DVD-Video titleset (dvdauthor)"
 #define DVBCUT_DEFAULT_PIPE_FORMAT (0)
+#define DVBCUT_DEFAULT_SEARCH_DUPS_RANGE 1500
 /* 
 // SOME OTHER EXAMPLES for the settings file ~/.qt/dvbcut.sf.netrc 
 // (ok, for time consuming conversions one does not save any time, but it may be convenient...) 
@@ -130,6 +131,7 @@ dvbcut_settings::load_settings() {
       prjfilter = readEntry("/prjfilter", DVBCUT_DEFAULT_PRJFILTER);
       loadfilter = readEntry("/loadfilter", DVBCUT_DEFAULT_LOADFILTER);
     endGroup();	// filter
+    search_dups_range = readNumEntry("/search_dups_range", DVBCUT_DEFAULT_SEARCH_DUPS_RANGE);
   }
   else {
     // old (unnumbered) config format
@@ -380,6 +382,7 @@ dvbcut_settings::save_settings() {
     writeEntry("/threshold", chapter_threshold);
     writeEntry("/minimum", chapter_minimum);
   endGroup();	// auto chapters
+  writeEntry("/search_dups_range", search_dups_range);
 }
 
 // private settings variable
diff --git a/src/settings.h b/src/settings.h
index 8050731..ae7253a 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -85,7 +85,7 @@ public:
   int chapter_tolerance;
   double chapter_threshold;
   int chapter_minimum;
-
+  int search_dups_range;
 };
 
 // access function
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
DVBCUT-devel mailing list
DVBCUT-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dvbcut-devel

Reply via email to