I have around 2000 ABGR Mats, around 20x20 px each.
At least half of them are solid-colored, the colors can be different for each Mat, and it can be any color.
Currently I'm iterating over these Mats like this:
private inline fun Mat.isSingleColor(): Boolean {
get(0, 0, singleColorReferencePixelData)
for (row in 0 until rows()) {
for (column in 0 until cols()) {
get(row, column, singleColorCurrentPixelData)
if (!singleColorReferencePixelData.contentEquals(singleColorCurrentPixelData)) {
return false
}
}
}
return true
}
It works, but it's slow for my task, it takes around 100ms to check all 2000 images.
Is there a way to speed it up?
Related
I'm working on finding maximum overlap rectangle.
I've tried using following lines of code but it returns with that rectangle is overlaping to other or not
public boolean isOverlapping(Rect r1, Rect r2) {
if (r1.top < r2.top || r1.left > r2.left) {
return false;
}
if (r1.width() < r2.width() || r1.height() > r2.height()) {
return false;
}
return true;
}
I expect output that rectangle 3 is most overlaping to given rectangle. Not list or number of rectangles that overlaping to given rectangle.
A bit of pseudo code to get you going:
for each rect in Rectangle list
overlap = compuateOverlap(rect, givenRect)
In other words: it is relatively easy to actually compute the overlap area for two rectangles. Just do that, and compare the results, and isolate the maximum.
In case you need more guidance how to compute that overlap, see this answer for some inspiration.
Or here, there you find even the exact formula to use to compute the overlap area of two rectangles!
I'm very new to Processing and am trying to make a simple program that handles a list of audio clips. When the user scrolls down using the mouse wheel, audio clips are skipped, and when they stop scrolling, an audio clip plays through.
The first step for this seems to be finding a way of converting the numbers returned from MouseWheel, which grow vastly larger or smaller as the mouse wheel is scrolled, into true/false-style values that are returned less frequently (every few seconds).
The code below returns true/false, but does so very quickly. If anybody could help me with saying, "scan for changes every 3 seconds", or similar, I'd be enormously appreciative.
int wheelVal; //reading from mouse wheel
boolean hasScrolled = false; // whether mouse has scrolled
void setup() {
size (750, 500);
println ("ready to scroll");}
void draw() {
background (450);}
void mouseWheel(MouseEvent me)
{ wheelVal = me.getCount();
if (wheelVal > 0) {
hasScrolled = true;
println ("true");}
if (wheelVal < 0) {
hasScrolled = false;
println ("false");}
}
I think you're on the right track, but you can probably actually simplify your logic a bit.
Step 1: Create a hasScrolled variable. Set it to true in the mouseWheel() function.
Step 2: Inside the draw() function, use the millis() function or the frameCount variable to check when 3 seconds has gone by. If so, check the hasScrolled variable, and set it back to false.
Here's a small example:
boolean hasScrolled = false;
void draw(){
background(32);
//180 frames is 3 seconds
if(frameCount % 180 == 0){
if(hasScrolled){
println("scrolled!");
}
}
}
void mouseWheel(MouseEvent me){
hasScrolled = true;
}
I have a live wallpaper that is running a looped animation by drawing each frame to the canvas. I have one single image, sized to the exact dimensions of the screen. I have a set of 400 frames sized exactly to fit about the bottom third of the screen; this is where the animation occurs. Here is the code that displays them:
public void updateBG() {
mHandler.removeCallbacks(mUpdateDisplay);
if (mVisible) {
mHandler.postDelayed(mUpdateDisplay, 40);
}
if (imagesLoaded < totalFrames) {
ShowLoadingProgress();
} else {
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
Paint p = new Paint();
p.setAntiAlias(true);
c.drawRect(0, 0, c.getWidth(), c.getHeight(), p);
Rect destinationRect = new Rect();
destinationRect.set(0, 0, canvasWidth, canvasHeight);
if (animStartX > 0 || animEndX > 0 || animStartY > 0 || animEndY > 0) {
c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[totalFrames], 0, bitmapArray[totalFrames].length), null, destinationRect, p);
Rect destinationRectAnim = new Rect();
destinationRectAnim.set(animX, animY, animX+animWidth, animY+animHeight);
c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[bgcycle], 0, bitmapArray[bgcycle].length), null, destinationRectAnim, p);
} else {
c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[bgcycle], 0, bitmapArray[bgcycle].length), null, destinationRect, p);
}
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
bgcycle++;
}
}
This code is running at approximately 10-12 FPS on an Xperia Ion (dual-core 1.5 GHz cpu) and worse on older devices. It was going much better when I saved entire frames at half the screen resolution. It actually got worse when I started using full frames at the screen resolution (which should have eliminated the need to interpolate on each frame). It then got even worse when I started using this code, which writes two bitmaps (presumably because it can't save the top half of the canvas from the last run).
How can I optimize this? I'd rather not save full frames as just saving the animated part for each frame really reduces memory usage. Something feels really wrong here, especially given that this is running with 3GHz of power behind it. I used to watch movies on a 450 MHz Pentium III. Is there something obvious that I'm doing wrong? Is the phone still trying to interpolate the images even though they are sized correctly?
You are decoding your bitmap on every frame, it's expensive and it will generate garbage that will trigger GCs. You are also rendering using software rendering. Here are your solutions, in order:
Don't re-decode the bitmaps on every frame
Reuse bitmap objects (see BitmapFactory.Options.inBitmap)
Use hardware acceleration (render directly into a View instead of a SurfaceView.) Software interpolation is very expensive.
I'm currently working on a system which displays video frames (as bitmaps) via OpenGL ES 1.0 on Android. My issue is that I have not been able to get more than about 10 fps.
After doing some testing, I've determined that one of the biggest bottlenecks is the need for the bitmap to have its width and height both be a power of 2. A 640x480 video has to be scaled up to 1024x1024, for example. Without the scaling, I've been able to get about 40-50fps, but the texture just appears white, which does me no good.
I know that OpenGL ES 2.0 supports using non-power of two textures, but I have no experience with shaders / anything else new in 2.0
Is there any way I can get around this issue? How do other video plays get such good performance in comparison to what I have? I have included some code for reference.
private Bitmap makePowerOfTwo(Bitmap bitmap)
{
// If one of the bitmap's resolutions is not a power of two
if(!isPowerOfTwo(bitmap.getWidth()) || !isPowerOfTwo(bitmap.getHeight()))
{
int newWidth = nextPowerOfTwo(bitmap.getWidth());
int newHeight = nextPowerOfTwo(bitmap.getHeight());
// Generate a new bitmap which has the needed padding
return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
}
else
{
return bitmap;
}
}
private static boolean isPowerOfTwo(int num)
{
// Check if a bitwise and of the number and itself minus one is zero
return (num & (num - 1)) == 0;
}
private static int nextPowerOfTwo(int num)
{
if(num <= 0)
{
return 0;
}
int nextPowerOfTwo = 1;
while(nextPowerOfTwo < num)
{
nextPowerOfTwo <<= 1; // Bitwise shift left one bit
}
return nextPowerOfTwo;
}
Just because a texture has to be a power of two, doesn't mean that your data has to be a power of two.
You're free to create a 1024x1024 (or 1024x512) texture during initialization with glTexImage, fill in the lower 640x480 with your bitmap data with glTexSubImage, and then display the lower 640x480 of the texture with some intelligent texcoords (0,0) to (640/1024, 480/1024). The remainder of the texture will just contain empty space that's never seen.
So I've got this nice Android game (a snake-clone with animations), doing the final testing, when BAM! My second testing device (Nexus 1, HTC Magic was my 1.) flickers when drawing.
Does anyone know why this code won't work correctly with the Nexus 1?
public void draw(Canvas canv) {
int count = 0;
isHead = false;
for (int i = 0; i < SPACES; i++) {
if (mDrawSpaces[i]) {
count++;
if (count == SPACES - 1) {
setDrawSpacesToFalse();
if (bmp != null)
super.drawPlaceable(canv);
}
} else {
mDrawSpaces[i] = true;
return;
}
}
}
I have a list of Birds (Birds / UFOs / others) with SPACES (4) times as many elements which are being drawn on the screen. So I thought to myself, instead of calculating the rotation and scale of the pictures for every Bird, I merely have 3 placeholders between the Birds which each have a picture to be drawn once they're set to visible. These pictures are generated by the first Bird:
public void drawHead(Canvas canv) {
//calculate the rotation & mirroring of the picture
super.drawPlaceable(canv);
//generate the pics for smaller birds following it
mat.preScale((float) 0.6, (float) 0.6);
this.bmp = Bitmap.createBitmap(SPRITESHEET, Bird.mCurFrame
* BIG_W[mUseBird], 0, BIG_W[mUseBird], BIG_H[mUseBird],
mat, true);
}
Any ideas? Is my draw(Canvas) method wrong in some part?
EDIT: I don't know why, I don't know how, but this afternoon when I tested it again, it magically worked...
I can see you are using matrix to scale - another option would be to use
canvas.DrawBitmap(spriteSheet, fromRect, toRect, paint);
Where toRect should be a Rect class of any size, in this way you would create no bitmap objects when drawing game frames. The piant should have filter bitmap enabled.
To rotate you would have to use:
canvas.save();
canvas.rotate(spriteAngle,spriteCenterX, spriteCenterY);
canvas.DrawBitmap(spriteSheet, fromRect, toRect, paint);
canvas.restore();
This is a fast enough code for many 2D games, though not as fast and powerful as OpenGL.