Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
New Contributor
jkelling
Posts: 3
Registered: ‎05-06-2010
My Device: Storm
My Carrier: Verizon

Re: BBThumbs.dat


yuusaku wrote:

please try:

 

http://acodapella.blogspot.com/2010/05/reading-bbthumbsdat-thumbnail.html


 

This doesn't seem to always work.  I'm looking at thumbs116x116.dat in UltraEdit.  If you search for the word "/samples", you can see where each picture starts.  I'm assuming that the pictures binary data starts somewhere near after the filename ends (.png.rem).    On of the files has FF D8 FF E1 right after the filename.  Others don't seem to have a header like that and looking at the data, there isn't even any exif data in the binary stream, so it doesn't seem to be an exif/jpeg file in the data stream - it's something else.  That's the confusing spot.  The data stream seems to have different type of objects in it.  I also don't know if the data stream has any type of length data for the not exif objects stored in it.  I can provide a copy of my thumbs116x116.dat file if anyone wants to have a peek.

 

Jeff

Please use plain text.
Contributor
yuusaku
Posts: 15
Registered: ‎03-10-2010
My Device: Q10,Z10
My Carrier: Telus

Re: BBThumbs.dat

in my case, i found that one image could have multiple EXIFs stored within the .dat.

 

http://acodapella.blogspot.com/2010/05/thumbs116x116dat-reader.html

 

this code snippet skips to next file of the same directory as soon as it finds the first occurence of the EXIF

 

not sure does this reader work for your .dat, feel free to improve it.

Please use plain text.
New Developer
daver69
Posts: 19
Registered: ‎12-23-2009
My Device: Not Specified

Re: BBThumbs.dat

Has anyone found a solution to this problem as I have this problem as well.

 

I have tried this BBThumbs.dat usage but it seems to be very slow as well. Nowhere near as fast as rims delivered image selectors and my phone becomes unresponsive.

 

 

Please use plain text.
Developer
rcmaniac25
Posts: 1,804
Registered: ‎04-28-2009
My Device: Z10 (STL100-4)-10.2.1.2174, Z10 (STL100-3)-10.3.0.700 Dev OS, Z30 (STA100-5)-10.3.0.700 Dev OS, PlayBook (16GB)-2.1.0.1917
My Carrier: Verizon

Re: BBThumbs.dat

[ Edited ]

I never really played around with BBThumbs.dat (<= 4.7) but I have played around with thumbsXXXxXXX.dat (5.0 >). The format I figured out is as follows:

0: [short]
2: [int]
6: [int]

"bunch of tags up until Reserved1 == 0"

Tag:
0: Reserved1: [short]
2: path length [int]
6: name length [int]
10: data length [int]
14: [int]
18: [int]
22: [int]
26: "gap" (zero in value) [byte]
27: Path [ASCII the length of Path Length]
27 + path length: Name [ASCII the length of Name Length]
27 + path length + name length: Image data [byte[] the length of Data Length]
27 + path length + name length + data length: "gap" (value of 17 if another tag exists) [byte]
27 + path length + name length + data length + 1: [short]

 If you can understand that.

 

Example reader:

private class TagGroup
{
    public int Reserved1;
    public int Reserved2;
    public Vector Tags;

    public TagGroup(InputStream st, long length) throws IOException
    {
        DataInputStream br = new DataInputStream(st);
        if (br.readShort() != 1570) //8710 for big-endian
        {
            //Not valid dataBase
            return;
        }
        Reserved1 = reverseEndian(br.readInt());
        Reserved2 = reverseEndian(br.readInt());
        Tags = new Vector();
        long pos;
        while (length > (pos = length - st.available())) //No the best way to do it but it gets the job done if all data is avalible.
        {
            st.mark(Integer.MAX_VALUE); //Again, not the best but if supported it gets the job done
            Tag g = new Tag(br);
            if (g.Reserved1 == 0)
            {
            	st.reset();
                break;
            }
            Tags.addElement(g);
        }
        //Not sure what other tags are
    }
    
    public static int reverseEndian(int value)
    {
        return ((value >> 24) & 0xFF) | (((value >> 16) & 0xFF) << 8) | (((value >> 8) & 0xFF) << 16) | ((value & 0xFF) << 24);
    }
    
    public static short reverseEndian(short value)
    {
        return (short)(((value >> 8) & 0xFF) | ((value & 0xFF) << 8));
    }
    
    public static char[] readChars(DataInputStream br, int count) throws IOException
    {
    	char[] chars = new char[count];
    	for(int i = 0; i < count; i++)
    	{
    		chars[i] = br.readChar();
    	}
    	return chars;
    }
}

private class Tag
{
    public short Reserved1;
    public int PathLength;
    public int NameLength;
    public int DataLength;
    public int Reserved2;
    public int Reserved3;
    public int Reserved4;
    public String Path;
    public String Name;
    public byte[] Image;
    public short Reserved5;

    public Tag(DataInputStream br) throws IOException
    {
        Reserved1 = TagGroup.reverseEndian(br.readShort());
        PathLength = TagGroup.reverseEndian(br.readInt());
        NameLength = TagGroup.reverseEndian(br.readInt());
        DataLength = TagGroup.reverseEndian(br.readInt());
        Reserved2 = TagGroup.reverseEndian(br.readInt());
        Reserved3 = TagGroup.reverseEndian(br.readInt());
        Reserved4 = TagGroup.reverseEndian(br.readInt());
        int b = br.read(); //Gap (0)
        Path = new String(TagGroup.readChars(br, PathLength));
        Name = new String(TagGroup.readChars(br, NameLength));
        if (b != 0 && Reserved1 != 0)
        {
            System.out.println("Invalid gap for " + Path + Name);
        }
        Image = new byte[DataLength];
        br.read(Image);
        b = br.read(); //Gap (17)
        if (b != 17 && Reserved1 != 0)
        {
        	System.out.println("Invalid 2nd gap for " + Path + Name);
        }
        Reserved5 = br.readShort();
    }
}

 

---Spends time in #blackberrydev on freenode (IRC)----
Three simple rules:
1. Please use the search bar before making new posts.
2. "Like" posts that you find helpful.
3. If a solution has been found for your post, mark it as solved.
--I code too much. Well, too bad.
Please use plain text.
New Developer
daver69
Posts: 19
Registered: ‎12-23-2009
My Device: Not Specified

Re: BBThumbs.dat

thanks for the code....

 

Wonderfull as bb developers we have to resort to hacks like this which may not work in future OS's.

 

At least in OS6.0 rim seems to have provided api's for decent pickers.

 

http://www.blackberry.com/developers/docs/6.0.0api/net/rim/device/api/ui/picker/FilePicker.html

 

Its in 5.0 but for images that filepicker is not particularly usefull unless you like micro thumbs.

 

This one at least gives you option of a view type VIEW_PICTURES which hopefully sizes thumbs nicely.

 

 

For pre os5.0, any suggestions on how to display thumbs in a file picker which works with large amount of images efficiently?

 

You can't load them all up and display them in a dialog. Its just way to slow.

 

Looking closely at rims picture dialog it seems to grab new thumbs when you scroll and clears ones from memory ones that are no longer visible.

 

Creating a blank bitmap as a place holder for 100's is thumbs from a dir listing slows down the application greatly so my guess is that they are only adding bitmaps for visible thumbs and removing bitmaps for ones no longer visible.

 

But even still they are being rendered incredibly fast. I have not been able to duplicate that type of speed. Even when reading from thumbs dat files instead of the original file.

 

 

 

 

Please use plain text.
Developer
rcmaniac25
Posts: 1,804
Registered: ‎04-28-2009
My Device: Z10 (STL100-4)-10.2.1.2174, Z10 (STL100-3)-10.3.0.700 Dev OS, Z30 (STA100-5)-10.3.0.700 Dev OS, PlayBook (16GB)-2.1.0.1917
My Carrier: Verizon

Re: BBThumbs.dat

I know this is an old thread but I have an update to my previous code. Missed what seems like a data "end point" and for one reason or another I was reversing the endian of the values.

 

Updated code:

public class TagGroup
{
    public int Reserved1;
    public int Reserved2;
    public Vector Tags;
    
    public TagGroup(InputStream st, long length) throws IOException
    {
        DataInputStream br = new DataInputStream(st);
        if (br.readShort() != 8710)
        {
            //Not valid dataBase
            return;
        }
        Reserved1 = br.readInt();
        Reserved2 = br.readInt();
        Tags = new Vector();
        long pos = 0;
        while (length > pos)
        {
            st.mark(Integer.MAX_VALUE); //Again, not the best but if supported it gets the job done
            Tag g = new Tag(br);
            pos += g.getSize();
            if (g.Reserved1 == 0)
            {
            	st.reset();
                break;
            }
            Tags.addElement(g);
            if(g.Reserved1 == 8720)
            {
            	//Appears to be a new tag database
            	break;
            }
        }
        //Not sure what other tags are
    }
    
    public static char[] readChars(DataInputStream br, int count) throws IOException
    {
    	char[] chars = new char[count];
    	for(int i = 0; i < count; i++)
    	{
    		chars[i] = (char)br.read();
    	}
    	return chars;
    }
}

public class Tag
{
    public short Reserved1;
    public int PathLength;
    public int NameLength;
    public int DataLength;
    public int Reserved2;
    public int Reserved3;
    public int Reserved4;
    public String Path;
    public String Name;
    public byte[] Image;
    public short Reserved5;

    public Tag(DataInputStream br) throws IOException
    {
        Reserved1 = br.readShort();
        PathLength = br.readInt();
        NameLength = br.readInt();
        DataLength = br.readInt();
        Reserved2 = br.readInt();
        Reserved3 = br.readInt();
        Reserved4 = br.readInt();
        int b = br.read(); //Gap (0)
        Path = new String(TagGroup.readChars(br, PathLength));
        Name = new String(TagGroup.readChars(br, NameLength));
        if (b != 0 && Reserved1 != 0)
        {
            System.out.println("Invalid gap for " + Path + Name);
        }
        Image = new byte[DataLength];
        br.read(Image);
        b = br.read(); //Gap (17)
        if (b != 17 && Reserved1 != 0 && Reserved1 != 8720)
        {
        	System.out.println("Invalid 2nd gap for " + Path + Name);
        }
        Reserved5 = br.readShort();
    }
    
    public int getSize()
    {
    	return (2 * 2) + (6 * 4) + PathLength + NameLength + DataLength;
    }
}

 

---Spends time in #blackberrydev on freenode (IRC)----
Three simple rules:
1. Please use the search bar before making new posts.
2. "Like" posts that you find helpful.
3. If a solution has been found for your post, mark it as solved.
--I code too much. Well, too bad.
Please use plain text.