Android GPUImage-13: Sepia

该代码示例展示了如何使用OpenGL着色器进行图像锐化处理。通过对中心像素和周围像素的不同权重计算,调整sharpness参数可以增强图像边缘,实现锐化效果。输入包括纹理坐标、图像宽度和高度因子以及锐度值。

1.效果图

2.shader

"attribute vec4 position;\n" +
            "attribute vec4 inputTextureCoordinate;\n" +
            "\n" +
            "uniform float imageWidthFactor; \n" +
            "uniform float imageHeightFactor; \n" +
            "uniform float sharpness;\n" +
            "\n" +
            "varying vec2 textureCoordinate;\n" +
            "varying vec2 leftTextureCoordinate;\n" +
            "varying vec2 rightTextureCoordinate; \n" +
            "varying vec2 topTextureCoordinate;\n" +
            "varying vec2 bottomTextureCoordinate;\n" +
            "\n" +
            "varying float centerMultiplier;\n" +
            "varying float edgeMultiplier;\n" +
            "\n" +
            "void main()\n" +
            "{\n" +
            "    gl_Position = position;\n" +
            "    \n" +
            "    mediump vec2 widthStep = vec2(imageWidthFactor, 0.0);\n" +
            "    mediump vec2 heightStep = vec2(0.0, imageHeightFactor);\n" +
            "    \n" +
            "    textureCoordinate = inputTextureCoordinate.xy;\n" +
            "    leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;\n" +
            "    rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;\n" +
            "    topTextureCoordinate = inputTextureCoordinate.xy + heightStep;     \n" +
            "    bottomTextureCoordinate = inputTextureCoordinate.xy - heightStep;\n" +
            "    \n" +
            "    centerMultiplier = 1.0 + 4.0 * sharpness;\n" +
            "    edgeMultiplier = sharpness;\n" +
            "}";

 

static final String SHARPEN_FRAGMENT_SHADER = "" +
            "precision highp float;\n" +
            "\n" +
            "varying highp vec2 textureCoordinate;\n" +
            "varying highp vec2 leftTextureCoordinate;\n" +
            "varying highp vec2 rightTextureCoordinate; \n" +
            "varying highp vec2 topTextureCoordinate;\n" +
            "varying highp vec2 bottomTextureCoordinate;\n" +
            "\n" +
            "varying highp float centerMultiplier;\n" +
            "varying highp float edgeMultiplier;\n" +
            "\n" +
            "uniform sampler2D inputImageTexture;\n" +
            "\n" +
            "void main()\n" +
            "{\n" +
            "    mediump vec3 textureColor = texture2D(inputImageTexture, textureCoordinate).rgb;\n" +
            "    mediump vec3 leftTextureColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;\n" +
            "    mediump vec3 rightTextureColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;\n" +
            "    mediump vec3 topTextureColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;\n" +
            "    mediump vec3 bottomTextureColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;\n" +
            "\n" +
            "    gl_FragColor = vec4((textureColor * centerMultiplier - (leftTextureColor * edgeMultiplier + rightTextureColor * edgeMultiplier + topTextureColor * edgeMultiplier + bottomTextureColor * edgeMultiplier)), texture2D(inputImageTexture, bottomTextureCoordinate).w);\n" +
            "}";

3.原理

取上下左右四个点,把中心点的像素按照一定的sharpness来改变,临近的像素是比较相似的。

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>复古奥特曼立方体</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: linear-gradient(45deg, #2c3e50, #4a6572); font-family: 'Arial', sans-serif; overflow: hidden; perspective: 1000px; } .container { width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px; } .title { color: #e0e0e0; text-align: center; margin-bottom: 40px; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); font-size: 2.5rem; letter-spacing: 2px; font-family: 'Impact', 'Arial Black', sans-serif; text-transform: uppercase; } .scene { width: 200px; height: 200px; perspective: 800px; margin: 0 auto 50px; } .cube { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transform: rotateX(-25deg) rotateY(-25deg); animation: rotate 15s infinite linear; } .cube-face { position: absolute; width: 200px; height: 200px; background-color: #7094a0; /* 青灰色 */ border: 2px solid #5a7c85; display: flex; justify-content: center; align-items: center; opacity: 0.9; box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.2), 0 0 30px rgba(0, 0, 0, 0.4); filter: sepia(0.3) contrast(1.1); } /* 奥特曼图案 */ .ultraman-face { width: 80%; height: 80%; background: /* 头部轮廓 */ radial-gradient(circle at center, #d0d0d0 10%, transparent 10.5%), /* 眼睛 */ radial-gradient(ellipse at 30% 45%, #ff6b00 15%, #ff4500 15.5%, #ff4500 20%, transparent 20.5%), radial-gradient(ellipse at 70% 45%, #ff6b00 15%, #ff4500 15.5%, #ff4500 20%, transparent 20.5%), /* 头部装饰 */ linear-gradient(165deg, transparent 40%, silver 40%, silver 45%, transparent 45%), linear-gradient(195deg, transparent 40%, silver 40%, silver 45%, transparent 45%); border-radius: 50%; position: relative; filter: contrast(1.2); } .ultraman-face::before { content: ''; position: absolute; top: 30%; left: 50%; transform: translateX(-50%); width: 20%; height: 10%; background: #333; border-radius: 50%; } /* 立方体各面的位置 */ .front { transform: translateZ(100px); } .back { transform: rotateY(180deg) translateZ(100px); } .right { transform: rotateY(90deg) translateZ(100px); } .left { transform: rotateY(-90deg) translateZ(100px); } .top { transform: rotateX(90deg) translateZ(100px); } .bottom { transform: rotateX(-90deg) translateZ(100px); } /* 动画 */ @keyframes rotate { from { transform: rotateX(-25deg) rotateY(0deg); } to { transform: rotateX(-25deg) rotateY(360deg); } } .controls { margin-top: 30px; display: flex; gap: 15px; } button { padding: 12px 25px; background: #5a7c85; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 1rem; transition: all 0.3s; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); } button:hover { background: #7094a0; transform: translateY(-2px); } .vintage-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at 20% 20%, rgba(255,255,255,0.1) 5px, transparent 5px), radial-gradient(circle at 80% 80%, rgba(255,255,255,0.1) 5px, transparent 5px); pointer-events: none; mix-blend-mode: overlay; z-index: 100; } .info { color: #c0c0c0; text-align: center; margin-top: 30px; max-width: 600px; line-height: 1.6; font-size: 1.1rem; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); } </style> </head> <body> <div class="vintage-overlay"></div> <div class="container"> <h1 class="title">复古风奥特曼立方体</h1> <div class="scene"> <div class="cube"> <div class="cube-face front"> <div class="ultraman-face"></div> </div> <div class="cube-face back"> <div class="ultraman-face"></div> </div> <div class="cube-face right"> <div class="ultraman-face"></div> </div> <div class="cube-face left"> <div class="ultraman-face"></div> </div> <div class="cube-face top"> <div style="width: 70%; height: 70%; background: #5a7c85; border-radius: 50%;"></div> </div> <div class="cube-face bottom"> <div style="width: 60%; height: 60%; background: #5a7c85; border-radius: 8px;"></div> </div> </div> </div> <div class="controls"> <button onclick="document.querySelector('.cube').style.animationPlayState = 'paused'">暂停旋转</button> <button onclick="document.querySelector('.cube').style.animationPlayState = 'running'">继续旋转</button> </div> <div class="info"> <p>这款青灰色立方体采用复古风格设计,每个面都刻有经典的奥特曼头部图案。立方体持续旋转以展示其3D效果,整体设计呈现出怀旧的科幻风格。</p> </div> </div> <script> // 添加随机抖动效果,增强复古感 document.addEventListener('DOMContentLoaded', function() { const cube = document.querySelector('.cube'); setInterval(() => { if (Math.random() > 0.7 && cube.style.animationPlayState !== 'paused') { cube.style.animation = 'none'; setTimeout(() => { cube.style.animation = 'rotate 15s infinite linear'; }, 50); } }, 3000); }); </script> </body> </html>
最新发布
09-14
### 代码分析与优化思路 #### HTML 部分 - **精简代码**:减少 HTML 的嵌套、DOM 节点数和无语义代码,删除多余的空格、换行符、缩进和不必要的注释,省略冗余标签和属性,使用相对路径的 URL ,并将文件放在合适的位置。例如对于立方体的 HTML 结构,可参考 `css3+javascript实现旋转3D立方体` 中的结构,若存在多余的包裹元素可进行精简。 ```html <!-- 精简后的立方体 HTML 示例 --> <div id="container"> <div class="face">1</div> <div class="face">2</div> <div class="face">3</div> <div class="face">4</div> <div class="face">5</div> <div class="face">6</div> </div> ``` #### CSS 部分 - **代码缩写**:使用 CSS 中可缩写的属性,如 `margin`、`padding`、`border`、`font`、`background` 和颜色值等。例如将 `font` 和 `padding` 进行缩写。 ```css li { font: 1.2em/1.4em Arial, Helvetica, sans-serif; padding: 5px 0 10px 5px; } ``` - **利用 CSS 继承**:如果页面中父元素的多个子元素使用相同的样式,将相同的样式定义在其父元素上,让子元素继承这些样式,以减少代码量和便于维护。 ```css /* 优化前 */ #container li { font-family: Georgia, serif; } #container p { font-family: Georgia, serif; } #container h1 { font-family: Georgia, serif; } /* 优化后 */ #container { font-family: Georgia, serif; } ``` - **多重选择器**:使用多重选择器来合并具有相同样式的元素选择器,减少重复代码。 #### JavaScript 部分 - **动画优化**:如果使用了类似 `CSS+HTML+JS立方体旋转展示动画特效` 中的 GSAP 动画库,可检查动画的性能,确保动画的流畅性。可以通过调整动画的帧率、减少不必要的重绘等方式来优化。 - **事件处理优化**:若实现了如 `css3 transform及原生js实现鼠标拖动3D立方体旋转` 中的鼠标拖动功能,要确保事件处理函数的高效性,避免频繁的 DOM 操作。 ### 相关知识获取 - **CSS 3D 变换**:用于创建立方体的 3D 效果,通过 `transform` 属性实现。 - **JavaScript 动画库**:如 GSAP ,可用于创建复杂的动画效果。 - **事件处理**:在 JavaScript 中处理鼠标拖动等事件,实现交互效果。 ### 可能存在的问题及解决办法 - **兼容性问题**:不同浏览器对 CSS 3D 变换和 JavaScript 动画的支持可能不同,可使用浏览器前缀来解决部分兼容性问题。 - **性能问题**:复杂的动画和大量的 DOM 操作可能导致性能下降,可通过优化代码和使用硬件加速(如 `will-change` 属性)来提高性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值