Java jmagick文字周围的圆圈稍微偏离
我对ImageMagick和java比较陌生,我正在做一个项目,在windows上使用ImageMagick 6.3.9 Q16和jmagick 6.3.9 Q16在以0度为中心的圆的外侧显示文本。我们正在移植现有的ImageMagick代码,该代码来自PHP MagickWand,但在java版本中,每个字母在圆弧上的位置都有点不合适,我认为这是因为以下差异 在MagickWand中,通过这一行代码将其放置在圆弧上,该代码使用浮点x、y坐标值和浮点角度值(为了更高的精度)来注释绘图棒(相当于jmagick中的DrawInfo),工作起来非常漂亮:Java jmagick文字周围的圆圈稍微偏离,java,imagemagick,jmagick,Java,Imagemagick,Jmagick,我对ImageMagick和java比较陌生,我正在做一个项目,在windows上使用ImageMagick 6.3.9 Q16和jmagick 6.3.9 Q16在以0度为中心的圆的外侧显示文本。我们正在移植现有的ImageMagick代码,该代码来自PHP MagickWand,但在java版本中,每个字母在圆弧上的位置都有点不合适,我认为这是因为以下差异 在MagickWand中,通过这一行代码将其放置在圆弧上,该代码使用浮点x、y坐标值和浮点角度值(为了更高的精度)来注释绘图棒(相当于j
MagickAnnotateImage($magick_wand, $drawing_wand, $origin_x + $x, $origin_y - $y, $angle, $character);
但是在jmagick中,annotateImage方法只接受一个参数,即DrawInfo,因此我最终使用了我认为唯一的其他替代方法,compositeImage方法。为了做到这一点,我将每个字符画成单独的绘制信息,然后将其注释为透明的PNG图像,然后通过旋转图像方法旋转该图像,然后使用CuleTimeIMAGE将其放置在画布图像上,而CuleItI图则只处理x&y作为int值(并且不考虑角度)。所以我把我的x&y双精度值舍入到那个点上(得到相同的小数位数,或者更像php版本只是为了排除这个问题而使用的小数位数),我怀疑这是它把字符放在圆圈上的主要原因
我执行这项工作的代码如下:Article是字体文件的本地路径(例如:E:\WCDE_ENT70\workspace\Stores\WebContent\AdminArea\coordscenertsection\font\ARIALN.TTF),nameNumStr是要在圆上呈现的字符串(例如:SAMUELSON),fsize是字体的点大小(例如:32),colorStr是字体颜色名称(例如:black),radVal是半径(ex:120),poix是x原点起始坐标(ex:150),poiy是y原点起始坐标(ex:150):
public byte[]getArcedImage(字符串文章、字符串名称numstr、int-fsize、字符串colorStr、int-radVal、int-poix、int-poy)
{
试一试{
Font f=null;
试一试{
f=Font.createFont(Font.TRUETYPE\u Font,新文件输入流(Article.replaceAll(“%20”,下同));
}catch(filenotfounde异常){
e、 printStackTrace();
}捕获(FontFormat异常){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
字符串fontName=f.getName();
//使用awt的字体度量,因为jmagick没有像php magickwand那样内置字体度量
FontMetrics fm=createFontMetrics(新字体(fontName、Font.PLAIN、fsize));
int strImgW=fm.STRINGWITH(名称NUMSTR);
int strImgH=fm.getHeight();
String spacerImg=“E:\\WCDE\u ENT70\\workspace\\Stores\\WebContent\\AdminArea\\coordscenertsection\\images\\600x600.png”;
//首先阅读大600 png作为我们的主画布
ImageInfo bi=新的ImageInfo(间隔器img);
MagickImage bmi=新MagickImage(bi);
//使画布图像透明
体重指数(真);
bmi.setBackgroundColor(PixelPacket.QueryColor数据库(“#FFFF8800”);
//默认值或参数VAL
最终int半径=radVal;
最终整数原点_x=poix;
最终整数原点_y=点;
最终整型中心文本开=0;
最终int charXGeom=150;
最终整数charYGeom=150;
双周长=0;
双倍百分比=0;
双度=0;
双启动=0;
双电流_度=0;
双角度=0;
双角度_调整=0;
双字符_中心=0;
/**
*计算绘制圆的周长并标记图像
*用它。
*/
周长=(2*Math.PI*半径);
/**
*计算字符串将显示的周长百分比
*消费。
*/
百分比=strImgW/周长;
/**
*把这个百分比转换成实际的程度。
*/
度=360*百分比;
/**
*因为字符串居中,我们需要计算起点
*通过将所需度数的一半从
*预期中心标记。
*/
开始=居中显示文字-(度/2);
/**
*初始化我们的遍历起点。
*/
当前_度=启动;
//
ImageInfo ci=null;
MagickImage cmi=null;
双x=0;
双y=0;
int finalStrWidth=0;
int charImgW=0;
int charImgH=0;
对于(int i=0;i
public byte[] getArcedImage(String Article, String nameNumStr, int fsize, String colorStr, int radVal, int poix, int poiy)
{
try {
Font f = null;
try {
f = Font.createFont(Font.TRUETYPE_FONT, new FileInputStream(Article.replaceAll("%20"," ")));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (FontFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String fontName = f.getName();
// Use awt's font metrics since jmagick doesn't have font metrics built in like php magickwand does
FontMetrics fm = createFontMetrics(new Font(fontName, Font.PLAIN, fsize));
int strImgW = fm.stringWidth(nameNumStr);
int strImgH = fm.getHeight();
String spacerImg = "E:\\WCDE_ENT70\\workspace\\Stores\\WebContent\\AdminArea\\CoordsCenterSection\\images\\600x600.png";
//Read in large 600 png first as our main canvas
ImageInfo bi = new ImageInfo(spacerImg);
MagickImage bmi = new MagickImage(bi);
// Make canvas image transparent
bmi.setMatte(true);
bmi.setBackgroundColor(PixelPacket.queryColorDatabase("#FFFF8800"));
//defaults or param vals
final int radius = radVal;
final int origin_x = poix;
final int origin_y = poiy;
final int center_text_on = 0;
final int charXGeom = 150;
final int charYGeom = 150;
double circumference = 0;
double percentage = 0;
double degrees = 0;
double start = 0;
double current_degree = 0;
double angle = 0;
double angle_adjustment = 0;
double character_center = 0;
/**
* Calculate the circumference of the drawn circle and label the image
* with it.
*/
circumference = (2 * Math.PI * radius);
/**
* Calculate the percentage of the circumference that the string will
* consume.
*/
percentage = strImgW / circumference;
/**
* Convert this percentage into something practical - degrees.
*/
degrees = 360 * percentage;
/**
* Because the string is centered, we need to calculate the starting point
* of the string by subtracting half of the required degrees from the
* anticipated center mark.
*/
start = center_text_on - (degrees / 2);
/**
* Initialize our traversal starting point.
*/
current_degree = start;
//
ImageInfo ci = null;
MagickImage cmi = null;
double x = 0;
double y = 0;
int finalStrWidth = 0;
int charImgW = 0;
int charImgH = 0;
for (int i=0; i<nameNumStr.length(); i++)
{
/**
* Isolate the appropriate character.
*/
String charVal = nameNumStr.substring(i, i+1);
charImgW = fm.stringWidth(charVal);
charImgH = strImgH;
ci = new ImageInfo(spacerImg);
cmi = new MagickImage(ci);
// Create Rectangle for cropping character image canvas to final width and height
Rectangle charRect = new Rectangle(0,0,charImgW,charImgH);
// Crop image to final width and height
cmi = cmi.cropImage(charRect);
// Make image transparent
cmi.setMatte(true);
cmi.setBackgroundColor(PixelPacket.queryColorDatabase("#FFFF8800"));
// Set a draw info for each character
DrawInfo cdi = new DrawInfo(ci);
// Set Opacity
cdi.setOpacity(0);
// Set Gravity
cdi.setGravity(GravityType.CenterGravity);
// Set Fill Color
cdi.setFill(PixelPacket.queryColorDatabase(colorStr));
// Set Font Size
cdi.setPointsize(fsize);
// Set Font
cdi.setFont(Article.replaceAll("%20"," "));
// Set the text
cdi.setText(charVal);
// Make the text smoother
cdi.setTextAntialias(true);
// Annotate the draw info to make the character image
cmi.annotateImage(cdi);
// For debug purposes
finalStrWidth += charImgW;
/**
* Calculate the percentage of the circumference that the character
* will consume.
*/
percentage = charImgW / circumference;
/**
* Convert this percentage into something practical - degrees.
*/
degrees = 360 * percentage;
/**
* Calculate the x and y axis adjustments to make, based on the origin
* of the circle, so we can place each letter.
*/
x = radius * Math.sin(Math.toRadians(current_degree));
y = radius * Math.cos(Math.toRadians(current_degree));
// Rotate the character image to the angle
cmi = cmi.rotateImage(angle);
// Composite character image to main canvas image
bmi.compositeImage(CompositeOperator.HardLightCompositeOp, cmi, (int)Math.round((origin_x+x)), (int)Math.round((origin_y-y)));
// Increment the degrees
current_degree += degrees;
}
bmi = bmi.trimImage();
byte[] pi = bmi.imageToBlob(ci);
return pi;
} catch (MagickException e) {
e.printStackTrace();
return null;
}
}
private FontMetrics createFontMetrics(Font font)
{
BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics g = bi.getGraphics();
FontMetrics fm = g.getFontMetrics(font);
g.dispose();
bi = null;
return fm;
}
private Rectangle2D createFontRectangle(Font font, String strVal)
{
BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics g = bi.getGraphics();
FontMetrics fm = g.getFontMetrics(font);
Rectangle2D rect = fm.getStringBounds(strVal, g);
g.dispose();
bi = null;
return rect;
}