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