📄 y4munsharp.c
字号:
/* * $Id: y4munsharp.c,v 1.6 2005/04/11 18:16:42 sms00 Exp $ * * Constructed using: * unsharp.c 0.10 -- This is a plug-in for the GIMP 1.0 * Copyright (C) 1999 Winston Chang <winstonc@cs.wisc.edu>/<winston@stdout.org> * * * Rewritten/modified from the GIMP unsharp plugin into y4munsharp by * Steven Schultz * * 2004/11/10 - used the core functions of the unsharp plugin and wrote a * y4m filter program. The original plugin was allocated/deallocated * memory for each picture/frame and of course that had to be done in a * more efficient manner. Additional work involved handling interlaced * input for the column blur function. * * By default only the LUMA (Y') is processed. Processing the CHROMA * (CbCr) can, in some cases, result in color shifts where the edge * enhancement is done. If it is desired to process the CHROMA planes * -C option must be given explicitly. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#ifdef HAVE_CONFIG_H#include "config.h"#else#define HAVE_STDINT_H#endif#include <stdlib.h>#include <math.h>#include <unistd.h>#include <string.h>#include <stdio.h>#include <yuv4mpeg.h>#define MAX(a,b) ((a) >= (b) ? (a) : (b))#define ROUND(x) ((int) ((x) + 0.5))extern char *__progname;void usage(void);void y4munsharp(void);static void get_column(u_char *, u_char *, int, int);static void put_column(u_char *, u_char *, int, int);static void blur_line (double *, double *, int, u_char *, u_char *, int );static double *gen_lookup_table (double *, int);static int gen_convolve_matrix(double, double **); u_char *i_yuv[3], *o_yuv[3], *cur_col, *dest_col, *cur_row, *dest_row; double y_radius = 3.0, y_amount = 0.30; double uv_radius = -1.0, uv_amount; int y_threshold = 4, uv_threshold, frameno; int interlaced, ywidth, uvwidth, yheight, uvheight, ylen, uvlen; int cmatrix_y_len, cmatrix_uv_len; double *cmatrix_y, *cmatrix_uv, *ctable_y, *ctable_uv; int lowy = 16, highy = 235, lowuv = 16, highuv = 240;intmain(int argc, char **argv) { int fdin, fdout, err, c, i, verbose = 1; y4m_stream_info_t istream, ostream; y4m_frame_info_t iframe; fdin = fileno(stdin); fdout = fileno(stdout); y4m_accept_extensions(1); y4m_init_stream_info(&istream); y4m_init_frame_info(&iframe); while ((c = getopt(argc, argv, "L:C:hv:N")) != EOF) { switch (c) { case 'N': lowuv = lowy = 0; lowuv = highy = 255; break; case 'L': i = sscanf(optarg, "%lf,%lf,%d", &y_radius, &y_amount, &y_threshold); if (i != 3) { mjpeg_error("-L r,a,t"); usage(); } break; case 'C': i = sscanf(optarg, "%lf,%lf,%d", &uv_radius, &uv_amount, &uv_threshold); if (i != 3) { mjpeg_error("-C r,a,t"); usage(); } break; case 'v': verbose = atoi(optarg); if (verbose < 0 || verbose > 2) mjpeg_error_exit1("-v 0|1|2"); break; case 'h': default: usage(); break; } } if (isatty(fdout)) mjpeg_error_exit1("stdout must not be a terminal"); mjpeg_default_handler_verbosity(verbose); err = y4m_read_stream_header(fdin, &istream); if (err != Y4M_OK) mjpeg_error_exit1("Couldn't read input stream header"); switch (y4m_si_get_interlace(&istream)) { case Y4M_ILACE_NONE: interlaced = 0; break; case Y4M_ILACE_BOTTOM_FIRST: case Y4M_ILACE_TOP_FIRST: interlaced = 1; break; default: mjpeg_error_exit1("Unsupported/unknown interlacing"); } if (y4m_si_get_plane_count(&istream) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); yheight = y4m_si_get_plane_height(&istream, 0); uvheight = y4m_si_get_plane_height(&istream, 1); ywidth = y4m_si_get_plane_width(&istream, 0); uvwidth = y4m_si_get_plane_width(&istream, 1); ylen = y4m_si_get_plane_length(&istream, 0); uvlen = y4m_si_get_plane_length(&istream, 1);/* Input and output frame buffers */ i_yuv[0] = (u_char *)malloc(ylen); i_yuv[1] = (u_char *)malloc(uvlen); i_yuv[2] = (u_char *)malloc(uvlen); o_yuv[0] = (u_char *)malloc(ylen); o_yuv[1] = (u_char *)malloc(uvlen); o_yuv[2] = (u_char *)malloc(uvlen);/* * general purpose row/column scratch buffers. Slightly over allocated to * simplify life.*/ cur_col = (u_char *)malloc(MAX(ywidth, yheight)); dest_col = (u_char *)malloc(MAX(ywidth, yheight)); cur_row = (u_char *)malloc(MAX(ywidth, yheight)); dest_row = (u_char *)malloc(MAX(ywidth, yheight));/* * Generate the convolution matrices. The generation routine allocates the * memory and returns the length.*/ cmatrix_y_len = gen_convolve_matrix(y_radius, &cmatrix_y); cmatrix_uv_len = gen_convolve_matrix(uv_radius, &cmatrix_uv); ctable_y = gen_lookup_table(cmatrix_y, cmatrix_y_len); ctable_uv = gen_lookup_table(cmatrix_uv, cmatrix_uv_len); y4m_init_stream_info(&ostream); y4m_copy_stream_info(&ostream, &istream); y4m_write_stream_header(fileno(stdout), &ostream); mjpeg_log(LOG_INFO, "Luma radius: %lf", y_radius); mjpeg_log(LOG_INFO, "Luma amount: %lf", y_amount); mjpeg_log(LOG_INFO, "Luma threshold: %d", y_threshold); if (uv_radius != -1.0) { mjpeg_log(LOG_INFO, "Chroma radius: %lf", uv_radius); mjpeg_log(LOG_INFO, "Chroma amount: %lf", uv_amount); mjpeg_log(LOG_INFO, "Chroma threshold: %d", uv_threshold); } for (frameno = 0; y4m_read_frame(fdin, &istream, &iframe, i_yuv) == Y4M_OK; frameno++) { y4munsharp(); err = y4m_write_frame(fdout, &ostream, &iframe, o_yuv); if (err != Y4M_OK) { mjpeg_error("y4m_write_frame err at frame %d", frameno); break; } } y4m_fini_frame_info(&iframe); y4m_fini_stream_info(&istream); y4m_fini_stream_info(&ostream); exit(0); }/* * Uses the globals defined above - probably not the best practice in the world * but beats passing a jillion arguments or going to the effort of * encapsulation.*/void y4munsharp(void) { int i, row, col, diff, value; u_char *i_ptr, *o_ptr; mjpeg_log(LOG_DEBUG, "Blurring Luma rows frame %d", frameno); for (row = 0; row < yheight; row++) { blur_line(ctable_y, cmatrix_y, cmatrix_y_len, &i_yuv[0][row * ywidth], &o_yuv[0][row * ywidth], ywidth); } if (uv_radius != -1.0) { mjpeg_log(LOG_DEBUG, "Blurring Chroma rows frame %d", frameno); for (row = 0; row < uvheight; row++) { blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, &i_yuv[1][row * uvwidth], &o_yuv[1][row * uvwidth], uvwidth); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, &i_yuv[2][row * uvwidth], &o_yuv[2][row * uvwidth], uvwidth); } } else { memcpy(o_yuv[1], i_yuv[1], uvlen); memcpy(o_yuv[2], i_yuv[2], uvlen); } mjpeg_log(LOG_DEBUG, "Blurring Luma columns frame %d", frameno); for (col = 0; col < ywidth; col++) {/* * Do the entire frame if progressive, otherwise this does the only * the first field.*/ get_column(&o_yuv[0][col], cur_col, interlaced ? 2 * ywidth : ywidth, interlaced ? yheight / 2 : yheight); blur_line(ctable_y, cmatrix_y, cmatrix_y_len, cur_col, dest_col, interlaced ? yheight / 2 : yheight); put_column(dest_col, &o_yuv[0][col], interlaced ? 2 * ywidth : ywidth, interlaced ? yheight / 2 : yheight);/* * If interlaced now process the second field (data source is offset * by 'ywidth').*/ if (interlaced) { get_column(&o_yuv[0][col + ywidth], cur_col, 2 * ywidth, yheight / 2); blur_line(ctable_y, cmatrix_y, cmatrix_y_len, cur_col, dest_col, interlaced ? yheight / 2 : yheight); put_column(dest_col, &o_yuv[0][col + ywidth], 2 * ywidth, yheight / 2); } } if (uv_radius == -1) goto merging; mjpeg_log(LOG_DEBUG, "Blurring chroma columns frame %d", frameno); for (col = 0; col < uvwidth; col++) {/* U */ get_column(&o_yuv[1][col], cur_col, interlaced ? 2 * uvwidth : uvwidth, interlaced ? uvheight / 2 : uvheight); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, cur_col, dest_col, interlaced ? uvheight / 2 : uvheight); put_column(dest_col, &o_yuv[1][col], interlaced ? 2 * uvwidth : uvwidth, interlaced ? uvheight / 2 : uvheight); if (interlaced) { get_column(&o_yuv[1][col + uvwidth], cur_col, 2 * uvwidth, uvheight / 2); blur_line(ctable_uv, cmatrix_uv, cmatrix_uv_len, cur_col, dest_col, interlaced ? uvheight / 2 : uvheight); put_column(dest_col, &o_yuv[1][col + uvwidth], 2 * uvwidth, uvheight / 2); }/* V */ get_column(&o_yuv[2][col], cur_col, interlaced ? 2 * uvwidth : uvwidth,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -