How to load Vuforia QCAR tracking file data during runtime in iOS - iphone

I am working on Augmented reality using Vuforia sdk, and i want to load 3d object on runtime, i want to fetch it from web-service and load it when i need that, So basically my question only is this how can we load any .h file on run time. First is this possible that we can load it on runtime and if possible then how can we do that.

If you have dynamic data, putting it into a .h file doesn't make sense. Headers are only useful while the program is being compiled, not at run time.

AFAIK vuforia just puts arrays of vertical, triangles, etc. into h file. So you don't need to load h file in runtime (and this is impossible, there is no h files when programm is running). Instead you need to get those arrays and give them to vuforia

just download that file from network, store it within application directories and load it like the sample data bundled with the app
NSString * pathToDownloadedFile; //should have path to your file
QCAR::DataSet *dataSet = nil;
QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*> (trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));
dataSet = imageTracker->createDataSet();
dataSet->load([pathToDownloadedFile cStringUsingEncoding:NSASCIIStringEncoding], QCAR::DataSet::STORAGE_ABSOLUTE);
imageTracker->activateDataSet(dataSet);

Related

JPEG encoder super slow, how to Optimize it?

I'm building an App with actionscript 3.0 in my Flash builder. This is a followup question this question.
I need to upload the bytearray to my server, but the function i use to convert the bitmapdata to a ByteArray is super slow, so slow it freezes up my mobile device. My code is as follows:
var jpgenc:JPEGEncoder = new JPEGEncoder(50);
trace('encode');
//encode the bitmapdata object and keep the encoded ByteArray
var imgByteArray:ByteArray = jpgenc.encode(bitmap);
temp2 = File.applicationStorageDirectory.resolvePath("snapshot.jpg");
var fs:FileStream = new FileStream();
trace('fs');
try{
//open file in write mode
fs.open(temp2,FileMode.WRITE);
//write bytes from the byte array
fs.writeBytes(imgByteArray);
//close the file
fs.close();
}catch(e:Error){
Is there a different way to convert it to a byteArray? Is there a better way?
Try to use blooddy library: http://www.blooddy.by . But i didn't test it on mobile devices. Comment if you will have success.
Use BitmapData.encode(), it's faster by orders of magnitude on mobile http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html#encode%28%29
You should try to find a JPEG encoder that is capable of encoding asynchronously. That way the app can still be used while the image is being compressed. I haven't tried any of the libraries, but this one looks promising:
http://segfaultlabs.com/devlogs/alchemy-asynchronous-jpeg-encoding-2
It uses Alchemy, which should make it faster than the JPEGEncoder from as3corelib (which I guess is the one you're using at the moment.)
A native JPEG encoder is ideal, asynchronous would be good, but possibly still slow (just not blocking). Another option:
var pixels:ByteArray = bitmapData.getPixels(bitmapData.rect);
pixels.compress();
I'm not sure of native performance, and performance definitely depends on what kind of images you have.
The answer from Ilya was what did it for me. I downloaded the library and there is an example of how to use it inside. I have been working on getting the CameraUI in flashbuilder to take a picture, encode / compress it, then send it over via a web service to my server (the data was sent as a compressed byte array). I did this:
by.blooddy.crypto.image.JPEGEncoder.encode( bmp, 30 );
Where bmp is my bitmap data. The encode took under 3 seconds and was easily able to fit into my flow of control synchronously. I tried async methods but they ultimately took a really long time and were difficult to track for things like when a user moved from cell service to wifi or from tower to tower while an upload was going on.
Comment here if you need more details.

Canon EDSDK sample code - help to understand save file to location

I am new to the EDSDK, but so far have been very happy with the results. I have my program working just fine saving to the camera, however when I set to saveTo Host I'm unclear on where it thinks it's supposed to save to.
Everything appears to work. Callback function gets called, progress bar animates but I have no idea where it thinks it's pointing the file to.
the closest I get is finding where the #"download" command is issued, the argument to this call should be getting cast as a (EdsDirectoryItemRef)
This all seems to be coming from the EDSCALLBACK handleObjectEvent but I can't figure out how it gets constructed.
Ideally I'd like to be able to specify where on disk I want the images to go. Can someone provide some aid?
[edit]
Okay, I see the images are going into the build directory, but perhaps someone could help me to understand why. Or even better how to specify a path for myself.
When you set saveTo_Host, the image is stored on a temporary memory in the camera. The camera then triggers a DirItemRequestTransfer event that would call the callback function 'handleObjectEvent'. The reference to the image, stored in the temporary camera memory, is passed to the callback function.
Within the handleObjectEvent callback function you probably would be creating a file stream and using EdsDownload to download the file to the location on the PC (which is specified by the file stream).
When you create a file stream you need to specify a file name (the first argument). This file name determines where the image would be stored. If you just specify the file name without a path the image gets stored in the build directory. If you would like to save the file in a particular location you need to specify the file name along with its path.
Hope this helps.

Using offline database in Route-Me

I'm trying to use an offline MBTiles database using Route-Me. To accomplish this, I'm using Landez, which in turn depends on MBUtil.
Right now, all I get is a gray screen with the pins in their proper locations. Here's what gets printed to the console:
initializing memory cache <RMMemoryCache: 0x4e42e50> with capacity 32
Opening database at /Users/chrislong/Library/Application Support/iPhone Simulator/4.3.2/Applications/E53BC885-1B02-4B06-B45B-408EB9A147DE/Documents/MapOpenStreetMap.sqlite
Map contents initialised. view: MapView at 0,0-320,411 tileSource <RMCachedTileSource: 0x4e428b0> renderer <RMCoreAnimationRenderer: 0x4e13dc0>
initializing memory cache <RMMemoryCache: 0x5929930> with capacity 32
Opening database at /Users/chrislong/Library/Application Support/iPhone Simulator/4.3.2/Applications/E53BC885-1B02-4B06-B45B-408EB9A147DE/Documents/MapMBTilestiles.mbtiles.sqlite
Warning: I could not find the column named 'tile_data'.
Warning: I could not find the column named 'tile_data'.
Warning: I could not find the column named 'tile_data'.
Warning: I could not find the column named 'tile_data'.
Map contents initialised. view: MapView at 0,0-320,411 tileSource <RMCachedTileSource: 0x592a400> renderer <RMCoreAnimationRenderer: 0x5925770>
It's worth noting that the file is named tiles.mbtiles, not MapMBTilestiles.mbtiles.sqlite, and is stored in the root of the bundle, not the Documents folder.
Here's the code I use to make the mapView and load the database:
CLLocationCoordinate2D center = {50, 50};
self.mapView = [[[RMMapView alloc] initWithFrame:self.view.frame] autorelease];
self.mapView.backgroundColor = [UIColor blackColor];
self.mapView.delegate = self;
NSURL *tilePath = [[NSBundle mainBundle] URLForResource:#"tiles" withExtension:#"mbtiles"];
RMMBTilesTileSource *tiles = [[[RMMBTilesTileSource alloc] initWithTileSetURL:tilePath] autorelease];
[self.mapView.contents removeAllCachedImages];
self.mapView.contents = [[[RMMapContents alloc] initWithView:self.mapView tilesource:tiles centerLatLon:center zoomLevel:0.0 maxZoomLevel:[tiles maxZoom] minZoomLevel:[tiles minZoom] backgroundImage:nil] autorelease];
[self addMarkers];
Route-Me is obviously not reading the file at all; even if I delete the database entirely, I get the same log output. IOW, the problem is probably as a result of Route-Me being unable to find the file. Any help would be appreciated!
Check out - (RMTileImage *)tileImage:(RMTile)tile from MapView->Map->Tile Source
I was having some issues with sqlite db's generated by map2sqlite until I changed the line:
NSInteger y = pow(2, zoom) - tile.y - 1;
to:
NSInteger y = tile.y;
I'm using tilemill generated db's right now, so I haven't dug into it further, but I'd toss in some debug statements if I were you and look at what tiles its looking for vs what the tile layout in your db is. I think it might have to to do with mbtiles tiling order vs osm's tiling order.
-- Randy
I actually wrestled with this very problem yesterday.
There seem to be two different tile formats out there, google xyz and TMS which is used by openstreetmap.
The line Randy highlighted
NSInteger y = pow(2, zoom) - tile.y - 1;
Is converting one to the other. So for example I am building my map using Maperative, then exporting it to tiles in a directory and finally using mb-util to generate the tiles.mbtiles file.
And I was having the exact same issue, make the changes that Randy suggested above and it works.
ultimately however I wrote a php script to rename the filenames of the tiles to be correct. I'll be honest I still haven't quite got my head around which pieces of software are exporting in what format. I think mbtiles is supposed to be TMS which implies that route-me is xyz, but I could be wrong on that.
I made your change above but then had some problems centering the map. After working on it for quite some time I change the line you mention above to this:
NSInteger y = tile.y - (pow(4, ((zoom / 2) - 1)));
Hope this helps anyone also having trouble.

How do I extract pixel data from DICOM files on iOS?

Does anyone know how I can extract the pixel data from a DICOM file and pass it to an image viewer on iOS?
Sorry if this is a simple question, but it seems to be a major component to a huge can of worms I have opened.
I'm using GDCM on iOS. I haven't pushed it very hard yet but it's working well so far. I basically followed the directions for hacking XCode projects to run in iOS in this excellent article on ITK.
Here's how I got it to compile for iOS:
Downloaded source from sourceforge, installed cmake via ports. You'll need a recent version of cmake (I'm using 2.8.2)
If the source is in a folder called gdcm-2.0.17/, then create another directory at that level (say gdcmbin), cd to that directory, and enter ccmake -GXCode ../gdcm-2.0.17/ in the terminal window. This creates the XCode project. When I did this I didn't create any of the example programs or create shared libraries (which won't work in iOS). Just run the defaults.
Follow the directions in the ITK paper on changing the build options (step #7 on page 4).
Then link GDCM into your project using the excellent instructions at Clint Harris' blog
When you're setting up the header search path in your project to GDCM - you have to enter two paths: blah/gdcm-2.0.17/Source/** and blah/gdcmbin/**. The trailing '/Source' on the first path is necessary - otherwise you get headers that aren't appropriate for your architecture.
One glitch (annoying but haven't spent the time to figure it out yet): you get a bunch of linking errors when you switch from simulator to device (or vice versa). This is because the gdcm project doesn't put the outputs into different directories for different targets. So - run a clean and rebuild in the gdcm project when you're switching. I'll probably get annoyed by this soon enough to change it :-).
Here's a rough snippet of how you'd call the library and put the results in an Objective-C dictionary:
NSMutableDictionary * imageDictionary = [[NSMutableDictionary alloc] initWithCapacity:40];
// The output of gdcm::Reader is a gdcm::File
gdcm::File &file = reader.GetFile();
// the dataset is the the set of element we are interested in:
gdcm::DataSet &ds = file.GetDataSet();
const Tag studyInstance(0x0020,0x000d); // Study Instance UID
const DataElement &dicomVal = ds.GetDataElement(studyInstance);
std::string stringVal( dicomVal.GetByteValue()->GetPointer(), dicomVal.GetByteValue()->GetLength() );
NSString *val = [NSString stringWithCString:stringVal.c_str() encoding:[NSString defaultCStringEncoding]];
[imageDictionary setObject:val forKey:#"studyInstanceUID"];
(Note: this is in an *.mm file that mixes C++ and ObjectiveC)
Imebra has an Objective-C wrapper that can be used also with Swift.
#import "imebraobjc/imebra.h"
// Get the DICOM dataset from file
NSError* error = nil;
ImebraDataSet* pDataSet = [ImebraCodecFactory loadFromFile:#"test.dcm" error:&error]
// CHeck the patient name (automatically convert from DICOM charsets to UTF-8)
NSString* checkPatientName = [pDataSet getString:[[ImebraTagId alloc] initWithGroup:0x10 tag:0x10] elementNumber:0 error:&error]; // Automatically converted to UTF-8 if necessary
// Get the frame 0
ImebraImage* pCheckImage = [pDataSet getImageApplyModalityTransform:0 error:&error];
// Get the image data
ImebraReadingDataHandlerNumeric* readingDataHandler = [pCheckImage getReadingDataHandler:&error];
// Scan the pixels. Access the data handler memory for faster data access
for(unsigned int pixel(0); pixel != readingDataHandler.size; ++pixel)
{
unsigned int pixelValue = [readingDataHandler getUnsignedLong:pixel error:&error];
}
ImebraDrawBitmap* pDrawBitmap = [[ImebraDrawBitmap alloc] init];
// Obtain a NSImage (UIImage on iOS)
NSImage* pNsImage = [pDrawBitmap getImebraImage:pCheckImage error:&pError];
If you want to find DICOM software, look at idoimaging.com, a clearinghouse for medical imaging software. You can choose your platform, input format, output format, language, etc. iOS isn't listed as a format, but much of the software listed there is available with source, useful in library form, and available for MacOS X. For example, I selected:
input format: DICOM
platform: Macintosh
language: C
and found several packages. Given the similarities between MacOS and iOS and the fact that some of these are cross-platform with source included, it shouldn't be too difficult to get one of them working on iOS.

iPhone/iPad Base64->NSData->PDF how to?

Obj-C or Monotouch.Net C# answers are fine.
I have a Base64 string that is a PDF document received over a web service. I can get the NSData.
How do I take the NSData and save it as a PDF?
-- I get the NSData this way --
byte[] encodedDataAsBytes = System.Convert.FromBase64String (myBase64String);
string decoded = System.Text.Encoding.Unicode.GetString (encodedDataAsBytes);
NSData data = NSData.FromString (decoded, NSStringEncoding.ASCIIStringEncoding);
The simplest way to save it is probably to use NSData's writeToFile:options:error: method.
I found that using the .NET framework works better than trying to use the iOS framework for this problem. This will take any file and convert it to it's original then save it to the iPhone/iPad device. "path" is just a folder on the dev ice.
using (var f = System.IO.File.Create (path))
{
byte[] encodedDataAsBytes = System.Convert.FromBase64String (Base64PDFString);
f.Write (encodedDataAsBytes, 0, encodedDataAsBytes.Length);
}
I'm working on a project where I recently had to accomplish the same thing you are describing. I get base64 encoded PDF files as strings from a .NET web service which need to be decoded to their original and saved as PDF files in the applications documents directory.
My solution was:
Use ASIHTTPRequest to communicate with the web service.
I then use TBXML to parse incoming xml and get the base64 as an NSString.
To decode the string I use a method from QSUtilities library called decodeBase64WithString.
Finally I save the result with NSData's writeToFile.
I have tested and successfully used this method with PDF files that are up to 25mb. I also had a couple of test runs with a 48mb file but that file made the decodeBase64WithString method take up too much memory and my app crashed. Haven't found a solution to this yet..
If you are working with multiple large files be sure to free up your memory once in a while. I got all my files in one loop in which I had to use my own nsautorelease pool and drain it at the end of the loop to free up any autoreleased objects.