1# Copyright 2017 Google Inc.
2#
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""
7Visualize bitmaps in gdb.
8
9(gdb) source <path to this file>
10(gdb) sk_bitmap <symbol>
11
12This should pop up a window with the bitmap displayed.
13Right clicking should bring up a menu, allowing the
14bitmap to be saved to a file.
15"""
16
17import gdb
18from enum import Enum
19try:
20  from PIL import Image
21except ImportError:
22  import Image
23
24class ColorType(Enum):
25    unknown = 0
26    alpha_8 = 1
27    rgb_565 = 2
28    argb_4444 = 3
29    rgba_8888 = 4
30    bgra_8888 = 5
31    gray_8 = 6
32    rgba_F16 = 7
33
34class AlphaType(Enum):
35    unknown = 0
36    opaque = 1
37    premul = 2
38    unpremul = 3
39
40class sk_bitmap(gdb.Command):
41  """Displays the content of an SkBitmap image."""
42
43  def __init__(self):
44      super(sk_bitmap, self).__init__('sk_bitmap',
45                                      gdb.COMMAND_SUPPORT,
46                                      gdb.COMPLETE_FILENAME)
47
48  def invoke(self, arg, from_tty):
49    frame = gdb.selected_frame()
50    val = frame.read_var(arg)
51    if str(val.type.strip_typedefs()) == 'SkBitmap':
52      pixels = val['fPixels']
53      row_bytes = val['fRowBytes']
54      info = val['fInfo']
55      width = info['fWidth']
56      height = info['fHeight']
57      color_type = info['fColorType']
58      alpha_type = info['fAlphaType']
59
60      process = gdb.selected_inferior()
61      memory_data = process.read_memory(pixels, row_bytes * height)
62      size = (width, height)
63      image = None
64      # See Unpack.c for the values understood after the "raw" parameter.
65      if color_type == ColorType.bgra_8888.value:
66        if alpha_type == AlphaType.unpremul.value:
67          image = Image.frombytes("RGBA", size, memory_data.tobytes(),
68                                  "raw", "BGRA", row_bytes, 1)
69        elif alpha_type == AlphaType.premul.value:
70          # RGBA instead of RGBa, because Image.show() doesn't work with RGBa.
71          image = Image.frombytes("RGBA", size, memory_data.tobytes(),
72                                  "raw", "BGRa", row_bytes, 1)
73
74      if image:
75        # Fails on premultiplied alpha, it cannot convert to RGB.
76        image.show()
77      else:
78        print ("Need to add support for %s %s." % (
79               str(ColorType(int(color_type))),
80               str(AlphaType(int(alpha_type)))
81        ))
82
83sk_bitmap()
84