Frequency distribution of an array - java

Hi I am trying to get the frequency of an array for text font sizes and colors, when I have string of words and I count the frequency I want to change the size of the word and color according to their overall value in size, I have tried to divide the frequency/average *10 but gives me null, but on my calculator it gives me ie, 80/100 *10 = 8, this would the take an index of 8 and have 180 font size
can anyone help me with this?
private static int[] fontWeight = { 40, 60, 80, 100, 120, 140, 160,180 };
private static Color[] Colors = { Color.blue, Color.cyan, Color.yellow, Color.green, Color.red,
Color.orange, Color.pink,Color.pink };
//main
for (String str: wordList) {
int wordFreq = randWord.getFrequency();//assume 80 comes here
int fontSize = getFontSize(wordFreq);
Font font = new Font(Font.SANS_SERIF, Font.ITALIC, fontWeight [fontSize ]);
graphics.setFont(font);
graphics.setColor(Colors[fontSize]);
FontMetrics fm = graphics.getFontMetrics();
graphics.drawString(randWord.getWord() + "", x, y);
}
//method
private static int getFontSize(int freq) {
int newFont = (int) (freq/100)*10;
if (newFont >= 5) newFont = 6;
// if(newFont<2)
// newFont = 1;
System.out.println("freq " + freq + " font index" + newFont + " font size "
+ fontWeight[newFont]);
return newFont;
}
Thanks for your help

Integer division behaves differently, if numerator is smaller than denominator the result is 0. for example 80/100 returns 0. what you would do is multiply numerator with that 10 and then divide it.
int newFont = (int) (freq/100)*10;
should change to
int newFont = (int) (freq*10 / 100);

Related

java android random colors

I want my code to automatically pick random colors... at the moment I have it static... I want it when it changes color, just randomly pick any color in the world of RGB...
the below is what I have, any kind of help I can get on this is greatly appreciated!
private float[][] BackgroundColors = { { 141, 189, 193 }, { 116, 84, 62 },
{ 73, 113, 116 }, { 193, 163, 141 }, { 15, 11, 6 }, };
private void getCurrentColor() {
CurrentColorNumber++;
if (CurrentColorNumber >= 5) {
CurrentColorNumber = 0;
}
CurrentColor = new Color(
BackgroundColors[CurrentColorNumber][0] / 255.0f,
BackgroundColors[CurrentColorNumber][1] / 255.0f,
BackgroundColors[CurrentColorNumber][2] / 255.0f, 1);
}
Suppose I have a text view and I want a random color for the text
on every button click.
Just check this code on your program.
I hope this logic helps you.
TextView Display = (TextView) findViewById(R.id.tvresult);
Random mRandom = new Random();
Display.setText("WHAT????");
Display.setTextSize(mRandom.nextInt(75));
Display.setTextColor(Color.rgb(mRandom.nextInt(265),
mRandom.nextInt(265), mRandom.nextInt(265)));
you could use Random to peek four numbers between 0 and 255, and then use Color.argb to return the correspondent color. E.g.
private Random mRandom = new Random();
private int randomColor() {
int r = mRandom.nextInt(256);
int g = mRandom.nextInt(256);
int a = mRandom.nextInt(256);
int b = mRandom.nextInt(256);
return Color.argb(a, r, g, b);
}
you don't need the alpha channel you can either set a = 255, or using
Color.rgb(r, g, b) instead of Color.argb. Thanks to #maraca that made me notice it
You can that with Random class:
Random r = new Random();
BackgroundColors[r.nextInt(BackgroundColors.length)];

Floyd-Steinberg algorithm implementation in Java

I'm trying to implement Floyd Steinberg algorithm in Java, working with java.awt.image.BufferedImage.
I've used the algorithm described here
with a custom palette, and I was expecting to get more or less the same image as in the wikipedia example (or as generated by Gimp for example), but I get a very different version.
You can see what I get
I'm obviously missing something (output image has color which doesn't belong to my palette), but I can't figure out what.
What I'm doing wrong ?
Here's the code :
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
import java.io.IOException;
public class FloydSteinbergTest {
private static final Color[] PALETTE = new Color[]{
new Color(221, 221, 221),
new Color(19, 125, 62),
new Color(179, 80, 188),
new Color(107, 138, 201),
new Color(177, 166, 39),
new Color(65, 174, 56),
new Color(208, 132, 153),
new Color(64, 64, 64),
new Color(154, 161, 161),
new Color(46, 110, 137),
new Color(126, 61, 181),
new Color(46, 56, 141),
new Color(79, 50, 31),
new Color(53, 70, 27),
new Color(150, 52, 48),
new Color(25, 22, 22)};
public static void main(String[] args) {
String lImgFile = "/tmp/test.jpg";
try {
// Load image
BufferedImage lImage = ImageIO.read(new File(lImgFile));
BufferedImage lOutImage = applyDitheredPalette(lImage, PALETTE);
ImageIO.write(lOutImage, "png", new File("/tmp/out.png"));
} catch (IOException lEx) {
System.out.println(lEx.getMessage());
}
}
/**
* #param pPalette Color palette to apply.
* #param pImage Image to apply palette on.
* #return {#link java.awt.image.BufferedImage} corresponding to pPalette applied on pImage using naive Floyd-Steinberg implementation
*/
public static BufferedImage applyDitheredPalette(BufferedImage pImage, Color[] pPalette) {
int lWidth = pImage.getWidth();
int lHeight = pImage.getHeight();
IndexColorModel lColorModel = paletteToColorModel(pPalette);
BufferedImage lImageOut = new BufferedImage(lWidth, lHeight, BufferedImage.TYPE_BYTE_INDEXED, lColorModel);
for (int y = (lHeight - 1); y >= 0; y--) {
for (int x = 0; x < lWidth; x++) {
// Get original pixel color channels
int lInitialPixelColor = pImage.getRGB(x, y);
// Finding nearest color in the palette
Color lNearestColor = getNearestColor(lInitialPixelColor, pPalette);
// Set quantized pixel
lImageOut.setRGB(x, y, lNearestColor.getRGB());
// Applying Floyd-Steinberg dithering
int quantizationError = lInitialPixelColor - lNearestColor.getRGB();
if ((x + 1) < lWidth) {
int lPixel = pImage.getRGB(x + 1, y);
lImageOut.setRGB(x + 1, y, lPixel + (quantizationError * (7 / 16)));
}
if ((x - 1) > 0 && (y + 1) < lHeight) {
int lPixel = pImage.getRGB(x - 1, y + 1);
lImageOut.setRGB(x - 1, y + 1, lPixel + (quantizationError * (3 / 16)));
}
if ((y + 1) < lHeight) {
int lPixel = pImage.getRGB(x, y + 1);
lImageOut.setRGB(x, y + 1, lPixel + (quantizationError * (5 / 16)));
}
if ((x + 1 < lWidth) && (y + 1 < lHeight)) {
int lPixel = pImage.getRGB(x + 1, y + 1);
lImageOut.setRGB(x + 1, y + 1, lPixel + (quantizationError * (1 / 16)));
}
// End of Floyd-Steinberg dithering
}
}
return lImageOut;
}
/**
* #param pPalette to load color model from
* #return {#link java.awt.image.IndexColorModel} Color model initialized using pPalette colors
*/
private static IndexColorModel paletteToColorModel(Color[] pPalette) {
int lSize = pPalette.length;
// Getting color component for each palette color
byte[] lReds = new byte[lSize];
byte[] lGreens = new byte[lSize];
byte[] lBlues = new byte[lSize];
for (int i = 0; i < lSize; i++) {
Color lColor = pPalette[i];
lReds[i] = (byte) lColor.getRed();
lGreens[i] = (byte) lColor.getGreen();
lBlues[i] = (byte) lColor.getBlue();
}
return new IndexColorModel(4, lSize, lReds, lGreens, lBlues);
}
/**
* #param pColor Color to approximate
* #param pPalette Color palette to use for quantization
* #return {#link java.awt.Color} nearest from pColor value took in pPalette
*/
private static Color getNearestColor(int pColor, Color[] pPalette) {
Color lNearestColor = null;
double lNearestDistance = Integer.MAX_VALUE;
double lTempDist;
for (Color lColor : pPalette) {
Color lRgb = new Color(pColor);
lTempDist = distance(lRgb.getRed(), lRgb.getGreen(), lRgb.getBlue(), lColor.getRed(), lColor.getGreen(), lColor.getBlue());
if (lTempDist < lNearestDistance) {
lNearestDistance = lTempDist;
lNearestColor = lColor;
}
}
return lNearestColor;
}
/**
* #return Distance between 2 pixels color channels.
*/
private static double distance(int pR1, int pG1, int pB1, int pR2, int pG2, int pB2) {
double lDist = Math.pow(pR1 - pR2, 2) + Math.pow(pG1 - pG2, 2) + Math.pow(pB1 - pB2, 2);
return Math.sqrt(lDist);
}}
This site is for questions, not for debugging. But as an attempt to at least answer the question "What I'm doing wrong?":
The term (7 / 16) will perform an integer division, and the result will be 0. Use (7.0 / 16.0) instead
You may not do arithmetic with RGB values! When you have an RGB value like 0x000000FF (blue) and you multiply it with 256, then the result will be 0x0000FF00 (green). The computations like lPixel + (quantizationError * (3.0 / 16.0) have to be done separately for the R, G and B channel
You're processing the image from the bottom to the top. Then distributing the error among the lower right pixels (as it is described on the wikipedia site) does not longer make sense. Change your loops from
for (int y = (lHeight - 1); y >= 0; y--)
to
for (int y = 0; y < lHeight; y++)
You can not store the quantization error directly in the pixels of BufferedImage, because the error may also be negative. The image can not handle this. (I also have doubts about your color model, but this is only a gut feeling)
The image that you described as the "expected result" contains colors that definitely are not contained in your palette.
Finally: Have a look at https://stackoverflow.com/a/5940260/3182664

How to calculate max fitting font size for Label?

I have a Canvas that contains a Label. I want to set font size of this label according to the Canvas size.
How we can do this?
EDIT: "contains" means, Canvas and Label bounds are same.
EDIT2: I have this for Swing, but I couldn't convert it to SWT;
Font labelFont = label.getFont();
String labelText = label.getText();
int stringWidth = label.getFontMetrics(labelFont).stringWidth(labelText);
int componentWidth = label.getWidth();
double widthRatio = (double)componentWidth / (double)stringWidth;
int newFontSize = (int)(labelFont.getSize() * widthRatio);
int componentHeight = label.getHeight();
int fontSizeToUse = Math.min(newFontSize, componentHeight);
EDIT3:
This is my font size calculator class for label
public class FitFontSize {
public static int Calculate(Label l) {
Point size = l.getSize();
FontData[] fontData = l.getFont().getFontData();
GC gc = new GC(l);
int stringWidth = gc.stringExtent(l.getText()).x;
double widthRatio = (double) size.x / (double) stringWidth;
int newFontSize = (int) (fontData[0].getHeight() * widthRatio);
int componentHeight = size.y;
System.out.println(newFontSize + " " + componentHeight);
return Math.min(newFontSize, componentHeight);
}
}
and this is my Label at the top of the window. I want its font size according the volume of Layer size.
Label l = new Label(shell, SWT.NONE);
l.setText("TITLE HERE");
l.setBounds(0,0,shell.getClientArea().width, (shell.getClientArea().height * 10 )/ 100);
l.setFont(new Font(display, "Tahoma", 16,SWT.BOLD));
l.setFont(new Font(display, "Tahoma", FitFontSize.Calculate(l),SWT.BOLD));
I have just ported the code above.
You can get the extent (length) of a String in SWT with the method GC.stringExtent(); and you need the Class FontData to get the font height and font width of the Label.
Label label = new Label(parent, SWT.BORDER);
label.setSize(50, 30);
label.setText("String");
// Get the label size and the font data
Point size = label.getSize();
FontData[] fontData = label.getFont().getFontData();
GC gc = new GC(label);
int stringWidth = gc.stringExtent(label.getText()).x;
// Note: In original answer was ...size.x + (double)..., must be / not +
double widthRatio = (double) size.x / (double) stringWidth;
int newFontSize = (int) (fontData[0].getHeight() * widthRatio);
int componentHeight = size.y;
int fontsizeToUse = Math.min(newFontSize, componentHeight);
// set the font
fontData[0].setHeight(fontsizeToUse);
label.setFont(new Font(Display.getCurrent(), fontData[0]));
gc.dispose();
Sources:
Stackoverflow: Change just the font size in SWT
Eclipse API: GC

trying to create an array of bufferedimages

I'm trying to create an array of bufferedimages that contain cropped images of a bigger image but I keep getting this error:
Exception in thread "main" java.awt.image.RasterFormatException: (y + height) is outside of Raster
at sun.awt.image.ByteInterleavedRaster.createWritableChild(ByteInterleavedRaster.java:1233)
at java.awt.image.BufferedImage.getSubimage(BufferedImage.java:1156)
at com.search.visual.ImageChunks.createImageArrays(ImageChunks.java:95)
at com.search.visual.ImageChunks.calculateChunks(ImageChunks.java:122)
at com.search.visual.ImageChunks.<init>(ImageChunks.java:59)
at com.search.visual.Driver.main(Driver.java:10)
This is the code I'm using:
private BufferedImage[][] createImageArrays()
{
BufferedImage[][] bitmapsArray = new BufferedImage[3][3];
//bitmap bmap = bitmapfactory.decoderesource(getresources(), image);
//bufferedimage bmapscaled = bufferedimage.createscaledbitmap(bmp, 240, 240, true);
//Image imageMap = scaledImage;
bitmapsArray[0][0] = bmp.getSubimage(0,0, 80, 80);
bitmapsArray[0][1] = bmp.getSubimage(80,0, 80, 80);
bitmapsArray[0][2] = bmp.getSubimage( 160, 0, 80, 80);
bitmapsArray[1][0] = bmp.getSubimage( 0, 80, 80, 80);
bitmapsArray[1][1] = bmp.getSubimage( 80, 80, 80, 80);
bitmapsArray[1][2] = bmp.getSubimage( 160, 80, 80, 80);
bitmapsArray[2][0] = bmp.getSubimage( 0, 160, 80, 80);
bitmapsArray[2][1] = bmp.getSubimage( 80, 160, 80, 80);
bitmapsArray[2][2] = bmp.getSubimage( 160, 160, 80, 80);
return bitmapsArray;
}
/*
* 1. split the complete image/bitmaps into several smaller images/bitmaps
* 2. calculate the average RGB for each of these smaller images/bitmaps
* 3. fill up the RGB[][] rgbList
*
*/
private void calculateChunks()
{
// 1. split the complete image/bitmaps into several smaller images/bitmaps
// this is a real con, as I've only implemented it as 3x3 of of 80x80
//BufferedImage[][] bmpList = createImageArrays();
// 2. calculate the average RGB for each of these smaller images/bitmaps
BufferedImage[][] bmpList = createImageArrays();
System.out.print(bmpList);
RGB rgb_temp = null;
BufferedImage bmp_temp = null;
int rgb = 0;
int red = 0;
int green = 0;
int blue = 0;
int running_total_red = 0;
int running_total_blue = 0;
int running_total_green = 0;
RGB temp_rgb = null;
for(int I=0; I < 3; I++)
for(int j=0; j < 3; j++)
{
bmp_temp = bmpList[I][j];
red = 0;
green = 0;
blue = 0;
for(int k=0; k < 80; k++)
for(int l=0; l < 80; l++)
{
temp_rgb = getPixelRGBvalues( bmp_temp.getRGB(k, l) );
/* rgb = bmp_temp.getPixel(k, l); //gets the values of the pixel at point k and l
red += (rgb & 0x00ff0000) >> 16; //stores only the red values of rgb to red
green += (rgb & 0x0000ff00) >> 8; //stores only the green values of rgb to green
blue += rgb & 0x000000ff; //stores only the blue values of rgb to blue
*/
running_total_red += temp_rgb.getR();
running_total_blue += temp_rgb.getB();
running_total_green += temp_rgb.getG();
}
// normalise these values
red = running_total_red/ (80*80);
green = running_total_green/ (80*80);
blue = running_total_blue/ (80*80);
// 3. fill up the RGB[][] rgbList
rgbList[I][j] = new RGB(red, green, blue);
}
}
Why does this keep happening?
Your source image is smaller then 240*240 pixels. The subimages you are trying to acquire are out of the original image.

Java (AWT): fitting text in a box

I have an application that extends a Frame. Then, it'll display a few lines of text using:
Font f = new Font("Arial", Font.PLAIN, 10);
g.setFont(f);
g.drawString("Test|great Yes ^.", x, y + 10);
Now what happens is that the text doesn't fit in the box around. E.g. I'm expecting the text to fit in [x,y]-[x+width, y+10] (don't care about the width) but it falls somewhat below the y+10 line. Now for most characters ('T', 'e', etc.) this fits but '|' and 'g' don't! They go below the y+10-line. It seems you can't use: draw at y + characterHeight. But what does work?
To see what I mean, here's some sample code:
import java.awt.*;
public class test extends Frame
{
public test()
{
/* retrieve max window size */
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
GraphicsConfiguration [] gc = gs[0].getConfigurations();
Rectangle r = gc[0].getBounds();
setSize(r.width, r.height);
setVisible(true);
}
public void paint(Graphics g)
{
final int windowWidth = getSize().width;
final int windowHeight = getSize().height;
g.setColor(Color.BLUE);
g.fillRect(0, 0, windowWidth, windowHeight);
g.setColor(Color.WHITE);
g.fillRect(0, 100, windowWidth, 110);
int textHeight = 100;
Font f = new Font("Arial", Font.PLAIN, textHeight);
g.setFont(f);
g.setColor(Color.BLACK);
g.drawString("Test|great Yes ^.", 10, 100 + textHeight);
}
public void guiLoop()
{
for(;;) { try { Thread.sleep(1000); } catch(Exception e) { } }
}
public static void main(String [] args)
{
new test().guiLoop();
}
}
I tried the following code as well:
public void paint(Graphics g)
{
final int windowWidth = getSize().width;
final int windowHeight = getSize().height;
g.setColor(Color.BLUE);
g.fillRect(0, 0, windowWidth, windowHeight);
g.setColor(Color.WHITE);
g.fillRect(0, 100, windowWidth, 110);
int textHeight = 100;
String str = "Test|great Yes ^.";
Font f = new Font("Arial", Font.PLAIN, textHeight);
Rectangle2D boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
f = f.deriveFont((float)(textHeight * (textHeight / boundingRectangle.getHeight())));
boundingRectangle = f.getStringBounds(str, 0, str.length(), new FontRenderContext(null, false, false));
g.drawString(str, 10, 100 + (int)boundingRectangle.getHeight());
g.setFont(f);
g.setColor(Color.BLACK);
g.drawString(str, 10, 100 + textHeight);
}
This is somewhat better: the text is smaller so it might fit, but there's still the problem that the y-position is incorrect.
All help is appreciated!
What about using FontMetrics? You can obtain it from Graphics object with g.getFontMetrics().
Than you can retrieve max descent or ascent or directly height (using getHeight), so your implementation will be font-indipendent and it should work fine.. check documentation here!
EDIT (to explain comments):
there is no a direct way to tell to a string to draw itself in a manner that can fit a box. You have to do it by yourself.. like start from a max font size and check if width fits the box, otherwise decrement size and try again. For height you should FIRST decide (or obtain) max font height, then you can set how many pixel should the box be.
I think I solved it somewhat:
boundingBoxHeight: height of box in which the text should fit
yOffset where to start drawing the font
Font f = new Font("Arial", Font.PLAIN, boundingBoxHeight);
g.setFont(f);
FontMetrics fm = g.getFontMetrics();
double shrink = ((double)textHeight / (double)fm.getHeight());
double newSize = (double)textHeight * shrink;
double newAsc = (double)fm.getAscent() * shrink;
int yOffset = (int)newAsc - fm.getLeading();
f = f.deriveFont((float)newSize);
g.setFont(f);
g.drawString(str, 10, 100 + yOffset);
There's quite a bit of whitespace above the text though.

Categories