how to resize image with my below code ? the code get image but I didnt how to resize it.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) {
//file name
filePath = data.getData();
try {
// Bundle extras2 = data.getExtras();
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
// imageview.setImageBitmap(bitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte imageInByte[] = stream.toByteArray();
Intent i = new Intent(this,
AddImage.class);
i.putExtra("image", imageInByte);
startActivity(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I read a so queston using this way , but its different then my way
File dir=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
Bitmap b= BitmapFactory.decodeFile(PATH_ORIGINAL_IMAGE);
Bitmap out = Bitmap.createScaledBitmap(b, 320, 480, false);
File file = new File(dir, "resize.png");
FileOutputStream fOut;
try {
fOut = new FileOutputStream(file);
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
b.recycle();
out.recycle();
} catch (Exception e) {}
I would like to suggest you that first set the bitmap image to imageview and apply scale i.e., resize as per your requirement using setScaleType method.
ex:
imageview.setScaleType(ScaleType.CENTER);
(or)
If you want to try in same way then I think this link may be help full.
https://argillander.wordpress.com/2011/11/24/scale-image-into-imageview-then-resize-imageview-to-match-the-image/
To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). Here’s a method to calculate a sample size value that is a power of two based on a target width and height:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Taken from here
Related
I'm attempting to scale down a bitmap to load a smaller version into memory. I'm pretty much following Google's example (search Loading Large Bitmaps Efficiently), except that I'm loading from the image gallery instead of a resource. But I seem to be getting back a null bitmap after calculating dimensions. Here's my code:
/** OnActivityResult Method **/
final Uri imageUri = data.getData();
final InputStream imageStream = getActivity().getContentResolver().openInputStream(imageUri);
Bitmap bitmapToLoad = Util.decodeSampledBitmapFromResource(imageStream, 500, 500); // bitmapToLoad is null.
mIvScreenshot.setImageBitmap(bitmapToLoad);
/**Helper Methods **/
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(InputStream is,
int reqWidth, int reqHeight) {
Rect rect = new Rect();
// First decode with inJustDecodeBounds = true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, rect, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(is, rect, options);
}
Can anyone catch what I'm doing wrong?
I managed to get it working. Thanks to Biraj Zalavadia (How to reduce an Image file size before uploading to a server) for the scaling logic, and the cursor code here (How to return workable filepath?). Here is my onActivityResult():
try {
final Uri imageUri = data.getData();
String[] filePath = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(imageUri, filePath, null, null, null);
cursor.moveToFirst();
String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
Uri newUri = Uri.parse(ScalingUtilities.scaleFileAndSaveToTmp(imagePath, 500, 500));
final Bitmap selectedImage = BitmapFactory.decodeFile(newUri.getEncodedPath());
mIvScreenshot.setImageBitmap(selectedImage);
} catch (Exception e) {
// Handle
}
I want to send a picture I took to server with multipart/form-data.
Of course, all the process goes very well.
I get the absolute path of the picture on onActivityResult. I sent it to AsyncTask class to change it into File object. Then, I use FileInputStream to send the picture to server.
Here's my code for sending picture.
MainActivity:
public void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode != RESULT_OK)
return;
if(requestCode == PICK_FROM_CAMERA){
// uri of selected picture
imageUri = data.getData();
// path of selected picture
Cursor c = this.getContentResolver().query(imageUri, null, null, null, null);
c.moveToNext();
absolutePath = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA));
Glide.with(this).load(imageUri).into(image);
}
}
Asynctask class:
absolutePath is in params[7]
FileInputStream fileInputStream ;
wr.writeBytes("\r\n--" + boundary + "\r\n");
wr.writeBytes("Content-Disposition: form-data; name=\"file1[]\"; " +
"filename=\"image.jpg\"\r\n");
wr.writeBytes("Content-Type: application/octet-stream\r\n\r\n");
fileInputStream = new FileInputStream(params[7]);
When I send the picture, I just send it without resizing.
It takes too much time and data to finish sending.
I want to make the picture smaller when sending to server.
that is, with absolute Path, I want to make smaller picture that can be turned into File object.
Can anyone give me some hint?
You can store your imageFile as Uri variable and then resize your image according to your desired width and height to be compressed.
Bitmap b = BitmapFactory.decodeFile(String.valueOf(fileUri));
Bitmap out = Bitmap.createScaledBitmap(b, IMG_WIDTH, IMG_HEIGHT, false);
FileOutputStream fOut;
try {
fOut = new FileOutputStream(fileUri);
out.compress(Bitmap.CompressFormat.JPEG, 60, fOut);
fOut.flush();
fOut.close();
b.recycle();
out.recycle();
Log.i("Compressing file", String.valueOf(uriFile));
} catch (Exception e) {
Log.e("ErrInCompressingPicture","" + e);
}
You can compress the picture you got before you send to server!
one solution is set inSampleSize directly:
public static Bitmap getImage(String imgPath){
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2;
try {
b=BitmapFactory.decodeFile(imgPath, options);
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
the other solution is set width and height of you want:
public static Bitmap getSmallBitmap(String imgPath,int reWidth,int reHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgPath, options);
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize=0;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(imgPath, options);
}
My App have an activity with a ImageView where i pick a picture from phone gallery and set in this ImageView as user's profile picture.
My problem is that some pictures when picked make app stop cause is too big, i want to know if someone can look my code and help me how can i resize this picked picture, so after set in this image view, how can user cut this picture before set, here below is my code where i pic the picture. i will be so greatful if someone do the needed changes and give me the code cause i dont know so much about developing. thank you.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
PreferenceManager.getDefaultSharedPreferences(this).edit().putString("picturePath", picturePath).commit();
cursor.close();
ImageView imageView = (ImageView) findViewById(R.id.User);
imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath));
}
}
Try this is image compression like whtsapp I have used in my application https://www.built.io/blog/2013/03/improving-image-compression-what-weve-learned-from-whatsapp/
You can use Picasso library. Get it from here.
The syntax looks like this:
Picasso.with(getContext()).load(imagePath).into(imageView);
Not gonna rewrite your code but this could be useful
Bitmap bitmap = BitmapFactory.decodeFile(foto.getFotoOrderFilePath());
Double height = (double)bitmap.getHeight();
Double scalingFactor = (960.0/height);
int tempWidht = bitmap.getWidth();
Double Dwidth = (tempWidht*scalingFactor);
int width = Dwidth.intValue();
Log.v("bitmap dimensions: ", String.valueOf(height) + " + " +String.valueOf(width) + " + " + String.valueOf(scalingFactor));
bitmap = Utilities.scaleBitmap(bitmap, width, 960);
An excerpt from code I use to scale a bitmap down. It sets the hight to 960 and get the scaling to change the width accordingly.
edit:
the ScaleBitmap method.
public static Bitmap scaleBitmap(Bitmap bitmap, int wantedWidth, int wantedHeight) {
Bitmap output = Bitmap.createBitmap(wantedWidth, wantedHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Matrix m = new Matrix();
m.setScale((float) wantedWidth / bitmap.getWidth(), (float) wantedHeight / bitmap.getHeight());
canvas.drawBitmap(bitmap, m, new Paint());
return output;
}
sorry for the late response
You can try this code to resize image as per your requirement
public Bitmap decodeSampledBitmapFromResource(String Filepath,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(Filepath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(Filepath, options);
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
int inSampleSize = 1;
final int height = options.outHeight;
final int width = options.outWidth;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
check here
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I'm working on xamarin forms project. I'm taking images from gallery and uploading those to server. My back-end is parse backend where we can not upload files having size more than 1MB. So, I'm trying to compress the image so that every time the image size is less than 1MB.
Mentioned below is my code :-
protected override async void OnActivityResult (int requestCode, Result resultCode, Intent intent)
{
if (resultCode == Result.Canceled)
return;
try {
var mediafile = await intent.GetMediaFileExtraAsync (Forms.Context);
// get byte[] from file stream
byte[] byteData = ReadFully (mediafile.GetStream ());
byte[] resizedImage = ResizeAndCompressImage (byteData, 60, 60, mediafile);
var imageStream = new ByteArrayContent (resizedImage);
imageStream.Headers.ContentDisposition = new ContentDispositionHeaderValue ("attachment") {
FileName = Guid.NewGuid () + ".Png"
};
var multi = new MultipartContent ();
multi.Add (imageStream);
HealthcareProfessionalDataClass lDataClass = HealthcareProfessionalDataClass.Instance;
lDataClass.Thumbnail = multi;
App.mByteArrayOfImage = byteData;
MessagingCenter.Send<IPictureTaker,string> (this, "picturetaken", mediafile.Path);
} catch (InvocationTargetException e) {
e.PrintStackTrace ();
} catch (Java.Lang.Exception e) {
e.PrintStackTrace ();
}
}
public static byte[] ReadFully (System.IO.Stream input)
{
using (var ms = new MemoryStream ()) {
input.CopyTo (ms);
return ms.ToArray ();
}
}
public static byte[] ResizeAndCompressImage (byte[] imageData, float width, float height, MediaFile file)
{
try {
// Load the bitmap
var options = new BitmapFactory.Options ();
options.InJustDecodeBounds = true;
options.InMutable = true;
BitmapFactory.DecodeFile (file.Path, options);
// Calculate inSampleSize
options.InSampleSize = calculateInSampleSize (options, (int)width, (int)height);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
var originalBitMap = BitmapFactory.DecodeByteArray (imageData, 0, imageData.Length, options);
var resizedBitMap = Bitmap.CreateScaledBitmap (originalBitMap, (int)width, (int)height, false);
if (originalBitMap != null) {
originalBitMap.Recycle ();
originalBitMap = null;
}
using (var ms = new MemoryStream ()) {
resizedBitMap.Compress (Bitmap.CompressFormat.Png, 0, ms);
if (resizedBitMap != null) {
resizedBitMap.Recycle ();
resizedBitMap = null;
}
return ms.ToArray ();
}
} catch (Java.Lang.Exception e) {
e.PrintStackTrace ();
return null;
}
}
public static int calculateInSampleSize (BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
int height = options.OutHeight;
int width = options.OutWidth;
int inSampleSize = 16;
if (height > reqHeight || width > reqWidth) {
int halfHeight = height / 2;
int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
But the problem is my image is not getting compressed.I'm not able to upload an image having size = 2MB and I want to upload images having size at-least 30 MB. Also I've observed that calculateInSampleSize always returns 16 as inSampleSize which is default one.
Please let me know if there's any issue in my code.
This seems like a very complicated and convoluted way of doing it. Here's a more concise sample that should help you resize your images:
protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var stream = this.Resize(data.Data, 60, 60);
// Send the stream to Parse
}
private Stream Resize(Android.Net.Uri uri, float maxWidth, float maxHeight)
{
var scale = 1;
using (var rawStream = this.ContentResolver.OpenInputStream(f))
using (var options = new BitmapFactory.Options { InJustDecodeBounds = true })
{
BitmapFactory.DecodeStream(rawStream, null, options);
while(options.OutWidth / scale / 2 > maxWidth ||
options.OutHeight / scale / 2 > maxHeight)
{
scale *= 2;
}
}
using (var options = new BitmapFactory.Options { InSampleSize = scale })
using (var bitmap = f.GetBitmap(options))
{
var memoryStream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Png, 0, memoryStream);
memoryStream.Position = 0;
return memoryStream;
}
}
Regarding why you are seeing InSampleSize = 16, my guess is that your image's height or width are less than 1920 (which is 60 * 2 * 16) and since you are using && in the while loop, the greater check for that side fails and thus, you never enter the while body.
Additionally, if you are looking to create smaller images, compressing them as Jpeg is a much better approach than using png's.
I am using native camera in my app. And after taking picture I am showing it to user on next activity in the Imageview. Now the problem is, when I save picture taken by front camera, the picture shows up in the next activity's imageview but not in the case when taken by back camera.
I am going to next activity after taking picture in the following way:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
case REQUEST_CODE_HIGH_QUALITY_IMAGE:
Toast.makeText(getApplicationContext(),
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
//refreshing gallery
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(mHighQualityImageUri);
sendBroadcast(mediaScanIntent);
Intent intentActivity = new Intent(MyCameraActivity.this,PhotoSortrActivity.class);
intentActivity.putExtra("data", mHighQualityImageUri);
Log.v("Uri before Sending",mHighQualityImageUri+"");
startActivity(intentActivity);
break;
default:
break;
}
}
and this where I am showing the captured image. :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photosortr);
this.setTitle(R.string.instructions);
image = (ImageView) findViewById(R.id.img_view);
InputStream iStream = null;
try {
iStream = getContentResolver().openInputStream(uri);
inputData = getBytes(iStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Bitmap cameraBitmap = BitmapFactory.decodeByteArray(inputData, 0, inputData.length);
Bitmap cameraScaledBitmap = Bitmap.createScaledBitmap(cameraBitmap, cameraBitmap.getWidth(), cameraBitmap.getHeight(), true);
Matrix matrix = new Matrix();
if(cameraScaledBitmap.getWidth()>cameraScaledBitmap.getHeight())
{
matrix = new Matrix();
matrix.postRotate(270);
}
// final Bitmap newImage = Bitmap.createBitmap(cameraScaledBitmap.getWidth(), cameraScaledBitmap.getHeight(), Bitmap.Config.ARGB_8888);
// ask the bitmap factory not to scale the loaded bitmaps
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;
Bitmap cameraScaledBitmap2 = Bitmap.createBitmap(cameraScaledBitmap, 0, 0, cameraScaledBitmap.getWidth(), cameraScaledBitmap.getHeight(), matrix, true);
// image.setImageURI(uri);
image.setImageBitmap(cameraScaledBitmap2);
BitmapDrawable bg = new BitmapDrawable(cameraScaledBitmap2);
// photoSorter.SetBackgroundFromUrl(data);
}
#Override
protected void onResume() {
super.onResume();
//photoSorter.loadImages(this);
}
#Override
protected void onPause() {
super.onPause();
//photoSorter.unloadImages();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
//photoSorter.trackballClicked();
return true;
}
return super.onKeyDown(keyCode, event);
}
public byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
Here is my layout of second activity:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/fl_camera">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
>
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:contentDescription="content_desc_overlay"
android:src="#drawable/ic_launcher"
android:id="#+id/img_view"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
/>
</RelativeLayout>
</FrameLayout>
Why it is not setting image in the Imageview when using backcamera whereas it is working when taken by front camera. please help me
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class ImageResizer {
public static Bitmap decodeSampledBitmapFromFile(String filename,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options
options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filename, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filename, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// BEGIN_INCLUDE (calculate_sample_size)
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
// This offers some additional logic in case the image has a strange
// aspect ratio. For example, a panorama may have a much larger
// width than height. In these cases the total pixels might still
// end up being too large to fit comfortably in memory, so we should
// be more aggressive with sample down the image (=larger inSampleSize).
long totalPixels = width * height / inSampleSize;
// Anything more than 2x the requested pixels we'll sample down further
final long totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels > totalReqPixelsCap) {
inSampleSize *= 2;
totalPixels /= 2;
}
}
return inSampleSize;
// END_INCLUDE (calculate_sample_size)
}
}
Usage of method
Bitmap bmp = ImageResizer.decodeSampledBitmapFromFile(new File(filePath).getAbsolutePath(), 512, 342);
This will resize your bitmap so that you can get rid from OOM error.process these inside UI thread which seems better.
Bitmap myBitmap = BitmapFactory.decodeFile(mediaFile.getAbsolutePath());
int height = (myBitmap.getHeight() * 512 / myBitmap.getWidth());
Bitmap scale = Bitmap.createScaledBitmap(myBitmap, 512, height, true);
// Here mediaFile is path of image.
// display scale bitmap to your ImageView