/** * Creates a new instance of the pool. * @param poolParams pool parameters * @param poolStatsTracker */ public BasePool( MemoryTrimmableRegistry memoryTrimmableRegistry, PoolParams poolParams, PoolStatsTracker poolStatsTracker) { mMemoryTrimmableRegistry = Preconditions.checkNotNull(memoryTrimmableRegistry); mPoolParams = Preconditions.checkNotNull(poolParams); mPoolStatsTracker = Preconditions.checkNotNull(poolStatsTracker); // initialize the buckets mBuckets = new SparseArray<Bucket<V>>(); initBuckets(new SparseIntArray(0)); mInUseValues = Sets.newIdentityHashSet(); mFree = new Counter(); mUsed = new Counter(); }
@Override protected Drawable createDrawable(CloseableReference<CloseableImage> image) { Preconditions.checkState(CloseableReference.isValid(image)); CloseableImage closeableImage = image.get(); maybeUpdateDebugOverlay(closeableImage); Drawable drawable = maybeCreateDrawableFromFactories(mCustomDrawableFactories, closeableImage); if (drawable != null) { return drawable; } drawable = maybeCreateDrawableFromFactories(mGlobalDrawableFactories, closeableImage); if (drawable != null) { return drawable; } drawable = mDefaultDrawableFactory.createDrawable(closeableImage); if (drawable != null) { return drawable; } throw new UnsupportedOperationException("Unrecognized image class: " + closeableImage); }
/** * Decodes a GIF into a CloseableImage. * @param encodedImage encoded image (native byte array holding the encoded bytes and meta data) * @param options the options for the decode * @param bitmapConfig the Bitmap.Config used to generate the output bitmaps * @return a {@link CloseableImage} for the GIF image */ public CloseableImage decodeGif( final EncodedImage encodedImage, final ImageDecodeOptions options, final Bitmap.Config bitmapConfig) { if (sGifAnimatedImageDecoder == null) { throw new UnsupportedOperationException("To encode animated gif please add the dependency " + "to the animated-gif module"); } final CloseableReference<PooledByteBuffer> bytesRef = encodedImage.getByteBufferRef(); Preconditions.checkNotNull(bytesRef); try { final PooledByteBuffer input = bytesRef.get(); AnimatedImage gifImage = sGifAnimatedImageDecoder.decode(input.getNativePtr(), input.size()); return getCloseableImage(options, gifImage, bitmapConfig); } finally { CloseableReference.closeSafely(bytesRef); } }
/** * Runs time forwards by a given duration, executing any commands scheduled for * execution during that time period, and any background tasks spawned by the * scheduled tasks. Therefore, when a call to tick returns, the executor * will be idle. */ private void tick() { long newNow = clock.now(); Preconditions.checkState(!isTicking); isTicking = true; try { tickRemaining = newNow - now; now = newNow; do { tickRemaining = deltaQueue.tick(tickRemaining); runUntilIdle(); } while (deltaQueue.isNotEmpty() && tickRemaining > 0); Preconditions.checkState(isTicking); } finally { isTicking = false; tickRemaining = 0; } }
/** * Downscales and rotates jpeg image * * @param inputStream * @param outputStream * @param exifOrientation 0, 90, 180 or 270 * @param scaleNumerator 1 - 16, image will be scaled using scaleNumerator/8 factor * @param quality 1 - 100 */ public static void transcodeJpegWithExifOrientation( final InputStream inputStream, final OutputStream outputStream, final int exifOrientation, final int scaleNumerator, final int quality) throws IOException { Preconditions.checkArgument(scaleNumerator >= MIN_SCALE_NUMERATOR); Preconditions.checkArgument(scaleNumerator <= MAX_SCALE_NUMERATOR); Preconditions.checkArgument(quality >= MIN_QUALITY); Preconditions.checkArgument(quality <= MAX_QUALITY); Preconditions.checkArgument(isExifOrientationAllowed(exifOrientation)); Preconditions.checkArgument( scaleNumerator != SCALE_DENOMINATOR || exifOrientation != ExifInterface.ORIENTATION_NORMAL, "no transformation requested"); nativeTranscodeJpegWithExifOrientation( Preconditions.checkNotNull(inputStream), Preconditions.checkNotNull(outputStream), exifOrientation, scaleNumerator, quality); }
public BitmapMemoryCacheKey( String sourceString, @Nullable ResizeOptions resizeOptions, RotationOptions rotationOptions, ImageDecodeOptions imageDecodeOptions, @Nullable CacheKey postprocessorCacheKey, @Nullable String postprocessorName, Object callerContext) { mSourceString = Preconditions.checkNotNull(sourceString); mResizeOptions = resizeOptions; mRotationOptions = rotationOptions; mImageDecodeOptions = imageDecodeOptions; mPostprocessorCacheKey = postprocessorCacheKey; mPostprocessorName = postprocessorName; mHash = HashCodeUtil.hashCode( sourceString.hashCode(), (resizeOptions != null) ? resizeOptions.hashCode() : 0, rotationOptions.hashCode(), mImageDecodeOptions, mPostprocessorCacheKey, postprocessorName); mCallerContext = callerContext; mCacheTime = RealtimeSinceBootClock.get().now(); }
/** Adds controller listener. */ public void addControllerListener(ControllerListener<? super INFO> controllerListener) { Preconditions.checkNotNull(controllerListener); if (mControllerListener instanceof InternalForwardingListener) { ((InternalForwardingListener<INFO>) mControllerListener).addListener(controllerListener); return; } if (mControllerListener != null) { mControllerListener = InternalForwardingListener.createInternal( mControllerListener, controllerListener); return; } // Listener only receives <INFO>, it never produces one. // That means if it can accept <? super INFO>, it can very well accept <INFO>. mControllerListener = (ControllerListener<INFO>) controllerListener; }
public DecodeProducer( final ByteArrayPool byteArrayPool, final Executor executor, final ImageDecoder imageDecoder, final ProgressiveJpegConfig progressiveJpegConfig, final boolean downsampleEnabled, final boolean downsampleEnabledForNetwork, final boolean decodeCancellationEnabled, final Producer<EncodedImage> inputProducer, final Supplier<Boolean> experimentalSmartResizingEnabled) { mByteArrayPool = Preconditions.checkNotNull(byteArrayPool); mExecutor = Preconditions.checkNotNull(executor); mImageDecoder = Preconditions.checkNotNull(imageDecoder); mProgressiveJpegConfig = Preconditions.checkNotNull(progressiveJpegConfig); mDownsampleEnabled = downsampleEnabled; mDownsampleEnabledForNetwork = downsampleEnabledForNetwork; mInputProducer = Preconditions.checkNotNull(inputProducer); mDecodeCancellationEnabled = decodeCancellationEnabled; mExperimentalSmartResizingEnabled = experimentalSmartResizingEnabled; }
/** * Determines type of WebP image. imageHeaderBytes has to be header of a WebP image */ private static ImageFormat getWebpFormat(final byte[] imageHeaderBytes, final int headerSize) { Preconditions.checkArgument(WebpSupportStatus.isWebpHeader(imageHeaderBytes, 0, headerSize)); if (WebpSupportStatus.isSimpleWebpHeader(imageHeaderBytes, 0)) { return DefaultImageFormats.WEBP_SIMPLE; } if (WebpSupportStatus.isLosslessWebpHeader(imageHeaderBytes, 0)) { return DefaultImageFormats.WEBP_LOSSLESS; } if (WebpSupportStatus.isExtendedWebpHeader(imageHeaderBytes, 0, headerSize)) { if (WebpSupportStatus.isAnimatedWebpHeader(imageHeaderBytes, 0)) { return DefaultImageFormats.WEBP_ANIMATED; } if (WebpSupportStatus.isExtendedWebpHeaderWithAlpha(imageHeaderBytes, 0)) { return DefaultImageFormats.WEBP_EXTENDED_WITH_ALPHA; } return DefaultImageFormats.WEBP_EXTENDED; } return ImageFormat.UNKNOWN; }
private static TriState shouldTranscode(final EncodedImage encodedImage) { Preconditions.checkNotNull(encodedImage); ImageFormat imageFormat = ImageFormatChecker.getImageFormat_WrapIOException( encodedImage.getInputStream()); if (DefaultImageFormats.isStaticWebpFormat(imageFormat)) { final WebpTranscoder webpTranscoder = WebpTranscoderFactory.getWebpTranscoder(); if (webpTranscoder == null) { return TriState.NO; } return TriState.valueOf( !webpTranscoder.isWebpNativelySupported(imageFormat)); } else if (imageFormat == ImageFormat.UNKNOWN) { // the image format might be unknown because we haven't fetched the whole header yet, // in which case the decision whether to transcode or not cannot be made yet return TriState.UNSET; } // if the image format is known, but it is not WebP, then the image shouldn't be transcoded return TriState.NO; }
private void doPostprocessing( CloseableReference<CloseableImage> sourceImageRef, int status) { Preconditions.checkArgument(CloseableReference.isValid(sourceImageRef)); if (!shouldPostprocess(sourceImageRef.get())) { maybeNotifyOnNewResult(sourceImageRef, status); return; } mListener.onProducerStart(mRequestId, NAME); CloseableReference<CloseableImage> destImageRef = null; try { try { destImageRef = postprocessInternal(sourceImageRef.get()); } catch (Exception e) { mListener.onProducerFinishWithFailure( mRequestId, NAME, e, getExtraMap(mListener, mRequestId, mPostprocessor)); maybeNotifyOnFailure(e); return; } mListener.onProducerFinishWithSuccess( mRequestId, NAME, getExtraMap(mListener, mRequestId, mPostprocessor)); maybeNotifyOnNewResult(destImageRef, status); } finally { CloseableReference.closeSafely(destImageRef); } }
private DiskCacheConfig(Builder builder) { mVersion = builder.mVersion; mBaseDirectoryName = Preconditions.checkNotNull(builder.mBaseDirectoryName); mBaseDirectoryPathSupplier = Preconditions.checkNotNull(builder.mBaseDirectoryPathSupplier); mDefaultSizeLimit = builder.mMaxCacheSize; mLowDiskSpaceSizeLimit = builder.mMaxCacheSizeOnLowDiskSpace; mMinimumSizeLimit = builder.mMaxCacheSizeOnVeryLowDiskSpace; mEntryEvictionComparatorSupplier = Preconditions.checkNotNull(builder.mEntryEvictionComparatorSupplier); mCacheErrorLogger = builder.mCacheErrorLogger == null ? NoOpCacheErrorLogger.getInstance() : builder.mCacheErrorLogger; mCacheEventListener = builder.mCacheEventListener == null ? NoOpCacheEventListener.getInstance() : builder.mCacheEventListener; mDiskTrimmableRegistry = builder.mDiskTrimmableRegistry == null ? NoOpDiskTrimmableRegistry.getInstance() : builder.mDiskTrimmableRegistry; mContext = builder.mContext; mIndexPopulateAtStartupEnabled = builder.mIndexPopulateAtStartupEnabled; }
/** * @param key * @return value associated with given key or null if no value is associated */ public synchronized EncodedImage get(final CacheKey key) { Preconditions.checkNotNull(key); EncodedImage storedEncodedImage = mMap.get(key); if (storedEncodedImage != null) { synchronized (storedEncodedImage) { if (!EncodedImage.isValid(storedEncodedImage)) { // Reference is not valid, this means that someone cleared reference while it was still in // use. Log error // TODO: 3697790 mMap.remove(key); FLog.w( TAG, "Found closed reference %d for key %s (%d)", System.identityHashCode(storedEncodedImage), key.getUriString(), System.identityHashCode(key)); return null; } storedEncodedImage = EncodedImage.cloneOrNull(storedEncodedImage); } } return storedEncodedImage; }
/** Sets a new drawable at the specified index, and return the previous drawable, if any. */ @Nullable public Drawable setDrawable(int index, @Nullable Drawable drawable) { Preconditions.checkArgument(index >= 0); Preconditions.checkArgument(index < mLayers.length); final Drawable oldDrawable = mLayers[index]; if (drawable != oldDrawable) { if (drawable != null && mIsMutated) { drawable.mutate(); } DrawableUtils.setCallbacks(mLayers[index], null, null); DrawableUtils.setCallbacks(drawable, null, null); DrawableUtils.setDrawableProperties(drawable, mDrawableProperties); DrawableUtils.copyProperties(drawable, this); DrawableUtils.setCallbacks(drawable, this, this); mIsStatefulCalculated = false; mLayers[index] = drawable; invalidateSelf(); } return oldDrawable; }
/** * Creates a bitmap from encoded bytes. * * @param encodedImage the encoded image with reference to the encoded bytes * @param bitmapConfig the {@link android.graphics.Bitmap.Config} used to create the decoded * Bitmap * @param regionToDecode optional image region to decode. currently not supported. * @return the bitmap * @throws TooManyBitmapsException if the pool is full * @throws java.lang.OutOfMemoryError if the Bitmap cannot be allocated */ @Override public CloseableReference<Bitmap> decodeFromEncodedImage( final EncodedImage encodedImage, Bitmap.Config bitmapConfig, @Nullable Rect regionToDecode) { BitmapFactory.Options options = getBitmapFactoryOptions( encodedImage.getSampleSize(), bitmapConfig); CloseableReference<PooledByteBuffer> bytesRef = encodedImage.getByteBufferRef(); Preconditions.checkNotNull(bytesRef); try { Bitmap bitmap = decodeByteArrayAsPurgeable(bytesRef, options); return pinBitmap(bitmap); } finally { CloseableReference.closeSafely(bytesRef); } }
@Override public void onAttach() { if (FLog.isLoggable(FLog.VERBOSE)) { FLog.v( TAG, "controller %x %s: onAttach: %s", System.identityHashCode(this), mId, mIsRequestSubmitted ? "request already submitted" : "request needs submit"); } mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER); Preconditions.checkNotNull(mSettableDraweeHierarchy); mDeferredReleaser.cancelDeferredRelease(this); mIsAttached = true; if (!mIsRequestSubmitted) { submitRequest(); } }
private void changeDraweeViewScaleType( SimpleDraweeView draweeView, ScaleType scaleType, @Nullable PointF focusPoint) { final GenericDraweeHierarchy hierarchy = draweeView.getHierarchy(); hierarchy.setActualImageScaleType(scaleType); hierarchy.setActualImageFocusPoint(focusPoint != null ? focusPoint : new PointF(0.5f, 0.5f)); final RoundingParams roundingParams = Preconditions.checkNotNull(hierarchy.getRoundingParams()); if (BITMAP_ONLY_SCALETYPES.contains(scaleType)) { roundingParams.setRoundingMethod(RoundingParams.RoundingMethod.BITMAP_ONLY); } else { roundingParams.setOverlayColor(mWindowBackgroundColor); } hierarchy.setRoundingParams(roundingParams); }
@VisibleForTesting static float determineDownsampleRatio( ImageRequest imageRequest, EncodedImage encodedImage) { Preconditions.checkArgument(EncodedImage.isMetaDataAvailable(encodedImage)); final ResizeOptions resizeOptions = imageRequest.getResizeOptions(); if (resizeOptions == null || resizeOptions.height <= 0 || resizeOptions.width <= 0 || encodedImage.getWidth() == 0 || encodedImage.getHeight() == 0) { return 1.0f; } final int rotationAngle = getRotationAngle(imageRequest, encodedImage); final boolean swapDimensions = rotationAngle == 90 || rotationAngle == 270; final int widthAfterRotation = swapDimensions ? encodedImage.getHeight() : encodedImage.getWidth(); final int heightAfterRotation = swapDimensions ? encodedImage.getWidth() : encodedImage.getHeight(); final float widthRatio = ((float) resizeOptions.width) / widthAfterRotation; final float heightRatio = ((float) resizeOptions.height) / heightAfterRotation; float ratio = Math.max(widthRatio, heightRatio); FLog.v( "DownsampleUtil", "Downsample - Specified size: %dx%d, image size: %dx%d " + "ratio: %.1f x %.1f, ratio: %.3f for %s", resizeOptions.width, resizeOptions.height, widthAfterRotation, heightAfterRotation, widthRatio, heightRatio, ratio, imageRequest.getSourceUri().toString()); return ratio; }
/** * Gets the drawable at the specified index. * @param index index of drawable to get * @return drawable at the specified index */ @Nullable public Drawable getDrawable(int index) { Preconditions.checkArgument(index >= 0); Preconditions.checkArgument(index < mLayers.length); return mLayers[index]; }
public ProgressiveJpegParser(ByteArrayPool byteArrayPool) { mByteArrayPool = Preconditions.checkNotNull(byteArrayPool); mBytesParsed = 0; mLastByteRead = 0; mNextFullScanNumber = 0; mBestScanEndOffset = 0; mBestScanNumber = 0; mParserState = READ_FIRST_JPEG_BYTE; }
/** Validates the parameters before building a controller. */ protected void validate() { Preconditions.checkState( (mMultiImageRequests == null) || (mImageRequest == null), "Cannot specify both ImageRequest and FirstAvailableImageRequests!"); Preconditions.checkState( (mDataSourceSupplier == null) || (mMultiImageRequests == null && mImageRequest == null && mLowResImageRequest == null), "Cannot specify DataSourceSupplier with other ImageRequests! Use one or the other."); }
/** * Sets a custom zoomable controller, instead of using the default one. */ public void setZoomableController(ZoomableController zoomableController) { Preconditions.checkNotNull(zoomableController); mZoomableController.setListener(null); mZoomableController = zoomableController; mZoomableController.setListener(mZoomableListener); }
private Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence( ImageRequest imageRequest) { Preconditions.checkNotNull(imageRequest); Uri uri = imageRequest.getSourceUri(); Preconditions.checkNotNull(uri, "Uri is null."); switch (imageRequest.getSourceUriType()) { case SOURCE_TYPE_NETWORK: return getNetworkFetchSequence(); case SOURCE_TYPE_LOCAL_VIDEO_FILE: return getLocalVideoFileFetchSequence(); case SOURCE_TYPE_LOCAL_IMAGE_FILE: return getLocalImageFileFetchSequence(); case SOURCE_TYPE_LOCAL_CONTENT: if (MediaUtils.isVideo(mContentResolver.getType(uri))) { return getLocalVideoFileFetchSequence(); } return getLocalContentUriFetchSequence(); case SOURCE_TYPE_LOCAL_ASSET: return getLocalAssetFetchSequence(); case SOURCE_TYPE_LOCAL_RESOURCE: return getLocalResourceFetchSequence(); case SOURCE_TYPE_QUALIFIED_RESOURCE: return getQualifiedResourceFetchSequence(); case SOURCE_TYPE_DATA: return getDataFetchSequence(); default: throw new IllegalArgumentException( "Unsupported uri scheme! Uri is: " + getShortenedUriString(uri)); } }
/** * Transcodes webp image given by input stream into jpeg. */ @Override public void transcodeWebpToJpeg( InputStream inputStream, OutputStream outputStream, int quality) throws IOException { StaticWebpNativeLoader.ensure(); nativeTranscodeWebpToJpeg( Preconditions.checkNotNull(inputStream), Preconditions.checkNotNull(outputStream), quality); }
/** * Transcodes Webp image given by input stream into png. */ @Override public void transcodeWebpToPng( InputStream inputStream, OutputStream outputStream) throws IOException { StaticWebpNativeLoader.ensure(); nativeTranscodeWebpToPng( Preconditions.checkNotNull(inputStream), Preconditions.checkNotNull(outputStream)); }
public void onStart() { Preconditions.checkNotNull(mTag); Preconditions.checkNotNull(mPerfListener); if (mState == ImageRequestState.STARTED) { onCancellation(); } mStartTime = System.currentTimeMillis(); mFinishTime = 0; mPerfListener.reportStart(); mState = ImageRequestState.STARTED; FLog.i(TAG, "Image [%s]: loading started...", mTag); }
public NetworkImagesProgressiveDecoder( final Consumer<CloseableReference<CloseableImage>> consumer, final ProducerContext producerContext, final ProgressiveJpegParser progressiveJpegParser, final ProgressiveJpegConfig progressiveJpegConfig, final boolean decodeCancellationEnabled) { super(consumer, producerContext, decodeCancellationEnabled); mProgressiveJpegParser = Preconditions.checkNotNull(progressiveJpegParser); mProgressiveJpegConfig = Preconditions.checkNotNull(progressiveJpegConfig); mLastScheduledScanNumber = 0; }
/** * Skips byteCount (or however many bytes are available) bytes in the stream * @param byteCount number of bytes to skip * @return number of bytes actually skipped */ @Override public long skip(long byteCount) { Preconditions.checkArgument(byteCount >= 0); int skipped = Math.min((int) byteCount, available()); mOffset += skipped; return skipped; }
public PooledByteArrayBufferedInputStream( InputStream inputStream, byte[] byteArray, ResourceReleaser<byte[]> resourceReleaser) { mInputStream = Preconditions.checkNotNull(inputStream); mByteArray = Preconditions.checkNotNull(byteArray); mResourceReleaser = Preconditions.checkNotNull(resourceReleaser); mBufferedSize = 0; mBufferOffset = 0; mClosed = false; }
@Override public int read() throws IOException { Preconditions.checkState(mBufferOffset <= mBufferedSize); ensureNotClosed(); if (!ensureDataInBuffer()) { return -1; } return mByteArray[mBufferOffset++] & 0xFF; }
@Override public int read(byte[] buffer, int offset, int length) throws IOException { Preconditions.checkState(mBufferOffset <= mBufferedSize); ensureNotClosed(); if (!ensureDataInBuffer()) { return -1; } final int bytesToRead = Math.min(mBufferedSize - mBufferOffset, length); System.arraycopy(mByteArray, mBufferOffset, buffer, offset, bytesToRead); mBufferOffset += bytesToRead; return bytesToRead; }
@Override public long skip(long byteCount) throws IOException { Preconditions.checkState(mBufferOffset <= mBufferedSize); ensureNotClosed(); final int bytesLeftInBuffer = mBufferedSize - mBufferOffset; if (bytesLeftInBuffer >= byteCount) { mBufferOffset += byteCount; return byteCount; } mBufferOffset = mBufferedSize; return bytesLeftInBuffer + mInputStream.skip(byteCount - bytesLeftInBuffer); }
/** * Starts next producer if it is not started yet and there is at least one Consumer waiting for * the data. If all consumers are cancelled, then this multiplexer is removed from mRequest * map to clean up. */ private void startInputProducerIfHasAttachedConsumers() { BaseProducerContext multiplexProducerContext; ForwardingConsumer forwardingConsumer; synchronized (Multiplexer.this) { Preconditions.checkArgument(mMultiplexProducerContext == null); Preconditions.checkArgument(mForwardingConsumer == null); // Cleanup if all consumers have been cancelled before this method was called if (mConsumerContextPairs.isEmpty()) { removeMultiplexer(mKey, this); return; } ProducerContext producerContext = mConsumerContextPairs.iterator().next().second; mMultiplexProducerContext = new BaseProducerContext( producerContext.getImageRequest(), producerContext.getId(), producerContext.getListener(), producerContext.getCallerContext(), producerContext.getLowestPermittedRequestLevel(), computeIsPrefetch(), computeIsIntermediateResultExpected(), computePriority()); mForwardingConsumer = new ForwardingConsumer(); multiplexProducerContext = mMultiplexProducerContext; forwardingConsumer = mForwardingConsumer; } mInputProducer.produceResults( forwardingConsumer, multiplexProducerContext); }
/** * Creates a new OrientedDrawable. * * @param rotationAngle multiples of 90 or -1 if the angle is unknown * @param exifOrientation EXIF values (1-8), or 0 if unknown */ public OrientedDrawable(Drawable drawable, int rotationAngle, int exifOrientation) { super(drawable); Preconditions.checkArgument(rotationAngle % 90 == 0); Preconditions.checkArgument(exifOrientation >= 0 && exifOrientation <= 8); mRotationMatrix = new Matrix(); mRotationAngle = rotationAngle; mExifOrientation = exifOrientation; }
/** * Decrements reference count for the shared reference. Returns value of mRefCount after * decrementing */ private synchronized int decreaseRefCount() { ensureValid(); Preconditions.checkArgument(mRefCount > 0); mRefCount--; return mRefCount; }
/** * Tries to match imageHeaderByte and headerSize against every known image format. If any match * succeeds, corresponding ImageFormat is returned. * * @param headerBytes the header bytes to check * @param headerSize the available header size * @return ImageFormat for given imageHeaderBytes or UNKNOWN if no such type could be recognized */ @Nullable @Override public final ImageFormat determineFormat(byte[] headerBytes, int headerSize) { Preconditions.checkNotNull(headerBytes); if (WebpSupportStatus.isWebpHeader(headerBytes, 0, headerSize)) { return getWebpFormat(headerBytes, headerSize); } if (isJpegHeader(headerBytes, headerSize)) { return DefaultImageFormats.JPEG; } if (isPngHeader(headerBytes, headerSize)) { return DefaultImageFormats.PNG; } if (isGifHeader(headerBytes, headerSize)) { return DefaultImageFormats.GIF; } if (isBmpHeader(headerBytes, headerSize)) { return DefaultImageFormats.BMP; } return ImageFormat.UNKNOWN; }
/** * Reconfigures bitmap after checking its allocation size. * * <p> This method is here to overcome our testing framework limit. Robolectric does not provide * KitKat specific APIs: {@link Bitmap#reconfigure} and {@link Bitmap#getAllocationByteCount} * are part of that. */ @TargetApi(19) public static void reconfigureBitmap( Bitmap bitmap, int width, int height, Bitmap.Config bitmapConfig) { Preconditions.checkArgument( bitmap.getAllocationByteCount() >= width * height * BitmapUtil.getPixelSizeForBitmapConfig(bitmapConfig)); bitmap.reconfigure(width, height, bitmapConfig); }
/** * This blits the pixel data from src to dest. * <p>The destination bitmap must have both a height and a width equal to the source. For maximum * speed stride should be equal as well. * <p>Both bitmaps must use the same {@link android.graphics.Bitmap.Config} format. * <p>If the src is purgeable, it will be decoded as part of this operation if it was purged. * The dest should not be purgeable. If it is, the copy will still take place, * but will be lost the next time the dest gets purged, without warning. * <p>The dest must be mutable. * @param dest Bitmap to copy into * @param src Bitmap to copy out of */ public static void copyBitmap(Bitmap dest, Bitmap src) { Preconditions.checkArgument(src.getConfig() == dest.getConfig()); Preconditions.checkArgument(dest.isMutable()); Preconditions.checkArgument(dest.getWidth() == src.getWidth()); Preconditions.checkArgument(dest.getHeight() == src.getHeight()); nativeCopyBitmap( dest, dest.getRowBytes(), src, src.getRowBytes(), dest.getHeight()); }
/** * Reads the content of the input stream until specified marker is found. Marker will be * consumed and the input stream will be positioned after the specified marker. * @param is the input stream to read bytes from * @param markerToFind the marker we are looking for * @return boolean: whether or not we found the expected marker from input stream. */ public static boolean moveToMarker(InputStream is, int markerToFind) throws IOException { Preconditions.checkNotNull(is); // ISO/IEC 10918-1:1993(E) while (StreamProcessor.readPackedInt(is, 1, false) == MARKER_FIRST_BYTE) { int marker = MARKER_FIRST_BYTE; while (marker == MARKER_FIRST_BYTE) { marker = StreamProcessor.readPackedInt(is, 1, false); } if (markerToFind == MARKER_SOFn && isSOFn(marker)) { return true; } if (marker == markerToFind) { return true; } // Check if the marker is SOI or TEM. These two don't have length field, so we skip it. if (marker == MARKER_SOI || marker == MARKER_TEM) { continue; } // Check if the marker is EOI or SOS. We will stop reading since metadata markers don't // come after these two markers. if (marker == MARKER_EOI || marker == MARKER_SOS) { return false; } // read block length // subtract 2 as length contain SIZE field we just read int length = StreamProcessor.readPackedInt(is, 2, false) - 2; // Skip other markers. is.skip(length); } return false; }
public FlexByteArrayPool( MemoryTrimmableRegistry memoryTrimmableRegistry, PoolParams params) { Preconditions.checkArgument(params.maxNumThreads > 0); mDelegatePool = new SoftRefByteArrayPool( memoryTrimmableRegistry, params, NoOpPoolStatsTracker.getInstance()); mResourceReleaser = new ResourceReleaser<byte[]>() { @Override public void release(byte[] unused) { FlexByteArrayPool.this.release(unused); } }; }