文章将会被同步至微信公众号:Android部落格

先看流程图:

一、发起请求

记得在AbstractDraweeController的submitRequest方法中先获取一个DataSource对象(getDataSource()),然后定义了一个DataSubscriber对象,是以内部类的方式初始化的,最后调用mDataSource.subscribe().

1) ControllerBuilder

//PipelineDraweeController@Overrideprotected DataSource<CloseableReference<CloseableImage>> getDataSource() {    DataSource<CloseableReference<CloseableImage>> result = mDataSourceSupplier.get();    return result;}

mDataSourceSupplier对象是在PipelineDraweeControllerBuilder的obtainController方法中,会执行一个initialize方法,第一个参数是obtainDataSourceSupplier,这个方法最终调用的是getDataSourceSupplierForRequest方法,在AbstractDraweeControllerBuilder类中,这个getDataSourceSupplierForRequest方法之前有讲到过:

return new Supplier<DataSource<IMAGE>>() {  @Override  public DataSource<IMAGE> get() {    return getDataSourceForRequest(        controller, controllerId, imageRequest, callerContext, cacheLevel);  }  @Override  public String toString() {    return Objects.toStringHelper(this).add("request", imageRequest.toString()).toString();  }};

getDataSource方法中的get调用的就是这里的方法(getDataSourceForRequest):

//PipelineDraweeControllerBuilder@Overrideprotected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest(  DraweeController controller,  String controllerId,  ImageRequest imageRequest,  Object callerContext,  AbstractDraweeControllerBuilder.CacheLevel cacheLevel) {    return mImagePipeline.fetchDecodedImage(        imageRequest,        callerContext,        convertCacheLevelToRequestLevel(cacheLevel),        getRequestListener(controller));}

cacheLevel是CacheLevel.FULL_FETCH。

  • fetchDecodedImage

看看fetchDecodedImage方法:

//ImagePipelinepublic DataSource<CloseableReference<CloseableImage>> fetchDecodedImage(  ImageRequest imageRequest,  Object callerContext,  ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,  @Nullable RequestListener requestListener) {    try {        Producer<CloseableReference<CloseableImage>> producerSequence = mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);        return submitFetchRequest(producerSequence, imageRequest, lowestPermittedRequestLevelOnSubmit, callerContext, requestListener);    } catch (Exception exception) {        return DataSources.immediateFailedDataSource(exception);    }}
  • getDecodedImageProducerSequence

先看看getDecodedImageProducerSequence方法:

//ProducerSequenceFactorypublic Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence(ImageRequest imageRequest) {    Producer<CloseableReference<CloseableImage>> pipelineSequence =        getBasicDecodedImageSequence(imageRequest);        if (imageRequest.getPostprocessor() != null) {      pipelineSequence = getPostprocessorSequence(pipelineSequence);    }        if (mUseBitmapPrepareToDraw) {//Bitmap.prepareToDraw      pipelineSequence = getBitmapPrepareSequence(pipelineSequence);    }    return pipelineSequence;}
  • getBasicDecodedImageSequence

getBasicDecodedImageSequence方法的目的是根据不同的请求类型新建不同的内容生产者对象:

//ProducerSequenceFactoryprivate Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence(ImageRequest imageRequest) {    try {      Uri uri = imageRequest.getSourceUri();      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));      }    } finally {    }}

2) ProducerSequenceFactory

以SOURCE_TYPE_NETWORK为例,获取的是网络请求内容的生产对象:

//ProducerSequenceFactoryprivate synchronized Producer<CloseableReference<CloseableImage>> getNetworkFetchSequence() {    if (mNetworkFetchSequence == null) {      mNetworkFetchSequence =          newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());    }    return mNetworkFetchSequence;}private synchronized Producer<EncodedImage> getCommonNetworkFetchToEncodedMemorySequence() {    if (mCommonNetworkFetchToEncodedMemorySequence == null) {        Producer<EncodedImage> inputProducer = newEncodedCacheMultiplexToTranscodeSequence(mProducerFactory.newNetworkFetchProducer(mNetworkFetcher));        mCommonNetworkFetchToEncodedMemorySequence = ProducerFactory.newAddImageTransformMetaDataProducer(inputProducer);        mCommonNetworkFetchToEncodedMemorySequence = mProducerFactory.newResizeAndRotateProducer( mCommonNetworkFetchToEncodedMemorySequence, mResizeAndRotateEnabledForNetwork && !mDownsampleEnabled,mImageTranscoderFactory);    }    return mCommonNetworkFetchToEncodedMemorySequence;}private Producer<EncodedImage> newEncodedCacheMultiplexToTranscodeSequence(      Producer<EncodedImage> inputProducer) {    if (WebpSupportStatus.sIsWebpSupportRequired &&        (!mWebpSupportEnabled || WebpSupportStatus.sWebpBitmapFactory == null)) {      inputProducer = mProducerFactory.newWebpTranscodeProducer(inputProducer);    }    if (mDiskCacheEnabled) {      inputProducer = newDiskCacheSequence(inputProducer);    }    EncodedMemoryCacheProducer encodedMemoryCacheProducer = mProducerFactory.newEncodedMemoryCacheProducer(inputProducer);    return mProducerFactory.newEncodedCacheKeyMultiplexProducer(encodedMemoryCacheProducer);}private Producer<EncodedImage> newDiskCacheSequence(Producer<EncodedImage> inputProducer) {    Producer<EncodedImage> cacheWriteProducer;    if (mPartialImageCachingEnabled) {      Producer<EncodedImage> partialDiskCacheProducer =          mProducerFactory.newPartialDiskCacheProducer(inputProducer);      cacheWriteProducer = mProducerFactory.newDiskCacheWriteProducer(partialDiskCacheProducer);    } else {      cacheWriteProducer = mProducerFactory.newDiskCacheWriteProducer(inputProducer);    }    DiskCacheReadProducer result = mProducerFactory.newDiskCacheReadProducer(cacheWriteProducer);    return result;}

上面的代码比较长,从getCommonNetworkFetchToEncodedMemorySequence方法开始罗列出了newEncodedCacheMultiplexToTranscodeSequence,newDiskCacheSequence方法,从这几个方法最终产生了一个Producer对象。在这三个方法里面总共产生了以下Producer:

  • 网络请求

NetworkFetchProducer(implements Producer)

  • Webp格式处理

WebpTranscodeProducer(implements Producer)

  • 部分缓存与请求的数据结合成一整个返回处理

PartialDiskCacheProducer(implements Producer)

  • 磁盘缓存写处理

DiskCacheWriteProducer(implements Producer)

  • 磁盘缓存读处理

DiskCacheReadProducer(implements Producer)

  • 已编码内存缓存处理

EncodedMemoryCacheProducer(implements Producer)

  • 编码缓存多路复用处理

EncodedCacheKeyMultiplexProducer(extends MultiplexProducer, EncodedImage>)

  • 裁剪旋转处理

ResizeAndRotateProducer(implements Producer)

将上述所有的图片处理封装到一个Producer对象中,然后传递给newBitmapCacheGetToDecodeSequence方法:

private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToDecodeSequence(  Producer<EncodedImage> inputProducer) {    if (FrescoSystrace.isTracing()) {      FrescoSystrace.beginSection("ProducerSequenceFactory#newBitmapCacheGetToDecodeSequence");    }    DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer);    Producer<CloseableReference<CloseableImage>> result =        newBitmapCacheGetToBitmapCacheSequence(decodeProducer);    if (FrescoSystrace.isTracing()) {      FrescoSystrace.endSection();    }    return result;}

先新建一个解码对象DecodeProducer,他实现了Producer接口。然后执行newBitmapCacheGetToBitmapCacheSequence方法将解码对象封装起来:

private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToBitmapCacheSequence(Producer<CloseableReference<CloseableImage>> inputProducer) {    BitmapMemoryCacheProducer bitmapMemoryCacheProducer = mProducerFactory.newBitmapMemoryCacheProducer(inputProducer);    BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer = mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer);    ThreadHandoffProducer<CloseableReference<CloseableImage>> threadHandoffProducer = mProducerFactory.newBackgroundThreadHandoffProducer( bitmapKeyMultiplexProducer, mThreadHandoffProducerQueue);    return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);}

一层一层叠加的封装,让代码看起来云里雾里,但是只要记住一个,就是Producer结尾的类,一定实现了produceResults方法,在这个方法里面干活。

AbstractDraweeController类的submitRequest方法中调用的getDataSource方法引申出了Producer类的初始化,然后接下来就是要依赖这些类干活了。

  • submitFetchRequest

从ImagePipeline类的fetchDecodedImage方法中调用的第一个方法getDecodedImageProducerSequence回来,接下来调用submitFetchRequest方法:

//ImagePipelineprivate <T> DataSource<CloseableReference<T>> submitFetchRequest(Producer<CloseableReference<T>> producerSequence, ImageRequest imageRequest, ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit, Object callerContext, @Nullable RequestListener requestListener) {    ImageRequest.RequestLevel lowestPermittedRequestLevel = ImageRequest.RequestLevel.getMax(imageRequest.getLowestPermittedRequestLevel(), lowestPermittedRequestLevelOnSubmit);    SettableProducerContext settableProducerContext = new SettableProducerContext(imageRequest, generateUniqueFutureId(), finalRequestListener, callerContext, lowestPermittedRequestLevel, /* isPrefetch */ false, imageRequest.getProgressiveRenderingEnabled() || !UriUtil.isNetworkUri(imageRequest.getSourceUri()), imageRequest.getPriority());    return CloseableProducerToDataSourceAdapter.create(producerSequence, settableProducerContext, finalRequestListener);}

先构造了一个SettableProducerContext对象,这个对象封装了请求的上下文,CloseableProducerToDataSourceAdapter.create方法则是最终返回:

//CloseableProducerToDataSourceAdapterpublic static <T> DataSource<CloseableReference<T>> create(Producer<CloseableReference<T>> producer, SettableProducerContext settableProducerContext, RequestListener listener) {    CloseableProducerToDataSourceAdapter<T> result = new CloseableProducerToDataSourceAdapter<T>(producer, settableProducerContext, listener);}//CloseableProducerToDataSourceAdapterprivate CloseableProducerToDataSourceAdapter(      Producer<CloseableReference<T>> producer,      SettableProducerContext settableProducerContext,      RequestListener listener) {    super(producer, settableProducerContext, listener);}//AbstractProducerToDataSourceAdapterprotected AbstractProducerToDataSourceAdapter(  Producer<T> producer,  SettableProducerContext settableProducerContext,  RequestListener requestListener) {  producer.produceResults(createConsumer(), settableProducerContext);}

可以看到最终调用到了AbstractProducerToDataSourceAdapter的构造函数,这个类继承自AbstractDataSource。在createConsumer()方法中我们可以看到订阅者:

private Consumer<T> createConsumer() {    return new BaseConsumer<T>() {      @Override      protected void onNewResultImpl(@Nullable T newResult, @Status int status) {        AbstractProducerToDataSourceAdapter.this.onNewResultImpl(newResult, status);      }      @Override      protected void onFailureImpl(Throwable throwable) {        AbstractProducerToDataSourceAdapter.this.onFailureImpl(throwable);      }      @Override      protected void onCancellationImpl() {        AbstractProducerToDataSourceAdapter.this.onCancellationImpl();      }      @Override      protected void onProgressUpdateImpl(float progress) {        AbstractProducerToDataSourceAdapter.this.setProgress(progress);      }    };}

每一个订阅的消息返回对应着不同的处理逻辑,都在AbstractProducerToDataSourceAdapter类中定义着。

3) Producer创建

接下来执行producer.produceResults方法。producer是从ImagePipeline的fetchDecodedImage方法中生成的。这些producer统一实现了Producer接口:

public interface Producer<T> {  /**   * Start producing results for given context. Provided consumer is notified whenever progress is   * made (new value is ready or error occurs).   * @param consumer   * @param context   */  void produceResults(Consumer<T> consumer, ProducerContext context);}

先看看从前到后生成的producer有哪些:

(NetworkFetchProducer->

(WebpTranscodeProducer -> PartialDiskCacheProducer -> DiskCacheWriteProducer -> DiskCacheReadProducer -> EncodedMemoryCacheProducer) ->

EncodedCacheKeyMultiplexProducer:MultiplexProducer -> AddImageTransformMetaDataProducer -> ResizeAndRotateProducer) ->

DecodeProducer -> BitmapMemoryCacheProducer -> BitmapMemoryCacheKeyMultiplexProducer:MultiplexProducer -> ThreadHandoffProducer -> BitmapMemoryCacheGetProducer:BitmapMemoryCacheProducer = mNetworkFetchSequence

前面的producer作为后面的inputProducer参数传入,然后封装,依次向后。

再来看看AbstractProducerToDataSourceAdapter类构造函数中的producer.produceResults方法,一石激起千层浪,看看这些层层封装的Producer调用顺序:
BitmapMemoryCacheProducer
ThreadHandoffProducer
BitmapMemoryCacheProducer
DecodeProducer
ResizeAndRotateProducer
AddImageTransformMetaDataProducer
EncodedMemoryCacheProducer
DiskCacheReadProducer
DiskCacheWriteProducer
NetworkFetchProducer

最后调用NetworkFetchProducer在线下载数据,数据下载完成之后,响应的顺序刚好相反,对应的producer实现的produceResults方法的第一个参数是Consumer,用来通知上一层的消费者,因为consumer对象是从上一个调用者传递过来的。

二、开始请求

  • NetworkFetchProducer

先看看NetworkFetchProducer在线下载图片。NetworkFetchProducer封装了一个mNetworkFetcher对象,这个对象是在ImagePipelineConfig构造的时候创建的,这个对象对应的是HttpUrlConnectionNetworkFetcher类,如果用户默认不指定的话。

  • produceResults

看看produceResult方法:

@Overridepublic void produceResults(Consumer<EncodedImage> consumer, ProducerContext context) {    final FetchState fetchState = mNetworkFetcher.createFetchState(consumer, context);    mNetworkFetcher.fetch(fetchState, new NetworkFetcher.Callback() {          @Override          public void onResponse(InputStream response, int responseLength) throws IOException {              NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);          }          @Override          public void onFailure(Throwable throwable) {            NetworkFetchProducer.this.onFailure(fetchState, throwable);          }          @Override          public void onCancellation() {            NetworkFetchProducer.this.onCancellation(fetchState);          }    });}

先封装了一个HttpUrlConnectionNetworkFetchState对象,他继承自FetchState,封装了consumer和请求上下文context,以及中间状态的时间点。

onResponse是请求的返回,也是在HttpUrlConnectionNetworkFetcher调用fetch有结果返回之后回调到这里的:

@Overridepublic void fetch(final HttpUrlConnectionNetworkFetchState fetchState, final Callback callback) {    fetchState.submitTime = mMonotonicClock.now();    final Future<?> future = mExecutorService.submit(        new Runnable() {          @Override          public void run() {            fetchSync(fetchState, callback);          }    });}@VisibleForTestingvoid fetchSync(HttpUrlConnectionNetworkFetchState fetchState, Callback callback) {    HttpURLConnection connection = null;    InputStream is = null;    try {      connection = downloadFrom(fetchState.getUri(), MAX_REDIRECTS);      if (connection != null) {        is = connection.getInputStream();        callback.onResponse(is, -1);      }    } catch (IOException e) {      callback.onFailure(e);    } finally {    }}

一个典型的HttpURLConnection请求下载,使用固定线程池,线程数量为3,这里不再展开分析。从callback.onResponse回调到produceResults的onResponse方法,然后处理:

protected void onResponse(FetchState fetchState, InputStream responseData, int responseContentLength) throws IOException {    final PooledByteBufferOutputStream pooledOutputStream;    if (responseContentLength > 0) {      pooledOutputStream = mPooledByteBufferFactory.newOutputStream(responseContentLength);    } else {      pooledOutputStream = mPooledByteBufferFactory.newOutputStream();    }    final byte[] ioArray = mByteArrayPool.get(READ_SIZE);    try {      int length;      while ((length = responseData.read(ioArray)) >= 0) {        if (length > 0) {          pooledOutputStream.write(ioArray, 0, length);          maybeHandleIntermediateResult(pooledOutputStream, fetchState);          float progress = calculateProgress(pooledOutputStream.size(), responseContentLength);          fetchState.getConsumer().onProgressUpdate(progress);        }      }      mNetworkFetcher.onFetchCompletion(fetchState, pooledOutputStream.size());      handleFinalResult(pooledOutputStream, fetchState);    } finally {      mByteArrayPool.release(ioArray);      pooledOutputStream.close();    }}

在while循环中读取数据,在此过程中计算进度,并把进度向上传递给上一层的消费者,这个消费者是DiskCacheWriteProducer。对于是否使用进度,由用户自己决定,不设置的话默认为false,这个开关创建是在ImagePipelineConfig中:

private boolean mProgressiveRenderingEnabled = false;private static DefaultImageRequestConfig  sDefaultImageRequestConfig = new DefaultImageRequestConfig();//ImageRequestBuilderpublic ImageRequestBuilder setProgressiveRenderingEnabled(boolean enabled) {    mProgressiveRenderingEnabled = enabled;    return this;}

看看下载完成之后调用的方法handleFinalResult:

protected void handleFinalResult(  PooledByteBufferOutputStream pooledOutputStream, FetchState fetchState) {    notifyConsumer(        pooledOutputStream,        Consumer.IS_LAST | fetchState.getOnNewResultStatusFlags(),        fetchState.getResponseBytesRange(),        fetchState.getConsumer());}protected static void notifyConsumer(  PooledByteBufferOutputStream pooledOutputStream,  @Consumer.Status int status,  @Nullable BytesRange responseBytesRange,  Consumer<EncodedImage> consumer) {    CloseableReference<PooledByteBuffer> result =        CloseableReference.of(pooledOutputStream.toByteBuffer());    EncodedImage encodedImage = null;    try {      encodedImage = new EncodedImage(result);      encodedImage.setBytesRange(responseBytesRange);      encodedImage.parseMetaData();      consumer.onNewResult(encodedImage, status);    } finally {      EncodedImage.closeSafely(encodedImage);      CloseableReference.closeSafely(result);    }}

CloseableReference.of方法将下载的stream转成bytebuffer封装成一个CloseableReference对象,这个方法的主要操作是new一个CloseableReference对象,对象中再new一个SharedReference对象,在这个类的构造函数中将bytebuffer存储到一个map中,private static final Map sLiveObjects = new IdentityHashMap<>();,key是bytebuffer值,value是针对这个对象的计数。

parseMetaData看方法名字就知道,读取图片流的元数据,详情如下:

public void parseMetaData() {    final ImageFormat imageFormat = ImageFormatChecker.getImageFormat_WrapIOException(getInputStream());    mImageFormat = imageFormat;    // BitmapUtil.decodeDimensions has a bug where it will return 100x100 for some WebPs even though    // those are not its actual dimensions    final Pair<Integer, Integer> dimensions;    if (DefaultImageFormats.isWebpFormat(imageFormat)) {      dimensions = readWebPImageSize();    } else {      dimensions = readImageMetaData().getDimensions();    }    if (imageFormat == DefaultImageFormats.JPEG && mRotationAngle == UNKNOWN_ROTATION_ANGLE) {      // Load the JPEG rotation angle only if we have the dimensions      if (dimensions != null) {        mExifOrientation = JfifUtil.getOrientation(getInputStream());        mRotationAngle = JfifUtil.getAutoRotateAngleFromOrientation(mExifOrientation);      }    } else if (imageFormat == DefaultImageFormats.HEIF        && mRotationAngle == UNKNOWN_ROTATION_ANGLE) {      mExifOrientation = HeifExifUtil.getOrientation(getInputStream());      mRotationAngle = JfifUtil.getAutoRotateAngleFromOrientation(mExifOrientation);    } else {      mRotationAngle = 0;    }}

getImageFormat_WrapIOException方法读取格式,传入的inputStream数据:

//ImageFormatCheckerpublic static ImageFormat getImageFormat(final InputStream is) throws IOException {    return getInstance().determineImageFormat(is);}private ImageFormatChecker() {    updateMaxHeaderLength();}private void updateMaxHeaderLength() {    mMaxHeaderLength = mDefaultFormatChecker.getHeaderSize();}//DefaultImageFormatCheckerfinal int MAX_HEADER_LENGTH =      Ints.max(          //https://developers.google.com/speed/webp/docs/riff_container              //WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器宽带资源和数据空间。          //VP8X,无损          EXTENDED_WEBP_HEADER_LENGTH,          //RIFF,有损          SIMPLE_WEBP_HEADER_LENGTH,          JPEG_HEADER_LENGTH,          PNG_HEADER_LENGTH,          GIF_HEADER_LENGTH,          //BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备有向量相关位图(DDB)和设备无向量相关位图(DIB),使用非常广。          BMP_HEADER_LENGTH,          //ico是Icon file的缩写,是Windows的图标文件格式的一种。图标文件可以存储单个图案、多尺寸、多色板的图标文件。一个图标实际上是多张不同格式的图片的集合体,并且还包含了一定的透明区域。          ICO_HEADER_LENGTH,          //高效率图像格式(High Efficiency Image Format ,HEIF),它所生成的图像文件相对较小,且图像质量也高于较早的 JPEG 标准。HEIF 这种新的图像格式基于高效视频压缩格式(也称为 HEVC 或 H.265),它通过使用更先进的压缩算法来实现图片的压缩存储。          HEIF_HEADER_LENGTH);//DefaultImageFormatChecker@Overridepublic int getHeaderSize() {    return MAX_HEADER_LENGTH;}  public ImageFormat determineImageFormat(final InputStream is) throws IOException {    Preconditions.checkNotNull(is);    final byte[] imageHeaderBytes = new byte[mMaxHeaderLength];    final int headerSize = readHeaderFromStream(mMaxHeaderLength, is, imageHeaderBytes);        ImageFormat format = mDefaultFormatChecker.determineFormat(imageHeaderBytes, headerSize);    if (format != null && format != ImageFormat.UNKNOWN) {      return format;    }    return ImageFormat.UNKNOWN;}

先获取header的大小,然后通过determineFormat方法获取格式:

//DefaultImageFormatChecker@Overridepublic final ImageFormat determineFormat(byte[] headerBytes, int headerSize) {    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;    }        if (isIcoHeader(headerBytes, headerSize)) {      return DefaultImageFormats.ICO;    }        if (isHeifHeader(headerBytes, headerSize)) {      return DefaultImageFormats.HEIF;    }        return ImageFormat.UNKNOWN;}

通过读取图片头部信息去判断。每一张图片的生成都要按照约定的协议,相关协议如下:

  • Webp

图片来源https://developers.google.com/speed/webp/docs/riff_container

头部信息长度大于等于20个字节,并且头部有ASCII字符RIFF和文件大小以及ASCII字符WEBP。

  • JPEG
    jpeg格式是也是分段存储相关信息,头信息的segment key是SOI,码值固定是十六进制的FF,D8,而且下一个segment是以FF开头的。所以代码里面的定义是:
private static final byte[] JPEG_HEADER = new byte[] {(byte) 0xFF, (byte)0xD8, (byte)0xFF};

见下图:

图表来源:https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format

  • PNG(Portable Network Graphics)
private static final byte[] PNG_HEADER = new byte[] {  (byte) 0x89,  'P', 'N', 'G',  (byte) 0x0D, (byte) 0x0A, (byte) 0x1A, (byte) 0x0A};

最开始高位0x89做数据位识别,50,4E,47是PNG字符,最后连续三个低位的16进制值固定。

见下图:

图片来源https://en.wikipedia.org/wiki/Portable_Network_Graphics

  • GIF
    格式信息主要在开始六个字节,直接上图:

数据详见http://www.onicos.com/staff/iz/formats/gif.html


代码配置如下:

private static final byte[] GIF_HEADER_87A = ImageFormatCheckerUtils.asciiBytes("GIF87a");private static final byte[] GIF_HEADER_89A = ImageFormatCheckerUtils.asciiBytes("GIF89a");
  • BMP
    格式信息在头部最开始的两个字节,用来存放BM字符:

图片来源http://www.onicos.com/staff/iz/formats/bmp.html

private static final byte[] BMP_HEADER = ImageFormatCheckerUtils.asciiBytes("BM");
  • ICO
    格式信息藏在头部的六个字节中,相关定义如下:

图片来源https://en.wikipedia.org/wiki/ICO_(file_format)

第一个字节必须是0,第二个字节是1或2,第三个字节定义了图片的数量,代码中定义如下:

//0x00000100private static final byte[] ICO_HEADER =  new byte[] {(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00};
  • HEIF
    以ftpy字符开始,结构见下图:

图片来源https://nokiatech.github.io/heif/technical.html


代码定义如下:

private static final String HEIF_HEADER_PREFIX = "ftyp";private static final String[] HEIF_HEADER_SUFFIXES = {"heic", "heix", "hevc", "hevx", "mif1", "msf1"};private static final int HEIF_HEADER_LENGTH =  ImageFormatCheckerUtils.asciiBytes(HEIF_HEADER_PREFIX + HEIF_HEADER_SUFFIXES[0]).length;

通过上面的一通分析,可以知道各种图片的封装协议,以及通过各个 参考网站知道数据存储在哪一块。

接下来的操作就是读取图片的分辨率,然后是JPEG和HEIF格式的话,获取图片的角度(横向或竖向),以及旋转角度。

至此生成一个编码后的图片对象的任务算是完成了,主要是将CloseableReference对象封装到EncodedImage对象中然后往上传递数据。

微信公众号:

更多相关文章

  1. Android(安卓)Butterknife 8.4.0 使用方法总结
  2. android开发环境 国内镜像 及Android(安卓)SDK manager使用国内
  3. Android中获取网络图片的方法(如果手机缓存里面有就从缓存获取)
  4. 关于Android用户定位获取location值为null的解决方法
  5. Android(安卓)APP常用图标尺寸规范
  6. Android: 缩放图片文件引起的OOM异常
  7. Android手动显示和隐藏软键盘方法总结
  8. Android(安卓)拦截Home键的常用方法
  9. Android(安卓)Binder异常传递流程分析

随机推荐

  1. 阻止dialog消失的方法 (Android(安卓)Pla
  2. android的单元测试
  3. Android(安卓)调用中国气象的webservice
  4. Android中给Activity添加返回键
  5. Android(安卓)studio 032 java Tomcat Se
  6. Android(安卓)--- 图片的特效处理
  7. android SeekBar(带滑动块的进度条)的应
  8. android按键两次退出程序
  9. Android(安卓)kill app Process 结束进程
  10. Android(安卓)BroadCast