+// -----------------------------------------------
+// stuff related to cropping
+
+#define DARK 32
+
+static inline int absdiff( int x, int y )
+{
+ return x < y ? y - x : x - y;
+}
+
+static inline int clampBlack( int x )
+{
+ // luma 'black' is 16 and anything less should be clamped at 16
+ return x < 16 ? 16 : x;
+}
+
+static int row_all_dark( hb_title_t *title, uint8_t* luma, int row )
+{
+ luma += title->width * row;
+
+ // compute the average luma value of the row
+ int i, avg = 0;
+ for ( i = 0; i < title->width; ++i )
+ {
+ avg += clampBlack( luma[i] );
+ }
+ avg /= title->width;
+ if ( avg >= DARK )
+ return 0;
+
+ // since we're trying to detect smooth borders, only take the row if
+ // all pixels are within +-16 of the average (this range is fairly coarse
+ // but there's a lot of quantization noise for luma values near black
+ // so anything less will fail to crop because of the noise).
+ for ( i = 0; i < title->width; ++i )
+ {
+ if ( absdiff( avg, clampBlack( luma[i] ) ) > 16 )
+ return 0;
+ }
+ return 1;
+}
+
+static int column_all_dark( hb_title_t *title, uint8_t* luma, int top, int bottom,
+ int col )
+{
+ int stride = title->width;
+ int height = title->height - top - bottom;
+ luma += stride * top + col;
+
+ // compute the average value of the column
+ int i = height, avg = 0, row = 0;
+ for ( ; --i >= 0; row += stride )
+ {
+ avg += clampBlack( luma[row] );
+ }
+ avg /= height;
+ if ( avg >= DARK )
+ return 0;
+
+ // since we're trying to detect smooth borders, only take the column if
+ // all pixels are within +-16 of the average.
+ i = height, row = 0;
+ for ( ; --i >= 0; row += stride )
+ {
+ if ( absdiff( avg, clampBlack( luma[row] ) ) > 16 )
+ return 0;
+ }
+ return 1;
+}
+#undef DARK
+
+typedef struct {
+ int n;
+ int t[HB_MAX_PREVIEWS];
+ int b[HB_MAX_PREVIEWS];
+ int l[HB_MAX_PREVIEWS];
+ int r[HB_MAX_PREVIEWS];
+} crop_record_t;
+
+static void record_crop( crop_record_t *crops, int t, int b, int l, int r )
+{
+ crops->t[crops->n] = t;
+ crops->b[crops->n] = b;
+ crops->l[crops->n] = l;
+ crops->r[crops->n] = r;
+ ++crops->n;
+}
+
+static int compare_int( const void *a, const void *b )
+{
+ return *(const int *)a - *(const int *)b;
+}
+
+static void sort_crops( crop_record_t *crops )
+{
+ qsort( crops->t, crops->n, sizeof(crops->t[0]), compare_int );
+ qsort( crops->b, crops->n, sizeof(crops->t[0]), compare_int );
+ qsort( crops->l, crops->n, sizeof(crops->t[0]), compare_int );
+ qsort( crops->r, crops->n, sizeof(crops->t[0]), compare_int );
+}
+
+// -----------------------------------------------
+// stuff related to title width/height/aspect info
+