GraphicsMagick++ draw text and auto-resize canvas - graphicsmagick

I am planning to generate an image with Magick (GraphicsMagick++) that have some text and I want the image canvas resized automatically based on the text drawn.
This is my code:
bool LoadText(const std::string& text, const std::string& fontface, int pointsize, Magick::Color color) {
image = Magick::Image( Magick::Geometry(1,1), Magick::Color("black"));
image.font(fontface);
image.fillColor(color);
image.strokeColor(color);
image.fontPointsize(pointsize);
image.read("CAPTION:" + text);
//image.annotate(text,CenterGravity);
return true;
}
With "annotate()" the canvas is not resized but the text color and background is right.
If I use "CAPTION:" protocol the canvas is resized but the fontcolor and background color is not respected.
What am I doing wrong?

You shouldn't have to allocated a blank image when reading from the caption protocol, but set the background color directly.
using namespace Magick;
bool LoadTextCaption(const std::string& text,
const std::string& fontface,
int pointsize,
Magick::Color color)
{
Image image; // Allocated but not initialized.
image.font(fontface);
image.fillColor(color);
image.strokeColor(color);
image.fontPointsize(pointsize);
image.backgroundColor(Color("BLACK")); // <- Set background
image.read("CAPTION:" + text);
return true;
}
// ...
LoadTextCaption("Hello Caption!", "TimesNewRoman", 32, Color("RED"));

Related

How to make a progressbar with a icon?

I know how to set the width of the progressBar by renderer it in ios/android.But is there anyway to add a image in the progressbar?
I have set its height.
protected override void OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
{
base.OnElementChanged(e);
Control.ScaleY = 20;
}
and in ios:
public override void LayoutSubviews()
{
base.LayoutSubviews();
var x = 1.0f;
var y = 20.0f;
CGAffineTransform transform = CGAffineTransform.MakeScale(x, y);
Control.Transform = transform;
}
but I wonder if there is anyway to add an icon?
this is my goal to achive:
progressBar
it is a 98 percent progressBar with a star in the end of the progress value.I've no idea to achive it
Maybe it's too late to reply now
Have you try to use Slider and use CustomRender to custom the style of SeekBar,it has the
android:thumb="#drawable/seekbarthumb" attribute,set your star icon to the thumb more easily
at last I use relativelayout to fix the postion of the image. as #Skin says.

NullPointerException when trying to use ImageView

I grabbed the following code from another site - I can't find a problem with it but it keeps giving me a nullpointerexception. The issue I think is right in the first part before the setContentView but including the whole thing just in case. Thanks in advance for the help!
public class TileSet extends Activity {
Bitmap originalImage = BitmapFactory.decodeResource(getResources(),
R.drawable.announcementbc);
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//Create an Image view and add our bitmap with reflection to it
imageView.setImageBitmap(getRefelection(originalImage));
//imageView.setImageBitmap(image);
//Add the image to a linear layout and display it
LinearLayout linLayout = new LinearLayout(this);
linLayout.addView(imageView, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// set LinearLayout as ContentView
setContentView(linLayout);
}
// public static Bitmap getRefelection(Bitmap image)
public static Bitmap getRefelection(Bitmap image)
{
//The gap we want between the reflection and the original image
final int reflectionGap = 4;
//Get you bit map from drawable folder
Bitmap originalImage = image;
int width = originalImage.getWidth();
int height = originalImage.getHeight();
//This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
//Create a Bitmap with the flip matix applied to it.
//We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);
//Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width
, (height + height/2), Config.ARGB_8888);
//Create a new Canvas with the bitmap that's big enough for
//the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
//Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
//Draw in the reflection
canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
//Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
//Set the paint to use this shader (linear gradient)
paint.setShader(shader);
//Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
//Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
reflectionImage.recycle();
return bitmapWithReflection;
}
}
imageView.setImageBitmap(getRefelection(originalImage));
This is the line it is crashing on, and the reason is that imageView is null.
When you create a member variable such as the one you listed, you need to either create an object for it to point to, or set it to an already-created object.
In your case, I'm guessing you want to set it to one already created by your layout. Your layout XML should have some ImageView declared, but in order to get it in the Java code, you'll need to call findViewById()
If your XML is declared like this, with an id:
<ImageView
android:id="#+id/my_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Then you'll need to write the following before you can call setImageBitmap():
imageView = (ImageView) findViewById(R.id.my_image_view);
Additionally, you cannot make the findViewById call until after you make the call to setContentView(), because that's the call that actually creates your ImageView.
Although, looking at your code a bit further, you probably don't need to do the reflection bit, or even the setImageBitmap() call, because you can specify the drawable directly in the XML (unless you want to change it when the program is running):
<ImageView
android:id="#+id/my_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/announcementbc"
/>
By adding the source line, and pointing it to your drawable, the setContentView call will automatically set the correct Bitmap on the ImageView.
Here is the latest failed code as per the comment above
public class Tile2 extends Activity{
// Bitmap originalImage = BitmapFactory.decodeResource(getResources(), R.drawable.announcementbc);
ImageView imageView;
Bitmap originalImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView (R.layout.tile);
imageView = (ImageView) findViewById(R.id.ivTile);
originalImage = BitmapFactory.decodeResource(getResources(), R.drawable.announcementbc);
// ImageView imageView = new ImageView(this);
imageView.setImageBitmap(getReflection(originalImage));
//Add the image to a linear layout and display it
LinearLayout linLayout = new LinearLayout(this);
linLayout.addView(imageView, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// set LinearLayout as ContentView
setContentView(linLayout);
}
public static Bitmap getReflection(Bitmap image)
{
//The gap we want between the reflection and the original image
final int reflectionGap = 4;
//Get you bit map from drawable folder
Bitmap originalImage = image;
int width = originalImage.getWidth();
int height = originalImage.getHeight();
//This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
//Create a Bitmap with the flip matix applied to it.
//We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);
//Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width
, (height + height/2), Config.ARGB_8888);
//Create a new Canvas with the bitmap that's big enough for
//the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
//Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
//Draw in the reflection
canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
//Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
//Set the paint to use this shader (linear gradient)
paint.setShader(shader);
//Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
//Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
reflectionImage.recycle();
return bitmapWithReflection;
}
}

Custom button field blackberry: onfocus, onUnfocus

I want to change the colors of background button and the color of text onfocus
How can I make it?
class RoundedRectField extends Field {
// Layout values
private static final int CURVE_X = 12; // X-axis inset of curve
private static final int CURVE_Y = 12; // Y-axis inset of curve
private static final int MARGIN = 2; // Space within component boundary
// Static colors
private static final int TEXT_COLOR = 0xFFFFFF; // White
private static final int BORDER_COLOR = 0xFF8000; // dark gray
private static final int BACKGROUND_COLOR = 0xFFFFFF; // White
private static final int TEXT_COLOR_selected = 0xFF6DB6;
private static final int BORDER_COLOR_selected = 0xFF8000;
private static final int BACKGROUND_COLOR_selected = 0xCCCCCC;
boolean _focus = false;
private static String text_button;
// Point types array for rounded rectangle. Each point type
// corresponds to one of the colors in the colors array. The
// space marks the division between points on the top half of
// the rectangle and those on the bottom.
private static final byte[] PATH_POINT_TYPES = {
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT, Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT, Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT, };
// Colors array for rounded rectangle gradient. Each color corresponds
// to one of the points in the point types array. Top light, bottom black.
private static final int[] PATH_GRADIENT = { 0xFF8000, 0xFF8000, 0xFF8000,
0xFF8000, 0xFF8000, 0xFF8000,
0xFC0500, 0xFC0500, 0xFC0500, 0xFC0500, 0xFC0500, 0xFC0500 };
// Center our readonly field in the space we're given.
public RoundedRectField(String text_button) {
super(FIELD_HCENTER | FIELD_VCENTER | READONLY);
this.text_button = text_button;
}
// This field in this demo has a fixed height.
public int getPreferredHeight() {
return 70;
}
// This field in this demo has a fixed width.
public int getPreferredWidth() {
return 240;
}
// When layout is requested, return our height and width.
protected void layout(int width, int height) {
setExtent(getPreferredWidth(), getPreferredHeight());
}
// When painting is requested, do it ourselves.
protected void paint(Graphics g) {
// Clear this area to white background, fully opaque.
g.clear();
g.setGlobalAlpha(255);
g.setBackgroundColor(BACKGROUND_COLOR);
// Drawing within our margin.
int width = getPreferredWidth() - (MARGIN * 2);
int height = getPreferredHeight() - (MARGIN * 2);
// Compute paths for the rounded rectangle. The 1st point (0) is on
// the left
// side, right where the curve in the top left corner starts. So the
// top left
// corner is point 1. These points correspond to our static arrays.
int[] xPts = { 0, 0, CURVE_X, width - CURVE_X, width, width, width,
width, width - CURVE_X, CURVE_X, 0, 0 };
int[] yPts = { CURVE_Y, 0, 0, 0, 0, CURVE_Y, height - CURVE_Y,
height, height, height, height, height - CURVE_Y };
// Draw the gradient fill.
g.drawShadedFilledPath(xPts, yPts, PATH_POINT_TYPES, PATH_GRADIENT,
null);
// Draw a rounded rectangle for the outline.
// I think that drawRoundRect looks better than drawPathOutline.
g.setColor(BORDER_COLOR);
g.drawRoundRect(0, 0, width, height, CURVE_X * 2, CURVE_Y * 2);
// Place some text in the center.
Font font = Font.getDefault().derive(Font.PLAIN, 9, Ui.UNITS_pt);
int textWidth = font.getAdvance(text_button);
int textHeight = font.getHeight();
g.setColor(TEXT_COLOR);
g.setFont(font);
g.drawText(text_button, (width / 2) - (textWidth / 2) - MARGIN,
(height / 2) - (textHeight / 2) - MARGIN);
}
protected void onFocus(int direction) {
_focus = true;
Dialog.alert("dcd");
invalidate();
super.onFocus(direction);
}
protected void onUnfocus() {
_focus = false;
invalidate();
super.onUnfocus();
}
}
You can do it several ways. One popular way is to provide custom focus drawing in the paint() method, which you already override.
You should be able to do this (I'm assuming you declared the _selected colors for the focused state):
if (isFocus()) {
g.setBackgroundColor(BACKGROUND_COLOR_selected);
else {
g.setBackgroundColor(BACKGROUND_COLOR);
}
...
if (isFocus()) {
g.setColor(TEXT_COLOR_selected);
} else {
g.setColor(TEXT_COLOR);
}
Those lines go in paint(), right where you are currently calling g.setBackgroundColor and g.setColor(TEXT_COLOR).
Then, you would override drawFocus() and do nothing, since your focus drawing is handled in paint():
protected void drawFocus(Graphics graphics, boolean on) {
// override superclass implementation and do nothing
}
Finally, you need to make your Field focusable, in order to ever receive focus. You can do so like this:
public RoundedRectField(String text_button) {
super(FIELD_HCENTER | FIELD_VCENTER | FOCUSABLE);
this.text_button = text_button;
}
If you need the field to be dynamically focusable (sometimes focusable, or sometimes not focusable), then you could implement this method:
public boolean isFocusable() {
But, if the field is always focusable, then using the FOCUSABLE flag in your constructor will work. I tested this out, and I saw the text color change with focus (on a OS 5.0 9550).

How can I draw a circle to the screen with PlayN?

This is about as basic as it gets. I don't want to use an image file. Rather, I want to programmatically draw a circle and blit it to a surface (as they say in pygame).
I tried to follow the "Using CanvasLayers" example here:
https://developers.google.com/playn/devguide/rendering
From my game class:
// Surface
SurfaceLayer surface;
// Background
int width = 640;
int height = 480;
//ImageLayer bgLayer;
CanvasImage bgImage;
Canvas canvas;
// Circle
CanvasImage circleImage;
//ImageLayer circleLayer;
int circleRadius = 20;
int circleX = 0;
int circleY = 0;
#Override
public void init() {
// create a surface
surface = graphics().createSurfaceLayer(width, height);
graphics().rootLayer().add(surface);
// create a solid background
// http://code.google.com/p/playn101/source/browse/core/src/main/java/playn101/core/J.java#81
bgImage = graphics().createImage(width, height);
canvas = bgImage.canvas();
canvas.setFillColor(0xff87ceeb);
canvas.fillRect(0, 0, width, height);
//bgLayer = graphics().createImageLayer(bgImage);
//graphics().rootLayer().add(bgLayer);
// create a circle
circleImage = graphics().createImage(circleRadius, circleRadius);
canvas = circleImage.canvas();
canvas.setFillColor(0xff0000eb);
canvas.fillCircle(circleX, circleY, circleRadius);
//circleLayer = graphics().createImageLayer(circleImage);
//graphics().rootLayer().add(circleLayer);
}
#Override
public void paint(float alpha) {
// the background automatically paints itself, so no need to do anything
// here!
surface.clear(0);
surface.drawImage(bgImage, 0, 0);
surface.drawImage(circleImage, 100, 100);
}
But I get a blank window in Java and Eclipse complains:
The method drawImage(CanvasImage, int, int) is undefined for the type
SurfaceLayer
That, however, is the way it is used in the example at the link.
If the code you provided even compiles, then you are using some very old version of PlayN.
Update to PlayN 1.1.1 and fix the compilation errors that result, and your code will work fine.
The following is your code updated to work with PlayN 1.1.1:
private SurfaceLayer surface;
private CanvasImage bgImage;
private CanvasImage circleImage;
#Override
public void init() {
// create a surface
int width = graphics().width(), height = graphics().height();
surface = graphics().createSurfaceLayer(width, height);
graphics().rootLayer().add(surface);
// create a solid background
bgImage = graphics().createImage(width, height);
Canvas canvas = bgImage.canvas();
canvas.setFillColor(0xff87ceeb);
canvas.fillRect(0, 0, width, height);
// create a circle
int circleRadius = 20;
int circleX = 0;
int circleY = 0;
circleImage = graphics().createImage(circleRadius, circleRadius);
canvas = circleImage.canvas();
canvas.setFillColor(0xff0000eb);
canvas.fillCircle(circleX, circleY, circleRadius);
}
#Override
public void paint(float alpha) {
Surface s = surface.surface();
s.clear();
s.drawImage(bgImage, 0, 0);
s.drawImage(circleImage, 100, 100);
}
If you really intend to make a game using this approach, you should use ImmediateLayer not SurfaceLayer. ImmediateLayer will issue your drawImage, etc. calls directly against the framebuffer. SurfaceLayer will make an off-screen framebuffer and render everything into that and then copy that off-screen framebuffer to the main framebuffer every frame (in addition to the double buffering naturally performed by OpenGL, etc.), resulting in a needless copy of your entire screen.
Your code looks fine to me...
set the canvasTransform,
canvas.setTransform(1, 0, 0, 1, 0, 0);
and please for testing purposes make the bg bigger
graphics().createImage(circleRadius, circleRadius); (400,400)

Qt painted content goes lost

I am writing an info-screen program. I created a full-screen widget and draw contents onto it.
In order to extend the life cycle of the TFT-display device, I want to implement a pixel-shifting feature. With other words, in every X minutes, I shift the screen to left/right/top/down for Y pixels.
My approach is as follows:
I use two layers (two QWidget).
I paint contents on the top layer.
When a pixel-shifting is performed, I just move the top layer for specified offset.
And then fill a background color to the bottom layer.
However, I found a problem:
If I move up the top layer for 10 pixels, the 10-pixel-content goes out of the screen. But when I move this layer down for 10 pixels. The 10-pixel-content will not be updated, it is gone.
How can I keep these 10-pixel-content? Is there any magic widget flag to solve this problem?
UPDATE 1:
The code is written in language D, but it is easy to understand:
class Canvas: QWidget
{
private QPixmap content;
this(QWidget parent)
{
super(parent);
setAttribute(Qt.WA_OpaquePaintEvent, true);
}
public void requestForPaint(QPixmap content, QRegion region)
{
this.content = content;
update(region);
}
protected override void paintEvent(QPaintEvent event)
{
if (this.content !is null)
{
QPainter painter = new QPainter(this);
painter.setClipping(event.region);
painter.fillRect(event.region.boundingRect, new QColor(0, 0, 0));
painter.drawPixmap(event.region.rect, this.content);
this.content = null;
painter.setClipping(false);
}
}
}
class Screen: QWidget
{
private Canvas canvas;
this()
{
super(); // Top-Level widget
setAutoFillBackground(True);
this.canvas = new Canvas(this);
showFullScreen();
}
public void requestForPaint(QPixmap content, QRegion region)
{
this.canvas.requestForPaint(content, region);
}
private updateBackgroundColor(QColor backgroundColor)
{
QPalette newPalette = palette();
newPalette.setColor(backgroundRole(), backgroundColor);
setPalette(newPalette);
}
public shiftPixels(int dx, int dy)
{
this.canvas.move(dx, dy);
updateBackgroundColor(new QColor(0, 0, 0)); // Just a demo background color
}
}
Screen screen = new Screen;
screen.requestForPaint(some_content, some_region);
screen.shiftPixels(0, -10);
screen.shiftPixels(0, 10);
Looking at the code, my first guess is that your region might be wrong. Try repainting the whole widget each time, and see if that solves the missing 10 pixel problem. If it does, then try working out why your region isn't covering the newly exposed portion.
One possibility along those lines: I notice in your Screen::requestForPaint method that you directly call the Canvas::requestForPaint without doing anything with the region. In Qt, the coordinates for anything like that are often assumed to be local, so if you don't account for the current position of the canvas widget, you might get an incorrect region.
Why not setting the position of the widget directly...? Another options might be using QPainter::translate(-1,-1) or something similar.

Resources