blob: 2b49a83310b255a9ee10d12293c596041d10bdac [file] [log] [blame]
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Brian Salomon72068172020-12-17 09:38:59 -05009#include "include/codec/SkEncodedOrigin.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkCanvas.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040011#include "include/core/SkFont.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkImage.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040013#include "include/core/SkMaskFilter.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040014#include "include/core/SkRefCnt.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040015#include "include/core/SkSize.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040016#include "include/core/SkString.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040017#include "include/core/SkSurface.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "tools/Resources.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040019#include "tools/ToolUtils.h"
20
21static constexpr int kImgW = 100;
22static constexpr int kImgH = 80;
23
24/**
25 This function was used to create the images used by these test. It saves them as PNGs (so they
26 are lossless). Then the following bash script was used to create the oriented JPGs with
Brian Salomon72068172020-12-17 09:38:59 -050027 imagemagick and exiftool:
Brian Salomon87d42e52020-08-24 09:18:16 -040028#!/bin/bash
29
Brian Salomon87d42e52020-08-24 09:18:16 -040030for s in 444 422 420 440 411 410; do
31 for i in {1..8}; do
Brian Salomon72068172020-12-17 09:38:59 -050032 magick convert $i.png -sampling-factor ${s:0:1}:${s:1:1}:${s:2:1} $i\_$s.jpg;
33 exiftool -orientation=$i -n -m -overwrite_original $i\_$s.jpg;
Brian Salomon87d42e52020-08-24 09:18:16 -040034 done
35done
Brian Salomon72068172020-12-17 09:38:59 -050036
Brian Salomon87d42e52020-08-24 09:18:16 -040037 */
38static void make_images() {
Brian Salomon87d42e52020-08-24 09:18:16 -040039 for (int i = 1; i <= 8; ++i) {
Brian Salomon72068172020-12-17 09:38:59 -050040 SkISize size{kImgW, kImgH};
41 SkEncodedOrigin origin = static_cast<SkEncodedOrigin>(i);
42 // We apply the inverse transformation to the PNG we generate, convert the PNG to a
43 // a JPEG using magick, then modify the JPEG's tag using exiftool (without modifying the
44 // stored JPEG data).
45 if (origin >= kLeftTop_SkEncodedOrigin) {
46 // The last four SkEncodedOrigin values involve 90 degree rotations
47 using std::swap;
48 swap(size.fWidth, size.fHeight);
49 }
50 using std::swap;
51 auto surf = SkSurface::MakeRaster(SkImageInfo::Make(size,
52 kRGBA_8888_SkColorType,
53 kPremul_SkAlphaType));
Brian Salomon87d42e52020-08-24 09:18:16 -040054 auto* canvas = surf->getCanvas();
Brian Salomon72068172020-12-17 09:38:59 -050055 SkMatrix m = SkEncodedOriginToMatrix(origin, kImgW, kImgH);
56 SkAssertResult(m.invert(&m));
57 canvas->concat(m);
Brian Salomon87d42e52020-08-24 09:18:16 -040058 canvas->clear(SK_ColorBLACK);
59 SkPaint paint;
60 paint.setColor(SK_ColorRED);
61 SkScalar midX = kImgW / 2.f;
62 SkScalar midY = kImgH / 2.f;
63 SkScalar w = midX - 1;
64 SkScalar h = midY - 1;
65 canvas->drawRect(SkRect::MakeXYWH(1, 1, w, h), paint);
66 paint.setColor(SK_ColorBLUE);
67 canvas->drawRect(SkRect::MakeXYWH(midX, 1, w, h), paint);
68 paint.setColor(SK_ColorGREEN);
69 canvas->drawRect(SkRect::MakeXYWH(1, midY, w, h), paint);
70 paint.setColor(SK_ColorYELLOW);
71 canvas->drawRect(SkRect::MakeXYWH(midX, midY, w, h), paint);
72 SkFont font(ToolUtils::create_portable_typeface(), kImgH / 4.f);
73
74 SkPaint blurPaint;
75 blurPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, .75f));
76 blurPaint.setColor(SK_ColorBLACK);
77 paint.setColor(SK_ColorWHITE);
78
79 auto drawLabel = [&](const char* string, SkScalar x, SkScalar y) {
80 canvas->save();
81 canvas->translate(1, 1);
82 canvas->drawString(string, x, y, font, blurPaint);
83 canvas->restore();
84 canvas->drawString(string, x, y, font, paint);
85 };
86
87 auto measure = [&font](const char* text) {
88 SkRect bounds;
89 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
90 return bounds;
91 };
92
93 static constexpr SkScalar kPad = 3.f;
94 SkRect bounds;
95
96 bounds = measure("top");
97 drawLabel("top", midX - bounds.centerX(), -bounds.top() + kPad);
98
99 bounds = measure("bottom");
100 drawLabel("bottom", midX - bounds.centerX(), kImgH - kPad - bounds.bottom());
101
102 // It looks weird if "left" and "right" and the number at the center aren't vertically
103 // aligned.
104 SkScalar baseY = midY - measure("leftright").centerY();
105 bounds = measure("left");
106 drawLabel("left", kPad - bounds.left(), baseY);
107
108 bounds = measure("right");
Brian Salomon72068172020-12-17 09:38:59 -0500109 drawLabel("right", kImgW - kPad - bounds.right(), baseY);
Brian Salomon87d42e52020-08-24 09:18:16 -0400110
111 SkString num = SkStringPrintf("%d", i);
112 bounds = measure(num.c_str());
113 drawLabel(num.c_str(), midX - bounds.centerX(), baseY);
114 num.append(".png");
115 SkPixmap pm;
116 surf->makeImageSnapshot()->peekPixels(&pm);
117 ToolUtils::EncodeImageToFile(num.c_str(), pm, SkEncodedImageFormat::kPNG, 100);
118 }
119}
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500120
121// This gm draws 8 images that are mostly the same when respecting the
122// EXIF orientation tag. Each one has four quadrants (red, blue, green,
123// yellow), and labels on the left, top, right and bottom. The only
124// visual difference is a number in the middle corresponding to the
125// EXIF tag for that image's jpg file.
Brian Salomon87d42e52020-08-24 09:18:16 -0400126static void draw(SkCanvas* canvas, const char* suffix) {
127 // Avoid unused function warning.
128 if (0) {
129 make_images();
130 }
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500131 canvas->save();
132 for (char i = '1'; i <= '8'; i++) {
Brian Salomon87d42e52020-08-24 09:18:16 -0400133 SkString path = SkStringPrintf("images/orientation/%c%s.jpg", i, suffix);
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500134 auto image = GetResourceAsImage(path.c_str());
Hal Canarybaa2a282018-11-26 15:34:12 -0500135 if (!image) {
136 continue;
137 }
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500138 canvas->drawImage(image, 0, 0);
139 if ('4' == i) {
140 canvas->restore();
141 canvas->translate(0, image->height());
142 } else {
143 canvas->translate(image->width(), 0);
144 }
145 }
146}
Brian Salomon87d42e52020-08-24 09:18:16 -0400147
148#define MAKE_GM(subsample) DEF_SIMPLE_GM(orientation_##subsample, canvas, 4*kImgW, 2*kImgH) { \
149 draw(canvas, "_" #subsample); \
150}
151
152MAKE_GM(410)
153MAKE_GM(411)
154MAKE_GM(420)
155MAKE_GM(422)
156MAKE_GM(440)
157MAKE_GM(444)