비트맵(bitmap) 전체 분석 1부
이 섹션 소개:
이전 섹션에서는 Android의 13가지 유형의 Drawable 유형을 직접 적용해 보셨나요? 프로젝트는 어떻습니까? 이 섹션에서는 이 섹션의 내용을 시작하기 전에 Bitmap의 몇 가지 용도에 대해 설명합니다. 먼저 여러 명사의 개념을 구별해 보겠습니다.
- Drawable: PNG 및 JPG와 같은 일반적인 형식의 이미지를 로드하는 데 사용되는 일반 그래픽 객체입니다. 앞서 배운 13가지 Drawable 유형의 시각적 개체이기도 합니다! 그림을 걸어두는 장소로 이해할 수 있어요 - 액자!
- Bitmap: 이젤이라고 생각하면 먼저 그림을 그 위에 올려놓은 다음 이미지 파일 정보 획득, 회전 및 잘라내기, 확대/축소 등의 일부 처리를 수행합니다!
- Canvas: 이름에서 알 수 있듯이 canvas, 그림을 그릴 수 있고 Paint(브러시)를 사용할 수도 있고, 다양한 모양을 그리거나 단어를 쓰려면 Path를 사용하여 여러 점을 그린 다음 다양한 모양으로 연결할 수도 있습니다!
- Matrix: 그래픽 특수 효과 처리, 컬러 매트릭스(ColorMatrix) 및 이미지 처리용 매트릭스에 사용됩니다. 팬, 확대/축소, 회전, 기울이기 등!
위 내용은 모두 Android의 기본 그래픽 클래스입니다. 인터페이스는 android.graphics에서 제공됩니다! 자, 더 이상 고민하지 말고 이 섹션을 시작하겠습니다! 추신: 공식 문서: Bitmap
1. Bitmap, BitmapFactory, BitmapFacotry.Options 이해하기
제목에서 알 수 있듯이 세 가지의 관계에 대해 직접 이야기할 수도 있었지만 그냥 츤데레하고 싶습니다. , 코드에 따라 다릅니다! Bitmap 클래스의 소스 코드를 열면 Bitmap의 생성 방법에서 다음과 같은 내용을 볼 수 있습니다.
제가 말하고 싶은 것은 아마도 Bitmap의 생성 방법은 비공개이며 외부에서 인스턴스화할 수 없다는 것입니다. .JNI를 통해 인스턴스화하세요! 물론 Bitmap을 생성할 수 있는 인터페이스가 확실히 제공될 것이며 이 인터페이스 클래스는 BitmapFactory입니다! 자, BitmapFactory 클래스를 엽니다. 왼쪽의 구조를 클릭하면 BitmapFactory가 제공하는 것을 볼 수 있습니다. 이러한 메소드가 제공되는데 대부분 decodeXxx로 다양한 형태의 Bitmap을 생성할 수 있습니다!
그런 다음 각 메소드에 옵션 유형 매개변수가 있다는 것을 발견했습니다. 이를 클릭하여 살펴보세요. 그래서 우리는 이것이 정적 내부 클래스인 BitmapFacotry.Options라는 것을 발견했습니다! 그리고 그는 디코딩 중에 옵션을 설정하는 데 사용됩니다!
여기에서는 OOM(메모리 오버플로)을 방지하기 위해 inJustDecodeBounds를 true로 설정하는 등 일부 매개변수의 값을 설정합니다. 뭐, OOM은 몰라 괜찮아 나중에 설명해줄게! 마지막으로 비트맵으로 돌아왔습니다! 음, 비트맵에서는 방법이 너무 많아서 하나씩 설명하진 않겠습니다. 더 많이 쓰이는 몇 가지만 골라서 설명드리겠습니다! 중국어 문서: Android 중국어 API(136) - Bitmap
2.Bitmap 일반 메소드
common 메소드
- public boolean compress(Bitmap.CompressFormat 형식, int 품질, OutputStream 스트림) 비트맵을 지정된 OutputStream으로 압축하는 것은 비트맵을 파일에 저장하는 것으로 이해될 수 있습니다! format: 형식, PNG, JPG 등 quality: 압축 품질, 0-100, 0은 가장 낮은 품질 압축을 나타내고 100은 최대 품질을 나타냅니다(PNG는 무손실이며 품질 설정은 무시됩니다) stream : 출력 스트림 반환 값은 지정된 스트림에 대한 압축이 성공했는지 여부를 나타냅니다!
- void recycle(): 비트맵이 차지하는 메모리 공간을 재활용하고 비트맵을 Dead
- boolean으로 표시합니다. isRecycled(): 비트맵 메모리가 해제되었는지 확인
- int getWidth(): 가져오기 비트 이미지의 너비
- int getHeight(): 비트맵의 높이를 가져옵니다
- boolean isMutable(): 이미지를 수정할 수 있는지 여부
- int getScaledWidth(캔버스 캔버스): 가져오기 지정된 밀도 변환 후 이미지의 너비
- int getScaledHeight(캔버스 캔버스): 지정된 밀도 변환 후 이미지의 높이를 가져옵니다.
Static method:
- Bitmap createBitmap(Bitmap src) : src를 원본 이미지로 사용하여 불변의 새 이미지 생성 Image
- Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter): src를 원본 이미지로 사용하여 새 이미지를 만들고 높이를 지정하고 새 이미지의 너비와 변경 여부.
- Bitmap createBitmap(int width, int height, Config config): 지정된 형식과 크기의 비트맵을 생성합니다.
- Bitmap createBitmap(Bitmap source, int x, int y, int width, int height)는 소스를 원본 이미지로 가져와 새 이미지를 만들고 시작 좌표와 새 이미지의 높이 및 너비를 지정합니다.
- 공용 정적 비트맵 createBitmap(비트맵 소스, int x, int y, int 너비, int 높이, 행렬 m, 부울 필터)
BitmapFactory.Option설정 가능한 매개변수:
- boolean inJustDecodeBounds——true로 설정하면 이미지를 가져오지 않고 메모리를 할당하지 않지만 이미지의 높이와 너비 정보를 반환합니다.
- int inSampleSize——이미지 크기 조정의 배수. 4로 설정하면 너비와 높이가 모두 원본 크기의 1/4이고 이미지는 원본 크기의 1/16입니다.
- int outWidth——이미지의 너비 값을 가져옵니다.
- int outHeight——이미지의 높이 값을 가져옵니다.
- int inDensity——비트맵에 사용되는 픽셀 압축 비율
- int inTargetDensity—— 대상 비트맵에 사용할 픽셀 압축 비율(생성할 비트맵)
- boolean inScaled - true로 설정된 경우 inDensity에서 inTargetDensity까지 이미지 압축.
그렇습니다. 문서를 직접 확인해야 합니다~
3. 비트맵 비트맵 가져오기
아래 그림과 같이 BitmapDrawable 또는 BitmapFactory를 통해 리소스에서 비트맵을 가져오는 방법이 두 가지 있습니다. : 먼저 이
BitmapDrawable 메소드를 가져와야 합니다.
스트림을 통해 BitmapDrawable을 구축하는 것과 같이 BitmapDrawable 객체를 생성하는 생성자를 만들 수 있습니다.
BitmapDrawable bmpMeizi = new BitmapDrawable(getAssets().open("pic_meizi.jpg")); Bitmap mBitmap = bmpMeizi.getBitmap(); img_bg.setImageBitmap(mBitmap);
BitmapFactory 메소드:
는 모두 정적 메소드입니다. , 리소스 ID, 경로, 파일, 데이터 스트림 등을 통해 직접 호출하여 비트맵을 얻을 수 있습니다!
//通过资源ID private Bitmap getBitmapFromResource(Resources res, int resId) { return BitmapFactory.decodeResource(res, resId); } //文件 private Bitmap getBitmapFromFile(String pathName) { return BitmapFactory.decodeFile(pathName); } //字节数组 public Bitmap Bytes2Bimap(byte[] b) { if (b.length != 0) { return BitmapFactory.decodeByteArray(b, 0, b.length); } else { return null; } } //输入流 private Bitmap getBitmapFromStream(InputStream inputStream) { return BitmapFactory.decodeStream(inputStream); }
4. 비트맵 관련 정보 가져오기:
이것은 비트맵 객체를 얻는 한 관련 메서드를 호출하여 해당 매개변수를 가져올 수 있으며, getByteCount는 크기를 가져옵니다. getHeight 및 getWidth ~ 여기서는 쓰지 않겠습니다. 문서를 직접 확인하세요!
5. 그림의 특정 모서리를 당기세요
때로는 그림의 특정 모서리를 당기고 싶을 수도 있습니다. Bitmap의 createBitmap()을 통해 직접 클릭하세요. 매개변수는 처리된 비트맵 객체, 시작 x, y 좌표 및 가로채기된 너비와 높이입니다.
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.mipmap.pic_meizi); Bitmap bitmap2 = Bitmap.createBitmap(bitmap1,100,100,200,200); img_bg = (ImageView) findViewById(R.id.img_bg); img_bg.setImageBitmap(bitmap2);
렌더링 실행 중:
원본 이미지:
모퉁이 자르기:
6. 비트맵 크기 조정
여기서는 비트맵 크기를 조정하기 위해 Matrix를 사용하지 않고, 이를 구현하기 위해 Bitmap에서 제공하는 createScaledBitmap을 직접 사용합니다. 매개변수는 순서대로입니다. 처리된 비트맵 객체, 크기 조정된 너비 및 높이,
7. 비트맵을 사용하여 스크린샷 찍기
렌더링 실행:
구현 코드:
public class MainActivity extends AppCompatActivity { static ByteArrayOutputStream byteOut = null; private Bitmap bitmap = null; private Button btn_cut; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_cut = (Button) findViewById(R.id.btn_cut); btn_cut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { captureScreen(); } }); } public void captureScreen() { Runnable action = new Runnable() { @Override public void run() { final View contentView = getWindow().getDecorView(); try{ Log.e("HEHE",contentView.getHeight()+":"+contentView.getWidth()); bitmap = Bitmap.createBitmap(contentView.getWidth(), contentView.getHeight(), Bitmap.Config.ARGB_4444); contentView.draw(new Canvas(bitmap)); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteOut); savePic(bitmap, "sdcard/short.png"); }catch (Exception e){e.printStackTrace();} finally { try{ if (null != byteOut) byteOut.close(); if (null != bitmap && !bitmap.isRecycled()) { // bitmap.recycle(); bitmap = null; } }catch (IOException e){e.printStackTrace();} } } }; try { action.run(); } catch (Exception e) { e.printStackTrace(); } } private void savePic(Bitmap b, String strFileName) { FileOutputStream fos = null; try { fos = new FileOutputStream(strFileName); if (null != fos) { boolean success= b.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); if(success) Toast.makeText(MainActivity.this, "截屏成功", Toast.LENGTH_SHORT).show(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
코드 분석:
코드는 매우 간단합니다. final View contentView = getWindow().getDecorView(); 이 코드는 현재 XML을 가져오는 것입니다. 루트 노드의 모습! 그런 다음 스크린샷의 크기를 설정하고 contentView.draw(new Canvas(bitmap))를 호출한 다음 OK를 클릭하세요. 비트맵이 스트림으로 변환된 후 SD 카드에 기록됩니다~ 물론 스크린샷에는 수정된 APP의 내용만 캡처된 것도 알 수 있습니다! 전체 화면을 캡쳐하고 싶다면 구글에서 직접~!
이 섹션 요약:
이 섹션에서는 Bitmap, BitmapFactory 및 해당 정적 내부 클래스 Options와 BitmapDrawable에 대해 설명합니다. 실제로 기본적인 사용을 위해서는 Bitmap을 생성하는 방법만 알면 됩니다. 그 확장은 일반적으로 Matrix와 Canvas를 통해 구현됩니다. Bitmap, 우리는 OOM 문제에 더 주의를 기울입니다. 다음 섹션에서는 Bitmap의 OOM 문제를 피하는 방법을 배우겠습니다! 감사합니다~