Strange Delphi Android image assign / image garbled issue - android

I have some code that works fine in iOs, but which results in completely messed up images when on Android. I have found a partial workaround (not call some code), but it hints something is terrible wrong:
// some bitmap object buffer for mainthread only
R.BitmapRef := FPersistentBitmapBuffer;
// this TImage now contains the original wrongly sized bitmap
ImageBackground.Bitmap.Assign(R.BitmapRef);
// calculated somewhere
TmpNewWidth := 500;
TmpNewHeight := 500;
// draw the bitmap resized to wanted size
R.BitmapRef.Width := Round(TmpNewWidth);
R.BitmapRef.Height := Round(TmpNewHeight);
R.BitmapRef.Canvas.BeginScene();
R.BitmapRef.Canvas.DrawBitmap(ImageBackground.Bitmap, RectF(0,0,ImageBackground.Bitmap.Width,ImageBackground.Bitmap.Height), RectF(0,0,TmpNewWidth,TmpNewHeight), 1);
R.BitmapRef.Canvas.EndScene();
// assign it back to the image
ImageBackground.Bitmap.Assign(R.BitmapRef);
// THIS code causes the image shown in TImageBackground to look completely garbled ... which would indicate something is shareing memory/reference somewhere somehow... There is more odd behavior like debugger unhooking (it seems) if mouse in Delphi debugger hovers over ImageBackground.Bitmap - no error is reported
R.BitmapRef.Clear(TAlphaColorRec.White);
As can be seen, it the last line that messes it up. In some tests it has seemed to be enough to remove he line, but not in others. This is my best lead/description/example of the problem.
Here is an example of how a garbled image looks like. Since they look garbled the same way each time I run the app, I suspect it must be somehow relate to the image, but there is not any visual similarity.
My question is what could be wrong? I am testing the Delphi XE7 trial, so I can not access the source. It worked flawlessly on iOS using XE4 and XE7, but with Android something is going on. I am thinking it could possibly be some bitmap data that is sharing a reference... Does anyone have any ideas on how to test this theory / possible workarounds?

This looks plainly wrong. I'd suggest that you fill a bugreport at http://quality.embarcadero.com
Try using CopyFromBitmap instead of the "Assign". This will create a unique copy of the image. You'll also get a new unique image if you call MyBitmap.Map(TMapAccess.Write, MyBitmapData); followed by MyBitmap.UnMap(MyBitmapData);.

Related

Unity canvas scaler hiding animations in high resolution display

I instantiate the following gameObject, which contains an Animator with the mode "always animate" on, the animation goes for 340ms, after that time I destroy the gameObject.
The gameObject Inspector properties:
I instantiate it using the following code:
instancia = (Instantiate(cardAnimation, new Vector3(0, 0, 0), Quaternion.identity) as GameObject).GetComponent<Image>();
instancia.rectTransform.SetParent(transform);
StartCoroutine(KillOnAnimationEnd());
Here is the Coroutine:
private IEnumerator KillOnAnimationEnd()
{
yield return new WaitForSeconds(0.34f);
DestroyImmediate(instancia);
}
Here is how the animation looks like when simulating in Unity (PC-Windows):
But on android after I open the chest it waits 340ms with nothing happening and then show the information above, does this have something to do with the plataform or is some unity or perhaps code related issue?
NOTE: I also have another animation in another scene that is just a already instantiated gameObject in the Hierarchy with always animated on and it works on Android.
--EDIT--
So I have ran the newest version of the app in a emulator which is almost about 1080x480 and the animation showed just as the PC, also running on a 720p smartphone did the job, the only problem I'm still having is with my QuadHD resolution from Galaxy S6, everything else shows but the animation, I have even tried making the animation run without any script so it runs in a loop, but it doesn't show up in galaxy screen.
Given the news about the issue I think this might change a little bit the perspective of answers and perhaps help someone else solve the same problem in the future.
Okay, figured out the problem, its something to do with "rotation" in animations using Unity3D in 2D mode, gonna be reporting it form Unity so it is fixed.
The solution: Animate your UI only using scale/position, if used rotation it will not show on high resolution display.
I am pretty sure your WaitForSeconds(0.34f) is not working properly because there is no thing such as yield keyword in Java. I recommend you to use a invoke method instead to call your method that destroys your GameObject.

How to work with anti-alias on delphi firemonkey and android

I work on delphi xe7 with firemonkey and testing on android.
When i work on a device that have a normal resolution of 1 (scene.scale=1) then component like TRoundRect, TPie, etc produce ugly result because they are not anti-aliased (or the anti-alias is not visible by humain eyes). if i work on high definition device (scene.scale=2 for exemple), then it's not really a big problem because high definition compensate the problem.
So first question, is their any way to make theses component produce anti-alias graphic ?
also how to draw directly on the canvas an anti-aliased disque (with an image in it) ?
Now when i work on bitmap and on canvas, i notice that the FillText produce anti-aliasing result. this is in someway good for what i want previously (for disque) but a little disaster for text because it's make them "blur".
it's even worse when i do first Mybitmap.canvas.FillText => produce a little of antialias and then later i do MyPaintBox.canvas.DrawBitmap(MyBitmap) it's will add AGAIN more anti-alias ! the text will be very blur at the end :( it's sound crazy for me that
doing canvas.drawBitmap without any distorsion in the srcRec and destRect not copy the exact pixel from bitmap to the canvas :(
so it's their a way to :
Call canvas.FillText without any anti-alias or to configure the level of anti-alias.
Call canvas.DrawBitmap without any anti-alias at all ! pixel perfect copy from bitmap to the canvas
thanks by advance for your help !
some solutions i found todays (and theirs problems) :
I found a way how to make all the visual controls (troundrect, etc) with anti-aliasing : set Tform.quality to highQuality !
But now i m facing another very strong problem that i can not understand :(
maybe a bug in delphi so if someone can look at it i will be very thanks to him ...
when you need a canvas for the form it's created via
constructor TCanvasGpu.CreateFromWindow(...AQuality: TCanvasQuality)
and here the quality is taken from the MyForm.quality
now the problem is with TBITMAP :( same as previous when we need the canvas for the bitmap it's created via
constructor TCanvasGpu.CreateFromBitmap(....AQuality: TCanvasQuality=TCanvasQuality.SystemDefault)
but here the problem their is NO PROPERTY at all in the bitmap to setup the quality of the canvas :(
so i try this solution :
aBitmap := Tbitmap.Create(w,h);
try
aCanvas := TCanvasManager.CreateFromBitmap(ABitmap, TCanvasQuality.HighQuality);
Try
aCanvas.BeginScene;
try
aCanvas.Fill.Kind := TbrushKind.solid;
acanvas.Fill.Color := $ff000000;
aCanvas.FillRect(TRectF.Create(0, 0, w, h), w / 2, h / 2, ALLcorners, 1);
finally
aCanvas.EndScene;
end;
Finally
aCanvas.Free;
End;
....
and i was thinking i will have now on my bitmap the same antialiasing effect of what i have when i draw directly on the canvas of the form ? absolutely not, nothing change and i still have ugly round without any anti-aliasing :(
what i miss ??
EDIT:
The only option i found for now to remove the antialias is to make the bitmap 2x more bigger and reduce it after by 2x! crazy :( but the algorithme of reduction remove the aliased ... but the cost of all of this is that the speed become slow, especially when we know that all the graphic function must be done in the main thread :(
Now more i think more i say to myself that it's crazy to have a graphic library that not support multi-thread ! i can not believe that it's a requirement of openGL and i think now more and more that it's a bug or bad conception in delphi :(
Speaking about the previous point, even if openGL really required that all graphic routines must be done in the main thread (but really i doubt), i don't understand why delphi not offer on android another TcanvasClass (other than TcanvasGPU) that support multithread ! more crazy is that when you work with TCanvasGPU on Tbitmap, the result will be in any case (as you can see in my previous post) different from what you will have working with TCanvasGPU on the visual component !
now i m looking for function to work directly on pixels grids (old school), that will make me possible to work in multi-thread. but unfortunately their is not to much compatible with firemonley/android :(
to finish this is the function i use to draw my bitmap. but as this function must be call in the main thread, it's slow down my application (especially the scroll) ... so if you have any idea to make this more fast or multithread i take :)
function DrawAdvertBitmap: Tbitmap;
var aBitmapAliased: Tbitmap;
begin
aBitmapAliased := Tbitmap.Create(trunc(FWidth * fScreenScale) * 2, trunc(FHeight * fScreenScale) * 2);
try
aBitmapAliased.Canvas.BeginScene;
try
aBitmapAliased.canvas.Clear(0);
aBitmapAliased.canvas.Fill.Color := $ff000000;
aBitmapAliased.Canvas.Fill.Kind := TbrushKind.Solid;
aBitmapAliased.Canvas.FillRect(...);
aBitmapAliased.Canvas.Fill.Color := $ff333844;
aBitmapAliased.Canvas.Font.Family := 'Roboto-Bold';
aBitmapAliased.Canvas.Font.Size := 12 * fScreenScale * 2;
aBitmapAliased.Canvas.Font.Style := [TFontStyle.fsBold];
aBitmapAliased.Canvas.FillText(...);
finally
aBitmapAliased.Canvas.EndScene;
end;
//reduce by 2 to make antialiased
result := Tbitmap.Create(trunc(FWidth * fScreenScale), trunc(FHeight * fScreenScale));
try
result.Canvas.BeginScene;
try
result.Canvas.Clear(0);
result.Canvas.DrawBitmap(aBitmapAliased,...);
finally
result.Canvas.EndScene;
end;
except
result.Free;
raise;
end;
result.BitmapScale := fScreenScale;
finally
aBitmapAliased.free;
end;
end;
If we talk about Firemonkey:
TImage has the property "DisableInterpolation: boolean"
TForm has the property "Quality: TCanvasQuality = (SystemDefault, HighPerformance, HighQuality)" — it is works in design-time
Important to know:
Anti-aliasing is very expensive operation, this is disabled by default on mobile platforms.
The same anti-aliasing should be supported by the device. To Support multisampling the OpenGL must have GL_EXT_multisampled_render_to_texture property. If the device hardware does not support multisampling, the AA will not be.
If you are seeing weird anti-aliasing on some controls, I would recommend that you check that the controls do not have fractional position and size values, make sure to use trunc/round on the position or the GPU canvas uses some low-quality interpolation effect on top of any anti-aliasing.
If you plan to do per-pixel manual adjustments, I recommend that you use optimized color-conversion code (scanline <> TAlphaColor) as the built-in code is designed for clear code and not performance:
https://github.com/bLightZP/OptimizedDelphiFMXScanline
As for drawing anti-aliased circles with pictures in them, I found the easiest way is to generate an anti-aliased opacity map and apply it to a TImage's TBitmap. You can find code for generating an anti-aliased opacity map here:
https://github.com/bLightZP/AntiAliasedCircle
1. Use FMXNativeDraw by OneChen (Aone), - it's very simple, you even do not need to change your standard code for Canvas - need to add only 2 lines (IFDEF). It also supports TPath.
It works on 4 platoforms - Win, Mac, Android, iOS. But you need it only on mobile platforms, because antialiasing works on Win and Mac.
I use FMXNativeDraw in my mobile projects and it works very well!
Read this article first with google translate about FMXNativeDraw: http://www.cnblogs.com/onechen/p/6350096.html
Download:
https://github.com/OneChen/FMXNativeDraw
Btw if you're using PaintBox Canvas - work as usual.
If you need to draw on TBitmap Canvas - prepare Bitmap first:
if Scene <> nil then
lScale := Scene.GetSceneScale
else
lScale := 1;
fBitmap.BitmapScale := lScale;
fBitmap.SetSize(Ceil(Width * lScale), Ceil(Height * lScale) );
2. (optional)
Also use ZMaterialComponents, that is a wrapper for FMXNativeDraw (circle, rectangle, line etc). You can place these components on a FMX Form as standard TCircle and others.
https://github.com/rzaripov1990/ZMaterialComponents

AS3 AIR (ios and android) CameraRoll issue

I've been trying to sort out an issue for a week or so now. Googled to no avail. I'm currently working on an iOS/Android app that has a feature in the game to take a screenshot and have it show up in the mobile device's gallery.
I'm using the CameraRoll object and the issue is that some objects on screen have smoothing applied. However the CameraRoll screenshot ignores this. Which makes the resulting screen shot have some objects with jaggies.
I've found a number of cries for help on the same issue while googling, but no answers.
Any help is much appreciated.
Jaggies in flash are common since smoothing on bitmaps is disabled by default (more cpu intensive). I'd recommend creating a new bitmap from the CameraRoll MediaEvent.SELECT event. Inside, it should return event.data which is a MediaPromise object. Inside that, you should find a read-only file property where you should be able to find the image.
Then it's just a matter of creating your new image with smoothing.
var img:Bitmap = new Bitmap();
img.bitmapData = file.bitmapData;
img.smoothing = true;
addChild(img);
I've never tried this on mobile before, but it's a common issue which I believe you're encountering.
Addendum:
If you're having an issue with the system based screenshot services, you could create your own using pure AS3. The logic being, AS3 should do a pixel-by-pixel block copy of the stage (thereby respecting the smoothing values of your images).
Try this:
var myBitmapData:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
myBitmapData.draw(stage);

Check if image is black

I'm running a Python script under Windows which deals with 480x800 PNG images with 32-bit depth. I need to check if the given image is fully black or not. After some searching I've found that ImageMagick could help me to achieve this but unfortunately there's no manual for such task.
So a more general question is how to check if the image consists only of one color?
Edit:
My apologies for not providing all the information about the environment from beginning. The python script is executed using Android's monkeyrunner. Since it uses it's own instance of Jython (version 2.5) it's not possible to use any modules from external libraries. Inside there's a MonkeyImage class to work with screenshots taken from the device. So I adopted #eumiro's answer for it.
import Image
im = Image.load("image.png")
diff_colors = list(set(im.getdata()))
if len(diff_colors) == 1 and diff_colors[0] == (0, 0, 0):
print "all black"
EDIT as #JonClements proposes, this will be faster and stop as soon as anything else than black is found:
import Image
im = Image.load("image.png")
if all(rgb == (0,0,0) for rgb in im.getdata()):
print "all black"
I am no expert in Python but I saw that there is a PNG module that you can use.
Load the PNG and export it to an RGB(A) array.
Checking if it is totally black should then be simple. Run through the array and make sure nothing differs from 0.
I think this should work.
Out of curiosity, why would you want to check if the image is black?

Android - Picture callback data returns an image that it black or jumbled

So I am using the Android camera to take pictures within an Android app. About 90% of my users have no issues, but the other 10% get a picture that returns pure black or a weird jumbling of pixels.
Has anyone else seen this behavior? or have any ideas why it happens?
Examples:
Black:
Jumbled:
I've had similar problems like this.
The problem in short is: Missing data.
It occurs to a Bitmap/Stream if the datastream was interrupted for too long or it is accidentally no more available.
Another example where it may occur: Downloading and uploading images.
If the user disables all of a sudden Wifi/mobile network no more data can be transmitted.
You end up in a splattered image.
The image will appear/view okay(where okay means black/splattered, it's still viewable!) but is invalid internally (missing or corrupted information).
If it's not too critical you can try to move all the data into a Bitmap object (BitmapFactory.decode*) and test if the returned Bitmap is null. If yes the data possibly is corrupted.
This is just solving the consequences of the problem, as you can guess.
The better way would be to take the problem on the foot:
Ensure a good connection to your data source (Large enough, stout buffer).
Try to avoid unneccesary casts (e.g. from char to int)
Use the correct type of buffers (Either Reader/Writer for character streams or InputStream/OutputStream for byte streams).
From android 4.0 they put hardwareAcceleration set to true as default in the manifest. Hardwareaccelerated canvas does not support Pictures and you will get a black screen...
Please also check that whether you use BitmapFactory.Options object for generating the bitmap or not. Because few methods of this object also makes the bitmap corrupted.

Categories

Resources