TTImageView shows black image (OR: replacement for TTImageView) - iphone

I'm using Three20's TTImageView for it's async image loading + caching.
I've noticed this issue a bunch of times where an image will show up as completely black, and never finish loading. Here's an example of what I'm seeing:
http://screencast.com/t/7O7fnedX5Z2
So...basically I'm wondering if this is a bug in three20, and if so, how I might go about fixing it (is there a patch out there that might fix it)...OR:
Is there a good TTImageView replacement that performs async image loading + caching?

Turns out I was seeing the following in my log:
TTRequestLoader connection:didReceiveResponse:: TTDASSERT failed: 0 == _queue.maxContentLength || contentLength <=_queue\
.maxContentLength
(one for each failed image)
After that, a little bit of googling rendered:
http://groups.google.com/group/three20/browse_thread/thread/8bfac3654a6d9674/caf797f265445971?pli=1
Jeff Verkoeyen:
The comment immediately before that
assert should shed some light on the
situation.
// If you hit this assertion it's because a massive file is about to be downloaded.
// If you're sure you want to do this, add the following line to your app delegate startup
// method. Setting the max content length to zero allows anything to go through. If you just
// want to raise the limit, set it to any positive byte size.
// [[TTURLRequestQueue mainQueue] setMaxContentLength:0]

Related

Load an Image from URL by many threads

I'm loading an image from URL into my app. The image size is large (around 1.5Mb). How can I use many threads (ex: 2 threads) to load this image to improve the speed? If using one thread to load this image, it takes me around 5s and I want to reduce this duration.
You are correct. 1.5Mb is a big image and the way to optimise is NOT to use many threads. Although you are on the right track. The technique is called "slicing" and is heavily used on web to load images faster. So take a image and slice it into 3 or 4 smaller pics (and not more) in your server. When rendering call these 4 images all at once. It will load faster than one big pic. Also this lessens the "perceived" latency for the end-user.
Also, when you slice up an image, it makes it easier to reduce the number of colors necessary to display that portion of the image, thus reducing your file size (sometimes fairly significantly).
As an example Google does used to do this for its main logo in its main search page. See 4 split us images of its logo?
The downside of slicing is that it increases maintenance costs. Some one has to maintain these image splits and make sure nothing goes amiss as the app keeps changing.
Please Try the following Code:
//in .h file declare the following objects:
IBOutlet UIImageView *imgTest;
-(IBAction)buttonTapped:(id)sender;
-(void)LoadImage:(NSString *) irlString;
-(void)setImage:(NSData *) imgData;
//in .m file write the following code:
-(IBAction)buttonTapped:(id)sender
{
[self performSelectorOnMainThread:#selector(LoadImage:) withObject:#"http://www.google.com/images/errors/logo_sm.gif" waitUntilDone:NO];
}
-(void)LoadImage:(NSString *) urlString
{
NSURL *imgURL=[NSURL URLWithString:urlString];
NSData *imgData=[NSData dataWithContentsOfURL:imgURL];
[self performSelectorInBackground:#selector(setImage:) withObject:imgData];
}
-(void)setImage:(NSData *) imgData;
{
imgTest.image=[UIImage imageWithData:imgData];
}
you can use activity indicator while loading the image as well. Start it in the buttonTapped method and stop it in the setImage method.
i hope this will help you.

three.js toDataURL PNG is black

I'm trying to grab a screenshot with renderer.domElement.toDataURL("image/png"), and save it to a file.
The image is the right size, but it's black.
I have preserveDrawingBuffer turned on.
I think I'm decoding and saving the file correctly, because when I hexdump it I can see the correct initial characters for the PNG format, as well as the IHDR and IDAT chunk headers. However the closing IEND is missing.
Any known issues here? Hints? Windows 7/Firefox up to date if it matters.
Thanks... (Sorry if this is dumb, I'm very new to three.js)
I had somewhat similar problems with Windows 7/Firefox. PNG Data URL's would be randomly truncated or something, much shorter than a successful PNG export. Trying to set that data url as image src resulted in "Image corrupt" exception or something in FF. As little sense it makse, setting a small window.setTimeout (10ms) between rendering and getting the data URL helped in my case. Maybe Firefox needs a rest from the JS engine before it refreshes some canvas internal state or something.. weird.
I switched to JPG format (smaller files => truncation less of an issue?) and still saw it not working, then I tried this tip which I found here
If you want to save data that is derived from a Javascript
canvas.toDataURL() function, you have to convert blanks into plusses.
If you do not do that, the decoded data is corrupted:
<?php
$encodedData = str_replace(' ','+',$encodedData);
$decodedData = base64_decode($encodedData);
?>
This worked. Thanks, Mekal.
This tip seems to apply to JPGs only. I saw PNGs decoding correctly without the + replacement, and corruptly with it. I can use JPGs so my personal problem is solved. However I never saw a PNG that wasn't black even when decoded correctly and not truncated.
Kind of a lousy situation either way, I feel like. What is up with the +'s?
A black texture is a sign that you did not indicate the texture needs to be updated.
Also, you do not need to use canvas.toDataURL(). You can pass in the canvas reference to the THREE.Texture object.
var canvas = document.getElementById('#myCanvas');
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
// Now render the scene

GPUImageMovieWriter frame presentationTime

I have a GPUImageColorDodgeBlend filter with two inputs connected:
A GPUImageVideoCamera which is getting frames from the iPhone video camera.
A GPUImageMovie which is an (MP4) video file that I want to have laid over the live camera feed.
The GPUImageColorDodgeBlend is then connected to two outputs:
A GPUImageImageView to provide a live preview of the blend in action.
A GPUImageMovieWriter to write the movie to storage once a record button is pressed.
Now, before the video starts recording, everything works OK 100% of the time. The GPUImageVideo is blended over the live camera video fine, and no issues or warnings are reported.
However, when the GPUImageMovieWriter starts recording, things start to go wrong randomly. About 80-90% of the time, the GPUImageMovieWriter works perfectly, there are no errors or warnings and the output video is written correctly.
However, about 10-20% of the time (and from what I can see, this is fairly random), things seem to go wrong during the recording process (although the on-screen preview continues to work fine).
Specifically, I start getting hundreds & hundreds of Program appending pixel buffer at time: errors.
This error originates from the - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex method in GPUImageWriter.
This issue is triggered by problems with the frameTime values that are reported to this method.
From what I can see, the problem is caused by the writer sometimes receiving frames numbered by the video camera (which tend to have extremely high time values like 64616612394291 with a timescale of 1000000000). But, then sometimes the writer gets frames numbered by the GPUImageMovie which are numbered much lower (like 200200 with a timescale of 30000).
It seems that GPUImageWriter is happy as long as the frame values are increasing, but once the frame value decreases, it stops writing and just emits Program appending pixel buffer at time: errors.
I seem to be doing something fairly common, and this hasn't been reported anywhere as a bug, so my questions are (answers to any or all of these are appreciated -- they don't all need to necessarily be answered sequentially as separate questions):
Where do the frameTime values come from -- why does it seem so arbitrary whether the frameTime is numbered according to the GPUImageVideoCamera source or the GPUImageMovie source? Why does it alternative between each -- shouldn't the frame numbering scheme be uniform across all frames?
Am I correct in thinking that this issue is caused by non-increasing frameTimes?
...if so, why does GPUImageView accept and display the frameTimes just fine on the screen 100% of the time, yet GPUImageMovieWriter requires them to be ordered?
...and if so, how can I ensure that the frameTimes that come in are valid? I tried adding if (frameTime.value < previousFrameTime.value) return; to skip any lesser-numbered frames which works -- most of the time. Unfortunately, when I set playsAtActualSpeed on the GPUImageMovie this tends to become far less effective as all the frames end up getting skipped after a certain point.
...or perhaps this is a bug, in which case I'll need to report it on GitHub -- but I'd be interested to know if there's something I've overlooked here in how the frameTimes work.
I've found a potential solution to this issue, which I've implemented as a hack for now, but could conceivably be extended to a proper solution.
I've traced the source of the timing back to GPUImageTwoInputFilter which essentially multiplexes the two input sources into a single output of frames.
In the method - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex, the filter waits until it has collected a frame from the first source (textureInput == 0) and the second, and then forwards on these frames to its targets.
The problem (the way I see it) is that the method simply uses the frameTime of whichever frame comes in second (excluding the cases of still images for which CMTIME_IS_INDEFINTE(frameTime) == YES which I'm not considering for now because I don't work with still images) which may not always be the same frame (for whatever reason).
The relevant code which checks for both frames and sends them on for processing is as follows:
if ((hasReceivedFirstFrame && hasReceivedSecondFrame) || updatedMovieFrameOppositeStillImage)
{
[super newFrameReadyAtTime:frameTime atIndex:0]; // this line has the problem
hasReceivedFirstFrame = NO;
hasReceivedSecondFrame = NO;
}
What I've done is adjusted the above code to [super newFrameReadyAtTime:firstFrameTime atIndex:0] so that it always uses the frameTime from the first input and totally ignores the frameTime from the second input. So far, it's all working fine like this. (Would still be interested for someone to let me know why this is written this way, given that GPUImageMovieWriter seems to insist on increasing frameTimes, which the method as-is doesn't guarantee.)
Caveat: This will almost certainly break entirely if you work only with still images, in which case you will have CMTIME_IS_INDEFINITE(frameTime) == YES for your first input'sframeTime.

iphone Dev: Invalid Context CGContextDrawLayerInRect

I have a uiscrollview within three subUIViews 1, 2, 3. I load content for subUIView1, 2,3 dynamically. Here are steps
I create scrollview with these 3
subUIview and with a default size
for each subUIView
I create an operation for each subUIView, let us say Operation 1,2,3. add to operation queue
every Operation (operation 1) calculate the content that will be later draw in related subUIView (subview 1). after calculate completed, create CGLayer and attach it with UISubview1. reset all UIsubviews frame and bound and layout scrollview subviews and setNeedDisplay for related subUIview1. then move to next operation
in SubUIView drawRect method, i call CGLayerDrawInRect.
then occasionly i
get this error Invalid Context.
sometimes, it work fine, no error sometime it happened
Any idea about this error will be welcome.
.
Take a very long time to debug and finally find what is the problem and resolved. Here is the thing
When operation 1 setNeedDisplay sent out, drawRect have not called yet
Once drawRect is called, operation 2 is already running, during drawRect running,operation 2 somehow change subview1,2,3, layout and frame at the same time.
So, the bad thing happened, context will become invalid that time because frame are changing, and also worst, you may receive exe_bad_access false message
Resolve solution, i set a singal to make sure operation 1 drawRect is done then let operation 2 start run.
I have to say XCode is terrible development tools compare what MS studio tools. It gives message like invalid Context or exe_bad_access randomly. where is the productivity for our poor developer. However, Iphone OSX is much better than MS windows mobile. that is why i am working hard to use XCode creatively.

Turning on anti-aliasing in SWT

I've called gc.setAntialias(SWT.ON); and it does nothing. According to that method, it should work.
The Javadoc states:
Sets the receiver's anti-aliasing
value to the parameter, which must be
one of SWT.DEFAULT, SWT.OFF or SWT.ON.
It's not working for me, and I'm painting on a simple Canvas.
The following worked for me in an app I built and my guesses at when/how you have to do this.
So I created a new GC, set the Antialias as you did and then drew what I needed to with that gc object. The key is attaching it to the shell you will draw in.
GC gc = new GC(shell);
gc.setAntialias(SWT.ON);
//then I attach to LightweightSystem for testing.
LightweightSystem lws = new LightweightSystem(shell);
Other than that make sure you do this before you draw anything. If you have to call it afterwards maybe try calling a repaint or redraw of the entire space.
Sorry without more information I am not sure exactly what is wrong.
Following derBiggi's answer, you ca also force the advanced option to true.
gc.setAdvanced(true)
Also, if you're drawing labels, make sure you use gc.setTextAntialias( SWT.ON );
You can also check if gc.getAdvanced() returns true, it should after setAntialias() or setTextAntialias was set.
Besides from that it's pretty straight forward.