• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
9 #include "include/codec/SkEncodedOrigin.h"
10 #include "include/core/SkBlurTypes.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkFont.h"
13 #include "include/core/SkImage.h"
14 #include "include/core/SkMaskFilter.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkSize.h"
17 #include "include/core/SkString.h"
18 #include "include/core/SkSurface.h"
19 #include "tools/DecodeUtils.h"
20 #include "tools/EncodeUtils.h"
21 #include "tools/Resources.h"
22 #include "tools/ToolUtils.h"
23 #include "tools/fonts/FontToolUtils.h"
24 
25 static constexpr int kImgW = 100;
26 static 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 
34 for 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
39 done
40 
41  */
make_images()42 static 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(
56                 SkImageInfo::Make(size, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
57         auto* canvas = surf->getCanvas();
58         SkMatrix m = SkEncodedOriginToMatrix(origin, kImgW, kImgH);
59         SkAssertResult(m.invert(&m));
60         canvas->concat(m);
61         canvas->clear(SK_ColorBLACK);
62         SkPaint paint;
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);
75         SkFont font(ToolUtils::DefaultPortableTypeface(), kImgH / 4.f);
76 
77         SkPaint blurPaint;
78         blurPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, .75f));
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);
120         ToolUtils::EncodeImageToPngFile(num.c_str(), 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.
draw(SkCanvas * canvas,const char * suffix)129 static 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 
155 MAKE_GM(410)
156 MAKE_GM(411)
157 MAKE_GM(420)
158 MAKE_GM(422)
159 MAKE_GM(440)
160 MAKE_GM(444)
161