blob: 46d2bc367b3554bb7b89ec96c6ba7ae4a3c7cda4 [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"
Kevin Lubick1ef156b2022-11-29 12:07:14 -050010#include "include/core/SkBlurTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkCanvas.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040012#include "include/core/SkFont.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkImage.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040014#include "include/core/SkMaskFilter.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040015#include "include/core/SkRefCnt.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040016#include "include/core/SkSize.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040017#include "include/core/SkString.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040018#include "include/core/SkSurface.h"
Kevin Lubick8b741882023-10-06 11:41:38 -040019#include "tools/DecodeUtils.h"
Kevin Lubick9b028372023-10-05 15:04:54 -040020#include "tools/EncodeUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "tools/Resources.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040022#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040023#include "tools/fonts/FontToolUtils.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040024
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
Brian Salomon72068172020-12-17 09:38:59 -050031 imagemagick and exiftool:
Brian Salomon87d42e52020-08-24 09:18:16 -040032#!/bin/bash
33
Brian Salomon87d42e52020-08-24 09:18:16 -040034for s in 444 422 420 440 411 410; do
35 for i in {1..8}; do
Brian Salomon72068172020-12-17 09:38:59 -050036 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;
Brian Salomon87d42e52020-08-24 09:18:16 -040038 done
39done
Brian Salomon72068172020-12-17 09:38:59 -050040
Brian Salomon87d42e52020-08-24 09:18:16 -040041 */
42static void make_images() {
Brian Salomon87d42e52020-08-24 09:18:16 -040043 for (int i = 1; i <= 8; ++i) {
Brian Salomon72068172020-12-17 09:38:59 -050044 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;
Kevin Lubick5c93acf2023-05-09 12:11:43 -040055 auto surf = SkSurfaces::Raster(
56 SkImageInfo::Make(size, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
Brian Salomon87d42e52020-08-24 09:18:16 -040057 auto* canvas = surf->getCanvas();
Brian Salomon72068172020-12-17 09:38:59 -050058 SkMatrix m = SkEncodedOriginToMatrix(origin, kImgW, kImgH);
59 SkAssertResult(m.invert(&m));
60 canvas->concat(m);
Brian Salomon87d42e52020-08-24 09:18:16 -040061 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);
Kevin Lubicke836c3a2023-10-20 06:55:35 -040075 SkFont font(ToolUtils::DefaultPortableTypeface(), kImgH / 4.f);
Brian Salomon87d42e52020-08-24 09:18:16 -040076
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");
Brian Salomon72068172020-12-17 09:38:59 -0500112 drawLabel("right", kImgW - kPad - bounds.right(), baseY);
Brian Salomon87d42e52020-08-24 09:18:16 -0400113
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);
Kevin Lubickf48d2b02023-04-11 18:37:34 -0400120 ToolUtils::EncodeImageToPngFile(num.c_str(), pm);
Brian Salomon87d42e52020-08-24 09:18:16 -0400121 }
122}
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500123
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.
Brian Salomon87d42e52020-08-24 09:18:16 -0400129static void draw(SkCanvas* canvas, const char* suffix) {
130 // Avoid unused function warning.
John Stiles4250eff2022-02-04 16:09:04 -0500131 if ((false)) {
Brian Salomon87d42e52020-08-24 09:18:16 -0400132 make_images();
133 }
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500134 canvas->save();
135 for (char i = '1'; i <= '8'; i++) {
Brian Salomon87d42e52020-08-24 09:18:16 -0400136 SkString path = SkStringPrintf("images/orientation/%c%s.jpg", i, suffix);
Kevin Lubick8b741882023-10-06 11:41:38 -0400137 auto image = ToolUtils::GetResourceAsImage(path.c_str());
Hal Canarybaa2a282018-11-26 15:34:12 -0500138 if (!image) {
139 continue;
140 }
Leon Scroggins III2e0fadb2018-01-16 21:10:29 -0500141 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}
Brian Salomon87d42e52020-08-24 09:18:16 -0400150
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)