Android ContentProvider generating data on-the-fly - android

In my app, I am exporting images with annotations. Because preparing all the images to be exported in advance would be too inefficient, I am rendering the images to be exported on the fly during the export. I do this with a custom ContentProvider for which the URI encodes the rendering parameters. The actual rendering is then done in ContentProvider.openFile(). This all works nicely.
However, I also have to provide results for the MediaStore MediaColumns in the query() method. But since the final image is not rendered yet, I do not know the SIZE of the data.
Searching for a solution, I came across this code:
http://code.google.com/p/openintents/source/browse/trunk/filemanager/FileManager/src/org/openintents/filemanager/FileManagerProvider.java?r=3267
which says in line 121 that for unknown sizes, we should return 'null' "according to the Android docs". But I cannot find this statement in any Android docs. Is this really the way to handle it? In fact, it works nicely with most apps I tried (e.g. GMail), but some simply show a zero file size (like AquaMail).
So, is returning 'null' for unknown file sizes in MediaStore.MediaColumns.SIZE the correct way to handle this?
And if yes, where is this documented?

Related

Reading custom files on storage card for android sdk 30

I have an app that creates custom files that are shown in a gallery. They are not images or other standard media files. Because the files are large, I ask users for access to a folder in which the files will be stored.
So far so good.
Reading those files or file info via DocumentFile is so much slower than via File. Operations like
DocumentsContract.findDocumentPath()
documentFile.isFile()
documentFile.getName()
take up to 15ms each, which accumulates to a large time when reading a large number of files.
What's the best way to handle this? Is there another way to do this? I don't want the files to be in internal app memory or users might lose their work when they uninstall the app.
Thanks in advance! This is stressing me out a lot.
Do it asynchronously. Do you need to get all of that data immediately? Probably not. So do it on a thread/in a coroutine, and just program your app to not display the data if you do not yet have it (and refresh itself when you do).
In addition, even if you do need it up front- do you need it for all files up front? In a gallery, you can make do with just the ones that are immediately displayed, and the next few which might be. So only fetch that, and get the others when you need them (or when its likely you'll need them soon). Treat it like fetching results from a web API- you don't fetch every post ever made, you fetch a few dozen, then you fetch a few dozen more when they're getting close to the bottom
In the end, DocumentFile is a wrapper around other APIs, a wrapper that is designed to provide a convenient, File-ish API for developers to use. It is not designed for bulk use. If you want to try to get more speed, you can look at the source code to DocumentFile and related classes used in its implementation, such as DocumentContract19, and work at a lower level.
For example, getName() winds up using this queryForString() method to do the real work. Making a query using ContentResolver adds IPC overhead, so if there are other values that you need that you can get in that same query, you could do the query yourself. For example, isFile() also winds up doing a query, so you could combine those two requests into one and cut the overall time in half (roughly).
Do not use DocumentFile class.
Only use DocumentsContract functions.
Its about twenty times as fast as DocumentFile and nearly as fast as classic file operations

How do I query the information needed to interpret a RAW_SENSOR image?

I need to write an Android app that, among other things, uses the Camera2 APIs to capture images in RAW format and process the resulting image data in the app. Other image formats such as YUV are not sufficient for my use case and true RAW images are required. I want to capture the image and immediately process it in-memory, without writing out an intermediate .dng file.
In order to do this, I need to use ImageFormat.RAW_SENSOR to get the image I want. The documentation for RAW_SENSOR states the following:
The layout of the color mosaic, the maximum and minimum encoding values of the raw pixel data, the color space of the image, and all other needed information to interpret a raw sensor image must be queried from the android.hardware.camera2.CameraDevice which produced the image.
However, the documentation for CameraDevice contains nothing about querying this information. A Google search turned up nothing helpful. I found this question with an answer that merely quotes what I quoted above and doesn't help figure out how to actually do it.
Thus I am lost. How do I query this information?
Android's RAW support is heavily based on what the Adobe DNG raw file format requires, so reading that spec can be helpful, to understand what the steps in RAW conversion actually are.
Quite a few fields in the CameraCharacteristics and CaptureResult objects are needed to interpret the raw buffer. The majority of the fields that start with SENSOR_ are required for processing.
See the list for the RAW capability as well, though that's still fairly vague.
The Android compliance tests include a very simple RAW processor, so you can also inspect it to see what it reads in.

Retrieving Pixels from a DNG file within Android

I am currently working on an HDR application that requires the use of Camera2 to be able to customize HDR settings.
I have developed a customized algorithm to retrieve certain data from Raw DNG images and I would like to implement it on Android.
I am unfortunately not an expert in Java/Android, so I taught myself how to code. Using other formats, I have usually worked with bitmaps to retrieve pixel data. ( which was relatively an easy task concerning the existing methods )
Concerning DNG files, I have found no documentation showing me how to retrieve the pixels data. I thought of bufferizing the image, however the DNG file format contains many information other than pixels and I'm afraid I am unable to find an extraction strategy using bufferstream. (I just want to store the pixels inside an array)
Anyone has an idea ? Would highly appreciate some tips.
Best regards
Camera2 does not produce DNGs directly - it produces plain RAW buffers, which you can then save to a DNG via DngCreator.
Are you operating on the initial RAW buffers, or saving DNGs and then loading them back?
In general, DNGs are not full baked images, so quite a bit of code is needed to render them completely - see for example Adobe's DNG SDK.

Does OneDrive change/re-encode jpg files?

I have encountered a strange problem I am unable to debug. An image is uploaded to Onedrive via some code very similar to the given example, and once uploaded, the image is visible in the OneDrive web interface.
http://msdn.microsoft.com/en-us/library/dn659727.aspx
Upon trying to download it, again using code from the example, the following line of code
Bitmap bMap = BitmapFactory.decodeStream(input);
also returns a null value for bMap. I know these files (which I obtain from copying from the Android Clipboard and writing to a file on disk) are valid, b/c I use them in Gridview elements and upload/download them to Dropbox in a similar way.
Is there some kind of jpg re-encoding performed in OneDrive (like RGB->CKMY conversion) what would no longer prevent them from working?
Also, is there some other type of query parameter like "/picture?type=thumbnail" or "/picture?type=normal" that needs to be appended to a file.XXXX OneDrive ID that would prevent any possible conversion?
Is there a way to debug exactly why the BitmapFactory.decodeStream() function fails, like debugging output?
EDIT: So, I came across the following SO post, and figured out this is the same problem I am having.
OneDrive - Wrong size for PNG files
For a certain file, if I download it using the Onedrive SDK and look at the stream length
public void onDownloadCompleted(LiveDownloadOperation operation) {
int length = operation.getContentLength();
}
it reports a size of 2723 bytes, but if I download the file and save it using a desktop web browser, the file is 1837 bytes. Is there something I am missing about reading the size of a stream, or is the API just broken?
This is documented behaviour as per http://msdn.microsoft.com/en-us/library/dn659726.aspx (see the first note under uploading).
You can disable conversion by adding downsize_photo_uploads=false to your query string.
The answer to this question apparently is, there is a bug in the Onedrive SDK. I ended up filing an issue on Github with Microsoft, and it turns out they discovered that with certain types of small images (and potentially PDFs), the actually file size being transmitted back after a download is wrong.
https://github.com/liveservices/LiveSDK-for-Android/issues/37#issuecomment-65457177
It's all just a weird artifact of the way I was testing my app. Since Chrome for Android is the only app I've discovered that lets you copy an image to the clipboard, I was just Google search to find images (tiny thumbnail images in the basic web search results), and copying those to the clipboard. Had I been using larger images, I may never have run across this bug.

storing information in png and jpg

I have found a number of resources but nothing that has quite helped me with what I am looking for. I am trying to understand the .png and.jpg file formats enough to be able to modify and/or read the exif or other meta data in the files or to create my own meta data if possible.
I want to do this in the context of an android application so we can keep if there but it is really not exclusive to that. I am trying to figure out how to do this using a simple imput stream byte array and go from there.
Android itself has to at least extract the RGB pixel information at some point when it creates a bmp image from the stream, I took a look in the BitMapFactory source to try and understand it but I got lost somewhere after delving into the Native files.
I assume the bmps are losing any exif/meta data in the files based on my research. So I guess I want to break the inputstreams down by byte arrays and remove meta data. In .pngs I know there is no 'standard' but based on this page it seems there is some organization of the meta data you can store.
With all that said, I wouldn't mind just leaving exif/png standards behind and trying to store my own information in some sort of standardized way, but I need to know more about how the image readers id the files as either jpg, png, ect. then determine where the pixel information is located.
So I guess my first question is, has anyone done something similar to this before so that they can file me in? If not, does anyone know of any good libraries that might be good for educational purposes into figuring out how to locate and extract this data?
Or even more basically, what is a good way to find meta data and/or the exif standard or even the rgb data programmatically using something like a byte array?
There are a lot of things to address in your question, but first I should clarify that when you say "Android itself has to at least extract the RGB pixel information," what you're referring to is the act of decompression, which is complicated in the case of JPEG, and non trivial even for PNG. I think it would be very useful for you to read through the wikipedias for JPEG and PNG before attempting to go any further (especially sections on header, syntax, file structure, etc).
That being said, you've got the right idea. It shouldn't be too difficult to read in the header of an image as a byte array/stream, make some changes, and replace the old file. A PNG file can be identified by the first 8 bytes, and there should be a similar way to identify a JPEG - I can't remember off the top of my head.
To modify PNG meta data, you'll have to understand "chunks" - types/names, ordering, format, CRC, etc. The libpng website has some good resources for this, here's general PNG info, as well as chunk specifications. Make sure you don't forget to recalculate the CRC if you change anything.
JPEG sections off a file using "markers," which are two bytes long and always start with FF. Exif is just a regular JPEG file with a more specific structure for meta data, and this seems like a reasonable introduction: Exit/TIFF
There are probably libraries for Android/Java that conveniently take care of this for you, but I've never used any myself. A quick google search turns up this, and I'm sure there are many other options if you don't want to take the time to write a parser yourself.

Categories

Resources