キャンバスの imageData をサーバーに送信して処理する際に問題が発生するという問題があります。
データを送信するための反応/還元アクションは次のとおりです。
export const edit = (e) => dispatch => {
let payload = store.getState().image.imageData
payload = payload[payload.length-1]
console.log(payload)
const id = e.target.id ? e.target.id : e.target.parentElement.id
fetch(`/api/editing/${id}`, {
method: 'POST',
// headers: {
// "Content-Type": "application/json"
// },
body: JSON.stringify({ imgData: payload })
})
.then(res => res.json())
.then(json => {
dispatch({ type: UPDATE_IMAGE, payload: json.imgData })
// handle response display
})
}
リクエストを処理する方法は次のとおりです。
const traitement = require('../../processing/traitement')
router.post('/:type', (req, res) => {
const { imgData } = req.body
const method = req.params.type
const imgDataProcessed = traitement[method](imgData)
return res.status(200).json({ imgData: imgDataProcessed })
})
以下は、traitement メソッドがどのようなものかの例です。
negatif: function(imgData) {
console.log(imgData)
var n = imgData.data.length;
for(i=0; i<n; i+=4){
imgData.data[i] = 255 - imgData.data[i];
imgData.data[i+1] = 255 - imgData.data[i+1];
imgData.data[i+2] = 255 - imgData.data[i+2];
imgData.data[i+3] = 255;
}
return imgData;
},
送信する直前の console.log() (送信する予定のもの):
ImageData {data: Uint8ClampedArray(180000), width: 300, height: 150}
data: Uint8ClampedArray(180000) [0, 0, 255, 255, 0, 0, 255, 255, 0, 0,
255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255,
255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0,
0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255,
255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0,
0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255,
255, …]
height: 150
width: 300
__proto__: ImageData
サーバーから取得したものを貼り付けることはできませんが、幅と高さのキーを失い、typeof は ImageData ではなく Object であり、データ キーは Uint8ClampedArray ではなく typeof Object です。
だから私の質問は次のとおりです:ルートが送信した同じデータにアクセスして処理できるようにするにはどうすればよいですか?
ご覧のとおり、文字列化されたjsonとして送信し、サーバーにjsonボディパーサーミドルウェアを持っています。おそらくそこからのものです。content-typeヘッダーについても考えました
EDIT:Kaiidoのおかげで、1つの例外で動作するようにコードを修正しました
私のコードをどのように変更したか、フロント:
let payload = store.getState().image.imageData
payload = payload[payload.length-1]
const id = e.target.id ? e.target.id : e.target.parentElement.id;
console.log(payload)
const meta = {
width: payload.width,
height: payload.height
}
const formData = new FormData();
formData.append("meta", JSON.stringify(meta));
formData.append("data", new Blob([payload.data.buffer]))
fetch(`/api/editing/${id}`, {
method: "POST",
body: formData
})
.then(res => res.arrayBuffer())
.then(buffer => {
console.log(buffer)
const data = new Uint8ClampedArray(buffer)
console.log(data.length)
const newImg = new ImageData(data, payload.width, payload.height)
return newImg
})
戻る:
router.post('/:type', (req, res) => {
let form = new formidable.IncomingForm()
form.parse(req, (err, fields, files) => {
fs.readFile(files.data.path, (err, data) => {
const imgProcessed = traitement[req.params.type](data)
console.log(imgProcessed.length)
return res.status(200).json([imgProcessed])
})
})
})
1 つの問題が残っています: テスト用に 150*300px の画像を使用していると仮定すると、サーバーの応答を送信するまで、データ配列の長さは 180000 (300*150*4) である必要があります。フロントが呼び出す応答を受信するとres.arrayBuffer()
、新しい Uint8ClampedArray が作成されますが、その場合、長さは 180000 ではなく 543810 になります。カイドウが言ったように、その配列をスライスしたいかもしれませんが、試してみましたが、うまくいきません。
どのようにスライスすればよいですか?180000 の最初のもの ? 180000 続くもの ? 他の方法?