• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python2
2#
3# Copyright 2016 The ANGLE Project Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# bmp_to_nv12.py:
8#   Script to convert a simple BMP file to an NV12 format. Used to create
9#   test images for the NV12 texture stream end to end tests
10
11import sys
12import struct
13
14if len(sys.argv) != 4:
15    print("Usage: bmp_to_nv12.py input output prefix")
16    exit(0)
17
18bmp_file = open(sys.argv[1], "rb")
19
20magic = bmp_file.read(2)
21if (magic != "BM"):
22    print("Invalid BMP magic")
23    exit(1)
24
25file_size, = struct.unpack("I", bmp_file.read(4))
26
27# eat reserved bytes
28bmp_file.read(4)
29
30offset, = struct.unpack("I", bmp_file.read(4))
31
32headersize, = struct.unpack("I", bmp_file.read(4))
33width, = struct.unpack("i", bmp_file.read(4))
34height, = struct.unpack("i", bmp_file.read(4))
35planes, = struct.unpack("H", bmp_file.read(2))
36bpp, = struct.unpack("H", bmp_file.read(2))
37compression, = struct.unpack("i", bmp_file.read(4))
38image_size, = struct.unpack("i", bmp_file.read(4))
39
40if (bpp != 24 or compression != 0):
41    print("Unsupported BMP file")
42    bmp_file.close()
43    exit(1)
44
45bmp_file.seek(offset, 0)
46pixels = bmp_file.read(width * height * 3)
47bmp_file.close()
48
49# convert to YUV 4:4:4
50converted_pixels = bytearray(pixels)
51for i in range(0, width * height):
52    R, = struct.unpack("B", pixels[i * 3 + 2])
53    G, = struct.unpack("B", pixels[i * 3 + 1])
54    B, = struct.unpack("B", pixels[i * 3])
55    converted_pixels[i * 3] = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16
56    converted_pixels[i * 3 + 1] = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128
57    converted_pixels[i * 3 + 2] = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128
58
59# downsample to packed UV buffer
60uv_buffer = bytearray(width * height / 2)
61for i in range(0, width * height / 2, 2):
62    U1 = converted_pixels[((((i / width) * 2) * width) + (i % width)) * 3 + 1]
63    U2 = converted_pixels[((((i / width) * 2) * width) + width + (i % width)) * 3 + 1]
64    V1 = converted_pixels[((((i / width) * 2) * width) + (i % width)) * 3 + 2]
65    V2 = converted_pixels[((((i / width) * 2) * width) + width + (i % width)) * 3 + 2]
66    uv_buffer[i] = (U1 + U2) / 2
67    uv_buffer[i + 1] = (V1 + V2) / 2
68
69# extract the Y buffer
70y_buffer = bytearray(width * height)
71for i in range(0, width * height):
72    y_buffer[i] = converted_pixels[i * 3]
73
74# write out the file as a C header
75nv12_file = open(sys.argv[2], "w")
76nv12_file.write("// Automatically generated from " + sys.argv[1] + "\n")
77nv12_file.write("static const size_t " + sys.argv[3] + "_width = " + str(width) + ";\n")
78nv12_file.write("static const size_t " + sys.argv[3] + "_height = " + str(height) + ";\n")
79nv12_file.write("static const unsigned char " + sys.argv[3] + "_data[] = \n{")
80for i in range(0, width * height):
81    if (i % 16) == 0:
82        nv12_file.write("\n    ")
83    nv12_file.write(str(y_buffer[i]) + ",")
84for i in range(0, width * height / 2):
85    if (i % 16) == 0:
86        nv12_file.write("\n    ")
87    nv12_file.write(str(uv_buffer[i]) + ",")
88nv12_file.write("\n};")
89nv12_file.close()
90