Carregue uma imagem nesse snippet de pilha e mova o mouse sobre ela. Uma curva preta que segue o ângulo da tonalidade , começando no ponto do cursor, será desenhada:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><style>canvas{border:1px solid black;}</style>Load an image: <input type='file' onchange='load(this)'><br><br>Max length <input id='length' type='text' value='300'><br><br><div id='coords'></div><br><canvas id='c' width='100' height='100'>Your browser doesn't support the HTML5 canvas tag.</canvas><script>function load(t){if(t.files&&t.files[0]){var e=new FileReader;e.onload=setupImage,e.readAsDataURL(t.files[0])}}function setupImage(t){function e(t){t.attr("width",img.width),t.attr("height",img.height);var e=t[0].getContext("2d");return e.drawImage(img,0,0),e}img=$("<img>").attr("src",t.target.result)[0],ctx=e($("#c")),ctxRead=e($("<canvas>"))}function findPos(t){var e=0,a=0;if(t.offsetParent){do e+=t.offsetLeft,a+=t.offsetTop;while(t=t.offsetParent);return{x:e,y:a}}return void 0}$("#c").mousemove(function(t){function e(t,e){var a=ctxRead.getImageData(t,e,1,1).data,i=a[0]/255,r=a[1]/255,o=a[2]/255;return Math.atan2(Math.sqrt(3)*(r-o),2*i-r-o)}if("undefined"!=typeof img){var a=findPos(this),i=t.pageX-a.x,r=t.pageY-a.y;$("#coords").html("x = "+i.toString()+", y = "+r.toString());var o=parseInt($("#length").val());if(isNaN(o))return void alert("Bad max length!");for(var n=[i],f=[r],h=0;n[h]>=0&&n[h]<this.width&&f[h]>=0&&f[h]<this.height&&o>h;)n.push(n[h]+Math.cos(e(n[h],f[h]))),f.push(f[h]-Math.sin(e(n[h],f[h]))),h++;ctx.clearRect(0,0,this.width,this.height),ctx.drawImage(img,0,0);for(var h=0;h<n.length;h++)ctx.fillRect(Math.floor(n[h]),Math.floor(f[h]),1,1)}});</script>
Eu só testei esse snippet no Google Chrome.
Por exemplo, quando o cursor está acima do vermelho, a curva tem uma inclinação de 0 °, mas quando está acima do amarelo, tem uma inclinação de 60 °. A curva continua pelo comprimento especificado, alterando continuamente sua inclinação para corresponder à tonalidade.
Carregue esta imagem e quando você mover o cursor sobre ela, a linha ao redor do cursor deverá fazer uma volta completa no sentido anti-horário:
Este e este são outras imagens nítidas para tentar. (Você precisará salvá-los e carregá-los com o snippet. Eles não podem ser vinculados diretamente devido a restrições de origem cruzada.)
Aqui está uma versão não minificada do snippet:
Desafio
Escreva um programa que faça o que o snippet está fazendo, mas não de maneira interativa. Tire uma imagem e uma coordenada (x, y) nos limites da imagem e um comprimento máximo da curva. Emita a mesma imagem com a curva preta adicionada que segue os ângulos de matiz começando em (x, y) e termina quando atinge o comprimento máximo ou atinge o limite de uma imagem.
Especificamente, inicie a curva em (x, y) e meça o ângulo da tonalidade lá. Vá uma unidade (largura de um pixel) nessa direção, observando que sua nova posição provavelmente não é uma coordenada inteira . Marque outro ponto na curva e mova-se novamente, usando a tonalidade do pixel mais próximo (usando algo como floor
ou round
, não vou verificar isso com precisão). Continue assim até que a curva saia dos limites ou exceda o comprimento máximo. Para finalizar, plote todos os pontos da curva como pixels pretos únicos (novamente, use os pixels mais próximos) sobrepostos na imagem e produza essa nova imagem.
O "ângulo de matiz" é apenas o matiz :
hue = atan2(sqrt(3) * (G - B), 2 * R - G - B)
Observe que, para valores em escala de cinza que tecnicamente não possuem matiz, isso retorna 0, mas tudo bem.
(Essa fórmula usa a atan2
maioria das bibliotecas matemáticas internas. R, G, B são de 0 a 1, não de 0 a 255.)
- Você pode usar qualquer formato de arquivo de imagem sem perdas comum, bem como quaisquer bibliotecas de imagens.
- Pegue a entrada do stdin ou da linha de comando ou escreva uma função com argumentos para o nome do arquivo de imagem, xey, e o comprimento máximo.
- O comprimento máximo e x e y são sempre números inteiros não negativos. Você pode assumir que xey estão dentro do alcance.
- Salve a imagem de saída com um nome de sua escolha ou simplesmente exiba-a.
- Sua implementação não precisa corresponder exatamente ao snippet. Alguns pixels em locais ligeiramente diferentes devido a um método de arredondamento / cálculo um pouco diferente são bons. (Em casos caóticos, isso pode levar a curvas muito diferentes, mas, desde que pareçam corretas visualmente, tudo bem.)
Pontuação
O menor envio em bytes vence.