diff options
-rw-r--r-- | gtk/src/ghb.ui | 19 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 254 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 2 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 2 | ||||
-rw-r--r-- | gtk/src/preview.c | 7 | ||||
-rw-r--r-- | libhb/hb.c | 39 |
6 files changed, 183 insertions, 140 deletions
diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index 489ebbb16..8d52e299b 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -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> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 3a327343e..80d85bee8 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -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; } diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 2b27d532a..d946b9224 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -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); diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index f2bc8d336..eb858d019 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -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> diff --git a/gtk/src/preview.c b/gtk/src/preview.c index ef5f8c738..5ec067b62 100644 --- a/gtk/src/preview.c +++ b/gtk/src/preview.c @@ -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); diff --git a/libhb/hb.c b/libhb/hb.c index 943e2389f..2ffa16976 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -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 |