I am creating an image from a byte array using a UIImageView control. I need to ensure that the max size of the image is 600 x 600. How can I do that? I have tried SizeThatFits() and SizeToFit(), however, that just moves the image around on the screen. I have tried setting the Bound property to new RectangleF(0, 0, 600, 600), however, that also does no good.
You could check UIImage Size property for exceeding your limits. If so, scale it:
const int limit = 600;
if ((View.Frame.Size.Width > limit) || (View.Frame.Size.Height > limit))
{
// Scale as on link above.
}
Alternatively, you could set Frame and ContentMode of your UIImageView to desirable values.
Related
I'm hitting a bit of a mathmatical brick wall. I have a IEnumerable of Images, each have been scaled (not stretched) to fit within the bounds of a rectangle that represents a Page (This could be, A4, A5 A6 etc.).
Given a portrait page, and images that have a portrait aspect this should leave me with images that fill at a minimum the width (unless of course the height is larger than that of the page once scaled).
In this scenario let's say we have 10 images with approximate heights per image of 400 each and the total page size is 850. What's the best way for me to loop through the images, getting their actual heights and calculating how many would fit within the page height.
I can't quite get my head around the approach in C# .Net that would allow me to essentially end up with a grouping (or list) of images per page.
This is how I'm scaling the images, works fine. Could be optimised but for the moment and for the first version of an application I'm building I'm happy with functional over elegant.
// Scale images first
var scaledImages = new List<Image>();
foreach(var imagePath in imagePaths)
{
// Get our image from path
using var imageStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var image = Image.GetInstance(imageStream);
// Configure image and resize where needed
image.ScaleToFit(new Rectangle(0, 0, imageWidth, imageHeight));
image.Alignment = Image.ALIGN_CENTER;
if ((decimal)image.PlainWidth > (decimal)imageWidth)
{
var diff = (decimal)image.PlainWidth - (decimal)imageWidth;
imageWidth = (float)((decimal)imageWidth - diff);
image.ScaleToFit(new Rectangle(0, 0, imageWidth, imageHeight));
}
if ((decimal)image.PlainHeight > (decimal)imageHeight)
{
var diff = (decimal)image.PlainHeight - (decimal)imageHeight;
imageHeight = (float)((decimal)imageHeight - diff);
image.ScaleToFit(new Rectangle(0, 0, imageWidth, imageHeight));
}
}
Any pointers in the right direction would be fantastic, I think ultimately what I'm trying to do is create groups of images, within a list.
I want an image within a PictureBox that will adjust automatically depending on the size of the window but, not larger than the original image. While PictureBoxSizeMode.Zoom almost does this, when the PictureBox is larger than the image it causes the image to pixelate. I'm currently executing this code on resize:
if (pBox.Height * pBox.Height < pBox.Image.Width * pBox.Image.Height) pBox.SizeMode = PictureBoxSizeMode.Zoom;
else pBox.SizeMode = PictureBoxSizeMode.CenterImage;
While this works most of the time, occasionally the image won't revert back to zoom:
Any better way to go about this?
How about setting the maximum size to the image size:
pictureBox1.MaximumSize = pictureBox1.Image.Size;
In Combination with :
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
You should use "if (pBox.Width * pBox.Height < pBox.Image.Width * pBox.Image.Height)" if() Statement. Both dimensions of pBox is taken as height, might cause some problem. Check it
I'm writing a game using the 2d features of unity.
I'm designing a sort of inventory for the player character, and I have a gameobject with a number of placeholder images inside it. The intention is that when I actually load this gameobject, I'll replace the sprites of the placeholder images and I'll display what I want.
My issue is that when I change the sprite using code like this
var ren = item1.GetComponentInChildren<SpriteRenderer>();
ren.sprite = Resources.Load<Sprite>("DifferentSprite");
The image loaded is correct, however the scaling applies to the new sprite. The issue is that these sprites have all different sizes. So whilst the original placeholder image takes up a small square, the replacement might be tiny or massive enough to cover the whole screen depending on how the actual png was sized.
I basically want the sprite to replace the other and scale itself such that it has the same width and height as the placeholder image did. How can I do this?
EDIT - I've tried playing around with ratios. It's still not working perfectly, but its close.
var ren = item1.GetComponentInChildren<SpriteRenderer>();
Vector2 beforeSize = ren.transform.renderer.bounds.size;
ren.sprite = Resources.Load<Sprite>("Day0/LampOn");
Vector2 spriteSize = ren.sprite.bounds.size;
//Get the ratio between the wanted size and the sprite's size ratios
Vector3 scaleMultiplier = new Vector3 (beforeSize.x/spriteSize.x, beforeSize.y/spriteSize.y);
//Multiple the scale by this multiplier
ren.transform.localScale = new Vector3(ren.transform.localScale.x * scaleMultiplier.x,ren.transform.localScale.y * scaleMultiplier.y);
puzzle.Sprite = Sprite.Create(t, new Rect(0, 0, t.width, t.height),Vector2.one/2,256);
the last int is for the pixelperUnity, its the cause of changing size.
It's fixed in my project,
my default pixelPerUnit=256 and unity default = 100 so its bigger 2.56 times
tell me if it helps
How to modify width and height: use RectTransform.sizeDelta.
Example for this type of script
Vector3 originalDelta = imageToSwap.rectTransform.sizeDelta; //get the original Image's rectTransform's size delta and store it in a Vector called originalDelta
imageToSwap.sprite = newSprite; //swap out the new image
imageToSwap.rectTransform.sizeDelta = originalDelta; //size it as the old one was.
More about sizeDeltas here
I would expose two public variables in the script, with some default values:
public int placeholderWidth = 80;
public int placeholderHeight = 80;
Then, whenever you change sprites, set the width & height to those pre-defined values.
I am using this code to draw a scrollable panel on win form. The ImageBox is 512x512 and image I am using is 1024x768 (added as resource):
imageBox1.Image = Properties.Resources.test;
Unfortunately, it seems like image is scaled for some reasons - I cannot scroll to it's border. If I use 512x512 image, it doesn't fit the ImageBox, it seems cropped. Any ideas what is going on here?
using System;
using System.Drawing;
using System.Windows.Forms;
class ImageBox : Panel {
public ImageBox() {
this.AutoScroll = true;
this.DoubleBuffered = true;
}
private Image mImage;
public Image Image {
get { return mImage; }
set {
mImage = value;
if (mImage != null) this.AutoScrollMinSize = mImage.Size;
else this.AutoScrollMinSize = new Size(0, 0);
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
if (mImage != null) e.Graphics.DrawImage(mImage, 0, 0);
base.OnPaint(e);
}
}
It is an issue with the resolution of the image, it is less than the resolution of your display. Pretty unusual.
There is more than one workaround for this. #TaW's approach works but favors the monitor resolution. You'll get a sharper image but it will not be close to the image size as originally recorded. The other approach is to keep the physical size, like DrawImage() does, and adjust the scrollbars accordingly. Change the Image property setter to:
set {
mImage = value;
if (value == null) this.AutoScrollMinSize = new Size(0, 0);
else {
var size = value.Size;
using (var gr = this.CreateGraphics()) {
size.Width = (int)(size.Width * gr.DpiX / value.HorizontalResolution);
size.Height = (int)(size.Height * gr.DpiY / value.VerticalResolution);
}
this.AutoScrollMinSize = size;
}
this.Invalidate();
}
Picking the "right" approach is not so obvious, you probably ought to consider adding another property so you can change it as needed.
DrawImage has many variants and it is well worth checking them all out carefully. You have chosen the wrong one for your purpose. Look at the doc at MSDN:
Graphics.DrawImage Method (Image, Int32, Int32)
...
Draws the specified image, using its original physical size,
at the location specified by a coordinate pair.
At first glance this sounds good. 'Physical size' - isn't that pixels? But read on at MSDN:
Remarks
An Image stores a value for pixel width and a value for horizontal resolution
(dots per inch). The physical width, measured in inches, of an image is
the pixel width divided by the horizontal resolution. For example,
an image with a pixel width of 216 and a horizontal resolution of 72 dots
per inch has a physical width of 3 inches. Similar remarks apply to pixel
height and physical height.
The DrawImage method draws an image using its physical size, so the image will
have its correct size in inches regardless of the resolution (dots per inch)
of the display device. For example, suppose an image has a pixel width of 216
and a horizontal resolution of 72 dots per inch. If you call DrawImage to
draw that image on a device that has a resolution of 96 dots per inch,
the pixel width of the rendered image will be (216/72)*96 = 288.
Ouch, that's not about pixels after all! It is about displays and the resolution the image has embedded in it..This is good if you want to get the image e.g. printed right on all printers.
But you want the pixels of the image to match the pixels of the display. You could adapt the resolution of the image to your screen; but that wouldn't work for a different screen. So this DrawImage call will not work for you..
So you should, quite simply, use the number of pixels your image has and feed them into the right DrawImage call:
e.Graphics.DrawImage(mImage, 0, 0, mImage.Width, mImage.Height);
Now it will not distort the image but put one image pixel onto one screen pixel..
Edit: Note: I had misquoted MSDN in my OP; now the right (but wrong for your purpose) method call is quoted in the first part..
I am trying to use a C# port of TwoDScrollView in a Xamarin/Android project.
It works fine. We are adding scale gesture (we are showing an image that can be zoomed in/out by the user). That works fine as well.
The issue is that TwoDScrollView relies on ImageView.Width and ImageView.Height to make its calculation and that does NOT change - causing problems when trying to scroll after scaling. On resizing we are doing:
fullscreenImageView.ScaleX = _scaleFactor;
fullscreenImageView.ScaleY = _scaleFactor;
var lp = fullscreenImageView.LayoutParameters;
lp.Width = (int) (fullscreenImageView.Drawable.IntrinsicWidth * _scaleFactor);
lp.Height = (int) (fullscreenImageView.Drawable.IntrinsicHeight * _scaleFactor);
fullscreenImageView.RequestLayout (); //the request layout was just a test,
// it doesn't work either way
We can see how the layoutparameter width and height change, but the View.Width and View.Height never change... it is always the dimensions of the original image we loaded. How can we make that update? (one solution is to scale the bitmap and assign it to the imageview, but that's lousy and slow).
thanks.
According to this answer you should be able to set the dimensions of an ImageView object like this
image_view.getLayoutParams().width = (int) (fullscreenImageView.Drawable.IntrinsicWidth * _scaleFactor);
image_view.getLayoutParams().height = (int) (fullscreenImageView.Drawable.IntrinsicHeight * _scaleFactor);
where image_view is a reference to the same ImageView instance that your TwoDScrollView is looking to for dimensions.
Assuming your fullscreenImageView extends ImageView you can add this method in your fullscreenImageView
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
setMeasuredDimension(width, height);
}