Java tutorial
/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.almalence.util; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.net.URI; import java.text.NumberFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.StringTokenizer; import android.annotation.TargetApi; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.location.Location; import android.net.Uri; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.os.StatFs; import android.provider.DocumentsContract; import android.provider.Settings; import android.support.v4.provider.DocumentFile; import android.util.DisplayMetrics; import android.util.Log; import android.view.OrientationEventListener; import android.view.Surface; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; /* <!-- +++ import com.almalence.opencam_plus.ApplicationScreen; import com.almalence.opencam_plus.cameracontroller.CameraController; +++ --> */ // <!-- -+- import com.almalence.opencam.ApplicationScreen; import com.almalence.opencam.cameracontroller.CameraController; //-+- --> /** * Collection of utility functions used in this package. */ public final class Util { private static final String TAG = "Util"; // The brightness setting used when it is set to automatic in the system. // The reason why it is set to 0.7 is just because 1.0 is too bright. // Use the same setting among the Camera, VideoCamera and Panorama modes. private static final float DEFAULT_CAMERA_BRIGHTNESS = 0.7f; // Orientation hysteresis amount used in rounding, in degrees private static final int ORIENTATION_HYSTERESIS = 5; private static final String REVIEW_ACTION = "com.android.camera.action.REVIEW"; private static boolean sIsTabletUI; private static float sPixelDensity = 1; // Workaround for QC cameras with broken face detection on front camera private static boolean sNoFaceDetectOnFrontCamera; private static boolean sNoFaceDetectOnRearCamera; private static Matrix mMeteringMatrix = new Matrix(); private Util() { } public static void initialize(Context context) { sIsTabletUI = false; DisplayMetrics metrics = new DisplayMetrics(); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(metrics); sPixelDensity = metrics.density; } public static boolean isTabletUI() { return sIsTabletUI; } public static int dpToPixel(int dp) { return Math.round(sPixelDensity * dp); } public static boolean noFaceDetectOnFrontCamera() { return sNoFaceDetectOnFrontCamera; } public static boolean noFaceDetectOnRearCamera() { return sNoFaceDetectOnRearCamera; } // Rotates the bitmap by the specified degree. // If a new bitmap is created, the original bitmap is recycled. public static Bitmap rotate(Bitmap b, int degrees) { return rotateAndMirror(b, degrees, false); } // Rotates and/or mirrors the bitmap. If a new bitmap is created, the // original bitmap is recycled. public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) { if ((degrees != 0 || mirror) && b != null) { Matrix m = new Matrix(); // Mirror first. // horizontal flip + rotation = -rotation + horizontal flip if (mirror) { m.postScale(-1, 1); degrees = (degrees + 360) % 360; if (degrees == 0 || degrees == 180) { m.postTranslate((float) b.getWidth(), 0); } else if (degrees == 90 || degrees == 270) { m.postTranslate((float) b.getHeight(), 0); } else { throw new IllegalArgumentException("Invalid degrees=" + degrees); } } if (degrees != 0) { // clockwise m.postRotate(degrees, (float) b.getWidth() / 2, (float) b.getHeight() / 2); } try { Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true); if (b != b2) { b.recycle(); b = b2; } } catch (OutOfMemoryError ex) { // We have no memory to rotate. Return the original bitmap. } } return b; } /* * Compute the sample size as a function of minSideLength and * maxNumOfPixels. minSideLength is used to specify that minimal width or * height of a bitmap. maxNumOfPixels is used to specify the maximal size in * pixels that is tolerable in terms of memory usage. * * The function returns a sample size based on the constraints. Both size * and minSideLength can be passed in as -1 which indicates no care of the * corresponding constraint. The functions prefers returning a sample size * that generates a smaller bitmap, unless minSideLength = -1. * * Also, the function rounds up the sample size to a power of 2 or multiple * of 8 because BitmapFactory only honors sample size this way. For example, * BitmapFactory downsamples an image by 2 even though the request is 3. So * we round up the sample size to avoid OOM. */ public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels); int roundedSize; if (initialSize <= 8) { roundedSize = 1; while (roundedSize < initialSize) { roundedSize <<= 1; } } else { roundedSize = (initialSize + 7) / 8 * 8; } return roundedSize; } private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { double w = options.outWidth; double h = options.outHeight; int lowerBound = (maxNumOfPixels < 0) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); int upperBound = (minSideLength < 0) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength)); if (upperBound < lowerBound) { // return the larger one when there is no overlapping zone. return lowerBound; } if (maxNumOfPixels < 0 && minSideLength < 0) { return 1; } else if (minSideLength < 0) { return lowerBound; } else { return upperBound; } } public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) { try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, options); if (options.mCancel || options.outWidth == -1 || options.outHeight == -1) { return null; } options.inSampleSize = computeSampleSize(options, -1, maxNumOfPixels); options.inJustDecodeBounds = false; options.inDither = false; options.inPreferredConfig = Bitmap.Config.ARGB_8888; return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, options); } catch (OutOfMemoryError ex) { Log.e(TAG, "Got oom exception ", ex); return null; } } public static void closeSilently(Closeable c) { if (c == null) return; try { c.close(); } catch (Exception t) { } } public static void Assert(boolean cond) { if (!cond) { throw new AssertionError(); } } public static <T> T checkNotNull(T object) { if (object == null) throw new NullPointerException(); return object; } public static int nextPowerOf2(int n) { n -= 1; n |= n >>> 16; n |= n >>> 8; n |= n >>> 4; n |= n >>> 2; n |= n >>> 1; return n + 1; } public static float distance(float x, float y, float sx, float sy) { float dx = x - sx; float dy = y - sy; return (float) Math.sqrt(dx * dx + dy * dy); } public static int clamp(int x, int min, int max) { if (x > max) return max; if (x < min) return min; return x; } public static float clamp(float x, float min, float max) { if (x > max) return max; if (x < min) return min; return x; } public static int getDisplayRotation(Activity activity) { int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); switch (rotation) { case Surface.ROTATION_0: return 0; case Surface.ROTATION_90: return 90; case Surface.ROTATION_180: return 180; case Surface.ROTATION_270: return 270; default: break; } return 0; } @TargetApi(9) public static int getDisplayOrientation(int degrees, int cameraId) { // See android.hardware.Camera.setDisplayOrientation for // documentation. Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } return result; } public static int roundOrientation(int orientation, int orientationHistory) { boolean changeOrientation = false; if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) { changeOrientation = true; } else { int dist = Math.abs(orientation - orientationHistory); dist = Math.min(dist, 360 - dist); changeOrientation = (dist >= 45 + ORIENTATION_HYSTERESIS); } if (changeOrientation) { return ((orientation + 45) / 90 * 90) % 360; } return orientationHistory; } //value to know current interval for orientation. Not using system functions consuming more resources //0 - unknown (need initial calculations), 1- [0 +-40], 2 [270 +-40], 3 - [180 +-40], 4 - [90 +-40] private static int orientationDisplayInterval = 0; public static void setOrientationIntervalInitial() { orientationDisplayInterval = 0; } private static void setOrientationInterval(int orientation) { if (orientation >= 320 || orientation < 40) orientationDisplayInterval = 1; else if (orientation >= 230 && orientation < 310) orientationDisplayInterval = 2; else if (orientation >= 140 && orientation < 220) orientationDisplayInterval = 3; else if (orientation >= 50 && orientation < 130) orientationDisplayInterval = 4; } public static boolean checkOrientationInterval(int orientation) { //if 0 - set initial interval, if not - check if new value is in the same interval switch (orientationDisplayInterval) { case 1: if (orientation >= 320 || orientation < 40) return true; break; case 2: if (orientation >= 230 && orientation < 310) return true; break; case 3: if (orientation >= 140 && orientation < 220) return true; break; case 4: if (orientation >= 50 && orientation < 130) return true; break; default: break; } setOrientationInterval(orientation); return false; } // Returns the largest picture size which matches the given aspect ratio. public static Size getOptimalVideoSnapshotPictureSize(List<Size> sizes, double targetRatio) { // Use a very small tolerance because we want an exact match. final double ASPECT_TOLERANCE = 0.001; if (sizes == null) return null; Size optimalSize = null; // Try to find a size matches aspect ratio and has the largest width for (Size size : sizes) { double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (optimalSize == null || size.width > optimalSize.width) { optimalSize = size; } } // Cannot find one that matches the aspect ratio. This should not // happen. // Ignore the requirement. if (optimalSize == null) { Log.w(TAG, "No picture size match the aspect ratio"); for (Size size : sizes) { if (optimalSize == null || size.width > optimalSize.width) { optimalSize = size; } } } return optimalSize; } public static void dumpParameters(Parameters parameters) { String flattened = parameters.flatten(); StringTokenizer tokenizer = new StringTokenizer(flattened, ";"); Log.d(TAG, "Dump all camera parameters:"); while (tokenizer.hasMoreElements()) { Log.d(TAG, tokenizer.nextToken()); } } private static int[] mLocation = new int[2]; // This method is not thread-safe. public static boolean pointInView(float x, float y, View v) { v.getLocationInWindow(mLocation); return x >= mLocation[0] && x < (mLocation[0] + v.getWidth()) && y >= mLocation[1] && y < (mLocation[1] + v.getHeight()); } public static void dumpRect(RectF rect, String msg) { Log.v(TAG, msg + "=(" + rect.left + "," + rect.top + "," + rect.right + "," + rect.bottom + ")"); } public static void rectFToRect(RectF rectF, Rect rect) { rect.left = Math.round(rectF.left); rect.top = Math.round(rectF.top); rect.right = Math.round(rectF.right); rect.bottom = Math.round(rectF.bottom); } public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, int viewWidth, int viewHeight) { // Need mirror for front camera. matrix.setScale(mirror ? -1 : 1, 1); // This is the value for android.hardware.Camera.setDisplayOrientation. matrix.postRotate(displayOrientation); // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). // UI coordinates range from (0, 0) to (width, height). matrix.postScale(viewWidth / 2000f, viewHeight / 2000f); matrix.postTranslate(viewWidth / 2f, viewHeight / 2f); } public static void fadeIn(View view) { if (view.getVisibility() == View.VISIBLE) return; view.setVisibility(View.VISIBLE); Animation animation = new AlphaAnimation(0F, 1F); animation.setDuration(400); view.startAnimation(animation); } public static void fadeOut(View view) { if (view.getVisibility() != View.VISIBLE) return; Animation animation = new AlphaAnimation(1F, 0F); animation.setDuration(400); view.startAnimation(animation); view.setVisibility(View.GONE); } public static void setGpsParameters(Parameters parameters, Location loc) { // Clear previous GPS location from the parameters. parameters.removeGpsData(); // We always encode GpsTimeStamp parameters.setGpsTimestamp(System.currentTimeMillis() / 1000); // Set GPS location. if (loc != null) { double lat = loc.getLatitude(); double lon = loc.getLongitude(); boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d); if (hasLatLon) { // Log.d(TAG, "Set gps location"); parameters.setGpsLatitude(lat); parameters.setGpsLongitude(lon); parameters.setGpsProcessingMethod(loc.getProvider().toUpperCase()); if (loc.hasAltitude()) { parameters.setGpsAltitude(loc.getAltitude()); } else { // for NETWORK_PROVIDER location provider, we may have // no altitude information, but the driver needs it, so // we fake one. parameters.setGpsAltitude(0); } if (loc.getTime() != 0) { // Location.getTime() is UTC in milliseconds. // gps-timestamp is UTC in seconds. long utcTimeSeconds = loc.getTime() / 1000; parameters.setGpsTimestamp(utcTimeSeconds); } } else { loc = null; } } } public static boolean isNumeric(String str) { NumberFormat formatter = NumberFormat.getInstance(); ParsePosition pos = new ParsePosition(0); formatter.parse(str, pos); return str.length() == pos.getIndex(); } 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) { // Calculate ratios of height and width to requested height and // width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will // guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } public static String createName(String format, long dateTaken) { Date date = new Date(dateTaken); SimpleDateFormat dateFormat = new SimpleDateFormat(format); return dateFormat.format(date); } public static String createNameForOriginalFrames(String format, long dateTaken, int frameIndex) { Date date = new Date(dateTaken); SimpleDateFormat dateFormat = new SimpleDateFormat(format); return dateFormat.format(date); } public static boolean isUriValid(Uri uri, ContentResolver resolver) { if (uri == null) return false; try { ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r"); if (pfd == null) { Log.e(TAG, "Fail to open URI. URI=" + uri); return false; } pfd.close(); } catch (IOException ex) { return false; } return true; } public static void viewUri(Uri uri, Context context) { if (!isUriValid(uri, context.getContentResolver())) { Log.e(TAG, "Uri invalid. uri=" + uri); return; } try { context.startActivity(new Intent(Util.REVIEW_ACTION, uri)); } catch (ActivityNotFoundException ex) { try { context.startActivity(new Intent(Intent.ACTION_VIEW, uri)); } catch (ActivityNotFoundException e) { Log.e(TAG, "review image fail. uri=" + uri, e); } } } public static void enterLightsOutMode(Window window) { WindowManager.LayoutParams params = window.getAttributes(); window.setAttributes(params); } public static void initializeScreenBrightness(Window win, ContentResolver resolver) { // Overright the brightness settings if it is automatic int mode = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); if (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) { WindowManager.LayoutParams winParams = win.getAttributes(); winParams.screenBrightness = DEFAULT_CAMERA_BRIGHTNESS; win.setAttributes(winParams); } } /** * SHAME@JAVA */ public static float mathSquare(double value) { return (float) (value * value); } /************************************************************************************************* * Returns size in MegaBytes. * * If you need calculate external memory, change this: StatFs statFs = new * StatFs(Environment.getRootDirectory().getAbsolutePath()); to this: StatFs * statFs = new * StatFs(Environment.getExternalStorageDirectory().getAbsolutePath()); **************************************************************************************************/ public static long TotalDeviceMemory() { StatFs statFs = new StatFs(Environment.getDataDirectory().getPath()); long blockSize = statFs.getBlockSize(); long blockCount = statFs.getBlockCount(); return (blockCount * blockSize) / 1048576; } public static long TotalExternalMemory() { StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getPath()); long blockSize = statFs.getBlockSize(); long blockCount = statFs.getBlockCount(); return (blockCount * blockSize) / 1048576; } public static long FreeDeviceMemory() { StatFs statFs = new StatFs(Environment.getDataDirectory().getPath()); long blockSize = statFs.getBlockSize(); long availableBloks = statFs.getAvailableBlocks(); return (availableBloks * blockSize) / 1048576; } public static long FreeExternalMemory() { StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getPath()); long blockSize = statFs.getBlockSize(); long availableBloks = statFs.getAvailableBlocks(); return (availableBloks * blockSize) / 1048576; } public static long BusyDeviceMemory() { StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath()); long Total = (statFs.getBlockCount() * statFs.getBlockSize()) / 1048576; long Free = (statFs.getAvailableBlocks() * statFs.getBlockSize()) / 1048576; return (Total - Free); } public static long BusyExternalMemory() { StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath()); long Total = (statFs.getBlockCount() * statFs.getBlockSize()) / 1048576; long Free = (statFs.getAvailableBlocks() * statFs.getBlockSize()) / 1048576; return (Total - Free); } public static long AvailablePictureCount() { long freeMemory = Util.FreeDeviceMemory() - 5; if (freeMemory < 5) return 0; // RAW size of picture is width*height*3 (rgb). JPEG compress picture on // average 86% (compress quality 95) CameraController.Size saveImageSize = CameraController.getCameraImageSize(); double imageSize = ((double) (saveImageSize.getWidth() * saveImageSize.getHeight() * 3 * 0.14) / 1048576d); if (imageSize == 0) return 0; return Math.round(freeMemory / imageSize); } public static <T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) { List<T> list = new ArrayList<T>(c); java.util.Collections.sort(list); return list; } public static void initializeMeteringMatrix() { Matrix matrix = new Matrix(); Util.prepareMatrix(matrix, CameraController.isFrontCamera(), 0, ApplicationScreen.getPreviewWidth(), ApplicationScreen.getPreviewHeight()); matrix.invert(mMeteringMatrix); } public static Matrix getMeteringMatrix() { return mMeteringMatrix; } public static Rect convertToDriverCoordinates(Rect rect) { RectF rectF = new RectF(rect.left, rect.top, rect.right, rect.bottom); mMeteringMatrix.mapRect(rectF); Util.rectFToRect(rectF, rect); if (rect.left < -1000) rect.left = -1000; if (rect.left > 1000) rect.left = 1000; if (rect.right < -1000) rect.right = -1000; if (rect.right > 1000) rect.right = 1000; if (rect.top < -1000) rect.top = -1000; if (rect.top > 1000) rect.top = 1000; if (rect.bottom < -1000) rect.bottom = -1000; if (rect.bottom > 1000) rect.bottom = 1000; return rect; } public static String toString(final Object[] objects, final char separator) { final StringBuilder stringBuilder = new StringBuilder(); for (final Object object : objects) { stringBuilder.append(object.toString()); stringBuilder.append(separator); } return stringBuilder.toString(); } public static String logMatrix(final float[] transform, final int width, final int height) { if (width * height < transform.length) { throw new ArrayIndexOutOfBoundsException( String.format("width(%d) * height(%d) > transform(%d)", width, height, transform)); } String format = ""; final Object[] args = new Object[width * height]; int cursor = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { format += "% #6.2f "; args[cursor] = transform[cursor]; cursor++; } format += "\n"; } return String.format(format, args); } public static boolean shouldRemapOrientation(final int orientationProc, final int rotation) { return (orientationProc == Configuration.ORIENTATION_LANDSCAPE && rotation == Surface.ROTATION_0) || (orientationProc == Configuration.ORIENTATION_LANDSCAPE && rotation == Surface.ROTATION_180) || (orientationProc == Configuration.ORIENTATION_PORTRAIT && rotation == Surface.ROTATION_90) || (orientationProc == Configuration.ORIENTATION_PORTRAIT && rotation == Surface.ROTATION_270); } // Get File object from DocumentFile object. // It's possible only if documentFile stored in phone memory, not SD-card. public static File getFileFromDocumentFile(DocumentFile documentFile) { try { File file = new File(URI.create(documentFile.getUri().toString())); return file; } catch (Exception e) { return null; } } // Get File absolute path from DocumentFile object. // This method should be used only for files saved to SD-card. public static String getAbsolutePathFromDocumentFile(DocumentFile documentFile) { // We can't get absolute path from DocumentFile or Uri. // It is a hack to build absolute path by DocumentFile. // May not work on some devices. Uri uri = documentFile.getUri(); final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String id = split[1]; String sd = null; sd = System.getenv("SECONDARY_STORAGE"); if (sd == null) { sd = System.getenv("EXTERNAL_STORAGE"); } if (sd != null) { // On some devices SECONDARY_STORAGE has several paths // separated with a colon (":"). This is why we split // the String. String[] paths = sd.split(":"); for (String p : paths) { File fileSD = new File(p); if (fileSD.isDirectory()) { sd = fileSD.getAbsolutePath(); } } String documentPath = sd + "/" + id; return documentPath; } return null; } public static int getMaxImageSizeIndex(android.util.Size[] ImageSizes) { int maxSizeIndex = 0; long maxSize = ImageSizes[0].getWidth() * ImageSizes[0].getHeight(); for (int i = 1; i < ImageSizes.length; i++) { long currentSize = ImageSizes[i].getWidth() * ImageSizes[i].getHeight(); if (currentSize > maxSize) { maxSizeIndex = i; maxSize = currentSize; } } return maxSizeIndex; } public static boolean listContainsSize(List<CameraController.Size> list, CameraController.Size size) { boolean res = false; for (CameraController.Size s : list) { if (s.getWidth() == size.getWidth() && s.getHeight() == size.getHeight()) { res = true; break; } } return res; } }