The problem of drawing Skia to Skbitmap

Source: Internet
Author: User
Tags skia intel pentium

An issue that cannot be drawn when using Skbitmap as a skcanvas back-end drawing

After compiling Skia on a PC with the Intel Pentium CPU using the default conditions (see compiling Skia from source under Windows), a strange problem was encountered when drawing with Skbitmap as the back end of Skcanvas: " No matter what you draw, it's not the same as painting . "

The code is as follows:

SkImageInfo ii = SkImageInfo::Make(480, 320, kRGBA_8888_SkColorType, kPremul_SkAlphaType);bitmap.allocPixels(ii, ii.minRowBytes());SkCanvas canvas(bitmap);

After experimentation, it is found that the following code can be used to draw success:

SkImageInfo ii = SkImageInfo::Make(480, 320, kBGRA_8888_SkColorType, kPremul_SkAlphaType);bitmap.allocPixels(ii, ii.minRowBytes());SkCanvas canvas(bitmap);

So I think it might be a color type problem. Along the way, for a long time did not understand ... Skcanvas drawing Source, a layer of one layer, looks more difficult ... Didn't look in, the middle detour was achieved by manually converting the pixels of the Skcanvas-drawn skbitmap to Rgba. But if the picture is large, the conversion is slow ... The easy way always has the trouble ...

Skbitmapdevice and Kn32_skcolortype

Bones still have to be chewed. I confirmed the use of Skbitmap as the back end of the Skcanvas, such as the above code, in fact Skcanvas himself assigned a skbitmapdevice to be used as a drawing device, the drawing operation will be submitted to Skbitmapdevice to complete.

Skbitmapdevice checks the Alpha type and color type of the Skbitmap object that was obtained when the drawing device was created with the Skimageinfo property.

Valid_for_bitmap_device () is called inside the constructor of Skbitmapdevice (SkBitmapDevice.cpp), and the Valid_for_bitmap_device () method, Filtered according to the incoming skimageinfo (that is, the Skimageinfo set when the Skbitmap was created), only for Kalpha_8_skcolortype, Krgb_565_skcolortype, kn32_ Skcolortype three color categories created skbitmapdevice, and Kn32_skcolortype==kbgra_8888_skcolortype so, when I set the color to Krgba_8888_skcolortype, The created Skbitmapdevice is not valid, so how to draw is not valid.

The code for Valid_for_bitmap_device () is as follows:

static bool Valid_for_bitmap_device (const skimageinfo& info, skalphatype* newalphat    ype) {if (Info.width () < 0 | | info.height () < 0) {return false;    }//Todo:can We stop supporting Kunknown in Skbitmkapdevice? if (Kunknown_skcolortype = = Info.colortype ()) {if (newalphatype) {*newalphatype = Kunknown_skalphatype        ;    } return true;        } switch (Info.alphatype ()) {case Kpremul_skalphatype:case kopaque_skalphatype:break;    Default:return false;    } Skalphatype Canonicalalphatype = Info.alphatype ();        Switch (Info.colortype ()) {case kalpha_8_skcolortype:break;            Case krgb_565_skcolortype:canonicalalphatype = Kopaque_skalphatype;        Break        Case Kn32_skcolortype:break;    Default:return false;    } if (newalphatype) {*newalphatype = Canonicalalphatype;} return true; 

In addition, according to the above code, only the Kpremul_skalphatype, kopaque_skalphatype two alpha types are processed, so when we give Skbitmap alpha type, if it is other, You cannot create skbitmapdevice successfully.

Now let's see why the default compiled Kn32_skcolortype==kbgra_8888_skcolortype.

Kn32_skcolortype is defined in SkImageInfo.h:

enum SkColorType {    kUnknown_SkColorType,    kAlpha_8_SkColorType,    kRGB_565_SkColorType,    kARGB_4444_SkColorType,    kRGBA_8888_SkColorType,    kBGRA_8888_SkColorType,    kIndex_8_SkColorType,    kGray_8_SkColorType,    kLastEnum_SkColorType = kGray_8_SkColorType,#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)    kN32_SkColorType = kBGRA_8888_SkColorType,#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)    kN32_SkColorType = kRGBA_8888_SkColorType,#else    #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order"#endif};

Kn32_skcolortype is actually a value that is determined by the byte order, and the macro Sk_pmcolor_byte_order used is defined in SkPostConfig.h:

#ifdef SK_CPU_BENDIAN    #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)             (SK_ ## C3 ## 32_SHIFT == 0  &&                      SK_ ## C2 ## 32_SHIFT == 8  &&                      SK_ ## C1 ## 32_SHIFT == 16 &&                      SK_ ## C0 ## 32_SHIFT == 24)#else    #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)         (SK_ ## C0 ## 32_SHIFT == 0  &&                  SK_ ## C1 ## 32_SHIFT == 8  &&                  SK_ ## C2 ## 32_SHIFT == 16 &&                  SK_ ## C3 ## 32_SHIFT == 24)#endif

Because my host is a small endian, Sk_pmcolor_byte_order is:

    #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)         (SK_ ## C0 ## 32_SHIFT == 0  &&                  SK_ ## C1 ## 32_SHIFT == 8  &&                  SK_ ## C2 ## 32_SHIFT == 16 &&                  SK_ ## C3 ## 32_SHIFT == 24)

This macro also uses the Sk_a32_shift, Sk_r32_shift, Sk_g32_shift, sk_b32_shift three macros. Analysis SkPostConfig.h that the values of these three macros are defined here at the default compile time:

#ifdef SK_BUILD_FOR_WIN#  ifndef WIN32_LEAN_AND_MEAN#    define WIN32_LEAN_AND_MEAN#    define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED#  endif#  ifndef NOMINMAX#    define NOMINMAX#    define NOMINMAX_WAS_LOCALLY_DEFINED#  endif##  include <windows.h>##  ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED#    undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED#    undef WIN32_LEAN_AND_MEAN#  endif#  ifdef NOMINMAX_WAS_LOCALLY_DEFINED#    undef NOMINMAX_WAS_LOCALLY_DEFINED#    undef NOMINMAX#  endif##  ifndef SK_A32_SHIFT#    define SK_A32_SHIFT 24#    define SK_R32_SHIFT 16#    define SK_G32_SHIFT 8#    define SK_B32_SHIFT 0#  endif##endif

Sk_a32_shift=24, Sk_r32_shift=16, sk_g32_shift=8, sk_b32_shift=0, so SkImageInfo.h, Sk_pmcolor_byte_order (B,G,R,A) Expand as follows:

SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && SK_A32_SHIFT == 24

The value of this expression is true, so kn32_skcolortype==kbgra_8888_skcolortype.

I want to use krgba_8888_skcolortype, I need to modify the Sk_a32_shift, Sk_r32_shift, Sk_g32_shift, sk_b32_shift at compile time the values of the three macros are as follows:

SK_A32_SHIFT=24SK_B32_SHIFT=16SK_G32_SHIFT=8SK_R32_SHIFT=0

This compiles the library, Kn32_skcolortype==krgba_8888_skcolortype.

There are two ways.

      1. Modifying variables such as cflags before compiling

Before generating the Ninja compilation script, execute the following command in Cmd.exe:

  set "CFLAGS=-DSK_A32_SHIFT=24 -DSK_B32_SHIFT=16 -DSK_G32_SHIFT=8 -DSK_R32_SHIFT=0"  set "CPPFLAGS=-DSK_A32_SHIFT=24 -DSK_B32_SHIFT=16 -DSK_G32_SHIFT=8 -DSK_R32_SHIFT=0"  set "CXXFLAGS=-DSK_A32_SHIFT=24 -DSK_B32_SHIFT=16 -DSK_G32_SHIFT=8 -DSK_R32_SHIFT=0"

When this is compiled, the skbitmapdevice is kn32_skcolortype==krgba_8888_skcolortype when validating the color type, The Skimageinfo color type of the skbitmap we pass is Krgba_8888_skcolortype, and the drawing device can be created successfully. However, Skbitmap as Skcanvas's back-end drawing device to use Kbgra_8888_skcolortype's color type is not.

It is also important to note that because the values of the Sk_a32_shift, Sk_r32_shift, Sk_g32_shift, and Sk_b32_shift three macros passed through Cflags at compile time, are not recorded in the header file, so when using Skia headers, Detection of Sk_a32_shift, Sk_r32_shift, Sk_g32_shift, sk_b32_shift or wrong, Kn32_skcolortype is also wrong ha. To avoid the pitfalls, set the values for the three macros in the VS project and compile-time consistent.

      1. Modify SkUserConfig.h

If you do not want to modify Sk_a32_shift, Sk_r32_shift, Sk_g32_shift, sk_b32_shift at compile time through environment variables, you can also modify SkUserConfig.h (within the Include\config directory). In this case, the changes are also recorded, because the SkTypes.h order contains SkPreConfig.h, SkUserConfig.h, SkPostConfig.h, where the changes are valid, but also save the setup vs project. A description of this file is available in SkUserConfig.h.

Red and blue channels are reversed when decoding a picture

After solving the problem, the new problem comes again: red and blue channel are reversed when decoding the image.

(⊙o⊙) ... We have to keep fighting.

Bite the bullet to read a half-day source, to PNG for example, didn't find how to go back. Later all want to use the following method to bypass: The decoded image data per pixel R, b Exchange.

Always want to take the easy way.

Then hard experiment, to see SkImageDecoder.cpp, Skimagedecoder_libpng.cpp, all over the sky add log information to view the creation process of the picture decoder, spent a day more time, finally understand the problem there (see Skia Image codec Module analysis ):

Although I have defined the Sk_a32_shift, Sk_r32_shift, Sk_g32_shift, Sk_b32_shift, the Kn32_skcolortype adjusted over, so skbitmapdevice can create Krgba_ 8888_skcolortype format of the drawing device, but the above three macros, and can not affect the image decoding, because the decoder is using the Windows Platform COM components, not affected by these three macros, the default decoding is Bgra (see SKIMAGEDECODER_WIC: :d Ecodestream method)!

So, had to analyze the decoder selection process, only the Skia picture codec module Analysis , found PNG, GIF, JPEG and so on did not compile. It would be nice to compile them in.

There are two ways:

    • Modify the Out\release\obj\gyp\images.ninja file directly and add the CPP file of the relevant decoder
    • Modify the Skia\gyp\images.gyp to change the conditions under win platform

I used the first kind of, hard to add PNG, and encountered a variety of mistakes, and then change, somehow came over ... skia\gyp\ Images.gyp said that the compilation sequence will affect the decoder selection, so, add in also not, finally had to directly call Createpngimagedecoder such methods, useless Skimagedecoder::D ecodexxx.

Now look at the second kind should be better, skia build system will handle all kinds of dependencies, but also can use a unified Skimagedecoder interface, but because of personal special needs to pollute the Skia compiled script ...

That's it.

Other reference articles are described in my column: "CEF and Ppapi development ".

The problem of drawing Skia to Skbitmap

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.