R
Rod Nibbe
I wrote a simple program several years ago that reads a Targa graphics
file (.tga) and displays it. It works fine, but today I had occasion to
resurrect this code and for the life of me I can't figure out what I did
in setting the rgb values. The entire program is below.
The part of the code I'm struggling with is here, where I set the rgb
value for each pixel used to populate a BufferedImage:
bi = new BufferedImage(image_width, image_height,
BufferedImage.TYPE_INT_RGB);
byte [] image = new byte[npixels*3];
int rgb = 0 ;
for(int i=npixels,r=2,g=1,b=0; i>0; r+=3,g+=3,b+=3,i--)
{ // WHY NOT SIMPLY THIS...?
rgb = image[r] << 16 ; // rgb = image[r] << 16 ;
rgb |= (image[g]&0xff) << 8 ; // rgb |= image[g] << 8 ;
rgb |= (image&0xff) ; // rgb |= image ;
bi.setRGB(x,y,rgb) ;
// increment x/y
...
}
If I mask the green(g) and blue(b) pixels with 0xff (8 bits of ones)
before the left bit shift, the picture displays perfectly. If I don't
mask first, the picture is produced but the colors are hokey. Here's
where I'm confused. Performing a logical AND (&) with 0xff on a given
value just returns the value. So why...
...isn't this ----> rgb = image[r] << 16 ;
rgb |= (image[g]&0xff) << 8 ;
rgb |= (image&0xff) ;
the same as this? ----> rgb = image[r] << 16 ;
rgb |= image[g] << 8 ;
rgb |= image ;
Thanks in advance,
-RKN
<code>
package Targa;
import java.io.*;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.BorderLayout;
public class TargaReader extends JPanel {
BufferedImage offs = null ;
Graphics2D g2 = null;
public TargaReader(){
super(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g) ;
g2 = (Graphics2D)g;
if(offs == null) {
return ;
}
g2.drawImage(offs,0,0,this) ;
g2.dispose() ;
}
public AppFrame getFrame() {
AppFrame app = new AppFrame("Display Targa File") ;
app.getContentPane().setLayout(new BorderLayout());
app.center();
app.setContentPane(this) ;
return app ;
}
public static void main(String [] args) {
DataInputStream tr = null;
String filename = null;
BufferedImage bi = null;
int lsb,msb,image_width=0,image_height=0;
short xorigin,yorigin,width,height ;
byte pixeldepth,imagedesc;
if(args.length > 0)
{
filename = new String(args[0]);
}
else {
System.out.println("Usage: java TargaReader targafile");
System.exit(-1);
}
try {
tr = new DataInputStream(new FileInputStream(filename));
tr.read() ; // ID Length <1 byte>
tr.read() ; // Colormap type <1 byte>
tr.read() ; // Image type <1 byte>
tr.skipBytes(5); // Colormap indicies, not used here. <5 bytes>
tr.skipBytes(4); // X and Y origin, ignore. <4 bytes>
lsb = tr.read() ;
msb = tr.read() ;
image_width = ((msb << 8) | lsb) ;
System.out.println("Image Width: "+ image_width ) ;
lsb = tr.read() ;
msb = tr.read() ;
image_height = ((msb << 8) | lsb) ;
System.out.println("Image Height: "+ image_height);
// Assuming 24-bit pixel depth with no alpha channel.
System.out.println("Pixel Depth: "+tr.read()) ; // Pixel
depth <1 byte>
System.out.println("Image Descriptor: "+tr.read()) ; // Image
descriptor <1 byte>
int npixels = image_width*image_height ;
int rgb = 0;
int x = 0;
int y = image_height-1;
bi = new BufferedImage(image_width, image_height,
BufferedImage.TYPE_INT_RGB);
byte [] image = new byte[npixels*3];
try
{
tr.readFully(image) ; //fetch image data, rgb <24-bit>
}
catch (EOFException eofe) { System.out.println( "EOF:" +
eofe.toString() ); }
for(int i=npixels,r=2,g=1,b=0; i>0; r+=3,g+=3,b+=3,i--)
{ // WHY NOT THIS?...
rgb = image[r] << 16 ; // rgb = image[r] << 16 ;
rgb |= (image[g]&0xff) << 8 ; // rgb |= image[g] << 8 ;
rgb |= (image&0xff) ; // rgb |= image ;
bi.setRGB(x,y,rgb) ;
x++ ;
if(x == image_width) //New scanline
{
x = 0;
y--;
}
}
}
catch (FileNotFoundException fnf)
{
System.out.println("File "+filename+" Not Found") ;
System.exit(-1);
}
catch (IOException ioe)
{
System.out.println("General IO Exception\n" + ioe.toString());
//System.exit(-2);
}
TargaReader targa = new TargaReader() ;
targa.offs = bi ;
AppFrame jf = targa.getFrame() ;
jf.setSize(image_width,image_height);
jf.center();
jf.setVisible(true);
}
}
</code>
file (.tga) and displays it. It works fine, but today I had occasion to
resurrect this code and for the life of me I can't figure out what I did
in setting the rgb values. The entire program is below.
The part of the code I'm struggling with is here, where I set the rgb
value for each pixel used to populate a BufferedImage:
bi = new BufferedImage(image_width, image_height,
BufferedImage.TYPE_INT_RGB);
byte [] image = new byte[npixels*3];
int rgb = 0 ;
for(int i=npixels,r=2,g=1,b=0; i>0; r+=3,g+=3,b+=3,i--)
{ // WHY NOT SIMPLY THIS...?
rgb = image[r] << 16 ; // rgb = image[r] << 16 ;
rgb |= (image[g]&0xff) << 8 ; // rgb |= image[g] << 8 ;
rgb |= (image&0xff) ; // rgb |= image ;
bi.setRGB(x,y,rgb) ;
// increment x/y
...
}
If I mask the green(g) and blue(b) pixels with 0xff (8 bits of ones)
before the left bit shift, the picture displays perfectly. If I don't
mask first, the picture is produced but the colors are hokey. Here's
where I'm confused. Performing a logical AND (&) with 0xff on a given
value just returns the value. So why...
...isn't this ----> rgb = image[r] << 16 ;
rgb |= (image[g]&0xff) << 8 ;
rgb |= (image&0xff) ;
the same as this? ----> rgb = image[r] << 16 ;
rgb |= image[g] << 8 ;
rgb |= image ;
Thanks in advance,
-RKN
<code>
package Targa;
import java.io.*;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.BorderLayout;
public class TargaReader extends JPanel {
BufferedImage offs = null ;
Graphics2D g2 = null;
public TargaReader(){
super(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g) ;
g2 = (Graphics2D)g;
if(offs == null) {
return ;
}
g2.drawImage(offs,0,0,this) ;
g2.dispose() ;
}
public AppFrame getFrame() {
AppFrame app = new AppFrame("Display Targa File") ;
app.getContentPane().setLayout(new BorderLayout());
app.center();
app.setContentPane(this) ;
return app ;
}
public static void main(String [] args) {
DataInputStream tr = null;
String filename = null;
BufferedImage bi = null;
int lsb,msb,image_width=0,image_height=0;
short xorigin,yorigin,width,height ;
byte pixeldepth,imagedesc;
if(args.length > 0)
{
filename = new String(args[0]);
}
else {
System.out.println("Usage: java TargaReader targafile");
System.exit(-1);
}
try {
tr = new DataInputStream(new FileInputStream(filename));
tr.read() ; // ID Length <1 byte>
tr.read() ; // Colormap type <1 byte>
tr.read() ; // Image type <1 byte>
tr.skipBytes(5); // Colormap indicies, not used here. <5 bytes>
tr.skipBytes(4); // X and Y origin, ignore. <4 bytes>
lsb = tr.read() ;
msb = tr.read() ;
image_width = ((msb << 8) | lsb) ;
System.out.println("Image Width: "+ image_width ) ;
lsb = tr.read() ;
msb = tr.read() ;
image_height = ((msb << 8) | lsb) ;
System.out.println("Image Height: "+ image_height);
// Assuming 24-bit pixel depth with no alpha channel.
System.out.println("Pixel Depth: "+tr.read()) ; // Pixel
depth <1 byte>
System.out.println("Image Descriptor: "+tr.read()) ; // Image
descriptor <1 byte>
int npixels = image_width*image_height ;
int rgb = 0;
int x = 0;
int y = image_height-1;
bi = new BufferedImage(image_width, image_height,
BufferedImage.TYPE_INT_RGB);
byte [] image = new byte[npixels*3];
try
{
tr.readFully(image) ; //fetch image data, rgb <24-bit>
}
catch (EOFException eofe) { System.out.println( "EOF:" +
eofe.toString() ); }
for(int i=npixels,r=2,g=1,b=0; i>0; r+=3,g+=3,b+=3,i--)
{ // WHY NOT THIS?...
rgb = image[r] << 16 ; // rgb = image[r] << 16 ;
rgb |= (image[g]&0xff) << 8 ; // rgb |= image[g] << 8 ;
rgb |= (image&0xff) ; // rgb |= image ;
bi.setRGB(x,y,rgb) ;
x++ ;
if(x == image_width) //New scanline
{
x = 0;
y--;
}
}
}
catch (FileNotFoundException fnf)
{
System.out.println("File "+filename+" Not Found") ;
System.exit(-1);
}
catch (IOException ioe)
{
System.out.println("General IO Exception\n" + ioe.toString());
//System.exit(-2);
}
TargaReader targa = new TargaReader() ;
targa.offs = bi ;
AppFrame jf = targa.getFrame() ;
jf.setSize(image_width,image_height);
jf.center();
jf.setVisible(true);
}
}
</code>