1b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav/* 2b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Copyright (C) 2013 The Android Open Source Project 3b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 4b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Licensed under the Apache License, Version 2.0 (the "License"); 5b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * you may not use this file except in compliance with the License. 6b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * You may obtain a copy of the License at 7b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 8b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * http://www.apache.org/licenses/LICENSE-2.0 9b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 10b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Unless required by applicable law or agreed to in writing, software 11b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * distributed under the License is distributed on an "AS IS" BASIS, 12b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * See the License for the specific language governing permissions and 14b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * limitations under the License. 15b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 16b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 17b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavpackage android.support.v4.print; 18b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 19b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.content.Context; 20b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.Bitmap; 21b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.BitmapFactory; 22b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.Matrix; 23b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.RectF; 24b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.pdf.PdfDocument.Page; 25b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.net.Uri; 26b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.os.Bundle; 27b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.os.CancellationSignal; 28b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.os.ParcelFileDescriptor; 29b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PageRange; 30b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintAttributes; 31b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintDocumentAdapter; 32b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintDocumentInfo; 33b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintManager; 34b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.pdf.PrintedPdfDocument; 35b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.util.Log; 36b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 37b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.FileNotFoundException; 38b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.FileOutputStream; 39b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.IOException; 40b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.InputStream; 41b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 42b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav/** 43b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Kitkat specific PrintManager API implementation. 44b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 45b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavpublic class PrintHelperKitkat { 46b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private static final String LOG_TAG = "PrintHelperKitkat"; 47b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // will be <= 300 dpi on A4 (8.3×11.7) paper (worst case of 150 dpi) 48b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private final static int MAX_PRINT_SIZE = 3500; 49b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav final Context mContext; 50b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 51b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * image will be scaled but leave white space 52b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 53b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public static final int SCALE_MODE_FIT = 1; 54b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 55b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * image will fill the paper and be cropped (default) 56b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 57b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public static final int SCALE_MODE_FILL = 2; 58b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 5909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 6009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * this is a black and white image 6109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 6209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public static final int COLOR_MODE_MONOCHROME = 1; 6309ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 6409ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 6509ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * this is a color image (default) 6609ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 6709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public static final int COLOR_MODE_COLOR = 2; 6809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 69b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int mScaleMode = SCALE_MODE_FILL; 70b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 7109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov int mColorMode = COLOR_MODE_COLOR; 7209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 73b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintHelperKitkat(Context context) { 74b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mContext = context; 75b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 76b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 77b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 78b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Selects whether the image will fill the paper and be cropped 79b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FIT} 80b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * or whether the image will be scaled but leave white space 81b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FILL}. 82b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 83b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param scaleMode {@link #SCALE_MODE_FIT} or 84b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FILL} 85b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 86b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void setScaleMode(int scaleMode) { 87b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mScaleMode = scaleMode; 88b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 89b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 90b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 91b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Returns the scale mode with which the image will fill the paper. 92b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 93b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @return The scale Mode: {@link #SCALE_MODE_FIT} or 94b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FILL} 95b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 96b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public int getScaleMode() { 97b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return mScaleMode; 98b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 99b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 100b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 10109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * Sets whether the image will be printed in color (default) 10209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * {@link #COLOR_MODE_COLOR} or in back and white 10309ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * {@link #COLOR_MODE_MONOCHROME}. 10409ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * 10509ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * @param colorMode The color mode which is one of 10609ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}. 10709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 10809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public void setColorMode(int colorMode) { 10909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov mColorMode = colorMode; 11009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov } 11109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 11209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 11309ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * Gets the color mode with which the image will be printed. 11409ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * 11509ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * @return The color mode which is one of {@link #COLOR_MODE_COLOR} 11609ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * and {@link #COLOR_MODE_MONOCHROME}. 11709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 11809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public int getColorMode() { 11909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov return mColorMode; 12009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov } 12109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 12209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 123b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Prints a bitmap. 124b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 125b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param jobName The print job name. 126b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param bitmap The bitmap to print. 127b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 128b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void printBitmap(final String jobName, final Bitmap bitmap) { 129b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (bitmap == null) { 130b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return; 131b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 132b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav final int fittingMode = mScaleMode; // grab the fitting mode at time of call 133b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE); 134b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintAttributes.MediaSize mediaSize = PrintAttributes.MediaSize.UNKNOWN_PORTRAIT; 135b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (bitmap.getWidth() > bitmap.getHeight()) { 136b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mediaSize = PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE; 137b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 13809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov PrintAttributes attr = new PrintAttributes.Builder() 13909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov .setMediaSize(mediaSize) 14009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov .setColorMode(mColorMode) 14109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov .build(); 142b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 143b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav printManager.print(jobName, 144b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav new PrintDocumentAdapter() { 145b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private PrintAttributes mAttributes; 146b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 147b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav @Override 148b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void onLayout(PrintAttributes oldPrintAttributes, 149b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintAttributes newPrintAttributes, 150b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav CancellationSignal cancellationSignal, 151b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav LayoutResultCallback layoutResultCallback, 152b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Bundle bundle) { 153b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 154b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mAttributes = newPrintAttributes; 155b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 156b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName) 157b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO) 158b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav .setPageCount(1) 159b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav .build(); 160b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav boolean changed = !newPrintAttributes.equals(oldPrintAttributes); 161b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav layoutResultCallback.onLayoutFinished(info, changed); 162b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 163b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 164b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav @Override 165b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor fileDescriptor, 166b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav CancellationSignal cancellationSignal, 167b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav WriteResultCallback writeResultCallback) { 168b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintedPdfDocument pdfDocument = new PrintedPdfDocument(mContext, 169b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mAttributes); 170b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 171b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Page page = pdfDocument.startPage(1); 172b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 173b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav RectF content = new RectF(page.getInfo().getContentRect()); 174b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Matrix matrix = new Matrix(); 175b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 176b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Compute and apply scale to fill the page. 177b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav float scale = content.width() / bitmap.getWidth(); 178b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (fittingMode == SCALE_MODE_FILL) { 179b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav scale = Math.max(scale, content.height() / bitmap.getHeight()); 180b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } else { 181b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav scale = Math.min(scale, content.height() / bitmap.getHeight()); 182b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 183b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav matrix.postScale(scale, scale); 184b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 185b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Center the content. 186b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav final float translateX = (content.width() 187b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav - bitmap.getWidth() * scale) / 2; 188b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav final float translateY = (content.height() 189b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav - bitmap.getHeight() * scale) / 2; 190b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav matrix.postTranslate(translateX, translateY); 191b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 192b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Draw the bitmap. 193b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav page.getCanvas().drawBitmap(bitmap, matrix, null); 194b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 195b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Finish the page. 196b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav pdfDocument.finishPage(page); 197b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 198b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 199b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Write the document. 200b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav pdfDocument.writeTo(new FileOutputStream( 201b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav fileDescriptor.getFileDescriptor())); 202b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Done. 203b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav writeResultCallback.onWriteFinished( 204b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav new PageRange[]{PageRange.ALL_PAGES}); 205b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } catch (IOException ioe) { 206b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Failed. 207b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Log.e(LOG_TAG, "Error writing printed content", ioe); 208b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav writeResultCallback.onWriteFailed(null); 209b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 210b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } finally { 211b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (pdfDocument != null) { 212b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav pdfDocument.close(); 213b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 214b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (fileDescriptor != null) { 215b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 216b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav fileDescriptor.close(); 217b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } catch (IOException ioe) { 218b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /* ignore */ 219b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 220b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 221b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 222b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 223b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav }, attr); 224b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 225b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 226b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 227b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Prints an image located at the Uri. Image types supported are those of 228b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * <code>BitmapFactory.decodeStream</code> (JPEG, GIF, PNG, BMP, WEBP) 229b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 230b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param jobName The print job name. 231b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param imageFile The <code>Uri</code> pointing to an image to print. 232b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image. 233b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 234b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void printBitmap(String jobName, Uri imageFile) throws FileNotFoundException { 235b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Bitmap bitmap = loadConstrainedBitmap(imageFile, MAX_PRINT_SIZE); 236b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav printBitmap(jobName, bitmap); 237b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 238b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 239b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 240b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Loads a bitmap while limiting its size 241b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 242b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param uri location of a valid image 243b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param maxSideLength the maximum length of a size 244b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @return the Bitmap 245b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @throws FileNotFoundException if the Uri does not point to an image 246b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 247b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private Bitmap loadConstrainedBitmap(Uri uri, int maxSideLength) throws FileNotFoundException { 248b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (maxSideLength <= 0 || uri == null || mContext == null) { 249b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav throw new IllegalArgumentException("bad argument to getScaledBitmap"); 250b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 251b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Get width and height of stored bitmap 252b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav BitmapFactory.Options opt = new BitmapFactory.Options(); 253b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav opt.inJustDecodeBounds = true; 254b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav loadBitmap(uri, opt); 255b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 256b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int w = opt.outWidth; 257b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int h = opt.outHeight; 258b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 259b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // If bitmap cannot be decoded, return null 260b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (w <= 0 || h <= 0) { 261b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return null; 262b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 263b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 264b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Find best downsampling size 265b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int imageSide = Math.max(w, h); 266b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 267b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int sampleSize = 1; 268b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav while (imageSide > maxSideLength) { 269b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav imageSide >>>= 1; 270b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav sampleSize <<= 1; 271b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 272b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 273b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Make sure sample size is reasonable 274b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (sampleSize <= 0 || 0 >= (int) (Math.min(w, h) / sampleSize)) { 275b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return null; 276b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 277b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav BitmapFactory.Options options = new BitmapFactory.Options(); 278b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav options.inMutable = true; 279b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav options.inSampleSize = sampleSize; 280b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return loadBitmap(uri, options); 281b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 282b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 283b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 284b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Returns the bitmap from the given uri loaded using the given options. 285b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Returns null on failure. 286b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 287b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private Bitmap loadBitmap(Uri uri, BitmapFactory.Options o) throws FileNotFoundException { 288b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (uri == null || mContext == null) { 289b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav throw new IllegalArgumentException("bad argument to loadBitmap"); 290b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 291b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav InputStream is = null; 292b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 293b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav is = mContext.getContentResolver().openInputStream(uri); 294b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return BitmapFactory.decodeStream(is, null, o); 295b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } finally { 296545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov if (is != null) { 297545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov try { 298545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov is.close(); 299545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov } catch (IOException t) { 300545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov Log.w(LOG_TAG, "close fail ", t); 301545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov } 302b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 303b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 304b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 305b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav}