Custom multi-style QR code

Source: Internet
Author: User

Label:

Reprinted from: http://sindrilin.com/ios-dev/2015/10/26/custom multi-style QR code

The QR Code/barcode is a black-and-white graphic record symbol information distributed in the platform (one-dimensional/two-dimensional direction) according to a certain geometric pattern. A number of geometric shapes corresponding to the binary are used to represent literal numeric information.


The most common QR code features include information acquisition, website Jump, e-commerce transaction, mobile phone payment and so on, it has the advantages of small density, large information capacity, strong fault tolerance, low cost, difficult to make. In mobile development, the status of two-dimensional code is becoming more and more important, mastering the basic operation of QR code is one of the important skills.

After IOS7, Apple itself integrates the generation and reading of the QR code. Generating a QR code consists of the following steps

    • Import coreimage/coreimage.h Header File

    • Using the Cifilter filter class to generate two-dimensional code

    • Process the generated QR code to make it clearer

In addition to the above three steps, we can further expand the two-dimensional code to deal with

    • Custom two-dimensional code pattern color

    • Insert fillet small picture in center of QR code

    • Add a rounded white picture below the rounded picture

Two-dimensional code generation

The code farmers to produce code at the same time never forget to reuse as much as possible, then in order to achieve this goal, the text of this article through the category extension UIImage method to complete. We first declare and implement a class method to receive two-dimensional code to store data and two-dimensional code size of the method:

+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress codeSize: (CGFloat)codeSize {    if (!networkAddress|| (NSNull *)networkAddress == [NSNull null]) {          return nil;       }    codeSize = [self validateCodeSize: codeSize];      CIImage * originImage = [self createQRFromAddress: networkAddress];    UIImage * result = [UIImage imageWithCIImage: originImage];      return result;}

In the above code, we have done four things: Verify the validity of the stored information, verify the size of the two-dimensional code reasonable size; Use stored information to generate two-dimensional code; turn the QR code into uiimage return. The implementations of these methods are as follows:

/*!    Verify QR code size legitimacy */+ (cgfloat) Validatecodesize: (cgfloat) codesize{codesize = MAX (codesize);    Codesize = MIN (Cgrectgetwidth ([UIScreen mainscreen].bounds)-N, Codesize); return codesize;} /*! Using system filters to generate a two-dimensional code map */+ (Ciimage *) createqrfromaddress: (NSString *) networkaddress{nsdata * StringData = [networkaddress DataU    Singencoding:nsutf8stringencoding];    Cifilter * Qrfilter = [Cifilter filterwithname: @ "Ciqrcodegenerator"];    [Qrfilter setvalue:stringdata Forkey: @ "InputMessage"];    [Qrfilter SetValue: @ "H" Forkey: @ "Inputcorrectionlevel"]; return qrfilter.outputimage;} /!    Verify QR code size legitimacy/-(CGFloat) Validatecodesize: (cgfloat) codesize{codesize = MAX (codesize);    Codesize = MIN (Cgrectgetwidth ([UIScreen mainscreen].bounds)-N, Codesize); return codesize;} /! Using system filters to generate a two-dimensional code map/-(Ciimage *) createqrfromaddress: (NSString *) networkaddress{nsdata * StringData = [networkaddress dataUs    Ingencoding:nsutf8stringencoding]; Cifilter * Qrfilter = [Cifilter filterwithname: @ "CIqrcodegenerator "];    [Qrfilter setvalue:stringdata Forkey: @ "InputMessage"];    [Qrfilter SetValue: @ "H" Forkey: @ "Inputcorrectionlevel"]; return qrfilter.outputimage;}

PS: for Cifilter to learn more, you can use shortcut keys shift+command+0 Open a document in Xcode, and then search the core Image filter reference for more filters to use, These filters can be used to implement similar 美图秀秀-like mapping functions.

The code above generates a rough two-dimensional code diagram, and we need to process the image again to make it clearer. Because, we need another type of method:

/! Clear image Processing/-(UIImage *) Excludefuzzyimagefromciimage: (Ciimage *) image size: (cgfloat) size{cgrect extent = Cgrectinteg    RAL (image.extent);    CGFloat scale = MIN (Size/cgrectgetwidth (extent), size/cgrectgetheight (extent));     size_t width = cgrectgetwidth (extent) * scale;    size_t height = cgrectgetheight (extent) * scale;    Create grayscale tone space cgcolorspaceref colorspace = Cgcolorspacecreatedevicegray ();    Cgcontextref bitmapref = cgbitmapcontextcreate (nil, width, height, 8, 0, ColorSpace, (Cgbitmapinfo) kcgimagealphanone);    Cicontext * context = [Cicontext Contextwithoptions:nil];    Cgimageref bitmapImage = [context createcgimage:image fromrect:extent];    Cgcontextsetinterpolationquality (Bitmapref, Kcginterpolationnone);    CGCONTEXTSCALECTM (bitmapref, scale, scale);    Cgcontextdrawimage (Bitmapref, extent, bitmapImage);    Cgimageref scaledimage = Cgbitmapcontextcreateimage (bitmapref);    Cgcontextrelease (BITMAPREF);    Cgimagerelease (BitmapImage); Cgcolorspacerelease (cOlorspace); return [UIImage imagewithcgimage:scaledimage];}

So at this point, we +(UIImage *)imageOfQRFromURL: codeSize: change the final

UIImage * result =[self excludeFuzzyImageFromCIImage: originImage size: codeSize];

The QR code generated after the sample is completed is as follows:

Two-dimensional code development

A single black-and-white QR code does not always meet the needs of development or the need for leadership. Like today's application many functional interfaces are moving toward learning, which includes more color, more style of QR code. This article will start with the color, QR Code Center small pattern two points to explain how to make similar to generate my QR code style.

The idea of customizing the color of the two-dimensional code is to traverse the pixel points of the generated QR code, fill the pixels with the white color as transparent, and non-white to fill in our custom colors. However, the white here does not mean only pure white, RGB values above a certain number of gray we can also be considered as white processing. Here I define white as the RGB value above 0xd0d0d0 The color value is white, this value is not OK, you can set their own. Based on the color setting, we changed the method interface of the original generation of the QR code to this:

 + (UIImage *) Imageofqrfromurl: (NSString *) networkaddress codesize: ( CGFloat) Codesize Red: (Nsuinteger) Red Green: (Nsuinteger) Green Blue: (Nsuinteger) Blue {if (!networkaddress | |    (NSNull *) networkaddress = = [NSNull null]) {return nil;}    /** color can not be too close to white */nsuinteger RGB = (red << +) + (green << 8) + blue; Nsassert ((RGB & 0xffffff00) <= 0xd0d0d000, @ "The color of the QR code is both close to white color than it'll diffcult    Y to scan ");     Codesize = [self validatecodesize:codesize];    Ciimage * Originimage = [self createqrfromaddress:networkaddress];      UIImage * Progressimage = [self excludefuzzyimagefromciimage:originimage size:codesize]; Here, the QR code is ready to be scanned. UIImage * Effectiveimage = [self imagefillblackcolorandtransparent:progressimage red:red green:gr  Een blue:blue]; Color rendering after the QR code return effectiveimage;}  

Compared to the previous code, two more steps: Determine the valid values of RGB , color rendering of the QR code. The process of color rendering involves getting the image's bitmap context, pixel substitution, binary image conversion, and so on, with the following code:

/*! Color fill the generated QR code image */+ (UIImage *) Imagefillblackcolorandtransparent: (UIImage *) image red: (Nsuinteger) Red Green: (  Nsuinteger) Green Blue: (Nsuinteger) Blue {const int imagewidth = Image.size.width;  const int imageheight = Image.size.height;  size_t Bytesperrow = imagewidth * 4;  uint32_t * Rgbimagebuf = (uint32_t *) malloc (Bytesperrow * imageheight);  Cgcolorspaceref colorspace = Cgcolorspacecreatedevicergb (); Cgcontextref context = Cgbitmapcontextcreate (Rgbimagebuf, ImageWidth, ImageHeight, 8, Bytesperrow, ColorSpace, Kcgbitmapbyteorder32little |  Kcgimagealphanoneskiplast); Cgcontextdrawimage (context, (CGRect) {(Cgpointzero), (image.size)}, image.  Cgimage);  Traverse pixel int pixelnumber = ImageHeight * imagewidth;  [Self fillwhitetotransparentonpixel:rgbimagebuf pixelnum:pixelnumber red:red green:green Blue:blue];  Cgdataproviderref Dataprovider = Cgdataprovidercreatewithdata (NULL, Rgbimagebuf, Bytesperrow, ProviderReleaseData); Cgimageref imageref = cgimagecreate (ImageWidth, Imageheight, 8, Bytesperrow, ColorSpace, Kcgimagealphalast |  Kcgbitmapbyteorder32little, Dataprovider, NULL, True, Kcgrenderingintentdefault);   UIImage * Resultimage = [UIImage imagewithcgimage:imageref];  Cgimagerelease (IMAGEREF);  Cgcolorspacerelease (ColorSpace);  Cgcontextrelease (context); return resultimage;} /! Traverse all pixels for color substitution/+ (void) Fillwhitetotransparentonpixel: (uint32_t *) rgbimagebuf pixelnum: (int) Pixelnum red: (Nsuinteger Red Green: (Nsuinteger) Green Blue: (Nsuinteger) Blue {uint32_t * pcurptr = rgbimagebuf;for (int i = 0; i < pixelnum; i+           +, pcurptr++) {if ((*pcurptr & 0xffffff00) < 0xd0d0d000) {uint8_t * ptr = (uint8_t *) pcurptr;           PTR[3] = red;           PTR[2] = green;        PTR[1] = blue;           } else {//turns white into transparent color uint8_t * ptr = (uint8_t *) pcurptr;        Ptr[0] = 0; }}}void providerreleasedata (void * info, const void * data, size_t size) {free (void *) data);}

PS: Before you modify the code, you should be aware of whether you need to delete the old code. Similar to this two-dimensional code extension, the old QR code generation interface can be left, and then invoke the multi-parameter All-in-one constructor Designated Initializer .

At this time the distance is a small step, we want to in the center of the QR code to insert our little avatar, the most direct way is to load up our avatar, the direct drawInRect: implementation of this method is correct, but before we draw, we also need to fillet image processing. (It may be easy to imageView load the avatar directly, then set the Avatar cornerRadius , this can also achieve the effect).

By this time, we need a more parameter of the two-dimensional code generation method interface, this time the new parameters should include inserting pictures, fillet radius These parameters, so the method is as follows:

+ (UIImage *) Imageofqrfromurl: (NSString *) networkaddress codesize: (cgfloat) codesize red: (Nsuinteger) Red Green: ( Nsuinteger) Green Blue: (Nsuinteger) Blue insertimage: (UIImage *) insertimage Roundradius: (cgfloat) Roundradius {if (!ne tworkaddress | |    (NSNull *) networkaddress = = [NSNull null]) {return nil;}    /** color can not be too close to white */nsuinteger RGB = (red << +) + (green << 8) + blue; Nsassert ((RGB & 0xffffff00) <= 0xd0d0d000, @ "The color of the QR code is both close to white color than it'll diffcult    Y to scan ");    Codesize = [self validatecodesize:codesize];    Ciimage * Originimage = [self createqrfromaddress:networkaddress];      UIImage * Progressimage = [self excludefuzzyimagefromciimage:originimage size:codesize]; Here, the QR code is ready to be scanned. UIImage * Effectiveimage = [self imagefillblackcolorandtransparent:progressimage red:red green:gr  Een blue:blue]; Two-dimensional code after color rendering return [self imageinsertedimage:effectiveimage insertimage:insertimage Radius:roundrAdius];} 

This generation method also only need to do an extra call method operation, when inserting the picture we need to note that similar to the figure in the middle of the image of the small head is a rounded white edge, the addition of this edge to let the avatar display more natural. So to do this, I added a small white background to the project, the same image is rounded, and then added under the avatar. The size of the white background image below the avatar should be larger than the avatar figure. The specific implementation of the PIP effect is as follows:

/! Insert the fillet image in the center of the two-dimensional code/+ (UIImage *) Imageinsertedimage: (UIImage *) originimage insertimage: (UIImage *) insertimage radius: (    CGFloat) radius{if (!insertimage) {return originimage;}    Insertimage = [UIImage imageofroundrectwithimage:insertimage size:insertImage.size Radius:radius];    UIImage * WHITEBG = [UIImage imagenamed: @ "WHITEBG"];    WHITEBG = [UIImage imageofroundrectwithimage:whitebg size:whiteBG.size Radius:radius];    White edge Width const cgfloat whitesize = 2.F;    Cgsize brinksize = Cgsizemake (ORIGINIMAGE.SIZE.WIDTH/4, ORIGINIMAGE.SIZE.HEIGHT/4);    CGFloat brinkx = (originimage.size.width-brinksize.width) * 0.5;    CGFloat brinky = (originimage.size.height-brinksize.height) * 0.5;    Cgsize imageSize = Cgsizemake (brinksize.width-2 * whitesize, brinksize.height-2 * whitesize);    CGFloat ImageX = brinkx + whitesize;    CGFloat imagey = Brinky + whitesize;    Uigraphicsbeginimagecontext (originimage.size); [Originimage drawinrect: (cgrect) {0, 0, (Originimage.size)}];    [WHITEBG drawinrect: (cgrect) {brinkx, Brinky, (Brinksize)}];    [Insertimage drawinrect: (cgrect) {ImageX, Imagey, (ImageSize)}];    UIImage * resultimage = Uigraphicsgetimagefromcurrentimagecontext ();    Uigraphicsendimagecontext (); return resultimage;} -(UIImage *) Imageofroundrectwithimage: (UIImage *) image size: (cgsize) Size radius: (cgfloat) radius{if (!image) {Retu RN Nil;    } Const CGFloat width = size.width;    Const cgfloat height = size.height;    Radius = MAX (5.f, RADIUS);    Radius = MIN (10.f, RADIUS);     UIImage * img = image;    Cgcolorspaceref colorspace = Cgcolorspacecreatedevicergb (); Cgcontextref context = Cgbitmapcontextcreate (NULL, width, height, 8, 4 * width, colorspace, Kcgimagealphapremultipliedfir    ST);    CGRect rect = CGRectMake (0, 0, width, height);    Draw rounded corners Cgcontextbeginpath (context); Addroundrecttopath (context, rect, Radius, img.    Cgimage);    Cgimageref imagemasked = cgbitmapcontextcreateimage (context); IMG = [UIImage iMagewithcgimage:imagemasked];    Cgcontextrelease (context);    Cgcolorspacerelease (ColorSpace);    Cgimagerelease (imagemasked); return img;}

PS: The image is drawn with rounded corners by drawing the path of the rounded rectangle in the context of the image and then cropping it so that the rounded corners of the picture can be achieved.

In the code, the central position of the Avatar is limited to One-fourth of the size of the two-dimensional code, the size of the avatar without loss of clarity, and the image size will not obscure the two-dimensional code storage data. The methods above can be used in the development of the method interface in the header file, which will enable the reuse of the code. In addition, all of the interfaces written in this article to generate the QR code should be declared in the header file, and the Almighty method should be called in its implementation (it should not be just the principle that the constructor should follow Designated Initializer ):

+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress {    return [self imageOfQRFromURL: networkAddress codeSize: 100.0f red: 0 green: 0 blue: 0 insertImage: nil roundRadius: 0.f];}

Custom multi-style QR code

Related Article

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.

Tags Index: