hello again,
i am having problems outputing the correct format of hex, the result i am aiming to achieve in my file should be :
78 00 07 D0 00 00 17 70 00 00 <-- aiming to achieve
D8 00 6F D0 00 00 7F F0 00 <-- actual output

The problem is i am trying to convert the values 16000 and 12000 that are int's into strings and output them as a single byte stream to achieve it.

RECT(int x, int y) {
        // set defaults
        Xmax = x;
        Ymax = y;
        Xmin = 0;
        Ymin = 0;
    }

String GETRECTANGLE() {
        // get total number of binary bits
        int binSize = Xmin + Xmax + Ymin + Ymax;
        String bins = Integer.toBinaryString(binSize);
        binSize = bins.length(); // stores the number of bits needed

        String output = padOut(Integer.toBinaryString(binSize),
                Integer.toBinaryString(binSize).length()+1)//+1 later
                .concat(padOut(Integer.toBinaryString(Xmin), binSize))
                .concat(padOut(Integer.toBinaryString(Xmax), binSize))
                .concat(padOut(Integer.toBinaryString(Ymin), binSize))
                .concat(padOut(Integer.toBinaryString(Ymax), binSize));
        //add all values into one string, padding each binary number to the size of largest number

        return output;

    }

    /*implementation of writing below*/
    RECT b = new RECT(16000, 12000);

    //write out the string as a series of 8 bits
    for (int i = 0; i < b.GETRECTANGLE().length(); i = i + 8) {

                if (i + 8 < b.GETRECTANGLE().length()) {
                    String output = b.GETRECTANGLE().substring(i, i + 8);
                    int value = Integer.parseInt(output);
                    out2.write((byte) value);
                }

                if (i + 8 > b.GETRECTANGLE().length()) {
                    int j = i + 8 - b.GETRECTANGLE().length();
                    String output = b.padOut(
                            b.GETRECTANGLE().substring(i, i + 8 - j), 8);
                    int value = Integer.parseInt(output);
                    out2.write((byte) value);
                }

Any help on finding why it outputs incorrectly would be fantastic :)

Edited 4 Years Ago by trishtren

I don't understand your example. 16000 in hex is 0x3e80 12000 in hex is 0x2ee0
What data is input that you want the following output to create:

78 00 07 D0 00 00 17 70 00 00

Does the above represent the byte contents in hex? When you talk about String values you must put them in "s to avoid confusion. For example on the following line the same byte value can be represented many different ways:

System.out.println('\u0041' + " " + (int)'A' + " " + (char)65 + " " + (char)0x41+ " " + (int)"A".charAt(0)); // A 65 A A 65

I'm trying to convert the values 16000 and 12000 that are int's into strings and output them as a single byte stream

Everything in the computer is in bytes. When you say "single byte stream" what do you mean?

Edited 4 Years Ago by NormR1

The hex is just what im reading from the file with an hex editor. The actual output is in bytes, since i know the output should be equivelant to

78 00 07 D0 00 00 17 70 00 00

based on others files of the same format, but when i try to generate the same result using the code i sent the equivelant hex is wrong. So i do not get why the binary files and in turn the hex representation is wrong. Somewhere in my transformation from 16000, and 12000 from int to binary string to file the values are incorrect.

If the int value: 16000 is 0x38e0 where does this 78 00 07 D0 00 00 17 70 00 00 come from? ( I assume that string of pairs of hex digits is what is viewed in a hex editor.)

This does not make sense.

The count of the bytes shown is 10. You have shown 2 5 character numeric strings as input. Is there any relationship there?

Do you have a definition for the algorithm that is supposed to "convert" an int value to the desired output?
Is there a definition for the format of the output(what was written to the file)?

Edited 4 Years Ago by NormR1

oh sorry, forgot to add in something. Page 14 on this http://csharksgames.blogspot.co.uk/2010/08/hacking-swf-slides.html slideshow is what i am trying to do.

basically im trying to take the 2 integer values as X max, and Y max as well as Xmin which is 0 and Ymin which is 0. Concatenate them into a string and output the binary string to a file, and the only way to do it seemed to be converting the string into a series of 8 bits, shown in my original code.

The values

78 00 07 D0 00 00 17 70 00 00

come from a pre-compiled file that i know to be 16000 and 12000 as their Xmax and Ymax values, the 0's are obviously the Xmin and Ymin values. And the file was viewed in a hex editor which compares the standard compiled swf to my swf.

16000 and 120
So the 78 is the hex representation of Nbits, in the slide show, so its clear i am calculating the number of bytes in the string wrong, and the representations of 16000 also do not match the ones from the file i know to be correct.

Sorry for it being such a lengthy problem, iv been working on it for a while now but im not great at the whole output in bytes thing. Which is why im working on it.

Edited 4 Years Ago by trishtren

Without a clearly defined (and posted here) algorithm for taking 2 int values and creating 10 bytes I don't know how I can help you.

This part does not make sense: take the 2 integer values, Concatenate them into a string and output the binary string to a file. The two int values in hex would be these 8 bytes: 00 00 38 e0 00 00 2e e0
How do you get 10 bytes from that?

Hey,
Thanks again, iv rewritten the algorithm to fit into main easily and seperated it into simple pieces:

public static void main(String[] args) throws IOException {
        Integer x = 16000;
        Integer y = 12000;
        Xmin = 0; //All these values are written out in order 
        Xmax = x; //in binary form
        Ymin = 0;
        Ymax = y;
        //set all values to be saved

        int binSize = Xmin + Xmax + Ymin + Ymax; 
        String bins = Integer.toBinaryString(binSize);
        //convert total to a string
        binSize = bins.length(); 

        //adds all binary numbers to one string and pads them out to set length
        String output = padOut(Integer.toBinaryString(binSize),Integer.toBinaryString(binSize).length()+1);
        output = output.concat(padOut(Integer.toBinaryString(Xmin), binSize));
        output = output.concat(padOut(Integer.toBinaryString(Xmax), binSize));
        output = output.concat(padOut(Integer.toBinaryString(Ymin), binSize));
        output = output.concat(padOut(Integer.toBinaryString(Ymax), binSize));

        //try and save to empty file
        OutputStream out = new FileOutputStream("Test.swf");
        try {


            for (int i = 0; i < output.length(); i = i + 8) 
            {
                if (i + 8 < output.length()) {
                    String roar = output.substring(i, i + 8);
                    int value = Integer.parseInt(roar);
                    out.write((byte) value);

                }
                // if binary too small pad it out
                if (i + 8 > output.length()) {

                    int j = i + 8 - output.length();
                    String roar = padOut(
                            output.substring(i, i + 8 - j), 8);
                    int value = Integer.parseInt(roar);
                    out.write((byte) value);

                }

            }

        } 
        catch (FileNotFoundException e)
        {

            e.printStackTrace();
        }
}

  public static String padOut(String s, int len) {
        if (s.length() >= len)
            return s;

        StringBuffer padding = new StringBuffer();
        for (int p = 0; padding.length() + s.length() < len; p++)
            padding.append("0");
        return padding.toString() + s;
    }

I get 9 bytes in total, but i know them not to be correct. The padding makes a large portion of the bytes. However the result is still one byte shorter than it should be and the values are also completely incorrect.

What is the algorithm for the code? How are the 64 bits from two int variables converted to the 80 bits in the 10 bytes?
I don't see anyway to write code without an algorithm.

For testing the code shouldn't require a file. All the output should be to the console.

Edited 4 Years Ago by NormR1

Unfortunately the only working program example i have of it is in c++. But as i understand the problem from reading the slides it should perform these tasks:
 set Xmin to 0, set Xmax to 16000,set Ymin to 0, set Ymax to 12000
Convert all numbers to binary
get longest binary string length and set int Nbits to the value of the longest binary string
write Nbits to file in binary
write Xmin binary to file
write Xmax binary to file
write Ymin binary to file
write Ymax binary to file

A complete example from the specification is 
**NBits**
**Xmin  0 **          
Binary  0
**Xmax :  550   **  
Binary  100010010
**Ymin  0     **      
Binary  0
**Ymax  400  **    
Binary 1110110110
Add binarys together  result   1110110110
**So Nbits  is 10**

So the complete output would be :
01010---0000000000--------1000100110--------0000000000 -----------00110010000
 Nbits------Xmin-------------Xmax--------------Ymin--------------------Ymax

This should work, however when i have tried this with the code i posted, the resulting string is correct, however i think its either a padding error or the fact its writing out a byte at  a time causing the fact that it reaches an odd number such as 45 in this case to cause 5 bits to either be ommitted, or have to pad it out to 8 bits causing inaccuracy, however i am not entirely sure. Any ideas?

Edited 4 Years Ago by trishtren

The specs youv'e posted do no make sense as written.

Convert all numbers to binary

Explain what this means by "binary", All values in the computer are in binary.

get longest binary string length

This does not make sense. An int has 32 bits.

set int Nbits to the value of the longest binary string

All ints are 32 bits.

write Nbits to file in binary

All values in a computer and in files are made of 8 bit bytes. What does this mean?

Norm - I had a look at the reference material the OP referred to earlier, and this is what I think it means:
The data is coded as one continuous bit stream (ignoring byte boundaries) with values compressed by omitting (some) leading zeros. The test data consts of 4 numbers. You look at each of them and find out what is the number of bits you need to encode the largest of them (eg 10 bits). The output then consists of the number-of-bits value (10) written as a 5-bit value, followed by the four data values written using number-of-bits bits each. In tis case a total of 5+4*10 bits. I have no idea what happens in the remainder of the last byte - maybe it just doesn't matter.

If this was my program I think I would stop trying to do it all in one go and write a simple class to store arbitrary bit strings (maybe as String of 1's and 0's) with methods to return their length, concatenate them, and finally convert them to byte arrays (8 values/byte). And test it.
Then I would go back to the original problem and code it's solution using the new tool I just created.

Basically i mean taking the integers, converting them to strings of binary numbers.
Get the longest string of binary values and use its length as the value of integer NBits.

So basically im dealing with a string of 1's and 0's and i want to write the entire string's value out as literal binary values not as a string. But in the example i provided the problem is that i cant find a way to output a string of 45 , 1's and 0's to the binary file since output is like you said stored in 8 bit bytes.

So basically im thinking the only problem is that the string i have generated either gets grouped for example '1000100011' removing the last two bits and adds those values to the next 8 bits causing the resulting output to be inaccurate.

What is done with the stream of bits by the program that reads them? What does it expect?
If the input numbers generate 45 bits for output, what should follow the last bit? The first 3 bits of the NBits value for the next set of numbers? In other words, no padding or filler. The bits for each set of numbers immediately follows those for the last set of numbers.

78 00 07 D0 00 00 17 70 00 00 <-- aiming to achieve

Does NBits always take 5 bits? Then for the above NBits = 15 First 5 bits=(0111 1) Then the total number of bits for those two numbers would be 5 + 15*4 = 65 bits. Vs the 80 shown???

Edited 4 Years Ago by NormR1

The values are read as below from the stream with the number of bits always being 5 as i understand it:

number of bits (nbits) - 5 bits (unsigned integer) - this number represents the 'bit length' of the next four fields
minimum X coordinate - nbits (signed integer) - X coordinate of upper left corner of the frame
minimum Y coordinate - nbits (signed integer) - Y coordinate of upper left corner of the frame
maximum X coordinate - nbits (signed integer) - X coordinate of lower right corner of the frame
maximum Y coordinate - nbits (signed integer) - Y coordinate of lower right corner of the frame

The problem is you can only output 8 bits a time, making the first 5 padded to 8 or the last 3 padded to 8 an inaccuracy in the entire stream atleast thats my thesis of the problem so far, The specification doesent state that there should be any filler, however in all my tests i found that i had to pad out the result with an extra 0 to make the 9 bytes file to 10 bytes.It states specifically that the idea of concatenating the output to a stream of 45 bits or whatever is to minimize the amount of data required,

"Now the unpleasant part is that when you read a file, the smallest 'part' you can get in one read cycle is 1 byte (1 char) = 8 bits. So the remaining 3 bits overlap. " <- i think this is fundamentally the problem i am having only when writing it.

I found a useful document here : http://thenobody.blog.matfyz.sk/p13084-how-to-get-dimensions-of-a-swf-file on the problem, but even after reading it and mapping out the example program that reads these values from the file i cant reverse and translate it to java.

Again i would like to apologise for taking up your time, its a pretty strange problem and i havent been able to express it as clearly as i would have liked.

Ignoring the padding at the end problem. my approach wwould be to build a StringBuffer of 0s and 1s containing the 5 groups of bits, convert it to a String, convert each 8 char substring to an int using parseInt and store the ints in an array.
Then write out the bytes from the int array.

Edited 4 Years Ago by NormR1

Comments
got it working great, thanks to your help :)

ok i implemented your approach and isolated the problem down to the first 5 bits.
Everything you said works except for the fact during the string to int conversion process it seems to drop the left most bit if its a 0.
I.e

                    if(i==0)
                    {
                    String binary = rectangle.GETRECTANGLE().substring(i, i + 5);
                    //get first 5 bits

                    int value = Integer.parseInt(binary,2);
                    //convert to integer

                    System.out.println(value);
                    //outputs 1010 instead of 0101, effectively dropping 1 bit

                    list.add((byte) value);
                    //adds to list output
                    }

So thanks for your patience and it nearly works! :p

Edited 4 Years Ago by trishtren

Why does line 3 only get 5 digits vs the full 8 digits that goes into a byte?
My approach was to build a String of binary digits for all 5 fields and then take them 8 at a time for each byte of 8 bits.

well i got it working anyway, but thanks to your comment just then i managed to remove the condition above, just use one if condition outputing the entire string 8 bits at a time, your advise has been very helpful and iv learned a lot, thanks.

Glad you got it working.

Here are the bits and pieces of code I worked on for this problem:

      int val = 16000+12000;
      int testBit = 0x80000000;
      // search for leftmost 1 bit
      for(int i=32; i > 0; i--) {
         if((val & testBit) != 0) {
           System.out.println("i=" + i + " " + Integer.toHexString(val));  //  i=15 6d60
           break;   // exit - found first 1 bit
         }
         testBit = testBit >> 1;     // move to next bit to the right
      } // end for(i)

      int nbrB = 15;        // Hard code for now
      StringBuilder sb = new StringBuilder();    // fill with 0s and 1s
      packer(sb, nbrB, 5);
      packer(sb, 0, nbrB);
      packer(sb, 16000, nbrB);
      packer(sb, 0, nbrB);
      packer(sb, 12000, nbrB);
      sb.append("0000000");              //<<<<<<<<<<<<<<   Q&D to even byte
      System.out.println(sb);
      //011110000000000000000111110100000000000000000000000101110111000000000000

      String binS = sb.toString();                     // the binary digits to convert
      int[] binI = new int[(binS.length()+7)/8];        // every 8 bits go here
      int ix = 0;     // index for binI
      // Go through String in 8 char groups to an int value
      for(int i=0; i < sb.length(); i +=8) {
        binI[ix] =  Integer.parseInt(binS.substring(i, i+8), 2);
        System.out.print(Integer.toHexString(binI[ix]) + " ");
        ix++;
      }

      System.out.println(java.util.Arrays.toString(binI)); //[120, 0, 7, 208, 0, 0, 23, 112, 0]




   // Packer: int value & nbr of bits
   // adds 0s & 1s to sb
   static void packer(StringBuilder sb, int val, int nbrB) {
      int testBit = 1 << nbrB-1;     // position the bit at leftmost bit to test
      while (testBit > 0) {
         char bVal = (val & testBit) != 0 ? '1' : '0';  // is selected bit 1 or 0?
         sb.append(bVal);
         testBit = testBit >> 1;    //move to next bit to the right
      }
   } // end packer()

Edited 4 Years Ago by NormR1

that is a much smaller version of what i ended up with. Thanks, i have used parts of your code to try and reduce my final output i hope thats ok.

This question has already been answered. Start a new discussion instead.