mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-18 05:16:05 +00:00
xsharpen video filter from Virtualdub
Original commit message from CVS: xsharpen video filter from Virtualdub
This commit is contained in:
parent
2b60d60286
commit
b821822691
5 changed files with 633 additions and 1 deletions
2
common
2
common
|
@ -1 +1 @@
|
||||||
Subproject commit 1a826743b023d38a14e16cf1b3fb85eabdbb65d6
|
Subproject commit 4ed4b888250d1081585717504b571ebf2de72c60
|
11
gst/virtualdub/Makefile.am
Normal file
11
gst/virtualdub/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
plugindir = $(libdir)/gst
|
||||||
|
|
||||||
|
plugin_LTLIBRARIES = libgstvirtualdub.la
|
||||||
|
|
||||||
|
libgstvirtualdub_la_SOURCES = gstvirtualdub.c gstxsharpen.c
|
||||||
|
libgstvirtualdub_la_CFLAGS = $(GST_CFLAGS)
|
||||||
|
libgstvirtualdub_la_LIBADD =
|
||||||
|
libgstvirtualdub_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
|
|
||||||
|
noinst_HEADERS = gstvirtualdub.h
|
||||||
|
|
122
gst/virtualdub/gstvirtualdub.c
Normal file
122
gst/virtualdub/gstvirtualdub.c
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* EffecTV:
|
||||||
|
* Copyright (C) 2001 FUKUCHI Kentarou
|
||||||
|
*
|
||||||
|
* EffecTV is free software. We release this product under the terms of the
|
||||||
|
* GNU General Public License version 2. The license is included in the file
|
||||||
|
* COPYING.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include "gstvirtualdub.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct _elements_entry {
|
||||||
|
gchar *name;
|
||||||
|
GType (*type) (void);
|
||||||
|
GstElementDetails *details;
|
||||||
|
gboolean (*factoryinit) (GstElementFactory *factory);
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct _elements_entry _elements[] = {
|
||||||
|
{ "xsharpen", gst_xsharpen_get_type, &gst_xsharpen_details, NULL },
|
||||||
|
{ NULL, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GstPadTemplate*
|
||||||
|
gst_virtualdub_src_factory (void)
|
||||||
|
{
|
||||||
|
static GstPadTemplate *templ = NULL;
|
||||||
|
if (!templ) {
|
||||||
|
templ = GST_PAD_TEMPLATE_NEW (
|
||||||
|
"src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_CAPS_NEW (
|
||||||
|
"virtualdub_src",
|
||||||
|
"video/raw",
|
||||||
|
"format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
|
||||||
|
"bpp", GST_PROPS_INT (32),
|
||||||
|
"depth", GST_PROPS_INT (32),
|
||||||
|
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||||
|
"red_mask", GST_PROPS_INT (0xff0000),
|
||||||
|
"green_mask", GST_PROPS_INT (0xff00),
|
||||||
|
"blue_mask", GST_PROPS_INT (0xff),
|
||||||
|
"width", GST_PROPS_INT_RANGE (16, 4096),
|
||||||
|
"height", GST_PROPS_INT_RANGE (16, 4096)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return templ;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstPadTemplate*
|
||||||
|
gst_virtualdub_sink_factory (void)
|
||||||
|
{
|
||||||
|
static GstPadTemplate *templ = NULL;
|
||||||
|
if (!templ) {
|
||||||
|
templ = GST_PAD_TEMPLATE_NEW (
|
||||||
|
"sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_CAPS_NEW (
|
||||||
|
"virtualdub_sink",
|
||||||
|
"video/raw",
|
||||||
|
"format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
|
||||||
|
"bpp", GST_PROPS_INT (32),
|
||||||
|
"depth", GST_PROPS_INT (32),
|
||||||
|
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||||
|
"red_mask", GST_PROPS_INT (0xff0000),
|
||||||
|
"green_mask", GST_PROPS_INT (0xff00),
|
||||||
|
"blue_mask", GST_PROPS_INT (0xff),
|
||||||
|
"width", GST_PROPS_INT_RANGE (16, 4096),
|
||||||
|
"height", GST_PROPS_INT_RANGE (16, 4096)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return templ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
plugin_init (GModule * module, GstPlugin * plugin)
|
||||||
|
{
|
||||||
|
GstElementFactory *factory;
|
||||||
|
gint i = 0;
|
||||||
|
|
||||||
|
while (_elements[i].name) {
|
||||||
|
factory = gst_element_factory_new (_elements[i].name,
|
||||||
|
(_elements[i].type) (),
|
||||||
|
_elements[i].details);
|
||||||
|
|
||||||
|
if (!factory) {
|
||||||
|
g_warning ("gst_virtualdub_new failed for `%s'",
|
||||||
|
_elements[i].name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gst_element_factory_add_pad_template (factory, gst_virtualdub_src_factory ());
|
||||||
|
gst_element_factory_add_pad_template (factory, gst_virtualdub_sink_factory ());
|
||||||
|
|
||||||
|
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
||||||
|
if (_elements[i].factoryinit) {
|
||||||
|
_elements[i].factoryinit (factory);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstPluginDesc plugin_desc = {
|
||||||
|
GST_VERSION_MAJOR,
|
||||||
|
GST_VERSION_MINOR,
|
||||||
|
"virtualdub",
|
||||||
|
plugin_init
|
||||||
|
};
|
38
gst/virtualdub/gstvirtualdub.h
Normal file
38
gst/virtualdub/gstvirtualdub.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* Filter:
|
||||||
|
* Copyright (C) 2000 Donald A. Graft
|
||||||
|
*
|
||||||
|
* EffecTV is free software. We release this product under the terms of the
|
||||||
|
* GNU General Public License version 2. The license is included in the file
|
||||||
|
* COPYING.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
typedef unsigned int Pixel;
|
||||||
|
typedef unsigned int Pixel32;
|
||||||
|
typedef unsigned char Pixel8;
|
||||||
|
typedef int PixCoord;
|
||||||
|
typedef int PixDim;
|
||||||
|
typedef int PixOffset;
|
||||||
|
|
||||||
|
|
||||||
|
#define R_MASK (0x00ff0000)
|
||||||
|
#define G_MASK (0x0000ff00)
|
||||||
|
#define B_MASK (0x000000ff)
|
||||||
|
#define R_SHIFT (16)
|
||||||
|
#define G_SHIFT (8)
|
||||||
|
#define B_SHIFT (0)
|
||||||
|
|
||||||
|
|
||||||
|
GType gst_xsharpen_get_type (void);
|
||||||
|
extern GstElementDetails gst_xsharpen_details;
|
||||||
|
|
||||||
|
extern GstPadTemplate *gst_virtualdub_sink_factory ();
|
||||||
|
extern GstPadTemplate *gst_virtualdub_src_factory ();
|
461
gst/virtualdub/gstxsharpen.c
Normal file
461
gst/virtualdub/gstxsharpen.c
Normal file
|
@ -0,0 +1,461 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* Filter:
|
||||||
|
* Copyright (C) 2000 Donald A. Graft
|
||||||
|
*
|
||||||
|
* Port done with help of transcode xsharpen filter by Tilmann Bitterberg
|
||||||
|
*
|
||||||
|
* EffecTV is free software. We release this product under the terms of the
|
||||||
|
* GNU General Public License version 2. The license is included in the file
|
||||||
|
* COPYING.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include "gstvirtualdub.h"
|
||||||
|
|
||||||
|
#define GST_TYPE_XSHARPEN \
|
||||||
|
(gst_xsharpen_get_type())
|
||||||
|
#define GST_XSHARPEN(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_XSHARPEN,GstXsharpen))
|
||||||
|
#define GST_XSHARPEN_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstXsharpen))
|
||||||
|
#define GST_IS_XSHARPEN(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_XSHARPEN))
|
||||||
|
#define GST_IS_XSHARPEN_CLASS(obj) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_XSHARPEN))
|
||||||
|
|
||||||
|
typedef struct _GstXsharpen GstXsharpen;
|
||||||
|
typedef struct _GstXsharpenClass GstXsharpenClass;
|
||||||
|
|
||||||
|
struct _GstXsharpen
|
||||||
|
{
|
||||||
|
GstElement element;
|
||||||
|
|
||||||
|
GstPad *sinkpad, *srcpad;
|
||||||
|
|
||||||
|
gint width, height;
|
||||||
|
gint strength, strengthinv, threshold;
|
||||||
|
gint srcpitch, dstpitch;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstXsharpenClass
|
||||||
|
{
|
||||||
|
GstElementClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GstElementDetails gst_xsharpen_details = {
|
||||||
|
"",
|
||||||
|
"Filter/Video/Effect",
|
||||||
|
"Apply a sharpen effect on video"
|
||||||
|
VERSION,
|
||||||
|
"Jeremy SIMON <jsimon13@yahoo.fr>",
|
||||||
|
"(C) 2000 Donald Graft",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Filter signals and args */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* FILL ME */
|
||||||
|
ARG_STRENGTH,
|
||||||
|
ARG_THRESHOLD,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ARG_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gst_xsharpen_class_init (GstXsharpenClass * klass);
|
||||||
|
static void gst_xsharpen_init (GstXsharpen * sharpen);
|
||||||
|
|
||||||
|
static void gst_xsharpen_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_xsharpen_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static void gst_xsharpen_chain (GstPad * pad, GstBuffer * buf);
|
||||||
|
|
||||||
|
static GstElementClass *parent_class = NULL;
|
||||||
|
|
||||||
|
GType gst_xsharpen_get_type (void)
|
||||||
|
{
|
||||||
|
static GType xsharpen_type = 0;
|
||||||
|
|
||||||
|
if (!xsharpen_type) {
|
||||||
|
static const GTypeInfo xsharpen_info = {
|
||||||
|
sizeof (GstXsharpenClass), NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_xsharpen_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstXsharpen),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_xsharpen_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
xsharpen_type = g_type_register_static (GST_TYPE_ELEMENT, "GstXsharpen", &xsharpen_info, 0);
|
||||||
|
}
|
||||||
|
return xsharpen_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_xsharpen_class_init (GstXsharpenClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_STRENGTH,
|
||||||
|
g_param_spec_int("strength", "strength", "strength",
|
||||||
|
0, 255, 255, (GParamFlags)G_PARAM_READWRITE ));
|
||||||
|
|
||||||
|
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_THRESHOLD,
|
||||||
|
g_param_spec_int("threshold", "threshold", "threshold",
|
||||||
|
0, 255, 255, (GParamFlags)G_PARAM_READWRITE ));
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_xsharpen_set_property;
|
||||||
|
gobject_class->get_property = gst_xsharpen_get_property;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstPadConnectReturn
|
||||||
|
gst_xsharpen_sinkconnect (GstPad * pad, GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstXsharpen *sharpen;
|
||||||
|
|
||||||
|
sharpen = GST_XSHARPEN (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
if (!GST_CAPS_IS_FIXED (caps))
|
||||||
|
return GST_PAD_CONNECT_DELAYED;
|
||||||
|
|
||||||
|
gst_caps_get_int (caps, "width", &sharpen->width);
|
||||||
|
gst_caps_get_int (caps, "height", &sharpen->height);
|
||||||
|
|
||||||
|
sharpen->strengthinv = 255 - sharpen->strength;
|
||||||
|
|
||||||
|
sharpen->dstpitch = sharpen->srcpitch = sharpen->width * sizeof (Pixel32);
|
||||||
|
|
||||||
|
if (gst_pad_try_set_caps (sharpen->srcpad, caps)) {
|
||||||
|
return GST_PAD_CONNECT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_PAD_CONNECT_REFUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_xsharpen_init (GstXsharpen * sharpen)
|
||||||
|
{
|
||||||
|
sharpen->sinkpad = gst_pad_new_from_template (gst_virtualdub_sink_factory (), "sink");
|
||||||
|
gst_pad_set_chain_function (sharpen->sinkpad, gst_xsharpen_chain);
|
||||||
|
gst_pad_set_connect_function (sharpen->sinkpad, gst_xsharpen_sinkconnect);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (sharpen), sharpen->sinkpad);
|
||||||
|
|
||||||
|
sharpen->srcpad = gst_pad_new_from_template (gst_virtualdub_src_factory (), "src");
|
||||||
|
gst_element_add_pad (GST_ELEMENT (sharpen), sharpen->srcpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_xsharpen_chain (GstPad * pad, GstBuffer * buf)
|
||||||
|
{
|
||||||
|
GstXsharpen *xsharpen;
|
||||||
|
GstBuffer *outbuf;
|
||||||
|
gint x, y;
|
||||||
|
gint r, g, b, R, G, B;
|
||||||
|
Pixel32 p, min, max;
|
||||||
|
gint luma, lumac, lumamax, lumamin, mindiff, maxdiff;
|
||||||
|
Pixel32 *src_buf, *dst_buf, *src, *dst;
|
||||||
|
|
||||||
|
xsharpen = GST_XSHARPEN (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
outbuf = gst_buffer_new ();
|
||||||
|
GST_BUFFER_SIZE (outbuf) = ( xsharpen->width * xsharpen->height * sizeof (Pixel32));
|
||||||
|
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
|
||||||
|
|
||||||
|
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
|
||||||
|
|
||||||
|
src_buf = (Pixel32 *)GST_BUFFER_DATA (buf);
|
||||||
|
dst_buf = (Pixel32 *)GST_BUFFER_DATA (outbuf);
|
||||||
|
min = max = 0;
|
||||||
|
|
||||||
|
/* First copy through the four border lines. */
|
||||||
|
src = src_buf;
|
||||||
|
dst = dst_buf;
|
||||||
|
for (x = 0; x < xsharpen->width; x++)
|
||||||
|
{
|
||||||
|
dst[x] = src[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
src = (Pixel *)((char *)src_buf + (xsharpen->height - 1) * xsharpen->srcpitch);
|
||||||
|
dst = (Pixel *)((char *)dst_buf + (xsharpen->height - 1) * xsharpen->dstpitch);
|
||||||
|
|
||||||
|
for (x = 0; x < xsharpen->width; x++)
|
||||||
|
{
|
||||||
|
dst[x] = src[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
src = src_buf;
|
||||||
|
dst = dst_buf;
|
||||||
|
|
||||||
|
for (y = 0; y < xsharpen->height; y++)
|
||||||
|
{
|
||||||
|
dst[0] = src[0];
|
||||||
|
dst[xsharpen->width-1] = src[xsharpen->width-1];
|
||||||
|
src = (Pixel *)((char *)src + xsharpen->srcpitch);
|
||||||
|
dst = (Pixel *)((char *)dst + xsharpen->dstpitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now calculate and store the pixel luminances for the remaining pixels. */
|
||||||
|
src = src_buf;
|
||||||
|
for (y = 0; y < xsharpen->height; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < xsharpen->width; x++)
|
||||||
|
{
|
||||||
|
r = (src[x] >> 16) & 0xff;
|
||||||
|
g = (src[x] >> 8) & 0xff;
|
||||||
|
b = src[x] & 0xff;
|
||||||
|
luma = (55 * r + 182 * g + 19 * b) >> 8;
|
||||||
|
src[x] &= 0x00ffffff;
|
||||||
|
src[x] |= (luma << 24);
|
||||||
|
}
|
||||||
|
src = (Pixel *)((char *)src + xsharpen->srcpitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally run the 3x3 rank-order sharpening kernel over the pixels. */
|
||||||
|
src = (Pixel *)((char *)src_buf + xsharpen->srcpitch);
|
||||||
|
dst = (Pixel *)((char *)dst_buf + xsharpen->dstpitch);
|
||||||
|
|
||||||
|
for (y = 1; y < xsharpen->height - 1; y++)
|
||||||
|
{
|
||||||
|
for (x = 1; x < xsharpen->width - 1; x++)
|
||||||
|
{
|
||||||
|
/* Find the brightest and dimmest pixels in the 3x3 window
|
||||||
|
surrounding the current pixel. */
|
||||||
|
|
||||||
|
lumamax = -1;
|
||||||
|
lumamin = 1000;
|
||||||
|
|
||||||
|
p = ((Pixel32 *)((char *)src - xsharpen->srcpitch))[x-1];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ((Pixel32 *)((char *)src - xsharpen->srcpitch))[x];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ((Pixel32 *)((char *)src - xsharpen->srcpitch))[x+1];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = src[x-1];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = src[x];
|
||||||
|
lumac = luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = src[x+1];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ((Pixel32 *)((char *)src + xsharpen->srcpitch))[x-1];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ((Pixel32 *)((char *)src + xsharpen->srcpitch))[x];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ((Pixel32 *)((char *)src + xsharpen->srcpitch))[x+1];
|
||||||
|
luma = p >> 24;
|
||||||
|
if (luma > lumamax)
|
||||||
|
{
|
||||||
|
lumamax = luma;
|
||||||
|
max = p;
|
||||||
|
}
|
||||||
|
if (luma < lumamin)
|
||||||
|
{
|
||||||
|
lumamin = luma;
|
||||||
|
min = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine whether the current pixel is closer to the
|
||||||
|
brightest or the dimmest pixel. Then compare the current
|
||||||
|
pixel to that closest pixel. If the difference is within
|
||||||
|
threshold, map the current pixel to the closest pixel;
|
||||||
|
otherwise pass it through. */
|
||||||
|
|
||||||
|
p = -1;
|
||||||
|
if (xsharpen->strength != 0)
|
||||||
|
{
|
||||||
|
mindiff = lumac - lumamin;
|
||||||
|
maxdiff = lumamax - lumac;
|
||||||
|
if (mindiff > maxdiff)
|
||||||
|
{
|
||||||
|
if (maxdiff < xsharpen->threshold)
|
||||||
|
{
|
||||||
|
p = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mindiff < xsharpen->threshold)
|
||||||
|
{
|
||||||
|
p = min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == -1)
|
||||||
|
{
|
||||||
|
dst[x] = src[x];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
R = (src[x] >> 16) & 0xff;
|
||||||
|
G = (src[x] >> 8) & 0xff;
|
||||||
|
B = src[x] & 0xff;
|
||||||
|
r = (p >> 16) & 0xff;
|
||||||
|
g = (p >> 8) & 0xff;
|
||||||
|
b = p & 0xff;
|
||||||
|
r = (xsharpen->strength * r + xsharpen->strengthinv * R) / 255;
|
||||||
|
g = (xsharpen->strength * g + xsharpen->strengthinv * G) / 255;
|
||||||
|
b = (xsharpen->strength * b + xsharpen->strengthinv * B) / 255;
|
||||||
|
dst[x] = (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src = (Pixel *)((char *)src + xsharpen->srcpitch);
|
||||||
|
dst = (Pixel *)((char *)dst + xsharpen->dstpitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
gst_pad_push (xsharpen->srcpad, outbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_xsharpen_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstXsharpen *xsharpen;
|
||||||
|
|
||||||
|
/* it's not null if we got it, but it might not be ours */
|
||||||
|
g_return_if_fail (GST_IS_XSHARPEN (object));
|
||||||
|
|
||||||
|
xsharpen = GST_XSHARPEN (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case ARG_STRENGTH:
|
||||||
|
xsharpen->strength = g_value_get_int (value);
|
||||||
|
xsharpen->strengthinv = 255 - xsharpen->strength;
|
||||||
|
case ARG_THRESHOLD:
|
||||||
|
xsharpen->threshold = g_value_get_int (value);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_xsharpen_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstXsharpen *xsharpen;
|
||||||
|
|
||||||
|
/* it's not null if we got it, but it might not be ours */
|
||||||
|
g_return_if_fail (GST_IS_XSHARPEN (object));
|
||||||
|
|
||||||
|
xsharpen = GST_XSHARPEN (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case ARG_STRENGTH:
|
||||||
|
g_value_set_int (value, xsharpen->strength );
|
||||||
|
break;
|
||||||
|
case ARG_THRESHOLD:
|
||||||
|
g_value_set_int (value, xsharpen->threshold );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue