Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development Knowledge Base

by BlackBerry Development Advisor on ‎09-20-2012 11:46 AM (6,649 Views)

This article will demonstrate how to transfer the image data from a skDevice (ex.:  a SkBitmap object) to cascades::image so that it can be displayed at UI. Also, this article will demonstrate some basic functionalities of the Skia lib:

 

    • Loading image data into a SkBitmap object from an image file.           
    • Drawing some Skia primitives (for example: drawing circle, drawing rect, and drawing text) on a Canvas
    • Drawing a bitmap on another bitmap.
    • Scale an image

Please note that the main focus of this article will not be showing how to use Skia library itself. For this, please refer to the Skia on BlackBerry® GitHub®:

https://developer.blackberry.com/native/beta/documentation/graphics.html#skia

 

Also, although there is a  pre-built Skia lib shipped with the BlackBerry® 10 Native SDK (10.0.6.545), it is intended to be used only by the OS itself. we need to build the Skia lib from source code so that we can use Skia lib in our Application. ( See

How to build the Source Code for details.)

 

These steps represent a typical procedure for drawing graphics using Skia Lib:

 

    1. Initialize a SKDevice. ( ex.: SkBitmap. The skBitmap uses a memory block (buffer) to represent the pixels of an image. The SkBitmap can be initized as a blank image or an image from a file.)
    2. Prepare a Canvas, e.g.: SkCanvas. A SkCanvas will be created on a SkDevice.
    3. Draw on a Canvas
    4. Transfer the drawing result from the skDevice to a cascades::image for display.

 

The SkiaImageScratchPad application(see the attachment) follows what QImageScratchPad does to use SkBitmap and SkCanvas as a “scratchpad” to prepare an image to be displayed in cascades.

 

http://supportforums.blackberry.com/t5/Cascades-Development-Knowledge/Using-QImage-and-QPainter-to-Prepare-a-cascades-Image/ta-p/1809841

 

Thereby, the UI and code organization are similar as that of QImageScratchPad.In this article. We will only focus on the differences between the drawing mechanism of Skia Lib and that of QImage/Qpainter.

 

When drawing vector graphic using Skia Lib, SkBitmap is an object users often need to use. For example, loading image file into an SkBitmap so that it can be further processed, drawing on it or drawing this image on another image. Let's first look at how to load an image file into a SkBitmap object.

 

Loading an asset image into a SkBitmap

 

A png file can be loaded into a SkBitmap object by using SkImageDecoder.

(SkImageDecoder is also able to load an image file in other formats into SkBitmap, please refer to Skia documentation for details.)

 

    

 SkBitmap tempImage;
 QString where = getImagePath(url);
 SkImageDecoder::DecodeFile(where.toUtf8().constData(), &tempImage);

 

 

Manipulating SkBitmap using SkCanvas and SkPainter.

 

We can not directly manipulate a SkBitmap object which can be initialized with an image file or a blank image.

A SkBitmap object has to be used as a SkDevice to create SkCanavas object; then, all the drawings on the SkCanvas object will be reflected on the underlying SkBitmap object. 

 

For example:

drawing circles, drawing texts, drawing a rect, or even drawing a bitmap on the canvas.

 

Also, when drawing a object (ex: circle) on the Canvas, we have to use a SkPainter object to define the drawing attributes.

 

Drawing circle:

 

Prepare a Canvas:

 

SkBitmap image;

// Create an image of the appropriate size.
// The underlying data is reference counted so is cleaned up as needed.
image.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
image.allocPixels();
image.eraseColor(0);

SkCanvas canvas(image);

 

 Prepare the paint:

 

SkPaint myPaint;
myPaint.setAntiAlias(true);
myPaint.setStyle(SkPaint::kStroke_Style);
myPaint.setColor(SK_ColorYELLOW);
myPaint.setStrokeWidth(SkIntToScalar(3));

 

 Fill the  background and draw the circle:

 

//fill the background
canvas.drawColor(SK_ColorBLUE);

//draw circle
canvas.drawCircle(centerX, centerY, radius, myPaint);

 

Drawing Text:

When drawing text, we need to prepare the paint (e.g. text font, text size, text color, etc.) before we can draw the text itself.

 

SkPaint textPaint;
SkTypeface* myFont = SkTypeface::CreateFromName(NULL/*default font*/,SkTypeface::kBold);
textPaint.setTypeface(myFont);
textPaint.setAntiAlias(true);
textPaint.setTextSize(SkIntToScalar(12));
textPaint.setColor(SK_ColorYELLOW);
textPaint.setTextAlign(SkPaint::kCenter_Align);

canvas.drawText("OK", 2, centerX, centerY, textPaint);

 

 

 

Drawing a square:

Drawing square is similar as drawing other primitives, e.g. prepare paint and draw the primitive.

 

 

SkPaint myPaint;
myPaint.setAntiAlias(true);
myPaint.setColor(SK_ColorYELLOW);

SkRect rect;
//Left, Top, Right, Bottom
rect.set(centerX - w / 2, centerY - h / 2, centerX + w / 2,
			centerY + h / 2);

canvas.drawRect(rect, myPaint);

 

Scaling a image:

Scaling an image is not straightforward.

First, we need to prepare a canvas ( e.g. create it on a blank target bitmap with desired size) and set its scale factor. All the later drawings (primitives or a bitmap) on this Canvas will be scaled.

 

Note: in the following example code, "replicant" is a SKBitmap (image to be scaled):

 

 

//scale is not straightforward.
//we have to setup the scaled bitmap.
//then draw the original bitmap to the scaled canvas
SkBitmap dst;
dst.setConfig(replicant.config(), desiredReplicantSize.width(),
			desiredReplicantSize.height());
dst.allocPixels();
dst.eraseColor(0);

SkCanvas replicantCanvas(dst);

replicantCanvas.scale(
		float(desiredReplicantSize.width()) / float(replicant.width()),
		float(desiredReplicantSize.height())
						/ float(replicant.height()));

replicantCanvas.drawBitmap(replicant, 0, 0, NULL);

 

 

Create a Cascades::image object from a SkBitmap object.

 

A SkBitmap object has an internal buffer to contain the pixel data. The way the pixel data is packaged depends on the SkBitmap object's configuration.

In this example, we will use SkBitmap::kARGB_8888_Config, which is equivalent to QImage::Format_ARGB32_Premultiplied. In your applicaton, you can convert  the configuration of the skBitmap object to be SkBitmap::kARGB_8888_Config using

 

 SkBitmap::copyTo(SkBitmap* dst, Config c, Allocator* allocator = NULL).

 

 

In this example code, we will demonstrate how to convert the data from an intermal memory buffer within a SkBitmap to the format defined by PixelBufferData::RGBX, which can be used by cascades::image.

 

The code below was borrowed from qt for doing rgb swap operation.

 

       //original skbitmap pixels are organized as ARGB
       //((*p << 16) & 0xff0000), we get  -B--
       //((*p >> 16) & 0xff),  we get     ---R
       //(*p & 0xff00ff00), we get        A-G-
       // combine all of them, we get ABGR

       *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);

 

With this operation, the memory buffer is ready to be used for contructring a bb::cascades::smileytongue:ixelBufferData object.

 

 

How to build the Source Code:

 

The attached file contains the SkiaImageScratchPad source code.

 When this app was written, the pre-built Skia lib shipped with the BlackBerry 10 Native SDK (10.0.6.545) is intended to be used only by OS.  We will have to build Skia lib from source code and bundle it together with our application, e.g.: overriding the skia lib shipped with the OS on the target.

 

Steps to build the attached sample:

1) Download skia  source code from: https://github.com/blackberry/Skia

2) Add the skia eclipse project to your workspace.

3) Download the attached sample project code.

   Note: the Skia source code and the application source code shall be located side by side. e.g.:  the app source code shall be extracted under the same  directory where the skia lib source code is located.

    e.g.:   ./Skia ,   ./skiaimage  

     

4) Add the SkiaImageScratchPad to your workspace.

 

5) build the skia lib

 

6) build SkiaImageScratchPad code 

 

Note:  make sure to build the Skia lib and SKiaImageScratchPad using same build configuration

 

 

The skiaimagescratchpad.pro  file and the bar-descriptor.xml within the source code have been modified so that the built Skia lib can be linked properly and  bundled together with the app.

It assumes that the source code of skia lib and the source code of this app are located side by side. If you prefer to organize the skia lib source code and your project source code differently, you can refer the following KB:

               How to use a third party shared or static library in a Cascades C++ project

 

 

Comments
by Developer on ‎11-02-2012 03:51 PM

Does this work with beta 3 sdk? got error compiling the library.

 

..\src\opts\SkBlitRow_opts_arm.cpp: In function 'void S32A_Opaque_BlitRow32_arm(SkPMColor*, const SkPMColor*, int, U8CPU)':
..\src\opts\SkBlitRow_opts_arm.cpp:655:1: error: r7 cannot be used in asm here

 

 

Users Online
Currently online: 4 members 606 guests
Please welcome our newest community members: