Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
orientation.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm/gm.h"
12#include "include/core/SkFont.h"
16#include "include/core/SkSize.h"
19#include "tools/DecodeUtils.h"
20#include "tools/EncodeUtils.h"
21#include "tools/Resources.h"
22#include "tools/ToolUtils.h"
24
25static constexpr int kImgW = 100;
26static constexpr int kImgH = 80;
27
28/**
29 This function was used to create the images used by these test. It saves them as PNGs (so they
30 are lossless). Then the following bash script was used to create the oriented JPGs with
31 imagemagick and exiftool:
32#!/bin/bash
33
34for s in 444 422 420 440 411 410; do
35 for i in {1..8}; do
36 magick convert $i.png -sampling-factor ${s:0:1}:${s:1:1}:${s:2:1} $i\_$s.jpg;
37 exiftool -orientation=$i -n -m -overwrite_original $i\_$s.jpg;
38 done
39done
40
41 */
42static void make_images() {
43 for (int i = 1; i <= 8; ++i) {
44 SkISize size{kImgW, kImgH};
45 SkEncodedOrigin origin = static_cast<SkEncodedOrigin>(i);
46 // We apply the inverse transformation to the PNG we generate, convert the PNG to a
47 // a JPEG using magick, then modify the JPEG's tag using exiftool (without modifying the
48 // stored JPEG data).
49 if (origin >= kLeftTop_SkEncodedOrigin) {
50 // The last four SkEncodedOrigin values involve 90 degree rotations
51 using std::swap;
52 swap(size.fWidth, size.fHeight);
53 }
54 using std::swap;
55 auto surf = SkSurfaces::Raster(
57 auto* canvas = surf->getCanvas();
59 SkAssertResult(m.invert(&m));
60 canvas->concat(m);
61 canvas->clear(SK_ColorBLACK);
63 paint.setColor(SK_ColorRED);
64 SkScalar midX = kImgW / 2.f;
65 SkScalar midY = kImgH / 2.f;
66 SkScalar w = midX - 1;
67 SkScalar h = midY - 1;
68 canvas->drawRect(SkRect::MakeXYWH(1, 1, w, h), paint);
69 paint.setColor(SK_ColorBLUE);
70 canvas->drawRect(SkRect::MakeXYWH(midX, 1, w, h), paint);
71 paint.setColor(SK_ColorGREEN);
72 canvas->drawRect(SkRect::MakeXYWH(1, midY, w, h), paint);
73 paint.setColor(SK_ColorYELLOW);
74 canvas->drawRect(SkRect::MakeXYWH(midX, midY, w, h), paint);
76
77 SkPaint blurPaint;
79 blurPaint.setColor(SK_ColorBLACK);
80 paint.setColor(SK_ColorWHITE);
81
82 auto drawLabel = [&](const char* string, SkScalar x, SkScalar y) {
83 canvas->save();
84 canvas->translate(1, 1);
85 canvas->drawString(string, x, y, font, blurPaint);
86 canvas->restore();
87 canvas->drawString(string, x, y, font, paint);
88 };
89
90 auto measure = [&font](const char* text) {
91 SkRect bounds;
92 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
93 return bounds;
94 };
95
96 static constexpr SkScalar kPad = 3.f;
97 SkRect bounds;
98
99 bounds = measure("top");
100 drawLabel("top", midX - bounds.centerX(), -bounds.top() + kPad);
101
102 bounds = measure("bottom");
103 drawLabel("bottom", midX - bounds.centerX(), kImgH - kPad - bounds.bottom());
104
105 // It looks weird if "left" and "right" and the number at the center aren't vertically
106 // aligned.
107 SkScalar baseY = midY - measure("leftright").centerY();
108 bounds = measure("left");
109 drawLabel("left", kPad - bounds.left(), baseY);
110
111 bounds = measure("right");
112 drawLabel("right", kImgW - kPad - bounds.right(), baseY);
113
114 SkString num = SkStringPrintf("%d", i);
115 bounds = measure(num.c_str());
116 drawLabel(num.c_str(), midX - bounds.centerX(), baseY);
117 num.append(".png");
118 SkPixmap pm;
119 surf->makeImageSnapshot()->peekPixels(&pm);
121 }
122}
123
124// This gm draws 8 images that are mostly the same when respecting the
125// EXIF orientation tag. Each one has four quadrants (red, blue, green,
126// yellow), and labels on the left, top, right and bottom. The only
127// visual difference is a number in the middle corresponding to the
128// EXIF tag for that image's jpg file.
129static void draw(SkCanvas* canvas, const char* suffix) {
130 // Avoid unused function warning.
131 if ((false)) {
132 make_images();
133 }
134 canvas->save();
135 for (char i = '1'; i <= '8'; i++) {
136 SkString path = SkStringPrintf("images/orientation/%c%s.jpg", i, suffix);
137 auto image = ToolUtils::GetResourceAsImage(path.c_str());
138 if (!image) {
139 continue;
140 }
141 canvas->drawImage(image, 0, 0);
142 if ('4' == i) {
143 canvas->restore();
144 canvas->translate(0, image->height());
145 } else {
146 canvas->translate(image->width(), 0);
147 }
148 }
149}
150
151#define MAKE_GM(subsample) DEF_SIMPLE_GM(orientation_##subsample, canvas, 4*kImgW, 2*kImgH) { \
152 draw(canvas, "_" #subsample); \
153}
154
155MAKE_GM(410)
156MAKE_GM(411)
157MAKE_GM(420)
158MAKE_GM(422)
159MAKE_GM(440)
160MAKE_GM(444)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkAssertResult(cond)
Definition SkAssert.h:123
@ kNormal_SkBlurStyle
fuzzy inside and outside
Definition SkBlurTypes.h:12
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
constexpr SkColor SK_ColorYELLOW
Definition SkColor.h:139
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
SkEncodedOrigin
@ kLeftTop_SkEncodedOrigin
static SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h)
@ kUTF8
uses bytes to represent UTF-8 or ASCII
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition SkRefCnt.h:341
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
constexpr int kPad
void restore()
Definition SkCanvas.cpp:465
void translate(SkScalar dx, SkScalar dy)
int save()
Definition SkCanvas.cpp:451
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setMaskFilter(sk_sp< SkMaskFilter > maskFilter)
void append(const char text[])
Definition SkString.h:203
const char * c_str() const
Definition SkString.h:133
const Paint & paint
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
std::u16string text
double y
double x
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
sk_sp< SkTypeface > DefaultPortableTypeface()
bool EncodeImageToPngFile(const char *path, const SkBitmap &src)
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition DecodeUtils.h:25
static void draw(SkCanvas *canvas, const char *suffix)
static constexpr int kImgH
static constexpr int kImgW
#define MAKE_GM(subsample)
static void make_images()
SkScalar w
SkScalar h
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659