bool EventRecorder::grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]) { if (!createScreenShot(screen)) { warning("Can't save screenshot"); return false; } Common::MemoryReadStream bitmapStream((const byte*)screen.getPixels(), screen.w * screen.h * screen.format.bytesPerPixel); computeStreamMD5(bitmapStream, md5); return true; }
int main(int argc, char** argv) { SkCommandLineFlags::SetUsage( "Usage: visualize_color_gamut --input <path to input image> " "--output <path to output image> " "--sRGB <draw canonical sRGB gamut> " "--adobeRGB <draw canonical Adobe RGB gamut> " "--uncorrected <path to reencoded, uncorrected " " input image>\n" "Description: Writes a visualization of the color gamut to the output image ." "Also, if a path is provided, writes uncorrected bytes to an unmarked " "png, for comparison with the input image.\n"); SkCommandLineFlags::Parse(argc, argv); const char* input = FLAGS_input[0]; const char* output = FLAGS_output[0]; if (!input || !output) { SkCommandLineFlags::PrintUsage(); return -1; } SkAutoTUnref<SkData> data(SkData::NewFromFileName(input)); if (!data) { SkDebugf("Cannot find input image.\n"); return -1; } SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); if (!codec) { SkDebugf("Invalid input image.\n"); return -1; } // Load a graph of the CIE XYZ color gamut. SkBitmap gamut; if (!GetResourceAsBitmap("gamut.png", &gamut)) { SkDebugf("Program failure.\n"); return -1; } SkCanvas canvas(gamut); // Draw the sRGB gamut if requested. if (FLAGS_sRGB) { sk_sp<SkColorSpace> sRGBSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); draw_gamut(&canvas, sRGBSpace->xyz(), "sRGB", 0xFFFF9394, false); } // Draw the Adobe RGB gamut if requested. if (FLAGS_adobeRGB) { sk_sp<SkColorSpace> adobeRGBSpace = SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named); draw_gamut(&canvas, adobeRGBSpace->xyz(), "Adobe RGB", 0xFF31a9e1, false); } // Draw gamut for the input image. sk_sp<SkColorSpace> colorSpace = sk_ref_sp(codec->getInfo().colorSpace()); if (!colorSpace) { SkDebugf("Image had no embedded color space information. Defaulting to sRGB.\n"); colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); } draw_gamut(&canvas, colorSpace->xyz(), input, 0xFF000000, true); // Finally, encode the result to the output file. SkAutoTUnref<SkData> out(SkImageEncoder::EncodeData(gamut, SkImageEncoder::kPNG_Type, 100)); if (!out) { SkDebugf("Failed to encode gamut output.\n"); return -1; } SkFILEWStream stream(output); bool result = stream.write(out->data(), out->size()); if (!result) { SkDebugf("Failed to write gamut output.\n"); return -1; } // Also, if requested, decode and reencode the uncorrected input image. if (!FLAGS_uncorrected.isEmpty()) { SkBitmap bitmap; int width = codec->getInfo().width(); int height = codec->getInfo().height(); SkAlphaType alphaType = codec->getInfo().alphaType(); bitmap.allocN32Pixels(width, height, kOpaque_SkAlphaType == alphaType); SkImageInfo decodeInfo = SkImageInfo::MakeN32(width, height, alphaType); if (SkCodec::kSuccess != codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes())) { SkDebugf("Could not decode input image.\n"); return -1; } out.reset(SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100)); if (!out) { SkDebugf("Failed to encode uncorrected image.\n"); return -1; } SkFILEWStream bitmapStream(FLAGS_uncorrected[0]); result = bitmapStream.write(out->data(), out->size()); if (!result) { SkDebugf("Failed to write uncorrected image output.\n"); return -1; } } return 0; }
void createBitmaps(std::string name) { constexpr unsigned SCALE_FACTOR = 24; // After changing this function to allocate a lot more memory for objects with // automatic storage duration, some of that memory started to look kind of nonrandom. // Dynamic storage duration seems to result in subjectively much more random memory. std::unique_ptr<std::array<std::array<char, 24 * 24 / 8>, N>> xBitMapsPointer{new std::array<std::array<char, 24 * 24 / 8>, N>}; std::array<std::array<char, 24 * 24 / 8>, N>& xBitMaps = *xBitMapsPointer; for (std::size_t bitmapNum = 0; bitmapNum < N; ++bitmapNum) { std::array<char, 24 * 24 / 8>& bits = xBitMaps[bitmapNum]; for (std::size_t i = 0; i < bits.size(); ++i) bits[i] = ~bits[i]; for (std::size_t i = 0 + 3 + 1; i < 24 - 3 + 1; i += 3) bits[i] = bits[i] ^ std::bitset<8>{"01111110"}.to_ulong(); for (std::size_t i = 24 + 3 + 2; i < 48 - 3 + 2; i += 3) bits[i] = bits[i] ^ std::bitset<8>{"01111110"}.to_ulong(); for (std::size_t i = 48 + 3; i < 72 - 3;) { bits[i] = bits[i] ^ std::bitset<8>{"01111110"}.to_ulong(); ++i; bits[i] = bits[i] ^ std::bitset<8>{"01111110"}.to_ulong(); ++i; bits[i] = bits[i] ^ std::bitset<8>{"01111110"}.to_ulong(); ++i; } std::stringstream sStream; sStream << std::setfill('0') << std::setw(2) << bitmapNum; // I was going to use std::int8_t in case there are more than 8 bits in a char, but // how can there be an int8_t then? #if (CHAR_BIT != 8) #error #endif #ifndef BOOST_LITTLE_ENDIAN #error #endif std::ofstream bitmapStream(name + sStream.str() + ".bmp", std::ios::binary); constexpr std::uint32_t dibHeaderSize = 40; char pixelArray[24 * SCALE_FACTOR * 24 * SCALE_FACTOR / 8]; constexpr char colorTable[8] = { 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00 }; constexpr std::uint32_t fileSize = 14 + dibHeaderSize + sizeof(colorTable) + sizeof(pixelArray); constexpr std::uint32_t offset = 14 + dibHeaderSize + sizeof(colorTable); const char bitmapFileHeader[14] = { 0x42, 0x4d, // "BM" reinterpret_cast<const char*>(&fileSize)[0], reinterpret_cast<const char*>(&fileSize)[1], reinterpret_cast<const char*>(&fileSize)[2], reinterpret_cast<const char*>(&fileSize)[3], 0, 0, 0, 0, reinterpret_cast<const char*>(&offset)[0], reinterpret_cast<const char*>(&offset)[1], reinterpret_cast<const char*>(&offset)[2], reinterpret_cast<const char*>(&offset)[3], }; // This will be supported soonish! Remember to change the color table to 3 byte per // entry. See github.com/wxWidgets/wxWidgets/commit/371928415ab3cf79647153f96907838 /* std::uint16_t bitmapWidth = 24 * SCALE_FACTOR; std::uint16_t bitmapHeight = 24 * SCALE_FACTOR; std::uint16_t one = 1; const char bitmapCoreHeader[dibHeaderSize] = { reinterpret_cast<const char*>(&dibHeaderSize)[0], reinterpret_cast<const char*>(&dibHeaderSize)[1], reinterpret_cast<const char*>(&dibHeaderSize)[2], reinterpret_cast<const char*>(&dibHeaderSize)[3], reinterpret_cast<const char*>(&bitmapWidth)[0], reinterpret_cast<const char*>(&bitmapWidth)[1], reinterpret_cast<const char*>(&bitmapHeight)[0], reinterpret_cast<const char*>(&bitmapHeight)[1], reinterpret_cast<const char*>(&one)[0], // Number of color planes, must be 1 reinterpret_cast<const char*>(&one)[1], reinterpret_cast<const char*>(&one)[0], // Number of bits per pixel reinterpret_cast<const char*>(&one)[1], }; */ std::int32_t bitmapWidth = 24 * SCALE_FACTOR; std::int32_t bitmapHeight = 24 * SCALE_FACTOR; std::uint16_t one = 1; std::uint32_t imageSize = sizeof(pixelArray); const char bitmapInfoHeader[dibHeaderSize] = { reinterpret_cast<const char*>(&dibHeaderSize)[0], reinterpret_cast<const char*>(&dibHeaderSize)[1], reinterpret_cast<const char*>(&dibHeaderSize)[2], reinterpret_cast<const char*>(&dibHeaderSize)[3], reinterpret_cast<const char*>(&bitmapWidth)[0], reinterpret_cast<const char*>(&bitmapWidth)[1], reinterpret_cast<const char*>(&bitmapWidth)[2], reinterpret_cast<const char*>(&bitmapWidth)[3], reinterpret_cast<const char*>(&bitmapHeight)[0], reinterpret_cast<const char*>(&bitmapHeight)[1], reinterpret_cast<const char*>(&bitmapHeight)[2], reinterpret_cast<const char*>(&bitmapHeight)[3], reinterpret_cast<const char*>(&one)[0], // Number of color planes, must be 1 reinterpret_cast<const char*>(&one)[1], reinterpret_cast<const char*>(&one)[0], // Number of bits per pixel reinterpret_cast<const char*>(&one)[1], 0, 0, 0, 0, reinterpret_cast<const char*>(&imageSize)[0], reinterpret_cast<const char*>(&imageSize)[1], reinterpret_cast<const char*>(&imageSize)[2], reinterpret_cast<const char*>(&imageSize)[3], 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0 }; for (unsigned rowNum = 0; rowNum < 24; ++rowNum) { for (unsigned colNum = 0; colNum < 24; ++colNum) { unsigned byteNum = (24 * rowNum + colNum) / 8; unsigned bitNum = (24 * rowNum + colNum) % 8; bool set = (bits[byteNum] >> bitNum) & 1; for (unsigned i = 0; i < SCALE_FACTOR; ++i) { for (unsigned j = 0; j < SCALE_FACTOR / 8; ++j) { int pixelNum = (SCALE_FACTOR * SCALE_FACTOR * 24 * (23 - rowNum) + SCALE_FACTOR * colNum + 24 * SCALE_FACTOR * i) / 8 + j; pixelArray[pixelNum] = set ? 0x00 : 0xff; } } } } bitmapStream.write(bitmapFileHeader, sizeof(bitmapFileHeader)); bitmapStream.write(bitmapInfoHeader, dibHeaderSize); bitmapStream.write(colorTable, sizeof(colorTable)); bitmapStream.write(pixelArray, sizeof(pixelArray)); } }