OSDN Git Service

LinGui: preview changes
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 4 May 2009 05:26:13 +0000 (05:26 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 4 May 2009 05:26:13 +0000 (05:26 +0000)
- update hb_get_preview to allow upscaling and remove borders
- allow upscaling in the gui
- add user option to show visible cropping borders
- gui generates borders when needed instead of hb_get_preview, which
  allows for flexible alternatives like alternate colors

git-svn-id: svn://localhost/HandBrake/trunk@2376 b64f7644-9d1e-0410-96f1-a4d463321fa5

gtk/src/ghb.ui
gtk/src/hb-backend.c
gtk/src/hb-backend.h
gtk/src/internal_defaults.xml
gtk/src/preview.c
libhb/hb.c

index 489ebbb..8d52e29 100644 (file)
@@ -5302,16 +5302,29 @@ the required multiple.</property>
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkCheckButton" id="show_crop">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="tooltip-text" translatable="yes">Show Cropped area of the preview</property>
+                        <property name="label" translatable="yes">Show Crop</property>
+                        <signal name="toggled" handler="scale_changed_cb"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkToggleButton" id="preview_fullscreen">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="tooltip-text" translatable="yes">View Fullscreen Preview</property>
                         <property name="label" translatable="yes">Fullscreen</property>
-                        <signal handler="fullscreen_clicked_cb" name="clicked"/>
+                        <signal handler="fullscreen_clicked_cb" name="toggled"/>
                       </object>
                       <packing>
                         <property name="expand">False</property>
-                        <property name="position">1</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                     <child>
@@ -5324,7 +5337,7 @@ the required multiple.</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
-                        <property name="position">2</property>
+                        <property name="position">3</property>
                       </packing>
                     </child>
                   </object>
index 3a32734..80d85be 100644 (file)
@@ -922,25 +922,6 @@ get_acodec_value(gint val)
        return value;
 }
 
-#if 0
-static GValue*
-get_abitrate_value(gint val)
-{
-       GValue *value = NULL;
-       gint ii;
-
-       for (ii = 0; ii < hb_audio_bitrates_count; ii++)
-       {
-               if (hb_audio_bitrates[ii].rate == val)
-               {
-                       value = ghb_string_value_new(hb_audio_bitrates[ii].string);
-                       break;
-               }
-       }
-       return value;
-}
-#endif
-
 static GValue*
 get_amix_value(gint val)
 {
@@ -2769,16 +2750,6 @@ ghb_set_scale(signal_user_data_t *ud, gint mode)
                max_height = MOD_DOWN(
                        ghb_settings_get_int(ud->settings, "PictureHeight"), mod);
        }
-       // Adjust dims according to max values
-       if (!max_height)
-       {
-               max_height = MOD_DOWN(crop_height, mod);
-       }
-       if (!max_width)
-       {
-               max_width = MOD_DOWN(crop_width, mod);
-       }
-       // Align max dims 
        g_debug("max_width %d, max_height %d\n", max_width, max_height);
 
        if (width < 16)
@@ -2788,6 +2759,8 @@ ghb_set_scale(signal_user_data_t *ud, gint mode)
 
        width = MOD_ROUND(width, mod);
        height = MOD_ROUND(height, mod);
+
+       // Adjust dims according to max values
        if (max_height)
                height = MIN(height, max_height);
        if (max_width)
@@ -2936,6 +2909,21 @@ set_preview_job_settings(hb_job_t *job, GValue *settings)
                ghb_settings_combo_int(settings, "PictureModulus");
        job->width = ghb_settings_get_int(settings, "scale_width");
        job->height = ghb_settings_get_int(settings, "scale_height");
+       if (ghb_settings_get_boolean(settings, "show_crop"))
+       {
+               gint c0, c1;
+
+               c0 = MAX(job->crop[0] - 32, 0);
+               c1 = MAX(job->crop[1] - 32, 0);
+               job->height += (job->crop[0] - c0) + (job->crop[1] - c1);
+               job->crop[0] = c0;
+               job->crop[1] = c1;
+               c0 = MAX(job->crop[2] - 32, 0);
+               c1 = MAX(job->crop[3] - 32, 0);
+               job->width += (job->crop[2] - c0) + (job->crop[3] - c1);
+               job->crop[2] = c0;
+               job->crop[3] = c1;
+       }
 
        gint deint = ghb_settings_combo_int(settings, "PictureDeinterlace");
        gint decomb = ghb_settings_combo_int(settings, "PictureDecomb");
@@ -3918,15 +3906,101 @@ ghb_pause_queue()
     }
 }
 
-#define RED_HEIGHT     720.0
-#define RED_WIDTH      1280.0
+static void
+vert_line(
+       GdkPixbuf * pb, 
+       guint8 r, 
+       guint8 g, 
+       guint8 b, 
+       gint x, 
+       gint y, 
+       gint len, 
+       gint width)
+{
+       guint8 *pixels = gdk_pixbuf_get_pixels (pb);
+       guint8 *dst;
+       gint ii, jj;
+       gint channels = gdk_pixbuf_get_n_channels (pb);
+       gint stride = gdk_pixbuf_get_rowstride (pb);
+
+       for (jj = 0; jj < width; jj++)
+       {
+               dst = pixels + y * stride + (x+jj) * channels;
+               for (ii = 0; ii < len; ii++)
+               {
+                       dst[0] = r;
+                       dst[1] = g;
+                       dst[2] = b;
+                       dst += stride;
+               }
+       }
+}
+
+static void
+horz_line(
+       GdkPixbuf * pb, 
+       guint8 r, 
+       guint8 g, 
+       guint8 b, 
+       gint x, 
+       gint y, 
+       gint len,
+       gint width)
+{
+       guint8 *pixels = gdk_pixbuf_get_pixels (pb);
+       guint8 *dst;
+       gint ii, jj;
+       gint channels = gdk_pixbuf_get_n_channels (pb);
+       gint stride = gdk_pixbuf_get_rowstride (pb);
+
+       for (jj = 0; jj < width; jj++)
+       {
+               dst = pixels + (y+jj) * stride + x * channels;
+               for (ii = 0; ii < len; ii++)
+               {
+                       dst[0] = r;
+                       dst[1] = g;
+                       dst[2] = b;
+                       dst += channels;
+               }
+       }
+}
+
+static void
+hash_pixbuf(
+       GdkPixbuf * pb,
+       gint        x,
+       gint        y,
+       gint        w,
+       gint        h,
+       gint        step,
+       gint            orientation)
+{
+       gint ii;
+
+       if (!orientation)
+       {
+               // vertical lines
+               for (ii = x; ii < x+w; ii += step)
+               {
+                       vert_line(pb, 0x80, 0x80, 0x80, ii, y, h, 4);
+               }
+       }
+       else
+       {
+               // horizontal lines
+               for (ii = y; ii < y+h; ii += step)
+               {
+                       horz_line(pb, 0x80, 0x80, 0x80, x, ii, w, 4);
+               }
+       }
+}
 
 GdkPixbuf*
 ghb_get_preview_image(
        gint titleindex, 
        gint index, 
        signal_user_data_t *ud,
-       gboolean borders,
        gint *out_width,
        gint *out_height)
 {
@@ -3946,14 +4020,6 @@ ghb_get_preview_image(
        if (title->job == NULL) return NULL;
        set_preview_job_settings(title->job, settings);
 
-       // hb_get_preview can't handle sizes that are larger than the original title
-       // dimensions
-       if (title->job->width > title->width)
-               title->job->width = title->width;
-       
-       if (title->job->height > title->height)
-               title->job->height = title->height;
-
        // hb_get_preview doesn't compensate for anamorphic, so lets
        // calculate scale factors
        gint width, height, par_width = 1, par_height = 1;
@@ -3964,63 +4030,15 @@ ghb_get_preview_image(
                                                                &par_width, &par_height );
        }
 
-       // And also creates artifacts if the width is not a multiple of 8
-       //title->job->width = ((title->job->width + 4) >> 3) << 3;
-       // And the height must be a multiple of 2
-       //title->job->height = ((title->job->height + 1) >> 1) << 1;
-       
-       // Make sure we have a big enough buffer to receive the image from libhb. libhb
-       // creates images with a one-pixel border around the original content. Hence we
-       // add 2 pixels horizontally and vertically to the buffer size.
-       gint srcWidth = title->width + 2;
-       gint srcHeight= title->height + 2;
-       gint dstWidth = title->width;
-       gint dstHeight= title->height;
-       gint borderTop = 1;
-       gint borderLeft = 1;
-    if (borders)
-    {
-        //     |<---------- title->width ----------->|
-        //     |   |<---- title->job->width ---->|   |
-        //     |   |                             |   |
-        //     .......................................
-        //     ....+-----------------------------+....
-        //     ....|                             |....<-- gray border
-        //     ....|                             |....
-        //     ....|                             |....
-        //     ....|                             |<------- image
-        //     ....|                             |....
-        //     ....|                             |....
-        //     ....|                             |....
-        //     ....|                             |....
-        //     ....|                             |....
-        //     ....+-----------------------------+....
-        //     .......................................
-               dstWidth = title->job->width;
-        dstHeight = title->job->height;
-               borderTop = (srcHeight - dstHeight) / 2;
-               borderLeft = (srcWidth - dstWidth) / 2;
-               g_debug("boarders removed\n");
-       }
-
-       g_debug("src %d x %d\n", srcWidth, srcHeight);
-       g_debug("dst %d x %d\n", dstWidth, dstHeight);
-       g_debug("job dim %d x %d\n", title->job->width, title->job->height);
-       g_debug("title crop %d:%d:%d:%d\n", 
-                       title->crop[0],
-                       title->crop[1],
-                       title->crop[2],
-                       title->crop[3]);
-       g_debug("job crop %d:%d:%d:%d\n", 
-                       title->job->crop[0],
-                       title->job->crop[1],
-                       title->job->crop[2],
-                       title->job->crop[3]);
+       // Make sure we have a big enough buffer to receive the image from libhb
+       gint dstWidth = title->job->width;
+       gint dstHeight= title->job->height;
+
        static guint8 *buffer = NULL;
        static gint bufferSize = 0;
-
        gint newSize;
-       newSize = srcWidth * srcHeight * 4;
+
+       newSize = dstWidth * dstHeight * 4;
        if( bufferSize < newSize )
        {
                bufferSize = newSize;
@@ -4029,23 +4047,22 @@ ghb_get_preview_image(
        hb_get_preview( h_scan, title, index, buffer );
 
        // Create an GdkPixbuf and copy the libhb image into it, converting it from
-       // libhb's format something suitable. Along the way, we'll strip off the
-       // border around libhb's image.
+       // libhb's format something suitable.
        
-       // The image data returned by hb_get_preview is 4 bytes per pixel, BGRA format.
-       // Alpha is ignored.
+       // The image data returned by hb_get_preview is 4 bytes per pixel, 
+       // BGRA format. Alpha is ignored.
 
        GdkPixbuf *preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, dstWidth, dstHeight);
        guint8 *pixels = gdk_pixbuf_get_pixels (preview);
        
        guint32 *src = (guint32*)buffer;
        guint8 *dst = pixels;
-       src += borderTop * srcWidth;    // skip top rows in src to get to first row of dst
-       src += borderLeft;              // skip left pixels in src to get to first pixel of dst
+
        gint ii, jj;
        gint channels = gdk_pixbuf_get_n_channels (preview);
        gint stride = gdk_pixbuf_get_rowstride (preview);
        guint8 *tmp;
+
        for (ii = 0; ii < dstHeight; ii++)
        {
                tmp = dst;
@@ -4058,11 +4075,23 @@ ghb_get_preview_image(
                        src++;
                }
                dst += stride;
-               src += (srcWidth - dstWidth);   // skip to next row in src
        }
+       gint w = ghb_settings_get_int(settings, "scale_width");
+       gint h = ghb_settings_get_int(settings, "scale_height");
+       ghb_par_scale(ud, &w, &h, par_width, par_height);
+
+       gint c0, c1, c2, c3;
+       c0 = ghb_settings_get_int(settings, "PictureTopCrop");
+       c1 = ghb_settings_get_int(settings, "PictureBottomCrop");
+       c2 = ghb_settings_get_int(settings, "PictureLeftCrop");
+       c3 = ghb_settings_get_int(settings, "PictureRightCrop");
+
+       gdouble xscale = (gdouble)w / (gdouble)(title->width - c2 - c3);
+       gdouble yscale = (gdouble)h / (gdouble)(title->height - c0 - c1);
+       
        ghb_par_scale(ud, &dstWidth, &dstHeight, par_width, par_height);
-       *out_width = dstWidth;
-       *out_height = dstHeight;
+       *out_width = w;
+       *out_height = h;
        if (ghb_settings_get_boolean(settings, "reduce_hd_preview"))
        {
                GdkScreen *ss;
@@ -4090,10 +4119,27 @@ ghb_get_preview_image(
                        dstHeight = s_h * factor / 100;
                        dstWidth = dstWidth * dstHeight / orig_h;
                }
+               xscale *= dstWidth / orig_w;
+               yscale *= dstHeight / orig_h;
        }
-       g_debug("scaled %d x %d\n", dstWidth, dstHeight);
+       g_debug("scaled %d x %d", dstWidth, dstHeight);
        GdkPixbuf *scaled_preview;
        scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
+       if (ghb_settings_get_boolean(settings, "show_crop"))
+       {
+               c0 = (32 + MIN(c0 - 32, 0)) * yscale;
+               c1 = (32 + MIN(c1 - 32, 0)) * yscale;
+               c2 = (32 + MIN(c2 - 32, 0)) * xscale;
+               c3 = (32 + MIN(c3 - 32, 0)) * xscale;
+               // Top
+               hash_pixbuf(scaled_preview, c2, 0, w, c0, 16, 0);
+               // Bottom
+               hash_pixbuf(scaled_preview, c2, dstHeight-c1, w, c1, 16, 0);
+               // Left
+               hash_pixbuf(scaled_preview, 0, c0, c2, h, 16, 1);
+               // Right
+               hash_pixbuf(scaled_preview, dstWidth-c3, c0, c3, h, 16, 1);
+       }
        g_object_unref (preview);
        return scaled_preview;
 }
index 2b27d53..d946b92 100644 (file)
@@ -144,7 +144,7 @@ gint ghb_longest_title(void);
 gchar* ghb_build_x264opts_string(GValue *settings);
 GdkPixbuf* ghb_get_preview_image(
        gint titleindex, gint index, signal_user_data_t *ud,
-       gboolean borders, gint *width, gint *height);
+       gint *width, gint *height);
 gint ghb_calculate_target_bitrate(GValue *settings, gint titleindex);
 gchar* ghb_dvd_volname(const gchar *device);
 gint ghb_get_title_number(gint titleindex);
index f2bc8d3..eb858d0 100644 (file)
@@ -38,6 +38,8 @@
                <integer>0</integer>
                <key>scale_width</key>
                <integer>0</integer>
+               <key>show_crop</key>
+               <false />
                <key>single_title</key>
                <integer>1</integer>
                <key>start_chapter</key>
index ef5f8c7..5ec067b 100644 (file)
@@ -122,7 +122,10 @@ ghb_par_scale(signal_user_data_t *ud, gint *width, gint *height, gint par_n, gin
        num = par_n * disp_par_d;
        den = par_d * disp_par_n;
 
-       *width = *width * num / den;
+       if (par_n > par_d)
+               *width = *width * num / den;
+       else
+               *height = *height * den / num;
 }
 
 void
@@ -667,7 +670,7 @@ ghb_set_preview_image(signal_user_data_t *ud)
 
        ud->preview->pix = 
                ghb_get_preview_image(titleindex, ud->preview->frame, 
-                                                               ud, TRUE, &width, &height);
+                                                               ud, &width, &height);
        if (ud->preview->pix == NULL) return;
        preview_width = gdk_pixbuf_get_width(ud->preview->pix);
        preview_height = gdk_pixbuf_get_height(ud->preview->pix);
index 943e238..2ffa169 100644 (file)
@@ -384,7 +384,7 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
     char                 filename[1024];
     FILE               * file;
     uint8_t            * buf1, * buf2, * buf3, * buf4, * pen;
-    uint32_t           * p32, swsflags;
+    uint32_t             swsflags;
     AVPicture            pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
     struct SwsContext  * context;
     int                  i;
@@ -395,14 +395,14 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
 
     buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
     buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
-    buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, job->width, job->height ) );
+    buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, rgb_width, job->height ) );
     buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGBA32, rgb_width, job->height ) );
     avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
                     title->width, title->height );
     avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
                     title->width, title->height );
     avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
-                    job->width, job->height );
+                    rgb_width, job->height );
     avpicture_fill( &pic_preview, buf4, PIX_FMT_RGBA32,
                     rgb_width, job->height );
 
@@ -439,7 +439,7 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
     context = sws_getContext(title->width  - (job->crop[2] + job->crop[3]),
                              title->height - (job->crop[0] + job->crop[1]),
                              PIX_FMT_YUV420P,
-                             job->width, job->height, PIX_FMT_YUV420P,
+                             rgb_width, job->height, PIX_FMT_YUV420P,
                              swsflags, NULL, NULL, NULL);
 
     // Scale
@@ -465,33 +465,12 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
     // Free context
     sws_freeContext( context );
 
-    if( job->height < title->height || job->width < title->width )
+    preview_size = pic_preview.linesize[0];
+    pen = buffer;
+    for( i = 0; i < job->height; i++ )
     {
-        /* Gray background */
-        p32 = (uint32_t *) buffer;
-        for( i = 0; i < ( title->width + 2 ) * ( title->height + 2 ); i++ )
-        {
-            p32[i] = 0xFF808080;
-        }
-
-        /* Draw the picture, centered, and draw the cropping zone */
-        preview_size = pic_preview.linesize[0];
-        pen = buffer + ( title->height - job->height ) *
-            ( title->width + 2 ) * 2 + ( title->width - job->width ) * 2;
-        memset( pen, 0xFF, 4 * ( job->width + 2 ) );
-        pen += 4 * ( title->width + 2 );
-        for( i = 0; i < job->height; i++ )
-        {
-            uint8_t * nextLine;
-            nextLine = pen + 4 * ( title->width + 2 );
-            memset( pen, 0xFF, 4 );
-            pen += 4;
-            memcpy( pen, buf4 + preview_size * i, 4 * job->width );
-            pen += 4 * job->width;
-            memset( pen, 0xFF, 4 );
-            pen = nextLine;
-        }
-        memset( pen, 0xFF, 4 * ( job->width + 2 ) );
+        memcpy( pen, buf4 + preview_size * i, 4 * job->width );
+        pen += 4 * job->width;
     }
 
     // Clean up