Unknown JPEG compression technique? - android

Well, so I've been digging through an android game's files trying to get sprites and the like. So I've managed to come across this folder called "raw", and inside were jpg files like imagelocal2.jpg (along with imagelocal2.list) and such. These files aren't valid images and can't be viewed normally, but they're big enough to contain many images inside of them.
What I'm wondering is, is there some unknown JPG compression-like method where they manage to squish a bunch of files into one? I opened the files with a hex editor but I couldn't make heads or tails of them (the fact that I have no experience with hex editors doesn't really help), so if anyone knows anything about how these files are compressed, please help.

There is no standard multi-image JPEG format. it would be anything with a JPG extension. No competently-written decoder would rely on the extension anyway.
You could take a look at the first few bytes and try to match the file signature.
http://en.wikipedia.org/wiki/List_of_file_signatures

Related

Android: How to load a vector drawable image into a webview?

Sorry if this is a repeat but I searched diligently and didn't find this question asked yet...
So back in ye olden days of Android, you could just add something like this to a WebView's source html:
<img src='file:///android_res/drawable/my.png'/>
And it would display my.png correctly in the WebView. But-- Android now supports (and prefers we use) these new-fangled vector drawables, and Android Studio's Vector Asset Studio makes it really easy to import them from SVG files or whatever.
The great thing is that for backwards compatibility, .pngs are automatically generated during the build for various dpi/screen sizes to support older devices. So if you're targeting an older device, there are .png images there.
If only I could reach them. Because, as far as I can tell, using vector graphics does break those file:///android_res/drawable/ img links in WebViews. Which is weird, because as I say there are .png files to see, if it only looked.
I've thought about a few methods to fix this, but none have worked:
Since .pngs are generated on-the-fly and are included in the .apk, I thought maybe I could point directly to one of the generated files with something like file:///android_res/drawable-hdpi-v4/my.png. (I checked the .apk file and that's where one of them was..) But no such luck there. Broken image.
Okay, I thought-- maybe there's a way to get the WebView to display the vector objects directly. That is, maybe the WebView would recognize an <img src="file:///android_res/drawable/my_image.xml"/> or something similar. I mean, Chrome can render svg right? Maybe it supports the .xml vector format too. But no dice here either. (Even if it had worked, it would be unlikely to support older pre-chromium webview versions.)
The third thing I tried is to include just one xxxhdpi-sized .png in res/drawable so that the webview would find it and hopefully display it. Unfortunately, this doesn't work either. It appears that just having an .xml vector in /drawable is enough to have it block the png, no matter if it's in the /drawable or /drawable-xxxhdpi directories.
So the obvious question: Is there a way to get the WebView to either display the vector xml (or the associated support .png that was generated)? How do we access drawables from HTML in a WebView w/Vector drawables? Esp. without having to do anything programmatically?
Anyone know how this is supposed to work? I guess the next thing to do is delve into the chromium/android source to try to find out how file:///android_res/drawable/ works, but that doesn't sound fun, so if anyone has an answer, that would be helpful.
I'm probably missing something really obvious here. Thx in advance!
Update: Other things I tried/ruled out include (1) removing underscores in image names (as I thought they might be replaced with "/"), (2) various permutations of baseurl in loadDataWithBaseUrl()
Well, four years later and the best solution I've come up with is just to have two vector files-- (1) the xml Android vector file for the app, and then (2) the identical image in the .svg format for the webview. This is still a smaller solution compared with providing a seperate .png or .gif for every dpi, etc.
SVG and the vector format are internally very similar, so it's not difficult to convert one to the other. In fact, Android Studio will convert SVG->XML. If you want to go the other way, just compare a few examples.
So just put your svgs in assets/svg/, and then you can access from a webview using <img src='file:///android_asset/svg/mysvg.svg'/> in your HTML.
There's still a storage hit. But svgs are relatively tiny (and you can minify-- ie, scoop out some of the extra fluff in the SVG file that isn't used by the webview) so it's not as bad as the alternative-- providing large binary image files in the apk.

Is it safe to read Android asset file with FileChannel?

I need to read binary file from asset folder in my app, and the way I'm trying to do it is by obtaining Channel:
AssetFileDescriptor assetFd = context.getAssets().openFd("file.db");
FileChannel fileChan = assetFd.createInputStream().getChannel();
The problem is that AssetManager, AssetFileDescriptor are very poorly documented classes and behave in unpredicted manner (as it seems to me). For example, if you will try to obtain fileChan.position() immediately after code above you won't get 0, in my case it'll be 976. After digging through StackOverflow I found out that it's normal behaviour and you need to be aware that assets are compressed into some internal binary form and AssetFileDescriptor isn't real file descriptor.
In my case I have a file structure with absolute byte positions stored in a header, so it seems like to read it properly I also need take into account assetFd.getStartOffset().
Also I've got zero clue about method AssetFileDescriptor.createInputStream behaviour after reading its doc:
This will either return a full asset AssetFileDescriptor.AutoCloseInputStream, or an underlying ParcelFileDescriptor.AutoCloseInputStream depending on whether the the object represents a complete file or sub-section of a file.
Lack of understanding whole picture and documentation makes me nervous about using this approach.
Should I be worried about AssetFileDescriptor.createInputStream behaviour when reading big files (over 1mb)? Is it safe to use Channels when reading asset files?
Thank you in advance!
The best way to deal with assets is to copy them to the internal or external storage and then read them with whatever method you want.
Thanks to #pskink for help!

Recover obfuscated/compressed font from an epub exported from InDesign

I've been trying to recover some fonts from an epub created with InDesign. I tried both Adobe and IDPF algorithms (I used this source). I tried obfuscating and undoing it with a font outside InDesign and it worked.
In my searches I found out that InDesign compress the fonts. What I wanted to know is how can I uncompress theses fonts in android. I tried using InflaterInputStream to uncompress it, but with no sucess causing a
IOException caused by: java.util.zip.DataFormatException: data error
I tried this approach because the font inside the epub file has 11kb and the original font has 253kb.
Well, tried to be as clearer as I could, any doubts please ask.
One piece of information that may be helpful is that InDesign CS5 now subsets fonts that are included in epub documents. The 253kb to 11kb size difference may simply be compression, but it seems somewhat unlikely.
So you may find that, even after extracting the font, it is not very helpful to reuse as it will be missing key characters that were not used in the ePub.

Android 2.2: best way to read small blocks of binary data from big files?

I'm developing for Android 2.2.
Things put to res and assets are compressed in the APK by default unless their extension indicates that they're already compressed (mp3, png). Moreover, before Android 2.3, to assets, you could only put uncompressed files of size less than 1 MB.
Question 1:
if I put a 1.5MB binary file to res/raw, and my program refers to it with its standard Android ID (R.raw.....), then will the system pull the whole file into memory? Since the 1.5MB is stored in a compressed way, I suppose it must. This is unpleasant because it is possible that the program only needs 1KB of data to be loaded from a given file offset. This can have a serious impact on app performance/speed.
I see two solutions:
(hack) Use mp3 or png extensions; but I am not sure this allows memory-efficient access after all (i.e. inputstream.skipbytes, etc.)
After the installation, at the first start of the app, the app will copy the files to its own writable working folder (in SD card). Since this point, it will always access the files from there instead of the R.raw... way. Therefore, the sequential read will work for sure, i.e. the memory usage will be no more than the actual data read from the specified file offset (apart from temporary read buffers used by inputstream.seek implementation, which are well-optimized i.e. small I suppose).
Question 2:
what is the best way of reading binary data memory-efficiently, from big files? I don't want to split my big files into many small ones unless that's the only way.
I'd go with #2 solution and then would use RandomAccessFile to avoid linear access.
I also would to opt for solution #2, but instead of using random access file, I would use java.nio.MappedByteBuffer - this way you will get fast random access with byte buffer semantic.

Reverse audio file in Android

I am in the very ealy stages of developing this app but looking into it I have already reached a problem. I need to be able to play an audio file backwards (you know like to reveal hidden messages ;)). I have no experience working with audio on android and have no idea if this is even possible.
I found a question on here which solves the problem in java (Click Here For Question)
But this makes use of the javax.sound library which android does not support. Will I need this library to solve this problem or is there another way to reverse an audio file?
A typical WAV file consists of a 44-byte header followed by the actual sample values. The size of a "frame" is dependent upon the WAV file's properties: a file that is stereo and 16-bits-per-sample will have a 4-byte frame size (two bytes for the left sample and two bytes for the right sample).
So in code, you would create a second WAV file by creating a byte array the same overall size as the original. You copy the 44-byte header from the original into the copy, and then iterate through the original frames starting at the last and working forward to the first. You copy each frame into the inverse location in the copy array (i.e. last original frame is copied into the copy array immediately after the header; second-to-last frame is copied after the first frame etc.). Then just play the reversed file.
So you don't need the javax.sound library to do this - you just need to be able to copy and manipulate bytes. FYI, not all WAV files are "canonical" like this (canonical means 44-byte header plus sample values, and nothing else). The WAV format is actually a RIFF format, which means in theory you need to do more complex extraction of the sample values. In practice (especially if you're creating the WAV files yourself) you can usually get away with a much simpler approach as I've described here.
NOTE: if your sounds are MP3 files, then reversing is a more complicated task, since the sample data are not stored as samples in an MP3 file. If you're using MP3s, one way to reverse them is to convert them to WAV and then reverse the WAV file.

Categories

Resources