Open JoaoBRBR opened 9 months ago
i just had access to the stu-540 model and reverse engineered it using wireshark with usbpcap and also reversing the OCX that wacom ships as browser extension or something like that... i dont fully recall now, but to work with other models it just should be matter of adapting the size settings and output image to what the tablet accepts.
As far as i know, all the firmwares use the same protocol not only for HID but also for serial tablets. and i implemented just enough protocol to make it workable. try adjusting the screen size, multiplier and other parameters to mach the device. Also bw devices may use 8bit bw images instead 24bgr color pixels
I looked around for SDK code and found this file wich have many clues about the protocol https://github.com/luguiant/wacomgss/blob/main/index.js
Cool, feel free to submit PR if you have it working and tested
Thanks! the resources you shared helped a lot! I took a while to realize I had to send 1bit array, now its working fine.
Hello @JoaoBRBR,
Could you please share your code or part of it so I can support STU-430 comms in my project? Great work!
Thank you! 👍
Hello. Could you tell me how I can save it in PNG format?
you can use a hidden canvas to export the svg paths into png, theres js libraries for that
Hello @JoaoBRBR, I´m also looking for a method to paint images on STU-430. I tried to convert Images to 1bit array from so many methods but never worked.
@devgar apart from sending the correct bitmap you have to update the packet header to inform the tablet of the format of the image:
EncodingMode_1bit : 0x00, // uncompressed monochrome
EncodingMode_1bit_Zlib : 0x01, // Zlib-compressed monochrome
EncodingMode_16bit : 0x02, // uncompressed color
EncodingMode_24bit : 0x04, // uncompressed color (530 only)
EncodingMode_1bit_Bulk : 0x10, // data will be sent using Interface::write() instead of Interface::set().
EncodingMode_16bit_Bulk : 0x12, // data will be sent using Interface::write() instead of Interface::set().
EncodingMode_24bit_Bulk : 0x14 // data will be sent using Interface::write() instead of Interface::set() (530 only).
my code is full color 24bpp so i use 0x14 in the library. you have to use 0x10
i did not add it since i cannot test, but if you make it work send a PR if you want
btw soy de almería xd
@devgar apart from sending the correct bitmap you have to update the packet header to inform the tablet of the format of the image:
...
my code is full color 24bpp so i use 0x14 in the library. you have to use 0x00 or 0x01 if you compress it with zlib
i did not add it since i cannot test, but if you make it work send a PR if you want
btw soy de almería xd
Hello @pabloko,
Changing the encoding value is not enough for monochrome tablets. Here is the initializer for the STU-430 that I tried so far but the Wacom tablet only shows random tiny characters across the screen:
...
Maybe there is a need to change the way to chunks are sent to the tablet? Your help is much appreciated, thank you!
please show me how you compose and send the image, the default code extract bgr color from canvas intead monochrome and the packing is different
looking at
https://github.com/pabloko/Wacom-STU-WebHID/blob/main/demo.html#L197C8-L198C32
you could use something like this
const rgb1 = new Uint8Array(imageData.data.length / 4 / 8)
var i = 0, j = 0;
var buffer = imageData.data;
var setBit = function (n, bitIndex, value) {
const bitMask = 1 << bitIndex;
return value? n | bitMask : n;
}
while (i < imageData.data.length) {
//Remap pixels
var pixel = 0;
// take 8 pixels per byte
// if the device is big endian maybe this loop has to be inverted from 7 to 0
for (var z = 0; z < 8; z++) {
// calculate yuv luminance for a good b/w balance
var luma = buffer[i] * 0.3 + buffer[i + 1] * 0.59 + buffer[i + 2] * 0.11; i += 4;
// set independent bits as binary black or white color on half scale threeshold
setBit(pixel, z, luma > 127)
}
// keep appending pixel groups until finished
rgb1[j++] = pixel
}
image = rgb1
this would convert colors to a single byte of luminance and then bitset 8 pixels into a each byte as the buffer for monochrome image
looking at
https://github.com/pabloko/Wacom-STU-WebHID/blob/main/demo.html#L197C8-L198C32
you could use something like this
...
this would convert colors to a single byte of luminance and then bitset 8 pixels into a each byte as the buffer for monochrome image
@pabloko Thank you very much for your help so far.
I tried something like that in the past after some research and were getting nowhere. After I tried your code it only displays a black screen on the Wacom STU-430, even after setting the screen size according to this tablet which is 320x200. Maybe it has something to do with the background that is being set when converting from white color to monochrome it just overrides and it shows a black screen on the tablet.
... removed code for uncluttering the conv.
@sirbig well without access to the device its very difficul to troubleshoot what is going wrong...
lets do one thing, download "wireshark", it has an option to sniff usb-hid traffic using usbpcap, start sniffing the the device (is useful if you select option to start on plug, so it captures all comms) and then using the official app from wacom set the image a few times capturing the comms, then pass the pen over the screen to test other stuff, try to annotate the timestamps and upload the .pcap file. I will be able then to examine the protocol and tell you whats going on.
I have access to a STU430 again and this is going really better.
I have set the loop to meet bigEndian needs, and also fix an Issue with setBit(..) return not being captured.
The image is so close to the desired result. I think it only needs to adjust luma treeshold to improve resolution.
Thank you @pabloko for this repo and all this support.
This is my current version
var byteArray = new Uint8Array(imageData.data.length / 4 / 8)
var i = 0, j = 0;
var buffer = imageData.data;
var setBit = function (n, bitIndex, value) {
const bitMask = 1 << bitIndex;
return value? n | bitMask : n;
}
while (i < imageData.data.length) {
//Remap pixels
var byte = 0;
// take 8 pixels per byte
// // if the device is big endian maybe this loop has to be inverted from 7 to 0
// This needs to be big endian
for (var z = 7; z >= 0; z--) {
// calculate yuv luminance for a good b/w balance
var luma = buffer[i] * 0.3 + buffer[i + 1] * 0.59 + buffer[i + 2] * 0.11; i += 4;
// set independent bits as binary black or white color on half scale threeshold
byte = setBit(byte, z, luma > 127)
}
// keep appending pixel groups until finished
byteArray[j++] = byte
}
console.log(byteArray.length, j);
image = byteArray
My screen is currently as this
I have access to a STU430 again and this is going really better.
I have set the loop to meet bigEndian needs, and also fix an Issue with setBit(..) return not being captured.
The image is so close to the desired result. I think it only needs to adjust luma treeshold to improve resolution.
Thank you @pabloko for this repo and all this support.
This is my current version
var byteArray = new Uint8Array(imageData.data.length / 4 / 8) var i = 0, j = 0; var buffer = imageData.data; var setBit = function (n, bitIndex, value) { const bitMask = 1 << bitIndex; return value? n | bitMask : n; } while (i < imageData.data.length) { //Remap pixels var byte = 0; // take 8 pixels per byte // // if the device is big endian maybe this loop has to be inverted from 7 to 0 // This needs to be big endian for (var z = 7; z >= 0; z--) { // calculate yuv luminance for a good b/w balance var luma = buffer[i] * 0.3 + buffer[i + 1] * 0.59 + buffer[i + 2] * 0.11; i += 4; // set independent bits as binary black or white color on half scale threeshold byte = setBit(byte, z, luma > 127) } // keep appending pixel groups until finished byteArray[j++] = byte } console.log(byteArray.length, j); image = byteArray
@devgar Great job! I can confirm the same behaviour with my STU-430 as well, it is getting pretty close to the desired result, just needs a little more tweaking to get the best possible results. Maybe changing the values of the luma calculations will do the trick.
hola @devgar por la foto parece que mas o menos el empaquetado de pixels funciona, el problema del monocromo es que necesitas ajustar el valor del threeshold (tanto si usas aproximación por luma, o como si usas la capa alpha) dependiendo de si quieres mostrar imágenes con objetos o líneas finas como texto, o ambos... Una cosa que deberías hacer es desactivar el antialiasing del canvas, puesto con el activado se van a generar montones de pixels grises adyacentes al texto y formas que computan en el luma. comprueba que la imagen no se esté escalando y tratar siempre que la fuente y tamaño seleccionado formen líneas de al menos 1px de ancho te ayudará a obtener mejores resultados.
Muchas gracias, @pabloko. Seguiré con las modificaciones que comentas.
Si alguna vez vienes a Castellón tienes una cerveza (u otra consumición) pagada.
de nada @devgar, estoy pensando que esta lib se está usando mucho más de lo que pensaba inicialmente, así que lo mismo saco un rato y la rehago incluyendo todo el tema del ui y las imágenes para hacerlo menos tedioso, este es otro caso de un proof-of-concept que fue a producción... y ya de paso me gustaría meter soporte para los 430, si puedes pasarme la impl cuando esté lista, o hacer un PR y lo rediseño bien
Por supuesto tendrás nuestra implementación cuando esté lista
Hi, this is not an issue with the code, it
s more of a question, I want to use web-Hid with stu-540 and 430, and your code helped a lot to use it with 540, so the question is: how do you find information about how the devices expect the report-id
s and the information's regarding device communication, I want it to work for stu-340 as well, the signing is working, but not the part of sending image to the device screen.