 |
 |
| Author |
Message |
HaLo2FrEeEk Overlord Extraordinaire
 Joined: 15 Aug 2006 Posts: 4773 Status: Offline Style: Xbox 360 Location: Trying really hard to do something
|
Post subject: The quest for the perfect panorama viewer |
|
|
A few nights ago I was looking through some old content that was related to a current project I'm doing and I found my Halo 3: ODST 360o panorama I made on NMPD HQ. I took a look at the flash panorama viewer I was using and re-realized how much it sucked. When I put it out, I recommended that people download the video or the full-res picture and NOT use the pano viewer because of how bad it looked. Well, not content to have something like that on the site, I went on a quest. A quest to find the perfect panorama viewer...or at least a better one.
I searched for hours, looking for a good, FREE, player. I wanted something flash-based, and I would settle for Silverlight if I had to. Much to my dismay, I couldn't find ANY good, free panorama players, they all cost money (which is stupid, if you ask me.)
Eventually I found a site that had comparisons of a lot of different players. I came across the one I was using, called pan0, and a few of the other's I'd seen during my search, specifically one called krpano, which is great, but pricey. Finally I found a program called Panorama2Flash. The download page didn't have anything about pricing, so I thought it was free. Excited, I downloaded and installed it, only to open it up and find that it wasn't free, I needed a serial number, or I could use a trial. I decided to go with the trial, which is fully-featured but puts a watermark on the output image, and see if I could crack the program to not need a serial. I've never been good at that, and thus failed. I figured I'd just see how bad it was and imported a panorama, the ODST one, and exported it. I opened up the player file and saw my beautiful panorama...completely ruined because of the multiple copies of a watermark going straight through the middle. I wasn't going to have any of that, there was something I could do about it.
First place I thought to look was the actual flash player file, thinking the watermark was built into it and I could just remove that image. I opened the player in a flash decompiler and learned that the watermark was not built in. That left one option, the watermark was actually built into the panorama image itself. The "image" that's outputted from the Panorama2Flash program has a .jpe extension, which is technically a JPEG extension. First thing I tried was opening the image in Windows Picture Viewer, but it said that it wasn't a valid image file. Odd. Next thing I did was open it in a hex editor.
first thing I noticed was that it definitely wasn't a standard JPEG, but something caught my eye. At offset 340 there were 4 characters: JFIF. "That's a JPEG header", I thought to myself. Now, a normal JPEG header actually starts with these bytes:
FF D8 FF E0 00 10 4A 46 49 46
The "4A 46 49 46" is hex for JFIF. I noticed that in my file, my JPEG header was missing the first 2 bytes, the "FF D8." I did a quick search for the text JFIF and found that there were 12 instances, all with the standard JPEG header, minus the first two bytes. I copied from the beginning of the first header to the beginning of the second one, inserted the missing bytes, and saved. Lo and behold, there was a portion of my panorama, 1/12 the width of the original and the same height. This led me to believe that the 12 instances of JFIF that I found were actually 12 portions of my original panorama, meaning that the viewer worked by taking those 12 blocks and putting them together to form the full rotation.
Next thing I needed to find out was how the flash player knew where to look for the files and how long each one was. Since I said that the first JFIF header was at offset 340, this meant that the data I need had to be somewhere in those first 340 bytes. I looked through and noticed a pattern, there was a certain character at offset 8, then the same character at 52, then again at 76...etc. Every 24 bytes after 52 was that same character, until offset 336, the beginning of the JFIF header. Digging through a little deeper I looked at the size of the first JPEG that I'd copied, then found that value in the .jpe file. Turns out that the jpe file has a 48 byte block at the beginning, then 12 24 byte blocks until the beginning of the first JPEG header. The first 4 bytes of each 24-byte block was the number of the image, so the first block was 0, the second was 1 (counting starts at 0 in computers,) etc. The next 8 bytes I didn't know what they did, I'll get to that later though. The next 8 bytes are null, and the last 4 bytes in the block were the size in bytes of the corresponding JPEG image. Interesting.
So, armed with that information, I built a program that could open a JPE image and export it's contents based on the information in that 336-byte header, and it WORKED! My next step was to add the ability to create my own JPE files. That came easily enough, I opened my picture in panorama in photoshop and sized it down to the nearest multiple of 12. My panorama was 6556x926, 6556 isn't evenly divisible by 12, the nearest multiple meant that I had to size it down to 6552, meaning each image would be 546 pixels wide. So I sized it down and chopped it into 12 evenly-sized parts, 546x926 each. Next I used some new features of my program to import those chopped up parts into a new JPE file. Remembering that the header contained the file sizes, I reconstructed it with that information from the new files. Also remembering that each JPEG in the JPE file was missing the first 2 bytes from it's header, I removed those before embedding the files. Crossing fingers, holding breath, dying of anticipation, I saved my file and opened back up my panorama viewer.......
IT WORKED! No watermark, perfect quality. I'd done it, I'd cracked the code.
BUT, I wasn't done. Next thing I wanted to try was if the technique worked on all images or if I just got lucky. I took another 360o panorama and chopped it into 12 parts, used my program to create the new JPE file and tried it. Well, I knew it was too good to be true. It didn't work, it was all messed up, it looked out of order, or like the images were overlapping. Well that's weird, why would they overlap? It's like the flash file wasn't calculating the width of each image properly. Maybe those 8 bytes that I didn't think did anything...actually did do something. Research wasn't hard for this one, but it was a lucky break. I'd just gotten done exporting out my 12 parts and I happened to look at the width of the created images. Going back to the JPE file's hex code, I noticed that the int32 value of the first 4 of those 8 bytes was the width of the image. On a hunch, I looked at the height and compared it to the next 4 bytes...what do you know, there it was. Those 8 mystery bytes were the width and height of each chunk. Knowing now why my images were overlapping in my second test, I recoded my program to take into account the width and height of the 12 input images, reconstructed the header with those values, re-embedded the JPEG files and saved.
BAM. It worked. I did a few more tests on multiple different (differently sized, width and height) panoramas and they all worked.
I was so proud of myself. I'd finally done something awesome. I started with nothing, no information, no research. I took what I knew about file formats and hex and researched and learned, then I took what I knew about C# and programming to make a tool to make the process easier. And all this for a panorama viewer without a watermark. Was it worth it?
Hell yes! Now all I have to do is write a method to do ALL the work, meaning all I do is input a full panorama image and the program resizes it, slices it up, reconstructs the header, embeds the files, and saves out the JPE file.
And this all started as me just wanting a better panorama viewer. Sheesh.
What does this mean for all of you? Well, for starters it means that you just spent...idk, 5-10 minutes reading about hex code and programming. For Infectionist it means that I have a better way of showing off full cylindrical and shperical panoramas (yes, shperical, meaning up/down left/right all-around view!) For the world? Probably nothing. I'm sure Panorama2Flash will continue to sell their product, regardless of if I release this information/program. I'm sure this is of very little interest to everyone except people like me...so pretty much just me. However, for me, it means that I've gone one step further in my research and learning, I've gained knowledge about one more subject, and I have one more useful program under my figurative belt. It's getting a little tight, that belt.
I wasn't sure if I was going to tell you all about this, seeing as I knew it would be a long post, trying to explain everything. I also didn't want to see it get ignored and pushed to the bottom, especially after how long it took me to write it. I hope some of you will find this interesting, and please, if you don't have something nice to say...think of something!
<3 _________________

~HaLo2FrEeEk
I wrote:
I'm sexy, admit it.
Are you?
 |
|
| Thursday, February 25, 2010 2:34:59 pm |
|
 |
 |
| Author |
Message |
HaLo2FrEeEk Overlord Extraordinaire
 Joined: 15 Aug 2006 Posts: 4773 Status: Offline Style: Xbox 360 Location: Trying really hard to do something
|
Post subject: |
|
|
You won't learn anything about C# in web design. You most likely won't learn anything about any sort of programming languages in Web Design. I took that class in high school for an easy A. On the first day I raised my hand and correctly answered every single one of the teacher's questions, and even corrected him a few times. He asked me if I'd redesign the school site and in return he'd give me an A in the class and I wouldn't have to do any of the classwork. I did, and I got my A, and the next year I was a Teacher's Assistant for that same class, even taught it a few times. Good times.
Anywho, HTML isn't a programming language, it's a markup language. Javascript isn't a programming language either, it's a scripting language. Javascript is not Java, they are completely different. CGI isn't really a language either, it's a language base. For example, Infectionist's server is running PHP as CGI. Being able to submit a form is pretty neat though, that's the basis of almost every data entry method on the internet, in fact when you typed a post you submitted a form to the server.
And for the record, C# is classified as a very-high-level programming language. I wrote my Xbox 360 Theme Extractor using C#, for example. _________________

~HaLo2FrEeEk
I wrote:
I'm sexy, admit it.
Are you?
 |
|
| Friday, February 26, 2010 12:54:21 am |
|
 |
 |
 |
 |
| Author |
Message |
HaLo2FrEeEk Overlord Extraordinaire
 Joined: 15 Aug 2006 Posts: 4773 Status: Offline Style: Xbox 360 Location: Trying really hard to do something
|
Post subject: |
|
|
I was actually thinking of making a program for viewing panoramas, but I want it to be freely available and web-accessible, C# programs are written in .NET, and only websites running ASP can run .NET programs. Since Infectionist is running PHP it wouldn't be possible. I do plan on improving the program so I don't have to cut the image up in photoshop, I just put in the whole panorama image and the program does all the work.
And Kool, line break tags don't need to be ended. XHTML uses <br /> and HTML uses <br>. The forum is XHTML, though it's not valid (not my fault, phpBB's fault). The frontpage uses HTML 4.01, which uses <br> line break tags, and it's fully HTML 4.01 compliant. There are a few examples of tags that don't require closing tags. For example, list items:
Code:
<ul>
<li>some list item
<li>some other list item
</ul>
An unordered list with 2 list items. This code would create this:
- some list item
- some other list item
notice how the <li> tags doesn't require a closing tag after the text. Another example would be input tags, they don't require to be closed either, though in XHTML you end them like this:
Code:
<input type="text" name="textbox" id="textbox" value="I'm a textbox" />
In HTML you wouldn't have the / at the end.
And Poison, I'm not sure what you mean by "enter text", but to make an error box with a tooltip you could do something like this:
Code:
<div style="width:250px;height:25px;border:1px solid #ff0000;color:#ff0000;font-weight:bold;text-align:center;">ERROR! YOU SUCK!</div>
This is a mix of HTML and CSS, but it makes a 250 pixels by 25 pixel box with a red 1 pixel border, and bold red text centered inside. _________________

~HaLo2FrEeEk
I wrote:
I'm sexy, admit it.
Are you?
 |
|
| Friday, February 26, 2010 2:00:30 pm |
|
 |
 |
 |
| Author |
Message |
HaLo2FrEeEk Overlord Extraordinaire
 Joined: 15 Aug 2006 Posts: 4773 Status: Offline Style: Xbox 360 Location: Trying really hard to do something
|
Post subject: |
|
|
So it turns out this technique only works with cylindrical panoramas. When working with a spherical panorama it uses a completely different format. I'll have to do some more research and see how spherical panorama JPEs are created and modify my program to suit those as well.
Edit: I did some research and finally nailed down what each value in the file does (except one). I wrote up a little whitepaper for it:
Code:
48-byte Header block
Offset | Size | Description
---------+--------+---------------------------------------------------------
0x0 | 0x4 | Unknown (version?) Seems to always be 20
0x4 | 0x4 | Number of image faces (12 for cylinder, 6 for spherical)
0x8 | 0x4 | Width of each image face
0xC | 0x4 | Height of each image face
0x10 | 0x4 | Number of tiles per image, X axis
0x14 | 0x4 | Number of tiles per image, Y axis
0x18 | 0x24 | Total number of images, 0x4 bytes long repeated 6 times
24-byte Image Information block
Offset | Size | Description
---------+--------+---------------------------------------------------------
0x0 | 0x4 | Image number (starting with 0, so 0=1, 1=2, etc.)
0x4 | 0x4 | Width of image
0x8 | 0x4 | Height of image
0xC | 0x4 | Top-left corner location, X axis (for tiled image faces)
0x10 | 0x4 | Top-left corner location, Y axis (for tiled image faces)
0x14 | 0x4 | Image size in bytes
The format is the same for Cylindrical and Spherical panoramas, spherical ones just have more images embedded into them.
A cylinder panorama only has 12 images, as described in the first post. A spherical one seems to have (at least in the panorama I used) as many as 54 images. The way the flash player makes a spherical panorama is actually a misnomer; it's not a sphere, it's a cube! There is no shadowing, and the way the image is mapped to the cube makes it so you'll never know that it's a cube, but it is. So basically what's happening is a cube has 6 sides, notice the second value in the first table above. Each side of the cube, each face, is split into 9 tiles, to speed up loading. That means there are 9 * 6 images total, or 54. The program uses the values in the information block to determine where to place each tile on each side in relation to the top-left corner, so for a 200x200 tile, tile 1 would be at (0,0), tile 2 would be at (200,0), and tile 3 would be at (400,0), then tile 4 would be at (0, 200), etc, until each tile is used and the full image face is constructed. I'm still not sure if there's a certain order to the whole thing, but I'm sure there has to be. I'll figure it out.
Now to update my program with my newfound knowledge...
...Eh, I'll do it later. _________________

~HaLo2FrEeEk
I wrote:
I'm sexy, admit it.
Are you?
 |
|
| Sunday, March 7, 2010 9:04:31 pm |
|
 |
Page 1 of 2
|
|
All times are GMT - 8 Hours Goto page 1, 2 Next
|
|
Display posts from previous:
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
 |
|
|