如何将图像转换为像素,编辑它,并在Javascript中绘制编辑的图像

时间:2017-07-11 23:33:06

标签: javascript

我是JS的新手,我想学习如何执行以下操作:

获取图像数据(将其转换为像素数组,以便我可以编辑它),然后从像素编辑功能返回已编辑的数组,以便我可以使用这些编辑的值来绘制已编辑的图像。

我甚至不确定这是否可以解决这个问题,但这是我到目前为止所得到的:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rentExtraLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">

<TextView
    android:id="@+id/nameTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="40dp"
    android:layout_marginStart="40dp"
    android:layout_marginTop="18dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:text="test" />

<ImageView
    android:id="@+id/checkImageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:layout_marginRight="16dp"
    app:layout_constraintBottom_toBottomOf="@+id/nameTextView"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="@+id/nameTextView" />

<TextView
    android:id="@+id/priceTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="24dp"
    android:layout_marginRight="24dp"
    app:layout_constraintRight_toLeftOf="@+id/checkImageView"
    app:layout_constraintTop_toTopOf="@+id/nameTextView"
    android:text="test" />

<View
    android:id="@+id/lineSplitting"
    android:layout_width="0dp"
    android:layout_height="1dp"
    android:layout_alignParentBottom="true"
    android:layout_marginTop="10dp"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintLeft_toLeftOf="@+id/nameTextView"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/nameTextView" />


<LinearLayout
    android:id="@+id/expandViewLinearLayout"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical"
    android:visibility="gone"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/lineSplitting">   
    </LinearLayout>
</merge>

控制台输出显示一个<?xml version="1.0" encoding="utf-8"?> <com.kunzisoft.myapplication.ExtraView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/item" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.kunzisoft.myapplication.MainActivity" /> 的数组。

为什么不将已编辑的像素推送到public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ExtraView itemData = (ExtraView) findViewById(R.id.item); itemData.addData("OUIIIIIII"); } }

3 个答案:

答案 0 :(得分:4)

有很多问题需要解决。如果要从画布获取getImageData,则图像需要位于同一个域中。更容易修复的是base64格式。不是网址。所以将图像转换为base64字符串。

你不是在任何地方调用编辑像素,即使你在某个地方调用它并且在问题中没有提到,也要形成你的参数,明确指出你传递的是上下文而不是图像数据。

使用getImageData和putImageData在画布中获取和设置数据。

对于循环需要更改,以便您不要在alpha数据上设置负值。图像数据的格式为rgba。

因为你没有提到如何操纵像素。我只是将rgb值减少100来显示原始图像和新图像之间的差异。

var img = new Image();
      img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAG1BMVEXMzMyWlpa3t7eqqqqcnJyjo6PFxcWxsbG+vr6NAD6nAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACjklEQVR4nO3XO2/bMBDA8fNTGn2OlGS00S8QAWnnaKi7xnBQdJSBFl3joY/RRpHv3SNFykYtdKOm/w8BHOkOIM3HkRYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/uddvWvsI38sj+7xT/2lJ2n8WH64iMbkdCaqurTPteqda98eX6+zKnu9OkdDckIH3W21kbmWlR5F9rrT+6ukTMv3ettFY3JC9UZyfZBJ0czrZxuWjXwtr5KmRSOnmy4ak9PJ3bc+PMveJvJ0a+OwslfNv1knG6Ks7KIhOaGxulYXsl7YmNy1j/XV4nLRXLtoSE4oczN2epLK5mRSuj/x/7tuPImfOfHDKXnRRUNyaq6l17bhu7aX/q1N1fY8Va7TIRqSE/tuS2a78i3Nludu7QsbsW4+54dlFw3JadVqM1Uf3b6XqSsO+4V/n+nrtGt7qrZdYzQkp6WuFLUtNW3DYebqzXoZk0ZqWzZGQ3LqblmLvhFtRq5Ho9Ct9c25OI1c52M0JKftlrzpc+9ozfSilOfbctjRsv226FtbtuBvLpJmOuza8hW7Zyfa4lpeJFl5H24nZr/Fz4srReNQt9ahW5nGpn8d/azFaEhOyJ8hNi+HtnBn5yrvClcsW+44slmL0UPyKj8Jh0/fmVjd12HxV+3hM+CZ6DZUFW4Q9+GOcPShuT6sw5o/3PovEKMhOaG5frZBWPXdt2a2xkMV2JeNuNI62H1LqmJXF9J3O7XbQ65t4xP9+OguFMPdTr9Zkd9I313eLaxt28X5VtUuqAPe5eVH/ckalPyl/THzFn/5jF0H9qEMZC/Fz4toTAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEjpL514clJrNSt2AAAAAElFTkSuQmCC';
      var canvas = document.getElementById('canvas');
      var canvasEdited =  document.getElementById('canvasEdited');
      var ctx = canvas.getContext('2d');
      var arr = [];
      img.onload = function() {
          ctx.drawImage(img, 0, 0);

          var imageData = ctx.getImageData(0,0, canvas.width, canvas.height)

           editPixels(imageData.data);

           drawEditedImage( imageData);
     };

     function editPixels(imgData) {
              for (var i=0; i < imgData.length; i += 4) {
                  imgData[i] = imgData[i] - 100;
                imgData[i+1] = imgData[i+1] - 100;
                imgData[i+2] = imgData[i+2] - 100;
             }
     }

     function drawEditedImage(newData) {
         var ctxEdited = canvasEdited.getContext('2d');
         ctxEdited.putImageData(newData, 0, 0);
     }

jsfiddle也一样 https://jsfiddle.net/karthick6891/3yhyyLyf/

答案 1 :(得分:2)

我没有其他人那么快,但无论如何我决定发布我的答案,因为它仍然有一些附加值(分解,base64,污点画布提到......)。

我假设您想通过画布更改图像的像素数据。

首先,将图像渲染到画布。你已经做对了:

var canvasEdited =  document.getElementById('canvasEdited');
var ctxEdited = canvasEdited.getContext('2d');
ctxEdited.drawImage(img, 0, 0, canvasEdited.width, canvasEdited.height);

然后,取出像素数据:

var imageData = ctxEdited.getImageData(0, 0, canvasEdited.width, canvasEdited.height);
// you will get an array of pixel data
// this array consists of rgba values
// each 'set' of four stands for red, green, blue and alpha

然后,用它做一些事情,在这个例子中将它变成灰色:

for(var i = 0; i < imageData.length; i += 4) {
    var brightness = 0.34 * imageData[i] + 0.5 * imageData[i + 1] + 0.16 * imageData[i + 2];
    imageData[i] = brightness;
    imageData[i + 1] = brightness;
    imageData[i + 2] = brightness;
}

然后,在画布上绘制更改后的像素数据:

ctxEdited.putImageData(imageData, 0, 0);

如果您想在画布外重复使用该图像,可以将其转换为base64,就像这样吗

var base64URI = canvasEdited.toDataURL();

然后,您可以将该数据设置为元素的来源,如下所示:

img.src = base64URI;

注意事项:

  • 您必须通过localhost或Web服务器打开您的页面,否则浏览器将阻止它。 (除非你设置了正确的标志)

  • 您无法从受污染的画布中获取像素数据。当您绘制未指定crossOrigin的图像时会发生这种情况。请在https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

  • 了解详情

答案 2 :(得分:1)

我使用以下内容检查给定像素是否不透明

canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 4 + 3] !== 0

以rgba格式返回画布数据,因此您需要以rgba值指定的颜色。

//red
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 4] = 0;

//green
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 1] = 0;

//blue
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 2] = 0;

//alpha
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 2] = 0;

一般情况下,在游戏中编辑图像将使用包含所有游戏元素的精灵图片的屏幕外画布。