从触摸点获取单个像素

Posted

技术标签:

【中文标题】从触摸点获取单个像素【英文标题】:Getting individual pixels from touch point 【发布时间】:2012-04-04 16:53:15 【问题描述】:

是否可以检测到每个被触摸的像素?更具体地说,当用户触摸屏幕时,是否可以跟踪用户触摸的点簇的所有 x-y 坐标?如何区分用户何时用拇指绘图和何时用指尖绘图?我想根据用户触摸屏幕的方式来反映画笔的差异,并且还想跟踪所有被触摸的像素。

我目前正在使用来自 Apple 开发者网站的 GLPaint 示例中的以下代码:

http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html

示例代码允许使用预定义的画笔大小进行绘图并沿途跟踪 x-y 坐标。如何根据用户触摸屏幕的方式更改画笔并跟踪所有被触摸的像素?

// Drawings a line onscreen based on where the user touches

- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end


     NSLog(@"x:%f   y:%f",start.x, start.y);

     static GLfloat*          vertexBuffer = NULL;

     static NSUInteger     vertexMax = 64;

     NSUInteger               vertexCount = 0,

                    count,

                    i;



     [EAGLContext setCurrentContext:context];

     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);



     // Convert locations from Points to Pixels

     CGFloat scale = self.contentScaleFactor;

     start.x *= scale;

     start.y *= scale;

     end.x *= scale;

     end.y *= scale;



     // Allocate vertex array buffer

     if(vertexBuffer == NULL)

          vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat));



     // Add points to the buffer so there are drawing points every X pixels

     count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);

     for(i = 0; i < count; ++i) 

          if(vertexCount == vertexMax) 

               vertexMax = 2 * vertexMax;

               vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat));

          



          vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);

          vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);

          vertexCount += 1;

     



     // Render the vertex array

     glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);

     glDrawArrays(GL_POINTS, 0, vertexCount);



     // Display the buffer

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

     [context presentRenderbuffer:GL_RENDERBUFFER_OES];




// Handles the start of a touch

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event



     CGRect                    bounds = [self bounds];

     UITouch*     touch = [[event touchesForView:self] anyObject];

     firstTouch = YES;

     // Convert touch point from UIView referential to OpenGL one (upside-down flip)

     location = [touch locationInView:self];

     location.y = bounds.size.height - location.y;



// Handles the continuation of a touch.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

  

     CGRect                    bounds = [self bounds];

     UITouch*               touch = [[event touchesForView:self] anyObject];



     // Convert touch point from UIView referential to OpenGL one (upside-down flip)

     if (firstTouch) 

          firstTouch = NO;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

      else 

          location = [touch locationInView:self];

         location.y = bounds.size.height - location.y;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

     



     // Render the stroke

     [self renderLineFromPoint:previousLocation toPoint:location];





// Handles the end of a touch event when the touch is a tap.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event



     CGRect                    bounds = [self bounds];

    UITouch*     touch = [[event touchesForView:self] anyObject];

     if (firstTouch) 

          firstTouch = NO;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

          [self renderLineFromPoint:previousLocation toPoint:location];

     




// Handles the end of a touch event.

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event



     // If appropriate, add code necessary to save the state of the application.

     // This application is not saving state.


【问题讨论】:

【参考方案1】:

AFAIK 没有 API 可以访问触摸区域进行触摸。考虑到电容式触摸屏的限制,我什至不确定你想要的东西在物理上是否可行。我记得最近在 Cocoa Heads 上的一个演示文稿,其中展示了一些信息在 OS X(通过私有 API)上可用于触控板,但不适用于 iOS。

我相信这是图形输入板采用内置传感器技术的特殊触控笔的原因之一。

对于绘图应用程序,部分解决方法可能是像某些桌面应用程序那样模拟“墨迹书写”:如果用户的触摸停留在给定位置,就好像墨水从“笔”中流出并逐渐扩散一样进行绘制通过“纸”。

【讨论】:

非常感谢您的回复。你知道这在 android 上是否可行吗? 我不知道,抱歉,我不是为 Android 开发的。不过,我相信其他人会有答案。如果您在搜索中找不到任何内容,我建议发布一个标记为 Android 的新问题。【参考方案2】:

iPad 中的 Broadcomm 硬件以 64 Hz 的频率扫描屏幕。它通过在构成触摸屏电极的 39 个透明导电层上连续放置一个信号,每个信号持续 400 µs。如果您的手指在 0.015625 秒内移动了超过一个像素距离,这很可能,硬件无法检测到这一点,因为它正忙于测量屏幕的其他部分以获取更多触摸事件。

无论是 iOS 还是 Android,这都是一样的。廉价的 Android 平板电脑和大屏幕的扫描率较低,因此它们的触摸事件间隔更广。

Wacom 数位板以 100 Hz 的频率运行数字化仪,因此点的顺序会更精细,但仍然会错过触控笔在两次测量之间接触的那些像素。

【讨论】:

以上是关于从触摸点获取单个像素的主要内容,如果未能解决你的问题,请参考以下文章

如何从 SKScene 内部获得触摸时的像素颜色?

在Carto移动SDK中获取触摸的MapTile的x和y像素

iOS WKWebView 从点获取 RGBA 像素颜色

从顶点数据中获取像素法线

将白色像素区域合并为单个区域opencv c ++

OpenGL获取像素的原始3d坐标