Re: Change decimal color code on the fly
On 11/16/2012 3:23 PM, Bob wrote:
[...]
There might quite a few "oops"
as this is a work in progress.
Okay. Just a few comments; take 'em or leave 'em.
import java.awt.Component;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.util.ArrayList;
import java.awt.event.*;
import java.awt.image.*;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.FileOutputStream;
public class BufferedImageSto extends Component {
ArrayList<String> colorpxl = new ArrayList<String>();
ArrayList<String> dimensions = new ArrayList<String>();
String alphaStr, redStr, greenStr, blueStr, wStr, hStr, mSet,mSetx;
These Strings would probably be better off as local variables
in the methods that use them. There are two main reasons for making
something an instance variable: Because it is part of the "state"
of the instance that persists even when no method of the class
happens to be running, or because it's a convenient way to share
something between two or more methods.
public static void main(String[] foo) {
new BufferedImageSto();
}
public void printPixelARGB(int pixel) {
int alpha = (pixel >> 24) & 0xff;
alphaStr = Integer.toString(alpha);
Since you never use `alphaStr', and since you use `alpha'
only to produce the never-used `alphaStr', why compute either
of them at all?
int red = (pixel >> 16) & 0xff;
redStr= Integer.toString(red);
if (redStr.length() < 2) {
redStr = "0" + redStr;}
if (redStr.length() < 3) {
redStr = "0" + redStr;}
int green = (pixel >> 8) & 0xff;
greenStr= Integer.toString(green);
if (greenStr.length() < 2) {
greenStr = "0" + greenStr;}
if (greenStr.length() < 3) {
greenStr = "0" + greenStr;}
int blue = (pixel) & 0xff;
blueStr= Integer.toString(blue);
if (blueStr.length() < 2) {
blueStr = "0" + blueStr;}
if (blueStr.length() < 3) {
blueStr = "0" + blueStr;}
mSet = redStr + greenStr + blueStr;
You are spending too much time doing things the hard way,
and not enough time reading the Javadoc! *All* of the code so
far in this method could be replaced by *one* statement:
mSet = String.format("%03d%03d%03d",
(pixel >> 16) & 0xff,
(pixel >> 8) & 0xff,
pixel & 0xff);
mSetx= "121000000";
if (mSet.equals( mSetx)) {
mSet = "";
Purposeless assignment.
mSet= Integer.toString (255255255);
System.out.println("revision "+ mSet);
}
//System.out.println(mSet);
colorpxl.add(mSet);
mSet = "";
Purposeless assignment.
}
Even with the suggested shortcuts you're still working too
hard. Let's restate the purpose: You want to produce a nine-
digit string representing the pixel's R,G,B values (ignoring A),
except that if R is 121 and B,G are both zero you want to set all
three to 255. Let's start with ARGB and get rid of the unwanted A:
pixel &= 0xffffff; // A is now zeroed out
Does this match the color you want to victimize?
if (pixel == 121 << 16) {
If so, change it to the replacement color:
pixel = (255 << 16) + (255 << 8) + 255;
// Print it if you want; doesn't seem informative.
}
Finally, develop your nine-digit string and add it to the list:
colorpxl.add(String.format("%03d%03d%03d",
pixel >> 16, (pixel >> 8) & 0xff, pixel & 0xff));
(You can do without R's `&0xff' because we know the A bits are zero.)
private void marchThroughImage(BufferedImage image) {
int w = image.getWidth();
String wStr= Integer.toString(w);
int h = image.getHeight();
String hStr = Integer.toString(h);
dimensions.add(wStr);
dimensions.add(hStr);
System.out.println("width, height: " + w + ", " + h);
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
// System.out.println("x,y: " + j + ", " + i);
int pixel = image.getRGB(i, j);
Perhaps this is what you want, but it looks a bit strange.
Most raster formats work their way across the top row, then move
down and work across the second row, then the third, and so on to
the bottom of the image. ("Interlaced" formats may jumble the row
order, but they still usually work across each row as a unit.) Your
code, instead, marches down the leftmost column, then moves one
place rightwards and marches down the next column, and so on until
it reaches the right-hand edge. It's possible that's your intent,
but it seems very strange.
printPixelARGB(pixel);
System.out.println("");
}
}
String respName = "ColorPixlData.txt";
Seems a strange name for a file that will be filled with
binary garbage. It's not really "garbage," of course: It's
a binary representation from which an ObjectInputStream could
reconstruct the `dimensions' and `colorpx1' lists and their
content. But ".txt" ordinarily means "Something that would
make sense to a program like `NotePad' or `more'," which this
file won't.
System.out.println("File Saved as "+ respName);
System.out.println(respName);
try {
FileOutputStream fout = new FileOutputStream(respName);
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(dimensions);
out.writeObject(colorpxl);
out.flush();
out.close();
repaint();
Why? Nothing has changed; in fact, as far as I can tell
nothing has been painted to begin with. It's (arguably) an
actual error to do this because this method is called from
the constructor, hence the constructor has not yet finished,
hence the object being repainted hasn't been fully initialized
yet. (See below.)
}
catch (IOException e) {e.printStackTrace();
}
}
public BufferedImageSto() {
try {
// get the BufferedImage, using the ImageIO class
BufferedImage image = ImageIO.read(this.getClass().getResource("MH0x.png"));
marchThroughImage(image);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
It's not exactly "wrong," but you probably don't want to be
doing so much heavy lifting in a constructor. The purpose of a
constructor should be to construct, but the purpose of this one
seems to load an image and spit out a file. As things stand, I
don't see any need for a BufferedImageSto object at all: A `static'
method or two would do all the work with fewer needless trappings.
}
--
Eric Sosman
esosman@comcast-dot-net.invalid