1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import com.android.layoutlib.bridge.util.NinePatchInputStream;
20 import com.android.ninepatch.GraphicsUtilities;
21 import com.android.ninepatch.NinePatch;
22 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
23 
24 import android.annotation.NonNull;
25 import android.graphics.Bitmap.Config;
26 import android.graphics.ImageDecoder.InputStreamSource;
27 import android.graphics.ImageDecoder.OnHeaderDecodedListener;
28 import android.graphics.ImageDecoder.ResourceSource;
29 import android.graphics.ImageDecoder.Source;
30 
31 import java.awt.image.BufferedImage;
32 import java.io.FileInputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 
36 public class ImageDecoder_Delegate {
37 
38     @LayoutlibDelegate
decodeBitmapImpl(@onNull Source src, @NonNull OnHeaderDecodedListener listener)39     /*package*/ static Bitmap decodeBitmapImpl(@NonNull Source src,
40             @NonNull OnHeaderDecodedListener listener) throws IOException {
41         if (src instanceof ResourceSource) {
42             // Bypass ImageDecoder for ResourceSource as it goes through the native AssetManager
43             // which is not supported in layoutlib.
44             ResourceSource source = (ResourceSource) src;
45             return BitmapFactory.decodeResource(source.mResources, source.mResId);
46         }
47         InputStream stream = src instanceof InputStreamSource ?
48                 ((InputStreamSource) src).mInputStream : null;
49         Bitmap bm = ImageDecoder.decodeBitmapImpl_Original(src, listener);
50         if (stream instanceof NinePatchInputStream && bm.getNinePatchChunk() == null) {
51             stream = new FileInputStream(((NinePatchInputStream) stream).getPath());
52             NinePatch ninePatch = NinePatch.load(stream, true /*is9Patch*/, false /* convert */);
53             BufferedImage image = ninePatch.getImage();
54 
55             // width and height of the nine patch without the special border.
56             int width = image.getWidth();
57             int height = image.getHeight();
58 
59             // Get pixel data from image independently of its type.
60             int[] imageData = GraphicsUtilities.getPixels(image, 0, 0, width, height, null);
61 
62             bm = Bitmap.createBitmap(imageData, width, height, Config.ARGB_8888);
63 
64             bm.setDensity(src.getDensity());
65             bm.setNinePatchChunk(ninePatch.getChunk().getSerializedChunk());
66         }
67         return bm;
68     }
69 }
70