IOS draws 1-pixel lines

Source: Internet
Author: User
Tags uikit

First, point Vs Pixel

In iOS, when we use frames such as quartz,uikit,coreanimation, all coordinate systems are measured by point. The system will help us deal with point-to-pixel conversions when actually rendering to settings.

The benefits of doing so isolate the change, i.e. we do not need to focus on whether the current device is retina after the layout, and can be laid out directly in a set of coordinate systems.

In practice we need to keep this in mind:

One point does isn't necessarily correspond to one physical pixel.

A line of 1 point on a non-retina screen is a pixel, which may be 2 or 3 on the Retina screen, depending on the DPI of the system device.

On iOS systems, the Uiscreen,uiview,uiimage,calayer class provides properties to get the scale factor.
Native rendering techniques naturally help us with scale factor, for example, in the DrawRect: method, Uikit automatically sets the tangent scale factor based on the currently running device. So the drawrect: anything drawn in the method will be automatically scaled to the physical screen of the device.

Based on the above information, we can see that we do not need to pay attention to pixel in most cases, but some cases need to consider the conversion of pixels.

For example, draw a 1-pixel split Line

The first idea you'll see is that you can calculate the point of a 1-pixel line directly based on the zoom factor of the current screen, and then set the line width.
The code is as follows:

1.0f /[UIScreen Mainscreen].scale

On the surface it looks normal, but with the actual device testing you will find that the rendered line width is not 1 pixels.

For good visuals, the drawing system usually uses a technique called antialiasing (anti-aliasing), and iOS is no exception.
The display screen has a lot of small display units, which can be understood as a single unit that represents a pixel. If you want to draw a black line, the lines just fall in a column or a row of display cells, will render a standard one pixel black line.
But if the line falls in the middle of two rows or columns, you get a "distorted" line, which is actually two pixels wide gray line.

As shown in the following:

if you draw a one-pixel-wide vertical line from (1.01.0) to (1.010.0get  get in even numbers of physical pixels unless-adjust their position to make them cover pixels fu Lly.

As an official explanation, simply translate:

Rule: An odd pixel width line will appear as a soft width extension to an upward integer width line at render time, unless you manually adjust the position of the line so that the line falls exactly within the row or column of the display unit.

How to align it?

On a low-resolution display (with a scale factor of1.0), a one-point-wide line isOne pixel wide. To avoid antialiasing if you draw a one-point-wide horizontal or vertical line,ifThe line isAn odd number of pixelsinchwidth, you must offset the position by0.5Points to either side of a whole-numbered position. If the line isAn even number of pointsinchwidth, to avoid a fuzzy line, you must not DoSo . On a high-resolution display (with a scale factor of2.0), a line that isOne point wide isNot antialiased @ all because it occupies---0.5to +0.5). To draw a line this covers only a single physical pixel, you would need to make it0.5Pointsinchthickness and offset its position by0.25Points. A comparison between the types of screens isShowninchFigure1-4.

Translate a bit

On a non-HD screen, a point corresponds to one pixel. To prevent distortion in the odd-pixel line rendering caused by "antialiasing", you need to set an offset of 0. 5 Point . On the HD screen, to draw a pixel line, you need to set the line width to 0.5 point, and the colleague set the offset to 0.  - Point . If the line width is even point, do not set the offset, or the line will be distorted. 

As shown in the following:

Read the above explanation, we understand the 1 pixel wide line distortion reasons, and solutions.
So the problem seems to have been solved? Think about why the position value is different on the non-retina and retina screens, the former is 0.5Point and the latter is 0.25Point, so how much is the 6 Plus device with scale 3?
To answer this question, we need to understand the principle of how much adjustment remains.

Looking back at the picture above, each of the squares in the picture represents a pixel, and the top tag is the coordinates of the code we are laying out.
You can see the non-Retina screen on the left, we want to draw a vertical line at this position (3,0), because the smallest unit of the rendering is pixels, and (3,0) This coordinate is located in the middle of two pixels, the system will be around the coordinates 3 of the two columns of pixels to fill, in order not to appear too wide, Fades the color of the line. So, based on the above information, we can conclude that if you want to draw a line with a wide pixel width, you have to move the plotted coordinates to (2.5, 0) or (3.5,0) This position, so that the system renders exactly one column of pixels, which is the standard one-pixel line.

Based on the above analysis, we can draw a "scale of 3 6 Plus" device if you want to draw 1 pixel-wide lines, the position adjustment should also be 0.5 pixels, the point should be calculated as follows:

(1.0f2;

A macro that draws a pixel line:

#define Single_line_width           (1/[UIScreen mainscreen].scale)#define Single_line_adjust_offset   ((1/[ UIScreen Mainscreen].scale)/2)

Use the following code:

50)];

Second, the correct drawing grid lines

Paste the code of the GridView, which offsets the odd pixels of the grid lines to prevent the blurring of lines.

SvGridView.h

////SvGridView.h//Svsinglepixel////Created by Xiaoyong.cxy on 6/23/15.//Copyright (c) smileevday. All rights reserved.// #import< uikit/uikit.h>@interfaceSvgridview:uiview/** * @brief grid spacing, default*/@property (nonatomic, assign) cgfloat gridspacing;/** * @brief grid line width, default is 1 pixel (1.0f/[UIScreen Mainscreen].scale)*/@property (nonatomic, assign) cgfloat gridlinewidth;/** * @brief grid color, default blue*/@property (nonatomic, strong) Uicolor*Gridcolor;@end

svgridview.m

////svgridview.m//Svsinglepixel////Created by Xiaoyong.cxy on 6/23/15.//Copyright (c) smileevday. All rights reserved.// #import" svgridview.h"#defineSingle_line_width (1/[UIScreen Mainscreen].scale)#defineSingle_line_adjust_offset ((1/[UIScreen Mainscreen].scale)/2)@implementationSvgridview@synthesizeGridcolor =_gridcolor;@synthesizeGridspacing =_gridspacing;-(Instancetype) initWithFrame: (cgrect) frame{ Self=[Super Initwithframe:frame]; if(self) {Self.backgroundcolor=[Uicolor Clearcolor]; _gridcolor=[Uicolor Bluecolor]; _gridlinewidth=Single_line_width; _gridspacing= -; }     returnSelf ;} - (void) Setgridcolor: (Uicolor *) gridcolor{_gridcolor=Gridcolor; [Self setneedsdisplay];} - (void) Setgridspacing: (cgfloat) gridspacing{_gridspacing=gridspacing; [Self setneedsdisplay];} - (void) Setgridlinewidth: (cgfloat) gridlinewidth{_gridlinewidth=Gridlinewidth; [Self setneedsdisplay];} //Only override Drawrect:if perform custom drawing.//An empty implementation adversely affects performance during animation.- (void) DrawRect: (cgrect) rect{cgcontextref context=Uigraphicsgetcurrentcontext ();    Cgcontextbeginpath (context); CGFloat Linemargin=self.gridspacing; /**     *  https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/ Graphicsdrawingoverview/graphicsdrawingoverview.html* The drawing position needs to be adjusted only if the line width you want to draw is an odd pixel*/cgfloat Pixeladjustoffset=0; if(((int) (Self.gridlinewidth * [UIScreen Mainscreen].scale) +1) %2==0) {Pixeladjustoffset=Single_line_adjust_offset; } cgfloat XPos= Linemargin-Pixeladjustoffset; CGFloat YPos= Linemargin-Pixeladjustoffset;  while(XPos < self.bounds.size.width) {Cgcontextmovetopoint (context, XPos,0);        Cgcontextaddlinetopoint (context, XPos, self.bounds.size.height); XPos+=Linemargin; }      while(YPos < self.bounds.size.height) {Cgcontextmovetopoint (context,0, YPos);        Cgcontextaddlinetopoint (context, self.bounds.size.width, YPos); YPos+=Linemargin;    } cgcontextsetlinewidth (context, self.gridlinewidth);    Cgcontextsetstrokecolorwithcolor (context, self.gridColor.CGColor); Cgcontextstrokepath (context);} @end

Here's how to use it:

Svgridview *gridview == Uiviewautoresizingflexiblewidth |  0.6= [Uicolor greencolor];[ Self.view Addsubview:gridview];

IOS draws 1-pixel lines

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.