Скопируйте бит-матрицу из растрового изображения в программировании ANDROID
Я занимаюсь разработкой приложения для Android, которое помогает пользователю копировать часть растрового изображения с помощью эскизов или рисунков. Я имею в виду, что пользователь нарисует некоторые формы на холсте, который имеет растровое изображение в качестве фона, а затем у меня есть точки, которые окрашены как растровое изображение (битовая матрица /2D битовый массив). Пока здесь каждый хитнг не звучит хорошо.
Теперь проблема в том, как я могу скопировать часть изображения, которая имеет соответствующий истинный бит в матрице?
Добавлено объяснение
1) Основное изображение:
![Image be fore any process]()
2) Изображение в качестве фона холста:
![Image as canvas background]()
3) Некоторые картины на холсте:
![User paints on canvas]()
4) Битовая матрица представления окрашенной области:
![Bit matrix]()
5) Ожидаемый результат:
![Where is painted is outputted]()
Ответы
Ответ 1
Вы можете сделать это так. В примере используется Bitmap
как источник, а другой Bitmap
- как матрица фильтра. Растровое изображение фильтра имеет прозрачный фон и поэтому имеет фильтрованное растровое изображение:
public Bitmap doFilter(Bitmap source, Bitmap filter) {
Bitmap filtered = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
Paint paint = new Paint();
Canvas canvas = new Canvas(filtered);
canvas.drawBitmap(source, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(filter, 0, 0, paint);
return filtered;
}
Например, с помощью этого источника:
![введите описание изображения здесь]()
И этот фильтр:
![введите описание изображения здесь]()
Вы получите это отфильтрованное изображение:
![введите описание изображения здесь]()
Ответ 2
Основываясь на ваших данных объяснениях, я сделал следующий пример проекта, и код приведен ниже -
public class ActivityImage extends AppCompatActivity{
Button grab;
CustomImageView iv_custom;
ImageView iv_later;
Bitmap bitmapBG,bitmapOrg;
int iMin,jMin,iMax,jMax;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.so_particular_img_section);
iv_custom = (CustomImageView)findViewById(R.id.iv_custom);
iv_custom.setDrawingCacheEnabled(true);
iv_later = (ImageView)findViewById(R.id.iv_later);
grab = (Button)findViewById(R.id.btn_grab);
grab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
iv_custom.buildDrawingCache();
bitmapBG = iv_custom.getDrawingCache();
getSelectedRegionOnly();
}
});
}
/**
* this method will return the whole image But only the selected region is highlighted and the rest section is simply white
*/
private void getSelectedRegionWithBG(){
int[] mainImageArray = iv_custom.getImagePixels();
int[] bgImageArray = new int[bitmapBG.getWidth() * bitmapBG.getHeight()];
int[] finalImageArray = new int[bitmapBG.getWidth() * bitmapBG.getHeight()];
bitmapBG.getPixels(bgImageArray,0,bitmapBG.getWidth(), 0, 0, bitmapBG.getWidth(), bitmapBG.getHeight());
if(mainImageArray.length == bgImageArray.length){
for(int i = 0; i < (bitmapBG.getWidth() * bitmapBG.getHeight());i++){
if(mainImageArray[i] == bgImageArray[i]){
finalImageArray[i] = Color.WHITE;
}else{
finalImageArray[i] = mainImageArray[i];
}
}
Bitmap finalBitmap = Bitmap.createBitmap(bitmapBG.getWidth(), bitmapBG.getHeight(), Bitmap.Config.ARGB_8888);
// Set the pixels
finalBitmap.setPixels(finalImageArray, 0, finalBitmap.getWidth(), 0, 0, finalBitmap.getWidth(), finalBitmap.getHeight());
iv_later.setImageBitmap(finalBitmap);
}else{
Toast.makeText(ActivityImage.this,"Array length are not same",Toast.LENGTH_SHORT).show();
}
}
/**
* This method will select only the selected region from the main image and create the bitmap
*/
private void getSelectedRegionOnly(){
generateBounds();
int count = 0;
int[] finalImageArray = new int[(1+iMax - iMin) * (1+jMax - jMin)];
Bitmap finalBitmap = Bitmap.createBitmap((1+jMax - jMin), (1+iMax - iMin), Bitmap.Config.ARGB_8888);
for(int i = iMin; i <= iMax; i++){
for(int j = jMin; j <= jMax; j++){
if(bitmapBG.getPixel(j,i) != bitmapOrg.getPixel(j,i)) {
finalImageArray[count] = bitmapOrg.getPixel(j, i);
}else {
finalImageArray[count] = Color.WHITE;
}
count++;
}
}
// Set the pixels
finalBitmap.setPixels(finalImageArray, 0, finalBitmap.getWidth(), 0, 0, finalBitmap.getWidth(), finalBitmap.getHeight());
iv_later.setImageBitmap(finalBitmap);
}
/**
* generates the bound of the coloured region
*/
private void generateBounds(){
bitmapOrg = iv_custom.getMainBitmap();
iMax = jMax = 0;
iMin = jMin = bitmapBG.getWidth() * bitmapBG.getHeight();
for(int i = 0; i < bitmapBG.getHeight(); i++){
for(int j = 0; j < bitmapBG.getWidth(); j++){
if(bitmapBG.getPixel(j,i) != bitmapOrg.getPixel(j,i)){
if(iMin > i){
iMin = i;
}
if(jMin > j){
jMin = j;
}
if(iMax < i){
iMax = i;
}
if(jMax < j){
jMax = j;
}
}
}
}
}
}
Файл макета -
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="GRAB IMAGE"
android:id="@+id/btn_grab"
android:layout_alignParentBottom="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:id="@+id/demo"
android:orientation="vertical"
android:layout_above="@id/btn_grab"
>
<com.wandertails.stackovrflw.CustomImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/iv_custom"
android:layout_weight="1" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/iv_later"
android:layout_weight="1"/>
</LinearLayout>
</RelativeLayout>
Наконец, пользовательский образ View -
public class CustomImageView extends ImageView {
int width,height;
Bitmap sample;
Context con;
Paint paint=new Paint();
public CustomImageView(Context context) {
super(context);
con = context;
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
con = context;
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
con = context;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
sample = createBackground(width,height,con);
canvas.drawBitmap(sample,0,0,paint);
canvas.drawBitmap(createForeground(width,height,con),0,0,paint);
paint.setColor(Color.RED);
//canvas.drawRect(400,400,600,600,paint);
//canvas.drawCircle(400,400,200,paint);
}
public int[] getImagePixels(){
int[] pixels = new int[sample.getWidth() * sample.getHeight()];
sample.getPixels(pixels, 0, sample.getWidth(), 0, 0, sample.getWidth(), sample.getHeight());
return pixels;
}
public Bitmap getMainBitmap(){
return sample;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
private Bitmap createBackground(int width, int height, Context con) {
Bitmap logo = null;
logo = BitmapFactory.decodeResource(con.getResources(), R.drawable.sample);
return Bitmap.createScaledBitmap(logo,width,height,true).copy(Bitmap.Config.ARGB_8888,true);
}
private Bitmap createForeground(int width, int height, Context con) {
Bitmap logo = null;
logo = BitmapFactory.decodeResource(con.getResources(), R.drawable.sample1);
return Bitmap.createScaledBitmap(logo,width,height,true).copy(Bitmap.Config.ARGB_8888,true);
}
}
Вот некоторые из снимков экрана, которые я получаю -
![Здесь зеленые изображения - это шаблон (например, желтая область вашего изображения 3) и изображение лошади является фактическим основным изображением]()
![Здесь фигуры красного цвета - это шаблоны]()
Возможно, этот код не оптимизирован, но я думаю, что он будет служить вашей цели. Кроме того, вы можете использовать любую форму или дизайн в качестве маски (регион, который нужно выбрать), спросите меня, нужно ли вам какое-либо объяснение.
Ответ 3
У меня было бы три растровых изображения. Первое - это то, что вы показываете в качестве фона. Второй - это то, где пользователь рисует маску, а третий - результат.
Покажите фоновое изображение и нарисуйте маску Bitmap поверх этого. Разрешить пользователю рисовать маску. Как только они довольны маской, просто перебирайте пиксели, и когда вы найдете ту, что не пуста, вы знаете, что пиксель, который нужно скопировать. У вас будет позиция пикселя с вашей итерации, чтобы вы могли просто читать в этом месте из фона Bitmap и записать это значение в результат Bitmap.