I have a image with high resolution shown in an image view on a tablet. In order to fit the image, android scales it down to available width & height. I want to show a marker on this image. I have coordinates of marker for original high resolution image. How do I translate them for new scaled down image?
I tried following code but doesn't work well with images of different sizes.
float scaleFactor = Math.min((float)(newHeight*1.0/originalHeight), (float)(newWidth*1.0/originalWidth));
float xCoordinate = Float.parseFloat(marker.getXCoordinate()) * scaleFactor;
float yCoordinate = Float.parseFloat(marker.getYCoordinate()) * scaleFactor;
Edit:
I am using the scaling of type FIT_CENTER for showing image in imageview.
I have also tried with different scaling factors for height & width but didn't work out well.
Related
I have an Image View which displays an image (e.g 2000x1000 pixels) and I have a coordinate (X,Y) on that image (not the image view). The canvas of my Image View is 600x800 for example. How can I convert the point (X,Y) to screen coordinate so that I can draw a path with them on the OnDraw(...) method of Image View. Any help is appreciated! Thank you.
Update: If I use matrix to draw the path between coordinates, it works but the path and objects i draw become really small. Here is the code i used.
final Matrix matrix = canvas.getMatrix();
matrix.preConcat( _view.getImageMatrix() );
matrix.preScale( 1.0f /_inSampleSize, 1.0f / _inSampleSize);
canvas.setMatrix( matrix );
//I draw the path here
Update: I add a picture to show the effect when using matrix to draw the path. I would like to have the 4 line and the 4 corner balls to be in normal size. The red color is the boundary of the Image View which holds the picture.
I think that might depend on how exactly you are displaying your image. Your ImageView (600x800) is not the same aspect ratio as your bitmap (2000x1000).
You are keeping the bitmap's aspect ratio stable as you scale it down? If so, which part (height or width) takes up the full screen and which has black (or whatever else) as padding? This will help you determine your scale factor.
scale_factor = goal_height/height1; //if height is what you are scaling by
scale_factor = goal_width/width1; //if width is what you are scaling by.
I would try:
x_goal = x1 * scale_factor;
y_goal = y1 * scale_factor;
That is, if you have a point (1333, 900) in your image, and your image takes up the full width, you would multiply both x and y by 600/2000 to get (399.9, 270). (you might want to round that decimal).
If you are NOT keeping the bitmaps aspect ratio stable (that is, you're squeezing it to fit), then you'd have a height_scale_factor and a width_scale factor. So you'd take (1333,900) and multiply x by 600/2000 and y by 800/1000 to get (399.9,720).
This more of a conceptual Android question
Say I have this static image that I want to load into an ImageView -
Say the image is 600px by 200px.(width by height)
Say my image view I try fitting it into is 300 px by 200px(width by height)
I just want to scale by height and cut off the left end of the image so that the image can fit into the imageview. Also if no cuts need to take place(fits already), I don't want to cut any of it off.
So in the end the ImageView(if it was 300 px by 200px) would hold this image
(basically so the F doesn't get distorted)
I've looked Scale To Fit but none of the scale types seems to achieve this custom effect. Does anyone know of how I would go about this? In my case, I wouldn't want to maintain the original aspect ratio.
You should crop the Bitmap so that it always fits into your ImageView. If you want the bottom-right corner cropped, you could do something similar to this:
if (needsCropping()) {
int startWidth = originalImage.getWidth() - 300;
int startHeight = originalImage.getHeight() - 200;
Bitmap croppedBitmap = Bitmap.createBitmap(originalImage, startWidth, startHeight, width, height);
// TODO set imageview
}
FIT_END would do this:
Compute a scale that will maintain the original src aspect ratio, but will also ensure that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. END aligns the result to the right and bottom edges of dst.
You can use ScaleType.CENTER_CROP BUT this will not rescale the image in any way.
Any combinations of those is impossible, for that you must have your own scale method (subclassing ImageView).
Or, the easy way would have .9PNGs as the source of the image, it would fit any space without distorcing.
Here is my problem:
I have an Android application that displays an image. The image itself is resized to 480 x 640 regardless of size.
The user can click on multiple points of the image. Based on where the user clicks on the image, the bitmap itself has some warping applied to it.
So let's say the original image is 1000 x 2000 (using whole numbers to make it simpler).
Once the image is loaded into the ImageView, it scales to display properly in the imageview.
This is obviously different for different phones with different resolutions.
Now when the user clicks on different points, I ultimately want to pass those points to my WCF Service along with the bitmap data to perform some image manipulation.
So the problem for me is how to take the points where the user touched on the phone and convert those to points that are relative to the normal unscaled bitmap.
Summary:
Bitmap is scaled to fit. User Clicks at 100,100. 100,100 is the point relative to the scaled image...not the actual bitmap itself. I'm looking for guidance on how to convert that 100,100 to the point on the actual bitmap.
Thanks in advance for any help you can give.
ok, so the Android ImageView has a default ScaleType of FIT_CENTER, so that means:
public static final Matrix.ScaleToFit CENTER
Compute a scale that will maintain the original src aspect ratio, but
will also ensure that src fits entirely inside dst. At least one axis
(X or Y) will fit exactly. The result is centered inside dst.
so if you're whole image view has 480x640 to show the image, and for example your image is 1000x2000, then:
2000/640 = scaleFactor = 3.125/1
so width will scale down to 320 leaving 80 pixels on either side empty, so it can maintain the aspect ratio.
//this one will be 80.
int xBuffer= (imageViewWidth - (realImageWidth*scaleFactor))/2;
//this one will be zero in your example
int yBuffer = (imageViewHeight - (realImageHeight*scaleFactor))/2;
int imageViewX = 0;//x coord where on the image view it was clicked
int imageViewY = 0;//y coord where on the image view it was clicked
if (imageViewX < xBuffer || imageViewX > imageViewWidth-xBuffer)
{
//ignore the click, outside of your image.
}
else if (imageViewY < yBuffer || imageViewY > imageViewHeight-yBuffer)
{
//ignore the click, outside of your image.
}
else
{
realImageY = imageViewY * scaleFactor;
realImageX = (imageViewY - 80) * scaleFactor;
//save click somehow..
saveClick(realImageX,realImageY);
}
I am trying to build a game and was wondering how would one go about supporting different resolution and screen sizes. For position of sprite I've implemented a basic function which sets the position according to a certain ratio, which I get by getting the screen width and height from sharedDirector's winSize method.
But this approach is not tested as I have yet to develop something to calculate the scaling factor for sprites depending upon the resolution of device. Can somebody advise me some method and tips by which I can correctly calculate the scaling of sprite and suggest a system to avoid the pixelation of sprites if I do apply any such method.
I searched on Google and found that Cocos2d-x supports different resolutions and sizes but I am bound to use Cocos2d only.
EDIT: I am bit confused as this is my first game. Please point out any mistakes that I may have made.
Okay I finally did this by getting the device display denitiy like
getResources().getResources().getDisplayMetrics().densityDpi
and based on it I am multiplying by PTM ratio by 0.75,1,1.5,2.0 for ldpi,mdpi,hdpi,and xhdpi respectively.
I am also changing the scale of sprites accordingly. And for positioning I've kept 320X480 as my base and then multiplying that with a ratio of my current x and y in pixels with my base pixels.
EDIT: Adding some code for better understanding:
public class MainLayer extends CCLayer()
{
CGsize size; //this is where we hold the size of current display
float scaleX,scaleY;//these are the ratios that we need to compute
public MainLayer()
{
size = CCDirector.sharedDirector().winSize();
scaleX = size.width/480f;//assuming that all my assets are available for a 320X480(landscape) resolution;
scaleY = size.height/320f;
CCSprite somesprite = CCSprite.sprite("some.png");
//if you want to set scale without maintaining the aspect ratio of Sprite
somesprite.setScaleX(scaleX);
somesprite.setScaleY(scaleY);
//to set position that is same for every resolution
somesprite.setPosition(80f*scaleX,250f*scaleY);//these positions are according to 320X480 resolution.
//if you want to maintain the aspect ratio Sprite then instead up above scale like this
somesprite.setScale(aspect_Scale(somesprite,scaleX,scaleY));
}
public float aspect_Scale(CCSprite sprite, float scaleX , float scaleY)
{
float sourcewidth = sprite.getContentSize().width;
float sourceheight = sprite.getContentSize().height;
float targetwidth = sourcewidth*scaleX;
float targetheight = sourceheight*scaleY;
float scalex = (float)targetwidth/sourcewidth;
float scaley = (float)targetheight/sourceheight;
return Math.min(scalex,scaley);
}
}
I am trying to build a game and was wondering how would one go about supporting different resolution and screen sizes. For position of sprite I've implemented a basic function which sets the position according to a certain ratio, which I get by getting the screen width and height from sharedDirector's winSize method.
But this approach is not tested as I have yet to develop something to calculate the scaling factor for sprites depending upon the resolution of device. Can somebody advise me some method and tips by which I can correctly calculate the scaling of sprite and suggest a system to avoid the pixelation of sprites if I do apply any such method.
I searched on Google and found that Cocos2d-x supports different resolutions and sizes but I am bound to use Cocos2d only.
EDIT: I am bit confused as this is my first game. Please point out any mistakes that I may have made.
Okay I finally did this by getting the device display denitiy like
getResources().getResources().getDisplayMetrics().densityDpi
and based on it I am multiplying by PTM ratio by 0.75,1,1.5,2.0 for ldpi,mdpi,hdpi,and xhdpi respectively.
I am also changing the scale of sprites accordingly. And for positioning I've kept 320X480 as my base and then multiplying that with a ratio of my current x and y in pixels with my base pixels.
EDIT: Adding some code for better understanding:
public class MainLayer extends CCLayer()
{
CGsize size; //this is where we hold the size of current display
float scaleX,scaleY;//these are the ratios that we need to compute
public MainLayer()
{
size = CCDirector.sharedDirector().winSize();
scaleX = size.width/480f;//assuming that all my assets are available for a 320X480(landscape) resolution;
scaleY = size.height/320f;
CCSprite somesprite = CCSprite.sprite("some.png");
//if you want to set scale without maintaining the aspect ratio of Sprite
somesprite.setScaleX(scaleX);
somesprite.setScaleY(scaleY);
//to set position that is same for every resolution
somesprite.setPosition(80f*scaleX,250f*scaleY);//these positions are according to 320X480 resolution.
//if you want to maintain the aspect ratio Sprite then instead up above scale like this
somesprite.setScale(aspect_Scale(somesprite,scaleX,scaleY));
}
public float aspect_Scale(CCSprite sprite, float scaleX , float scaleY)
{
float sourcewidth = sprite.getContentSize().width;
float sourceheight = sprite.getContentSize().height;
float targetwidth = sourcewidth*scaleX;
float targetheight = sourceheight*scaleY;
float scalex = (float)targetwidth/sourcewidth;
float scaley = (float)targetheight/sourceheight;
return Math.min(scalex,scaley);
}
}