Font to Image in SWT - java

I want to draw single character with specified Font and transparent background to an SWT Image, later save it to file. I do it like this:
FontData fontData; // info about the font
char ch = 'a'; // character to draw
Display display = Display.getDefault();
TextLayout textLayout = new TextLayout(display);
textLayout.setAlignment(SWT.CENTER);
textLayout.setFont(font);
textLayout.setText("" + ch);
Rectangle r = textLayout.getBounds();
Image img = new Image(display, r.width, r.height);
GC gc = new GC(img);
textLayout.draw(gc, 0, 0);
The character is drawn but it gets white background.
I tried to solve it by setting transparentPixel to white color, this makes background transparent but character looks ugly.
I also tried to set alphaData of the Image with 0's (fully transparent) before drawing anything on it, but alphaData doesn't update after drawing anything on the Image, it stays transparent all the time.
How to draw character with transparent background on the Image?

Have u tried drawing to BufferedImage with TYPE_INT_ARGB?
Image fontImage= new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = fontImage.createGraphics();
//here u write ur code with g2d Graphics
g2d.drawImage(fontImage, 0, 0, null);
g2d.dispose();

You have to use an intermediary ImageData to enable transparency
TextLayout textLayout = new TextLayout(font.getDevice());
textLayout.setText(s);
textLayout.setFont(font);
Rectangle bounds = textLayout.getBounds();
PaletteData palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
ImageData imageData = new ImageData(bounds.width, bounds.height, 32, palette);
imageData.transparentPixel = palette.getPixel(font.getDevice().getSystemColor(SWT.COLOR_TRANSPARENT).getRGB());
for (int column = 0; column < imageData.width; column++) {
for (int line = 0; line < imageData.height; line++) {
imageData.setPixel(column, line, imageData.transparentPixel);
}
}
Image image = new Image(font.getDevice(), imageData);
GC gc = new GC(image);
textLayout.draw(gc, 0, 0);
return image;

Related

Java change background color png image

I have been following some StackOverflow links using Graphics2D to change the background color of a BufferedImage.
The project I am working on requires that I read in a png image from a given url; the png image retrieved has a transparent background, and I would like to set it to white.
Here is what I have:
String u = this.format() ;
BufferedImage image = null ;
try{
URL url = new URL(u) ;
image = ImageIO.read(url) ;
Graphics2D graphics = image.createGraphics() ;
graphics.setBackground(Color.WHITE) ;
graphics.clearRect(0, 0, image.getWidth(), image.getHeight()) ;
ImageIO.write(image, "png", new File(outPath + fileName)) ;
graphics.dispose() ;
}
catch(IOException e){
e.printStackTrace() ;
}
The problem I am running into is that when I view the image, the image appears as a solid white box. Apparently I have overlaid a white background on top of the existing image that I retrieved.
How can I preserve the original image and only change the background? Or set the background first and then overlay the retrieved image?
1- Load your image
image = ImageIO.read(url) ;
2- Create a new BufferedImage of the same size
BufferedImage background = new BufferedImage(image.getWidth(), image.getHeight, BufferedImage.TYPE_INT_RGB);
3- Fill the background image with the desired color
Graphics2D g2d = background.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, background.getWidth(), background.getHeight());
4- Draw the original image onto the background...
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
background is now filled with the desired color and has the image painted on top o it.

ColorFilter only specific color

A short question regarding the ColorFilter() function; I am trying to replace an specific color of an Image with an new color:
Default:
result:
So in this example I just want to replace the red color with the blue color. But don't modify the black color of this image.
At the moment Iam using the following code:
int color = Color.parseColor("#0000FF");
iv1.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
From the description of the "PorterDuff" Mode I should use "SRV_ATOP". But how should I use this mode so that only the red color will be replaced?
I've now found a way which works perfectly. So for everyone who faces the same probleme...here is the code which works for me:
//Decode *.png file to Bitmap
Bitmap Bitmap_temp = BitmapFactory.decodeResource(getResources(), R.drawable.image_1);
Bitmap Bitmap_final = Bitmap_temp.copy(android.graphics.Bitmap.Config.ARGB_8888, true);
//Get Pixel and change color if pixel color match
int [] allpixels = new int [Bitmap_final.getHeight() * Bitmap_final.getWidth()];
Bitmap_final.getPixels(allpixels, 0, Bitmap_final.getWidth(), 0, 0, Bitmap_final.getWidth(), Bitmap_final.getHeight());
for(int i = 0; i < allpixels.length; i++)
{
if(allpixels[i] == Color.parseColor("#fff000"))
{
allpixels[i] = Color.parseColor("#0D0D0D");
}
}
Bitmap_final.setPixels(allpixels,0,Bitmap_final.getWidth(),0, 0, Bitmap_final.getWidth(),Bitmap_final.getHeight());
//Set Bitmap to ImageView
iv_image1.setImageBitmap(Bitmap_final);

Generate thumbnail and fill empty space with color

Is it possible to implement the first example with Scalr?
My code is the following:
BufferedImage thumbnail = Scalr.resize(ImageIO.read(sourceFile), Scalr.Method.ULTRA_QUALITY, Scalr.Mode.FIT_TO_WIDTH,
width, height, Scalr.OP_ANTIALIAS);
ImageIO.write(thumbnail, destinationfile.getExtension(), destinationfile);
What I want is to receive the image like this:
where the blue bars are the space I want to fill with the color.
Thank you
Update: maybe it is possible to implement with Thumbnailator?
Just done! Perhaps it can help you!
public static BufferedImage resizeAndCrop(BufferedImage bufferedImage) throws IOException {
int himg = bufferedImage.getHeight();
int wimg = bufferedImage.getWidth();
double rateh = himg/dim;
double ratew = wimg/dim;
double rate = ratew;
if(rateh>ratew)
rate = rateh;
int dimhimg = (int) (himg/rate);
int dimwimg = (int) (wimg/rate);
double startw = dim/2 - dimwimg/2;
double starth = dim/2 - dimhimg/2;
BufferedImage tThumbImage = new BufferedImage( dim, dim, BufferedImage.TYPE_INT_RGB );
Graphics2D tGraphics2D = tThumbImage.createGraphics(); //create a graphics object to paint to
tGraphics2D.setBackground( Color.WHITE );
tGraphics2D.setPaint( Color.WHITE );
tGraphics2D.fillRect( 0, 0, dim, dim );
tGraphics2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
tGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
tGraphics2D.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
tGraphics2D.drawImage( bufferedImage, (int)startw, (int)starth, dimwimg, dimhimg, null ); //draw the image scaled
File ff = new File(path + "jdata/tmp/prova.jpg");
ImageIO.write( tThumbImage, "JPG", ff); //write the image to a file
BufferedImage croppedContainMethod = ImageIO.read(ff);
return croppedContainMethod;
}
Nobody has idea so I will publish my solution...
I decided to continue to use Scalr (I didn't checked the Thumbnailator's last version but the previous ones failed on big pictures).
So first of all I call resize method, and then, if sizes of the new thumbnail are bigger then given ones I call crop method that crops a thumbnail by the center.. The code is the following:
BufferedImage thumbnail = Scalr.resize(sourceFile, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC, destinationSize.width, destinationSize.height);
if (thumbnail.getWidth() > destinationSize.width)
thumbnail = Scalr.crop(thumbnail, (thumbnail.getWidth() - destinationSize.width) / 2, 0, destinationSize.width, destinationSize.height);
else if (thumbnail.getHeight() > destinationSize.height)
thumbnail = Scalr.crop(thumbnail, 0, (thumbnail.getHeight() - destinationSize.height) / 2, destinationSize.width, destinationSize.height);
It is not ideal, but at least it handles 'wide' images after generation of thumbnails

Drawing two overlayed images

I'm trying to draw 2 images, one on top of the other. The 1'st image is an arrow (that should appear like a header in the final image). The 1'st image (arrow) is 32x32 px while the 2'nd is 24x24.
Ideally I would like to draw the 2'nd image on top of the 1'st, starting from the right-bottom corner of the 1'st image.
Currently I'm using such code
// load source images
BufferedImage baseImage = ImageIO.read(new File(baseImg.getFileLocation()));
BufferedImage backgroundImage = ImageIO.read(new File(backgroundImg.getFileLocation()));
// create the new image, canvas size is the max. of both image sizes
int w = Math.max(baseImage.getWidth(), backgroundImage.getWidth());
int h = Math.max(baseImage.getHeight(), backgroundImage.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(baseImage, 0, 0, null);
g.drawImage(backgroundImage, 0, 0, null);
int index = baseImg.getFileLocation().lastIndexOf(".png");
String newFileName = baseImg.getFileLocation().substring(0, index);
// Save as new image
ImageIO.write(combined, "PNG", new File(newFileName + "_combined.png"));
but this won't quite work for me because the end result is a 32x32 image with the 2nd image being drawn only.
Any help is appreciated.
Thanks !
It looks like the issue here is you are drawing the 32x32 background image last, meaning it will be printed on top of the other image making it seem as if the 24x24 image was never drawn at all.
If you swap these two lines around, you should see both images. From:
g.drawImage(baseImage, 0, 0, null);
g.drawImage(backgroundImage, 0, 0, null);
to:
g.drawImage(backgroundImage, 0, 0, null);
g.drawImage(baseImage, 0, 0, null);
However this will draw the 24x24 image in the top-left corner, and you said you'd like it in the bottom-right. This can be done with some basic subtraction:
g.drawImage(baseImage, w - baseImage.getWidth(), h - baseImage.getHeight(), null);

Background is black when rotating an image

I'm trying to rotate an image using this code:
File imgPath = new File("c:\\tmp\\7.jpg");
BufferedImage src = ImageIO.read(imgPath);
AffineTransform tx = new AffineTransform();
int width = src.getWidth();
int height = src.getHeight();
tx.rotate(radiant ,width, height);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
BufferedImage out = op.filter(src, null);
File outFile = new File("c:\\tmp\\out.jpg");
ImageIO.write(out, "jpg", outFile);
For some reason the background after the rotation is black.
How can make the background white or transparent?
When you are using AffineTransformOp.filter(src, null) for creating new images, the new image uses the same ColorModel as the source image.
Your input image is a jpeg, which means it is not transparent, so the destination image is an RGB image, without the alpha (transparency) level.
When rotated with such a small angle, the image no longer occupies exactly the same bounds, so the background is visible in its edges and because there is no alpha level, it is normal that the background is black.
However, if you save it to a format that supports transparency like gif or png, your image will not display the black background anymore.
ImageIO.write(out, "gif", outFile);
The full code:
try {
File imgPath = new File("d:\\downloads\\about.jpg");
BufferedImage src = ImageIO.read(imgPath);
AffineTransform tx = new AffineTransform();
int width = src.getWidth();
int height = src.getHeight();
tx.rotate(0.02050493823247637, width, height);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
BufferedImage out = op.filter(src, null);
File outFile = new File("d:\\downloads\\about0.gif");
ImageIO.write(out, "gif", outFile);
} catch (Exception e) {
e.printStackTrace();
}
Take a look at this for even more information and tricks.
Here is my image after rotation to gif:

Categories

Resources