⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pixbuf_util.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * GQview * (C) 2004 John Ellis * * Author: John Ellis * * This software is released under the GNU General Public License (GNU GPL). * Please read the included file COPYING for more information. * This software comes with no warranty of any kind, use at your own risk! */#include "gqview.h"#include "pixbuf_util.h"#include "icons/icons_inline.h"#include <math.h>/* *----------------------------------------------------------------------------- * png save *----------------------------------------------------------------------------- */gboolean pixbuf_to_file_as_png (GdkPixbuf *pixbuf, const char *filename){	GError *error = NULL;	gint ret;	if (!pixbuf || !filename) return FALSE;	ret = gdk_pixbuf_save(pixbuf, filename, "png", &error,			      "tEXt::Software", "GQview "VERSION, NULL);	if (error)		{		printf("Error saving png file: %s\n", error->message);		g_error_free(error);		}	return ret;}/* *----------------------------------------------------------------------------- * jpeg save *----------------------------------------------------------------------------- */gboolean pixbuf_to_file_as_jpg(GdkPixbuf *pixbuf, const gchar *filename, gint quality){	GError *error = NULL;	gchar *qbuf;	gboolean ret;	if (!pixbuf || !filename) return FALSE;	if (quality == -1) quality = 75;	if (quality < 1 || quality > 100)		{		printf("Jpeg not saved, invalid quality %d\n", quality);		return FALSE;		}	qbuf = g_strdup_printf("%d", quality);	ret = gdk_pixbuf_save(pixbuf, filename, "jpeg", &error, "quality", qbuf, NULL);	g_free(qbuf);	if (error)		{		printf("Error saving jpeg to %s\n%s\n", filename, error->message);		g_error_free(error);		}	return ret;}/* *----------------------------------------------------------------------------- * pixbuf from inline *----------------------------------------------------------------------------- */typedef struct _PixbufInline PixbufInline;struct _PixbufInline{	const gchar *key;	const guint8 *data;};static PixbufInline inline_pixbuf_data[] = {	{ PIXBUF_INLINE_FOLDER_CLOSED,	folder_closed },	{ PIXBUF_INLINE_FOLDER_LOCKED,	folder_locked },	{ PIXBUF_INLINE_FOLDER_OPEN,	folder_open },	{ PIXBUF_INLINE_FOLDER_UP,	folder_up },	{ PIXBUF_INLINE_SCROLLER,	icon_scroller },	{ PIXBUF_INLINE_BROKEN,		icon_broken },	{ PIXBUF_INLINE_LOGO,		gqview_logo },	{ PIXBUF_INLINE_ICON_FLOAT,	icon_float },	{ PIXBUF_INLINE_ICON_THUMB,	icon_thumb },	{ NULL, NULL }};GdkPixbuf *pixbuf_inline(const gchar *key){	gint i;	if (!key) return NULL;	i = 0;	while (inline_pixbuf_data[i].key)		{		if (strcmp(inline_pixbuf_data[i].key, key) == 0)			{			return gdk_pixbuf_new_from_inline(-1, inline_pixbuf_data[i].data, FALSE, NULL);			}		i++;		}	printf("warning: inline pixbuf key \"%s\" not found.\n", key);	return NULL;}/* *----------------------------------------------------------------------------- * misc utils *----------------------------------------------------------------------------- */gint util_clip_region(gint x, gint y, gint w, gint h,		      gint clip_x, gint clip_y, gint clip_w, gint clip_h,		      gint *rx, gint *ry, gint *rw, gint *rh){	if (clip_x + clip_w <= x ||	    clip_x >= x + w ||	    clip_y + clip_h <= y ||	    clip_y >= y + h)		{		return FALSE;		}	*rx = MAX(x, clip_x);	*rw = MIN((x + w), (clip_x + clip_w)) - *rx;	*ry = MAX(y, clip_y);	*rh = MIN((y + h), (clip_y + clip_h)) - *ry;	return TRUE;}/* *----------------------------------------------------------------------------- * pixbuf rotation *----------------------------------------------------------------------------- */static void pixbuf_copy_block_rotate(guchar *src, gint src_row_stride, gint x, gint y,				     guchar *dest, gint dest_row_stride, gint w, gint h,				     gint bytes_per_pixel, gint counter_clockwise){	gint i, j;	guchar *sp;	guchar *dp;	for (i = 0; i < h; i++)		{		sp = src + ((i + y) * src_row_stride) + (x * bytes_per_pixel);		for (j = 0; j < w; j++)			{			if (counter_clockwise)				{				dp = dest + ((w - j - 1) * dest_row_stride) + (i * bytes_per_pixel);				}			else				{				dp = dest + (j * dest_row_stride) + ((h - i - 1) * bytes_per_pixel);				}			*(dp++) = *(sp++);	/* r */			*(dp++) = *(sp++);	/* g */			*(dp++) = *(sp++);	/* b */			if (bytes_per_pixel == 4) *(dp) = *(sp++);	/* a */			}		}	}static void pixbuf_copy_block(guchar *src, gint src_row_stride, gint w, gint h,			      guchar *dest, gint dest_row_stride, gint x, gint y, gint bytes_per_pixel){	gint i;	guchar *sp;	guchar *dp;	for (i = 0; i < h; i++)		{		sp = src + (i * src_row_stride);		dp = dest + ((y + i) * dest_row_stride) + (x * bytes_per_pixel);		memcpy(dp, sp, w * bytes_per_pixel);		}}#define ROTATE_BUFFER_WIDTH 48#define ROTATE_BUFFER_HEIGHT 48/* * Returns a copy of pixbuf src rotated 90 degrees clockwise or 90 counterclockwise * */GdkPixbuf *pixbuf_copy_rotate_90(GdkPixbuf *src, gint counter_clockwise){	GdkPixbuf *dest;	gint has_alpha;	gint sw, sh, srs;	gint dw, dh, drs;	guchar *s_pix;        guchar *d_pix;#if 0	guchar *sp;        guchar *dp;#endif	gint i, j;	gint a;	GdkPixbuf *buffer;        guchar *b_pix;	gint brs;	gint w, h;	if (!src) return NULL;	sw = gdk_pixbuf_get_width(src);	sh = gdk_pixbuf_get_height(src);	has_alpha = gdk_pixbuf_get_has_alpha(src);	srs = gdk_pixbuf_get_rowstride(src);	s_pix = gdk_pixbuf_get_pixels(src);	dw = sh;	dh = sw;	dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, dw, dh);	drs = gdk_pixbuf_get_rowstride(dest);	d_pix = gdk_pixbuf_get_pixels(dest);	a = (has_alpha ? 4 : 3);	buffer = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8,				ROTATE_BUFFER_WIDTH, ROTATE_BUFFER_HEIGHT);	b_pix = gdk_pixbuf_get_pixels(buffer);	brs = gdk_pixbuf_get_rowstride(buffer);	for (i = 0; i < sh; i+= ROTATE_BUFFER_WIDTH)		{		w = MIN(ROTATE_BUFFER_WIDTH, (sh - i));		for (j = 0; j < sw; j += ROTATE_BUFFER_HEIGHT)			{			gint x, y;			h = MIN(ROTATE_BUFFER_HEIGHT, (sw - j));			pixbuf_copy_block_rotate(s_pix, srs, j, i,						 b_pix, brs, h, w,						 a, counter_clockwise);			if (counter_clockwise)				{				x = i;				y = sw - h - j;				}			else				{				x = sh - w - i;				y = j;				}			pixbuf_copy_block(b_pix, brs, w, h,					  d_pix, drs, x, y, a);			}		}	gdk_pixbuf_unref(buffer);#if 0	/* this is the simple version of rotation (roughly 2-4x slower) */	for (i = 0; i < sh; i++)		{		sp = s_pix + (i * srs);		for (j = 0; j < sw; j++)			{			if (counter_clockwise)				{				dp = d_pix + ((dh - j - 1) * drs) + (i * a);				}			else				{				dp = d_pix + (j * drs) + ((dw - i - 1) * a);				}			*(dp++) = *(sp++);	/* r */			*(dp++) = *(sp++);	/* g */			*(dp++) = *(sp++);	/* b */			if (has_alpha) *(dp) = *(sp++);	/* a */			}		}#endif	return dest;}/* * Returns a copy of pixbuf mirrored and or flipped. * TO do a 180 degree rotations set both mirror and flipped TRUE * if mirror and flip are FALSE, result is a simple copy. */GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gint mirror, gint flip){	GdkPixbuf *dest;	gint has_alpha;	gint w, h, srs;	gint drs;	guchar *s_pix;        guchar *d_pix;	guchar *sp;        guchar *dp;	gint i, j;	gint a;	if (!src) return NULL;	w = gdk_pixbuf_get_width(src);	h = gdk_pixbuf_get_height(src);	has_alpha = gdk_pixbuf_get_has_alpha(src);	srs = gdk_pixbuf_get_rowstride(src);	s_pix = gdk_pixbuf_get_pixels(src);	dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, w, h);	drs = gdk_pixbuf_get_rowstride(dest);	d_pix = gdk_pixbuf_get_pixels(dest);	a = has_alpha ? 4 : 3;	for (i = 0; i < h; i++)		{		sp = s_pix + (i * srs);		if (flip)			{			dp = d_pix + ((h - i - 1) * drs);			}		else			{			dp = d_pix + (i * drs);			}		if (mirror)			{			dp += (w - 1) * a;			for (j = 0; j < w; j++)				{				*(dp++) = *(sp++);	/* r */				*(dp++) = *(sp++);	/* g */				*(dp++) = *(sp++);	/* b */				if (has_alpha) *(dp) = *(sp++);	/* a */				dp -= (a + 3);				}			}		else			{			for (j = 0; j < w; j++)				{				*(dp++) = *(sp++);	/* r */				*(dp++) = *(sp++);	/* g */				*(dp++) = *(sp++);	/* b */				if (has_alpha) *(dp++) = *(sp++);	/* a */				}			}		}	return dest;}/* *----------------------------------------------------------------------------- * pixbuf drawing (rectangles) *----------------------------------------------------------------------------- *//* * Fills region of pixbuf at x,y over w,h * with colors red (r), green (g), blue (b) * applying alpha (a), use a=255 for solid. */void pixbuf_draw_rect_fill(GdkPixbuf *pb,			   gint x, gint y, gint w, gint h,			   gint r, gint g, gint b, gint a){	gint p_alpha;	gint pw, ph, prs;	guchar *p_pix;	guchar *pp;	gint i, j;	if (!pb) return;	pw = gdk_pixbuf_get_width(pb);	ph = gdk_pixbuf_get_height(pb);	if (x < 0 || x + w > pw) return;	if (y < 0 || y + h > ph) return;	p_alpha = gdk_pixbuf_get_has_alpha(pb);	prs = gdk_pixbuf_get_rowstride(pb);	p_pix = gdk_pixbuf_get_pixels(pb);        for (i = 0; i < h; i++)		{		pp = p_pix + (y + i) * prs + (x * (p_alpha ? 4 : 3));		for (j = 0; j < w; j++)			{			*pp = (r * a + *pp * (256-a)) >> 8;			pp++;			*pp = (g * a + *pp * (256-a)) >> 8;			pp++;			*pp = (b * a + *pp * (256-a)) >> 8;			pp++;			if (p_alpha) pp++;			}		}}void pixbuf_draw_rect(GdkPixbuf *pb,		      gint x, gint y, gint w, gint h,		      gint r, gint g, gint b, gint a,		      gint left, gint right, gint top, gint bottom){	pixbuf_draw_rect_fill(pb, x + left, y, w - left - right, top,			      r, g, b ,a);	pixbuf_draw_rect_fill(pb, x + w - right, y, right, h,			      r, g, b ,a);	pixbuf_draw_rect_fill(pb, x + left, y + h - bottom, w - left - right, bottom,			      r, g, b ,a);	pixbuf_draw_rect_fill(pb, x, y, left, h,			      r, g, b ,a);}void pixbuf_set_rect_fill(GdkPixbuf *pb,			  gint x, gint y, gint w, gint h,			  gint r, gint g, gint b, gint a){	gint p_alpha;	gint pw, ph, prs;	guchar *p_pix;	guchar *pp;	gint i, j;	if (!pb) return;	pw = gdk_pixbuf_get_width(pb);	ph = gdk_pixbuf_get_height(pb);	if (x < 0 || x + w > pw) return;	if (y < 0 || y + h > ph) return;	p_alpha = gdk_pixbuf_get_has_alpha(pb);	prs = gdk_pixbuf_get_rowstride(pb);	p_pix = gdk_pixbuf_get_pixels(pb);        for (i = 0; i < h; i++)		{		pp = p_pix + (y + i) * prs + (x * (p_alpha ? 4 : 3));		for (j = 0; j < w; j++)			{			*pp = r; pp++;			*pp = g; pp++;			*pp = b; pp++;			if (p_alpha) { *pp = a; pp++; }			}		}}void pixbuf_set_rect(GdkPixbuf *pb,		     gint x, gint y, gint w, gint h,		     gint r, gint g, gint b, gint a,		     gint left, gint right, gint top, gint bottom){	pixbuf_set_rect_fill(pb, x + left, y, w - left - right, top,			     r, g, b ,a);	pixbuf_set_rect_fill(pb, x + w - right, y, right, h,			     r, g, b ,a);	pixbuf_set_rect_fill(pb, x + left, y + h - bottom, w - left - right, bottom,			     r, g, b ,a);	pixbuf_set_rect_fill(pb, x, y, left, h,			     r, g, b ,a);}void pixbuf_pixel_set(GdkPixbuf *pb, gint x, gint y, gint r, gint g, gint b, gint a){	guchar *buf;	gint has_alpha;	gint rowstride;	guchar *p;	if (x < 0 || x >= gdk_pixbuf_get_width(pb) ||            y < 0 || y >= gdk_pixbuf_get_height(pb)) return;	buf = gdk_pixbuf_get_pixels(pb);	has_alpha = gdk_pixbuf_get_has_alpha(pb);	rowstride = gdk_pixbuf_get_rowstride(pb);        p = buf + (y * rowstride) + (x * (has_alpha ? 4 : 3));	*p = r; p++;	*p = g; p++;	*p = b; p++;	if (has_alpha) *p = a;}/* *----------------------------------------------------------------------------- * pixbuf text rendering *----------------------------------------------------------------------------- */static void pixbuf_copy_font(GdkPixbuf *src, gint sx, gint sy,			     GdkPixbuf *dest, gint dx, gint dy,			     gint w, gint h,			     guint8 r, guint8 g, guint8 b, guint8 a){	gint sw, sh, srs;	gint s_alpha;	gint s_step;	guchar *s_pix;	gint dw, dh, drs;	gint d_alpha;	gint d_step;	guchar *d_pix;	guchar *sp;	guchar *dp;	gint i, j;	if (!src || !dest) return;	sw = gdk_pixbuf_get_width(src);	sh = gdk_pixbuf_get_height(src);	if (sx < 0 || sx + w > sw) return;	if (sy < 0 || sy + h > sh) return;	dw = gdk_pixbuf_get_width(dest);	dh = gdk_pixbuf_get_height(dest);	if (dx < 0 || dx + w > dw) return;	if (dy < 0 || dy + h > dh) return;	s_alpha = gdk_pixbuf_get_has_alpha(src);	d_alpha = gdk_pixbuf_get_has_alpha(dest);	srs = gdk_pixbuf_get_rowstride(src);	drs = gdk_pixbuf_get_rowstride(dest);	s_pix = gdk_pixbuf_get_pixels(src);	d_pix = gdk_pixbuf_get_pixels(dest);	s_step = (s_alpha) ? 4 : 3;	d_step = (d_alpha) ? 4 : 3;	for (i = 0; i < h; i++)		{		sp = s_pix + (sy + i) * srs + sx * s_step;		dp = d_pix + (dy + i) * drs + dx * d_step;		for (j = 0; j < w; j++)			{			if (*sp)				{				guint8 asub;				asub = a * sp[0] / 255;				*dp = (r * asub + *dp * (256-asub)) >> 8;				dp++;				asub = a * sp[1] / 255;				*dp = (g * asub + *dp * (256-asub)) >> 8;				dp++;				asub = a * sp[2] / 255;				*dp = (b * asub + *dp * (256-asub)) >> 8;				dp++;				if (d_alpha)					{					*dp = MAX(*dp, a * ((sp[0] + sp[1] + sp[2]) / 3) / 255);					dp++;					}				}			else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -