canvas2base64.js
6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import base64 from 'base-64'
import { isFunc } from './tools'
function makeURI (strData, type) {
return 'data:' + type + ';base64,' + strData
}
function fixType (type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg')
const r = type.match(/png|jpeg|bmp|gif/)[0]
return 'image/' + r
}
function encodeData (data) {
let str = ''
if (typeof data === 'string') {
str = data
} else {
for (let i = 0; i < data.length; i++) {
str += String.fromCharCode(data[i])
}
}
return base64.encode(str)
}
/**
* 获取图像区域隐含的像素数据
* @param canvasId canvas标识
* @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
* @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
* @param width 将要被提取的图像数据矩形区域的宽度
* @param height 将要被提取的图像数据矩形区域的高度
* @param done 完成回调
*/
function getImageData (canvasId, x, y, width, height, done) {
wx.canvasGetImageData({
canvasId,
x,
y,
width,
height,
success (res) {
done(res, null)
},
fail (res) {
done(null, res)
}
})
}
/**
* 生成bmp格式图片
* 按照规则生成图片响应头和响应体
* @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData
* @returns {*} base64字符串
*/
function genBitmapImage (oData) {
//
// BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
// BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
//
const biWidth = oData.width
const biHeight = oData.height
const biSizeImage = biWidth * biHeight * 3
const bfSize = biSizeImage + 54 // total header size = 54 bytes
//
// typedef struct tagBITMAPFILEHEADER {
// WORD bfType;
// DWORD bfSize;
// WORD bfReserved1;
// WORD bfReserved2;
// DWORD bfOffBits;
// } BITMAPFILEHEADER;
//
const BITMAPFILEHEADER = [
// WORD bfType -- The file type signature; must be "BM"
0x42, 0x4D,
// DWORD bfSize -- The size, in bytes, of the bitmap file
bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
// WORD bfReserved1 -- Reserved; must be zero
0, 0,
// WORD bfReserved2 -- Reserved; must be zero
0, 0,
// DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
54, 0, 0, 0
]
//
// typedef struct tagBITMAPINFOHEADER {
// DWORD biSize;
// LONG biWidth;
// LONG biHeight;
// WORD biPlanes;
// WORD biBitCount;
// DWORD biCompression;
// DWORD biSizeImage;
// LONG biXPelsPerMeter;
// LONG biYPelsPerMeter;
// DWORD biClrUsed;
// DWORD biClrImportant;
// } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
//
const BITMAPINFOHEADER = [
// DWORD biSize -- The number of bytes required by the structure
40, 0, 0, 0,
// LONG biWidth -- The width of the bitmap, in pixels
biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
// LONG biHeight -- The height of the bitmap, in pixels
biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
// WORD biPlanes -- The number of planes for the target device. This value must be set to 1
1, 0,
// WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
// has a maximum of 2^24 colors (16777216, Truecolor)
24, 0,
// DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
0, 0, 0, 0,
// DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
// LONG biXPelsPerMeter, unused
0, 0, 0, 0,
// LONG biYPelsPerMeter, unused
0, 0, 0, 0,
// DWORD biClrUsed, the number of color indexes of palette, unused
0, 0, 0, 0,
// DWORD biClrImportant, unused
0, 0, 0, 0
]
const iPadding = (4 - ((biWidth * 3) % 4)) % 4
const aImgData = oData.data
let strPixelData = ''
const biWidth4 = biWidth << 2
let y = biHeight
const fromCharCode = String.fromCharCode
do {
const iOffsetY = biWidth4 * (y - 1)
let strPixelRow = ''
for (let x = 0; x < biWidth; x++) {
let iOffsetX = x << 2
strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) +
fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) +
fromCharCode(aImgData[iOffsetY + iOffsetX])
}
for (let c = 0; c < iPadding; c++) {
strPixelRow += String.fromCharCode(0)
}
strPixelData += strPixelRow
} while (--y)
const strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData)
return strEncoded
}
/**
* 转换为图片base64
* @param canvasId canvas标识
* @param x 将要被提取的图像数据矩形区域的左上角 x 坐标
* @param y 将要被提取的图像数据矩形区域的左上角 y 坐标
* @param width 将要被提取的图像数据矩形区域的宽度
* @param height 将要被提取的图像数据矩形区域的高度
* @param type 转换图片类型
* @param done 完成回调
*/
function convertToImage (canvasId, x, y, width, height, type, done = () => {}) {
if (type === undefined) { type = 'png' }
type = fixType(type)
if (/bmp/.test(type)) {
getImageData(canvasId, x, y, width, height, (data, err) => {
const strData = genBitmapImage(data)
isFunc(done) && done(makeURI(strData, 'image/' + type), err)
})
} else {
console.error('暂不支持生成\'' + type + '\'类型的base64图片')
}
}
export default {
convertToImage: convertToImage,
// convertToPNG: function (width, height, done) {
// return convertToImage(width, height, 'png', done)
// },
// convertToJPEG: function (width, height, done) {
// return convertToImage(width, height, 'jpeg', done)
// },
// convertToGIF: function (width, height, done) {
// return convertToImage(width, height, 'gif', done)
// },
convertToBMP: function ({ canvasId, x, y, width, height } = {}, done = () => {}) {
return convertToImage(canvasId, x, y, width, height, 'bmp', done)
}
}