Jump to content

Welcome to Geeks to Go - Register now for FREE

Geeks To Go is a helpful hub, where thousands of volunteer geeks quickly serve friendly answers and support. Check out the forums and get free advice from the experts. Register now to gain access to all of our features, it's FREE and only takes one minute. Once registered and logged in, you will be able to create topics, post replies to existing threads, give reputation to your fellow members, get your own private messenger, post status updates, manage your profile and so much more.

Create Account How it Works
Photo

JFIF Image class - Java


  • Please log in to reply

#1
staticVoid

staticVoid

    Member

  • Member
  • PipPip
  • 94 posts
hi, I recently posted a topic on implementing my own image class , but I don't think I gave enough details on the subject.

Im looking to create a class from scratch that will be able to read a JFIF image file and extract all relevant data from it.

I've been reading the JFIF specification and understand the structure of the file type:

SOI;
APP0;
JFIF APP0;
Additional APP0;
Application Specific APP0;
Image Data;

(I think thats right)

The problem is that the begining of any jpg image I try to read from looks a bit like this:

JFIF  H H YExif MM *

which I don't understand.

The specification says the first 2 bytes should be the total APP0 byte count , then the next five bytes should be the identifier and so on.

thanx in advance for any help.
  • 0

Advertisements


#2
bdlt

bdlt

    Member

  • Member
  • PipPipPip
  • 875 posts
Hi staticVoid,

I can suggest a couple of things to help get you started.

1. JFIF  H H YExif MM *
you are seeing this because the image is a binary file and the text editor is trying to read text

suggestion - go online and download a free hex-text-editor

or if you already have visual c++ loaded use that editor(select binary)

2. when you write your java code you want to read bytes ... the java tutorial should be able to show you how to read bytes

this is just a start.

this project is a real challenge, especially if you are going to parse the entire image.

good luck,

bdlt
  • 0

#3
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
I know that the image is text, but its probaly a lot worst when I read the actual bytes:

Ϡ ►JFIF ☺☻☺ H H ↔YExif MM * ♫

heres the program I used to display:

import java.io.*;

public class jpg {

public static void main(String[] args) {

new jpg();

}


public jpg() {

try {

File f = new File("C:/1.jpg");

FileInputStream fis = new FileInputStream(f);

int c;

for(int x = 0; x < 40; x++) {

c = fis.read();

System.out.print((char)c);

}

fis.close();

} catch(Exception e) {

}

}

}
  • 0

#4
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
Sorry... the byte stream looks more like this

-1-40-1-3201674707370012107207200-1-312989691201051020077770420008014

I parsed c to a char instead of a byte
  • 0

#5
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
I think I'm starting to understand it now but im running into a few problems -

> When the length of a marker is stored in two bytes I cannot find its true value because each byte I read in sequence from the stream is in decimal form therefore 1D 59 is 29 and 89 when it should be 7513 ?

> What's in the extension markers , Do you really need them? because I was going to just skip them using the total byte length - I thought it was just copyright info. and stuff about the software that produced the image.

Edited by staticVoid, 22 August 2007 - 05:36 AM.

  • 0

#6
bdlt

bdlt

    Member

  • Member
  • PipPipPip
  • 875 posts
it sounds like you are making good progress

1D59 = 256*29 + 89 = 7513

or

(4096 * 1) + (256 * 13) + (16 * 5) + 9 = 7513

hex is base 16 so the weight of consecutive bits differ by a factor of 16

...................................................
I'm not sure if I understand your extension question(and may not be able to answer it if I did). Can you rephrase it?
  • 0

#7
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
I've wrote a basic program that tells you when each marker is identified: (this is not the full source code):

(fis = FileInputStream)

while( (a = fis.read()) != -1 && (b = fis.read()) != -1) {

if( (a == 255) && (b == 216)) {

System.out.println("SOI Marker Identified " + a + " " + b);

}

if( (a == 255) & (b == 224) ) {

System.out.println("JFIF Marker Identified " + a + " " + b);

length1 = fis.read() * 256;
length2 = fis.read();
t_length = length1 + length2;

for(int x = 0; x < t_length-2; x++) { fis.read(); }

length1 = length2 = t_length = 0;

}

}

thats just two markers I've included there(SOI and JFIF) but ive also implemented:

Define Quantization Table
Define Huffman Table Marker
Start Of Frame Marker
Start Of Scan Marker
Comment Marker
EOI

I'm only referring to http://www.obrador.c.../HeaderInfo.htm for the markers that im including but are there any more I need to know about?

and I thought that after the EOI marker that that was the end of all the header information and it went onto the image data but when i displayed the remainder of the file it had words like adobe reader etc. which I though where only supposed to be in the markers.?

I could copy the full program in my next post if you want and you could test it.
  • 0

#8
bdlt

bdlt

    Member

  • Member
  • PipPipPip
  • 875 posts
I believe EOI is end of image, not the end of the header. EOI is where the pixel data ends.

HeaderInfo.htm mentions only a few markers

if you are going to parse any jpeg file, you need to know about EVERY marker in that file, otherwise your program will return garbage(or crash) at the point where an unrecognized marker is found.

suggestions:
1. identify EVERY marker in your test image

change
if( (a == 255) && (b == 216)) {
to
if( (a == 255) {

warning: this will see every FF(255, -1) ... some of it may be pixel values and return 'false' markers

2. find a source that has EVERY possible marker - eventually you will run into an image that uses some of the oddball markers

.............................................................
I'm running java 1.3 ... you can attach your code in a zip file and I can try to run it
  • 0

#9
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts


the image file name is passed in args[0] if your testing it.

thanx.
  • 0

#10
bdlt

bdlt

    Member

  • Member
  • PipPipPip
  • 875 posts
your program runs fine

now the project begins ... you are about 1% done

markers are explained in detail near the end of jpeg.txt
http://www.opennet.r...ormats/jpeg.txt

the best source is ISO standard 10918-1

................................................................................

jpeg.txt give an overview of the jpeg encoding process. to decode(what you want to do), perform the encoding steps in reverse. there are many steps to the process(7? 8?). each is unique. some steps require a lot of coding, some are simple.

I can try to help you on Wed & Sun when I'm in town. then next trip is Sep 6-17.

look at the marker section at the end of jpeg.txt
I didn't find jpeg.txt 'easy' to read(as the author claims), but it has good info and describes each step in detail. try to read through a couple of steps(huffman is the most complex ... get some of the other steps under your belt before looking at huffman)

I would recommend working on one step at a time. select the easy ones first(like diff).

coding - the code will be easier to manage if you create a separate class for each step.

questions?comments?
  • 0

Advertisements


#11
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
I'm going to start coding the classes for each stage of decompression , though I'm still not sure on how to isolate the image data or separate it from the markers because It would be stupid passing data like "Adobe Photoshop" etc. into a class used to decompress the image data?
  • 0

#12
bdlt

bdlt

    Member

  • Member
  • PipPipPip
  • 875 posts
you are correct - the adobe info is most likely preceded by some kind of comment marker ... that info can be ignored

here's a very general approach to decompression:

read the file one byte at a time(you are doing that already)

read the entire file looking for markers(you are doing that already)

when you find a marker - process the bytes that follow until you get to the next marker

repeat the step above until reaching EOI(EOI is off the top of my head, there may be another marker that tells you that you are done)

................................................................................


eventually you will have 7 or 8(9?) blocks of data(one from each step).

the output of one step is the input to the next step
  • 0

#13
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
But my program recognises the EOI and then the data that follows has words - "adobe photoshop" etc.

im currently trying to code the 8x8 DCT decompressor :whistling:

but would this be right for the last stage(decompress):

public class TransformColorSpace {

private int R, G, B;

public TransformColorSpace(int Y, int Cb, int Cr) {

R = (int)(Y + 1.402 * (Cr - 128));

G = (int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128));

B = (int)(Y + 1.722 * (Cb-128));

}

public ThreeByte getRGB() {

return new ThreeByte(R, G, B);

}

}


ThreeByte is just a class I made that holds three integers

Edited by staticVoid, 22 August 2007 - 12:19 PM.

  • 0

#14
bdlt

bdlt

    Member

  • Member
  • PipPipPip
  • 875 posts
it sounds like 'adobe ...' immediately follows EOI

that tells us to stop reading the file at EOI - all of the meaningful data has been read from the file

I'm going to trust your formulas - use the standard to verify ALL formulas

...........................................................................

you may need to add a check for negative numbers

or add 256 to each negative number read from the file

Cb and Cr must be a least 128

use the standard to determine the expected range of Y Cb and Cr

you can write a tester that will make sure the R G & B range from 0-255
  • 0

#15
staticVoid

staticVoid

    Member

  • Topic Starter
  • Member
  • PipPip
  • 94 posts
I've just added this to transformcolorspace class:

if(Y < 0)
Y = Y + 256;

if(Cb < 0)
Cb = Cb + 256;

if(Cr < 0)
Cr = Cr + 256;

I'm not to sure about Y, Cb, Cr , I know that Y is luminance , Cb is chrominance blue and Cr is chrominance red but it don't know what their ranges are.

I've wrote the transform color space class and level shift class but I'm sort of strugling with the 8x8 DCT, Is there any easy breakdown of the method? - I think the data that should be passed into it is the signed values for Y, Cb, Cr? after level shift but its talking about splitting the image into blocks of eight and im totally lost.
  • 0






Similar Topics

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

As Featured On:

Microsoft Yahoo BBC MSN PC Magazine Washington Post HP