Java tutorial
/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2011 Funambol, Inc. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * "Powered by Funambol" logo. If the display of the logo is not reasonably * feasible for technical reasons, the Appropriate Legal Notices must display * the words "Powered by Funambol". */ package com.funambol.foundation.util; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.IndexColorModel; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import org.apache.commons.lang.StringUtils; import org.apache.sanselan.common.IImageMetadata; import org.apache.sanselan.formats.jpeg.JpegImageMetadata; import org.apache.sanselan.formats.tiff.TiffField; import org.apache.sanselan.formats.tiff.TiffImageMetadata; import org.apache.sanselan.formats.tiff.constants.TiffConstants; import org.apache.sanselan.ImageFormat; import org.apache.sanselan.ImageReadException; import org.apache.sanselan.Sanselan; import mediautil.image.jpeg.LLJTran; import mediautil.image.jpeg.LLJTranException; import net.sf.json.JSONObject; import com.funambol.common.media.file.FileDataObject; import com.funambol.common.pim.utility.TimeUtils; import com.funambol.framework.tools.IOTools; import com.funambol.foundation.exception.FileDataObjecyUtilsException; import com.funambol.foundation.items.model.FileDataObjectWrapper; /** * This class contains usefull methods to use for working with FileDataObject * objects type, in particular when they represent media objects (picture, * video and so on). * * @version $Id: MediaUtils.java 36684 2011-02-24 16:38:19Z ubertu $ */ public class MediaUtils { // --------------------------------------------------------------- Constants // JPEG: .jpg, .jpeg, .jpe, .jif, .jfif // PNG: .png // GIF: .gif private final static String[] SUPPORTED_PICTURE_EXTENSIONS = { ".jpg", ".jpeg", ".png", ".gif", ".jpe", ".jfif", ".jif" }; public final static String EXIF_PROPERTY_NAME = "exif"; public final static String ROTATION_PROPERTY_NAME = "rotation"; // ---------------------------------------------------------- Public methods /** * Returns an array of thumbnail keys created on file system starting from * the given picture. * * @param fdow the FDO wrapper * @param userId the user identifier * @param thumbnailFolderPath the absolute path where the thumbnails should * be saved * @param thumbnailsSize an array of valid size for thumbnails. It can be * either a number, for example 200, or 2D, for example 200x150. * Better to respect JPEG Minimum Coded Unit (MCU) and choose number that * can be diveded by 8. * @param thumbnailThreshold the thumbnail size threshold. * It is a percentage tolerance in the minimum image size used to create a * thumbnail. The default is 20, so for example a 400x400 image will not be * rescaled for 500x375 thumbnail size. Set it to 0 means that the thumbnail * is always generated if maximum size is larger than thumbnail size. * @return a map of thumbnail key and the corresponding thumbnail file * @throws FileDataObjecyUtilsException if an error occurs */ public Map<String, File> createThumbnails(FileDataObjectWrapper fdow, String userId, String thumbnailFolderPath, String[] thumbnailsSize, double thumbnailThreshold) throws FileDataObjecyUtilsException { if (fdow == null) { throw new FileDataObjecyUtilsException("The FileDataObjectWrapper cannot be null."); } if (thumbnailsSize == null) { throw new FileDataObjecyUtilsException("The thumbnails size must be set."); } FileDataObject fdo = fdow.getFileDataObject(); // // even if it is not possible to create a FDOWrapper with a FDO null // it's better to check it once // if (fdo == null) { throw new FileDataObjecyUtilsException("The FileDataObject cannot be null."); } // checks if file extention and format are supported if (!isAValidPicture(fdo)) { throw new FileDataObjecyUtilsException("The file extension or the format is not supported."); } createExtFolderIfNeeded(thumbnailFolderPath); int thumbnailsSizeLength = thumbnailsSize.length; Map<String, File> thumbnails = new HashMap<String, File>(); for (int j = 0; j < thumbnailsSizeLength; j++) { String thumbnailFileName = createThumbnailName(thumbnailsSize[j]); File thumbnailFile = new File(thumbnailFolderPath, thumbnailFileName); int x = 0; int y = 0; //Support both 200x300 and 200 formats in conf if (thumbnailsSize[j].toLowerCase().indexOf('x') > 0) { //200x300 x = Integer.parseInt(thumbnailsSize[j].substring(0, thumbnailsSize[j].indexOf('x'))); y = Integer.parseInt(thumbnailsSize[j].substring(thumbnailsSize[j].indexOf('x') + 1)); } else { //200 x = Integer.parseInt(thumbnailsSize[j]); y = Integer.parseInt(thumbnailsSize[j]); } boolean isCreated = false; try { isCreated = createThumbnail(fdo.getBodyFile(), thumbnailFile, x, y, fdo.getName(), thumbnailThreshold); } catch (IOException e) { // // If the thumbnail has not been created for some reasons, // the original FDO body will be used as thumbnail. // In this way, we will have always all the required // thumbnails even if they should contain the original file // instead of a resized file. // } if (!isCreated) { forceThumbnailCreation(thumbnailFile, fdo.getBodyFile()); thumbnails.put(thumbnailFileName, thumbnailFile); } else { thumbnails.put(thumbnailFileName, thumbnailFile); } //create rotated thumbnails and add it on thumbnails array for (int degree = 90; degree < 360; degree += 90) { String rotatedThumbnailName = createRotatedThumbnailName(thumbnailsSize[j], degree); File rotatedThumbnail = new File(thumbnailFolderPath, rotatedThumbnailName); // rotate thumbnail according to degree byte[] rotatedBA = rotateImage(thumbnailFile, degree); try { ImageIO.write(ImageIO.read(new ByteArrayInputStream(rotatedBA)), ImageFormat.IMAGE_FORMAT_JPEG.name, rotatedThumbnail); } catch (IOException ex) { throw new FileDataObjecyUtilsException( "Error creating the rotated thumbnail, file can't be written", ex); } thumbnails.put(rotatedThumbnailName, rotatedThumbnail); } } return thumbnails; } /** * Retrieves the EXIF data from the FDO body file and set it in the * properties map. * The EXIF data are supported by JPEG, TIFF Rev. 6.0, and RIFF WAV file * formats. It is not supported in JPEG 2000, PNG, or GIF. * * @param fdow the wrapper containing the file to retrieve the EXIF data * @throws FileDataObjecyUtilsException if an error occurs */ public void handleEXIF(FileDataObjectWrapper fdow) throws FileDataObjecyUtilsException { FileDataObject fdo = fdow.getFileDataObject(); Map<String, String> properties = fdo.getProperties(); JSONObject exifData = new JSONObject(); File bodyFile = fdo.getBodyFile(); String degree = "0"; try { ArrayList exifItems = null; IImageMetadata metadata = Sanselan.getMetadata(bodyFile); if (metadata != null && metadata instanceof JpegImageMetadata) { JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; exifItems = jpegMetadata.getItems(); int size = exifItems.size(); Object exifItem = null; String tagName = null; String tagValueDesc = null; String createDateTag = TiffConstants.EXIF_TAG_CREATE_DATE.name; String modifyDateTag = TiffConstants.EXIF_TAG_MODIFY_DATE.name; String orientationTag = TiffConstants.EXIF_TAG_ORIENTATION.name; String createDate = null; String modifyDate = null; for (int i = 0; i < size; i++) { exifItem = exifItems.get(i); if (exifItem instanceof TiffImageMetadata.Item) { TiffImageMetadata.Item item = (TiffImageMetadata.Item) exifItem; TiffField field = item.getTiffField(); if (field != null) { tagName = field.getTagName(); tagValueDesc = field.getValueDescription(); if (tagValueDesc != null && !"".equals(tagValueDesc)) { if (createDateTag.equals(tagName)) { createDate = fixExifDate(tagValueDesc); } else if (modifyDateTag.equals(tagName)) { modifyDate = fixExifDate(tagValueDesc); } else if (orientationTag.equals(tagName)) { degree = calculateDegree(tagValueDesc); } } } exifData.put(tagName, tagValueDesc); } } setFDODates(fdo, createDate, modifyDate); } if (!exifData.isEmpty()) { properties.put(EXIF_PROPERTY_NAME, exifData.toString()); } properties.put(ROTATION_PROPERTY_NAME, degree); } catch (IOException e) { throw new FileDataObjecyUtilsException("Error retrieving file metadata for '" + fdow.getId() + "'", e); } catch (ImageReadException e) { throw new FileDataObjecyUtilsException("Error reading Image metadata for '" + fdow.getId() + "'", e); } } /** * Sets creation and modification dates for the given file data object. * If the input create date is null and in the fdo this date is not set, * set it with the value of modify date (if set). * If the input modify date is null and in the fdo this date is not set, * set it with the value of the create date (if set). * * @param fdo the file data object which on set dates * @param createDate the creation date of the fdo * @param modifyDate the modification date of the fdo */ public static void setFDODates(FileDataObject fdo, String createDate, String modifyDate) { boolean isCreateDateSet = (createDate != null); boolean isModifyDateSet = (modifyDate != null); if (isCreateDateSet) { fdo.setCreated(createDate); if (!isModifyDateSet && (fdo.getModified() == null || "".equals(fdo.getModified()))) { fdo.setModified(createDate); } } if (isModifyDateSet) { fdo.setModified(modifyDate); if (!isCreateDateSet && (fdo.getCreated() == null || "".equals(fdo.getCreated()))) { fdo.setCreated(modifyDate); } } } // --------------------------------------------------------- Private methods /** * Checks if the file extention and it's format are supported. * * @param fdo the object containing the picture file to check * @return true if the file is supported, false otherwise */ private static boolean isAValidPicture(FileDataObject fdo) { if (!hasASupportedExtension(fdo.getName())) { return false; } File bodyFile = fdo.getBodyFile(); if (bodyFile == null || !bodyFile.isFile()) { return false; } try { ImageFormat image_format = Sanselan.guessFormat(bodyFile); if (!hasASupportedFormat(image_format)) { return false; } } catch (IOException ex) { return false; } catch (ImageReadException e) { return false; } return true; } /** * Checks if the given file name ends with a supported extension. * * @param name the file name to check * @return true if the extension is a supported one, false otherwise */ private static boolean hasASupportedExtension(String name) { if (name == null) { return false; } name = name.toLowerCase(); for (int ii = 0; ii < SUPPORTED_PICTURE_EXTENSIONS.length; ii++) { if (name.endsWith(SUPPORTED_PICTURE_EXTENSIONS[ii])) { return true; } } return false; } /** * Checks if the given image format is supported. * * @param format the image format to check * @return true if the image format is a supported one, false otherwise */ private static boolean hasASupportedFormat(ImageFormat format) { if (format == null) { return false; } if (format.equals(ImageFormat.IMAGE_FORMAT_JPEG) || format.equals(ImageFormat.IMAGE_FORMAT_PNG) || format.equals(ImageFormat.IMAGE_FORMAT_GIF)) { return true; } return false; } /** * Creates the thumbnail. * * @param imageFile the image file * @param thumbFile the empty thumbnail file * @param thumbX the width of the thumbnail * @param thumbY the height of the thumbnail * @param imageName the image file name with extension * @param tolerance the percentage of tolerance before creating a thumbnail * @return true is the thumbnail has been created, false otherwise * @throws IOException if an error occurs */ private static boolean createThumbnail(File imageFile, File thumbFile, int thumbX, int thumbY, String imageName, double tolerance) throws IOException { FileInputStream fileis = null; ImageInputStream imageis = null; Iterator readers = null; try { readers = ImageIO.getImageReadersByFormatName(imageName.substring(imageName.lastIndexOf('.') + 1)); if (readers == null || (!readers.hasNext())) { throw new IOException("File not supported"); } ImageReader reader = (ImageReader) readers.next(); fileis = new FileInputStream(imageFile); imageis = ImageIO.createImageInputStream(fileis); reader.setInput(imageis, true); // Determines thumbnail height, width and quality int thumbWidth = thumbX; int thumbHeight = thumbY; double thumbRatio = (double) thumbWidth / (double) thumbHeight; int imageWidth = reader.getWidth(0); int imageHeight = reader.getHeight(0); // // Don't create the thumbnail if the original file is smaller // than required size increased by % tolerance // if (imageWidth <= (thumbWidth * (1 + tolerance / 100)) && imageHeight <= (thumbHeight * (1 + tolerance / 100))) { return false; } double imageRatio = (double) imageWidth / (double) imageHeight; if (thumbRatio < imageRatio) { thumbHeight = (int) (thumbWidth / imageRatio); } else { thumbWidth = (int) (thumbHeight * imageRatio); } ImageReadParam param = reader.getDefaultReadParam(); param.setSourceSubsampling(3, 3, 0, 0); BufferedImage bi = reader.read(0, param); Image thumb = bi.getScaledInstance(thumbWidth, thumbHeight, Image.SCALE_SMOOTH); BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = thumbImage.createGraphics(); graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); graphics2D.drawImage(thumb, 0, 0, thumbWidth, thumbHeight, null); FileOutputStream fileOutputStream = new FileOutputStream(thumbFile); ImageIO.write(thumbImage, "jpg", fileOutputStream); thumb.flush(); thumbImage.flush(); fileOutputStream.flush(); fileOutputStream.close(); graphics2D.dispose(); } finally { if (fileis != null) { fileis.close(); } if (imageis != null) { imageis.close(); } } return true; } /** * Creates the ext folder if it doesn't exist. * * @param folderPath the folder path to create * @throws FileDataObjecyUtilsException */ private void createExtFolderIfNeeded(String folderPath) throws FileDataObjecyUtilsException { File extFolder = new File(folderPath); if (!extFolder.exists()) { if (!extFolder.mkdirs()) { throw new FileDataObjecyUtilsException("Unable to create folder '" + folderPath + "'"); } } } /** * Creates a thumbnail name based on the given thumbnail size. * * @param thumbnailsSize the thumbnail size (i.e 200, 200x175 formats) * @return a thumbnail name */ private String createThumbnailName(String thumbnailsSize) { // TODO for now the thumbnail name does not have the timestamp // but may be necessary to change the name if the file is changed // this to avoid cacheing on browser // : append('_').append(System.currentTimeMillis()). return new StringBuilder().append(thumbnailsSize).append(".jpg").toString(); } /** * Creates a rotated thumbnail name based on the given thumbnail size and rotation degree * * @param thumbnailsSize the thumbnail size (i.e 200, 200x175 formats) * @return a thumbnail name */ private String createRotatedThumbnailName(String thumbnailsSize, int degree) { // TODO for now the thumbnail name does not have the timestamp // but may be necessary to change the name if the file is changed // this to avoid cacheing on browser // : append('_').append(System.currentTimeMillis()). return new StringBuilder().append(thumbnailsSize).append(degree).append(".jpg").toString(); } /** * Copies the file data object body in a new file using it as thumbnail. * In this way, we will have always all the required thumbnails even if they * should contain the original file instead of a resized file. * * @param thumbnailFile the final thumbnail file * @param bodyFile the original file */ private void forceThumbnailCreation(File thumbnailFile, File bodyFile) { try { FileInputStream inStream = new FileInputStream(bodyFile); FileOutputStream outStream = new FileOutputStream(thumbnailFile); IOTools.copyStream(inStream, outStream); } catch (IOException e) { // do nothing } } /** * The dates in the EXIF have the format yyyy:MM:dd HH:mm:ss that should * be converted in the UTC format. Since the exif specification does not * declare that this is a date in local time, no timezone will be applied * during convertion in UTC format. * * @param date the exif string date to convert * @return the date in UTC format (yyyyMMdd'T'HHmmss'Z') or null */ private String fixExifDate(String tagValueDesc) { try { tagValueDesc = StringUtils.removeStart(tagValueDesc, "'"); tagValueDesc = StringUtils.removeEnd(tagValueDesc, "'"); return TimeUtils.convertDateFromTo(tagValueDesc, TimeUtils.PATTERN_EXIF_DATE, TimeUtils.PATTERN_UTC); } catch (ParseException e) { // don't set the creation date of the FDO } return null; } /** * Rotates given image file by given amount of degree. * The valid degree values are 0, 90, 180, 270. * If the image is a jpg, the rotation is lossless, exif data are preserved * and image size is almost the same. * * @param imageFile the image file * @param degree amount of degree to apply * @return a byte array containing rotated image data * @throws PicturesException if amount of degree is invalid or if an * IOException occurs */ protected static byte[] rotateImage(File imageFile, int degree) throws FileDataObjecyUtilsException { if (!isAValidRotationDegree(degree)) { throw new FileDataObjecyUtilsException( "Error rotating image since the '" + degree + "' degree value is unsupported"); } String format = getImageFormat(imageFile); if ("jpg".equalsIgnoreCase(format) || "jpeg".equalsIgnoreCase(format)) { return rotateJpeg(imageFile, degree); } else { BufferedImage image; try { image = ImageIO.read(imageFile); } catch (IOException ex) { throw new FileDataObjecyUtilsException("Error reading data from input byte array during rotation", ex); } BufferedImage rotatedImage = rotateImage(image, degree); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(rotatedImage, format, out); return out.toByteArray(); } catch (IOException ex) { throw new FileDataObjecyUtilsException("Error writing rotated image data into body", ex); } finally { try { out.close(); } catch (IOException e) { // do nothing } } } } /** * Rotates given buffered image by given amount of degree. * The valid degree values are 0, 90, 180, 270. * If the image is a jpg, the rotation is lossless, exif data are preserved * and image size is almost the same. * * @param bufImage the buffered image * @param degree amount of degree to apply * @return a buffered image containing rotated image data * @throws PicturesException if amount of degree is invalid or if an * IOException occurs */ private static BufferedImage rotateImage(BufferedImage bufImage, int degree) throws FileDataObjecyUtilsException { degree = degree % 360; int h; int w; switch (degree) { case 0: case 180: h = bufImage.getHeight(); w = bufImage.getWidth(); break; case 90: case 270: h = bufImage.getWidth(); w = bufImage.getHeight(); break; default: throw new FileDataObjecyUtilsException( "Error rotating image since the '" + degree + "' degree value is unsupported"); } BufferedImage out = null; int bufImageType = bufImage.getType(); if (BufferedImage.TYPE_BYTE_INDEXED == bufImageType || BufferedImage.TYPE_BYTE_BINARY == bufImageType) { IndexColorModel model = (IndexColorModel) bufImage.getColorModel(); out = new BufferedImage(w, h, bufImage.getType(), model); } else if (BufferedImage.TYPE_CUSTOM == bufImageType) { // we don't know what type of image it can be // there's a bug in some VM that cause some PNG images to have // type custom: this should take care of this issue //check if we need to have alpha channel boolean alpha = bufImage.getTransparency() != BufferedImage.OPAQUE; if (alpha) { // TYPE_INT_ARGB_PRE gives you smaller output images // than TYPE_INT_ARGB out = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); } else { out = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); } } else { out = new BufferedImage(w, h, bufImage.getType()); } Graphics2D g2d = out.createGraphics(); Map renderingHints = new HashMap(); renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); renderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g2d.setRenderingHints(renderingHints); g2d.rotate(Math.toRadians(degree)); switch (degree) { case 90: g2d.translate(0, -w); break; case 180: g2d.translate(-w, -h); break; case 270: g2d.translate(-h, 0); break; } g2d.drawImage(bufImage, null, 0, 0); g2d.dispose(); return out; } /** * Checks if the given degree is a valid number. * The valid values are only: 0, 90, 180, 270, 360. * * @param degree the value to check * @return true if the value is valid, false otherwise */ public static boolean isAValidRotationDegree(int degree) { return degree == 0 || degree == 90 || degree == 180 || degree == 270 || degree == 360; } /** * Retrieves the guess image format reading the file 'magic number' (it's * the first bytes of the file) and returns the corresponding format * extension. * If image format could not be guessed, returns file extension. * * @param file the file to check * @return guessed format extension, or file extension if unable to guess. */ public static String getImageFormat(File file) { try { return Sanselan.guessFormat(file).extension; } catch (Exception ex) { // returning extension String filename = file.getName(); String ext = filename.substring(filename.lastIndexOf(".") + 1, filename.length()); return ext; } } /** * Rotates the given jpg image applying the specified degree. * * @param imageFile the image to rotate * @param degree the degree to apply * @return a byte array containing the rotated image * @throws FileDataObjecyUtilsException if an error occurs */ private static byte[] rotateJpeg(File imageFile, int degree) throws FileDataObjecyUtilsException { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { int op = getLLJRotationOp(degree); LLJTran llj = new LLJTran(imageFile); try { llj.read(LLJTran.READ_ALL, true); } catch (LLJTranException ex) { throw new FileDataObjecyUtilsException("Error rotating jpg image", ex); } // this means we are cropping images with sizes that is // not a multiple of MCU. int options = LLJTran.OPT_DEFAULTS & LLJTran.OPT_WRITE_APPXS | LLJTran.OPT_XFORM_TRIM | LLJTran.OPT_XFORM_ORIENTATION; llj.transform(op, options); llj.save(out, LLJTran.OPT_WRITE_ALL); llj.freeMemory(); return out.toByteArray(); } catch (IOException ex) { throw new FileDataObjecyUtilsException("Error writing rotated jpg image", ex); } finally { try { out.close(); } catch (IOException e) { // do nothing } } } /** * Returns the corresponding LLJTRAN operation given degree. * Accepted values are 0, 90, 180, 270 and for the other values returns * LLJTran.NONE operation. * * @param degree the degree to check * @throws FileDataObjecyUtilsException if an error occurs */ private static int getLLJRotationOp(int degree) throws FileDataObjecyUtilsException { switch (degree % 360) { case 0: return LLJTran.NONE; case 90: return LLJTran.ROT_90; case 180: return LLJTran.ROT_180; case 270: return LLJTran.ROT_270; default: throw new FileDataObjecyUtilsException("Error retrieving LLJTRAN value for '" + degree + "'"); } } /** * This method returns the correct rotation degree starting from * @param orientation * @return */ private String calculateDegree(String orientation) { String degree = "0"; /* * device orientation: * A 6 * | * 1 <-----> 3 * | * V 8 * */ switch (Integer.valueOf(orientation).intValue()) { case 1: case 2: { //means device placed horizontal, i.e. Iphone with //power button on the left side degree = "0"; break; } case 3: case 4: { //means device placed horizontal, i.e. Iphone with //power button on the right side degree = "180"; break; } case 5: case 6: { //means device placed vertical, i.e. Iphone with //power button on the up side degree = "90"; break; } case 7: case 8: { //means device placed vertical, i.e. Iphone with //power button on the bottom side degree = "270"; break; } default: { degree = "0"; break; } } return degree; } }