私はいくつかのデモコードにPixbufを持っていますが、現在は画面のタッチによって時計回りまたは反時計回りに回転しています。GDK Pixbufを90度未満回転させることはできますか?
これはRotateSimple
を使用して行いますが、これは90度の倍数に制限されています。
Pixbufバッファ内のイメージを45度(以下)回転させる方法はありますか?
私はいくつかのデモコードにPixbufを持っていますが、現在は画面のタッチによって時計回りまたは反時計回りに回転しています。GDK Pixbufを90度未満回転させることはできますか?
これはRotateSimple
を使用して行いますが、これは90度の倍数に制限されています。
Pixbufバッファ内のイメージを45度(以下)回転させる方法はありますか?
いいえ、RotateSimple
(または基礎となるライブラリのgdk_pixbuf_rotate_simple()
)ではありません。 documentationによれば、それは「90度の倍数」だけ回転することに限定されている。
しかし、あなたはがを行うことができます一つのことは、あなたが小さい値で回転しているかのようにを表示さ作るために複数の画像を提供しています。
45度の特定の例では、2つの画像だけが必要です。第1は、90度の回転(すなわち、SimpleRotate
を使用)を使用して8つの必要な回転のうちの4つ、すなわち0
,90
,180
および270
を得ることができる「直立」画像である。
他にもの4つの可能性があります。イメージ編集ソフトウェアにイメージを置き、それを45度回転させて「傾斜」イメージとして保存します。 特に解像度があれば、あなたが同様のことを行うことができ、よりきめ細かな回転のために
Desired rotation Uses image Actual rotation
---------------- ---------- ---------------
0 upright 0
45 tilted 0
90 upright 90
135 tilted 90
180 upright 180
225 tilted 180
270 upright 270
315 tilted 270
:
そのように、あなたは様々な2枚の画像の回転を利用して可能性の全てを取得することができますバビロニア人(またはシュメール人、誰か、私の歴史は少し錆びています)の先見的な性質のおかげで、360はかなり多くの要因を持っています。
私は汎用のpixbuf回転関数を書いています。引数:
full_size - この関数は、2つの モードで動作します。完全に回転された画像(余分な三角形に加えて、 アルファ= 0)を入れるにはちょうど十分な大きさの新しいpixbufを生成するか、最大値の を埋め込んだpixbufを生成します(水平/垂直)矩形を回転した画像内に表示します。 full_sizeがtrueの場合、(空白のコーナー) の大きい方の矩形が生成されます。full_sizeがfalseの場合、小さい方の矩形が生成されます。 が45度に近づくと、小さな矩形のサイズは0 になり、NULL pixbufが返されます。
#include <gtk/gtk.h>
/* There are two reasonable sizes for a rotated image-- Either the minimum */
/* bounding box which contains all rotated pixels (and a bunch of white space)*/
/* or the maximum rectangle where all pixels come from the source image (but */
/* where we lose some of the corners) */
/* The first is easy to calculate: The minimum bounding box will have the corners */
/* of the rotated image on its edges, this leaves us with four triangles in */
/* the corners of the bb. Two triangles have edges width*sin(theta), width*cos(theta) */
/* and two have edges height*sin(theta), height*cos(theta) */
/* so the new width height will be the sum of two adjacent triangle edges: */
/* width" = width*cos + height*sin */
/* height"= width*sin + height*cos */
/* Now for the maximum inscribed rectangle we draw a similar picture (except */
/* the unknown rectangle is internal now) and get similar triangles. Here the*/
/* equations are: */
/* width = width'*cos + height'*sin */
/* height= width'*sin + height'*cos */
/* solving for height'... */
/* height' = (width-width'*cos)/sin */
/* height' = (height-width'*sin)/cos */
/* (width-width'*cos)/sin = (height-width'*sin)/cos */
/* width*cos - width'*cos^2 = height*sin - width'*sin^2 */
/* width' * (sin^2-cos^2) = height*sin-width*cos */
/* width' = (height*sin - width*cos)/(sin^2-cos^2) */
/* height'= (width*sin - height*cos)/(sin^2-cos^2) */
/* Note this produces garbage (0/0) when rotated by 45 degrees (135,225,...) */
/* A little experimentation shows that at 45 degrees the only thing with */
/* an internal rectangle is a square, all other aspect ratios have a height */
/* of 0. A square, however, has an internal square with sides 1/sqrt(2) of the original */
/* When creating a full_size image (minimum bounding box) we should return */
/* an image with an alpha channel (whether the original had one or no). */
/* otherwise we should create an alpha channel only if the original had one */
/* A pixel at (x,y) will be rotated to: */
/* ((x-width/2)*cos + (y-height/2)*sin + width'/2 , */
/* =(x-width/2)*sin + (y-height/2)*cos + height'/2) */
/* A pixel at (x',y') will have come from: */
/* ((x'-width'/2)*cos - (y'-height'/2)*sin + width/2 , */
/* (x'-width'/2)*sin + (y'-height'/2)*cos + height/2) */
static GdkPixbuf *gdk_pixbuf_rotate(GdkPixbuf *src,double radian,gboolean full_size) {
double s = sin(radian), c = cos(radian);
double as= s<0 ? -s : s, ac= c<0 ? -c : c;
int width, height, nwidth, nheight;
int hasalpha, nhasalpha;
GdkPixbuf *ret;
int nr,nc,r,col;
double nmodr, nmodc;
int alpha=0;
guchar *pixels, *npixels, *pt, *npt;
int rowstride, nrowstride, pixellen;
if (src==NULL)
return(NULL);
width = gdk_pixbuf_get_width(src);
height = gdk_pixbuf_get_height(src);
hasalpha = gdk_pixbuf_get_has_alpha(src);
rowstride = gdk_pixbuf_get_rowstride(src);
pixels = gdk_pixbuf_get_pixels(src);
pixellen = hasalpha ? 4 : 3;
if (full_size) {
nwidth = round(ac*width + as*height);
nheight= round(as*width + ac*height);
nhasalpha = TRUE;
} else {
double denom = as*as - ac*ac;
if (denom<.1e-7 && denom>-1.e-7) {
if (width!=height)
return(NULL);
nwidth = nheight = round(width/sqrt(2.0));
} else {
nwidth = round((height*as - width*ac)/denom);
nheight = round((width*as - height*ac)/denom);
}
if (nwidth<=0 || nheight<=0)
return(NULL);
nhasalpha = hasalpha;
}
ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB,nhasalpha,8,nwidth,nheight);
if (ret==NULL)
return(NULL);
nrowstride = gdk_pixbuf_get_rowstride(ret);
npixels = gdk_pixbuf_get_pixels(ret);
for (nr=0; nr<nheight; ++nr) {
nmodr = nr-nheight/2.0;
npt = npixels + nr*nrowstride;
for (nc=0; nc<nwidth; ++nc) {
nmodc = nc-nwidth/2.0;
/* Where did this pixel come from? */
r = round(height/2 - nmodc*s + nmodr*c);
col = round(width/2 + nmodc*c + nmodr*s);
if (r<0 || col<0 || r>=height || col>=width) {
alpha = 0;
if (r<0) r=0;
else if (r>=height) r = height-1;
if (col<0) col = 0;
else if (col>=width) col = width-1;
} else
alpha = 0xff;
pt = pixels + r*rowstride + col*pixellen;
*npt++ = *pt++;
*npt++ = *pt++;
*npt++ = *pt++;
if (hasalpha && alpha!=0)
alpha = *pt;
if (nhasalpha)
*npt++ = alpha;
}
}
return(ret);
}