1 /* 2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. 3 * (C) 2007 Graham Dennis (graham.dennis (at) gmail.com) 4 * (C) 2007 Eric Seidel <eric (at) webkit.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "PixelDumpSupportCG.h" 33 34 #include "DumpRenderTree.h" 35 #include "PixelDumpSupport.h" 36 #include <ImageIO/CGImageDestination.h> 37 #include <algorithm> 38 #include <ctype.h> 39 #include <wtf/Assertions.h> 40 #include <wtf/RefPtr.h> 41 #include <wtf/RetainPtr.h> 42 #include <wtf/StringExtras.h> 43 44 #if PLATFORM(WIN) 45 #include "MD5.h" 46 #elif PLATFORM(MAC) 47 #include <LaunchServices/UTCoreTypes.h> 48 #define COMMON_DIGEST_FOR_OPENSSL 49 #include <CommonCrypto/CommonDigest.h> 50 #endif 51 52 using namespace std; 53 54 #if PLATFORM(WIN) 55 static const CFStringRef kUTTypePNG = CFSTR("public.png"); 56 #endif 57 58 static void printPNG(CGImageRef image) 59 { 60 RetainPtr<CFMutableDataRef> imageData(AdoptCF, CFDataCreateMutable(0, 0)); 61 RetainPtr<CGImageDestinationRef> imageDest(AdoptCF, CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0)); 62 CGImageDestinationAddImage(imageDest.get(), image, 0); 63 CGImageDestinationFinalize(imageDest.get()); 64 65 const UInt8* data = CFDataGetBytePtr(imageData.get()); 66 CFIndex dataLength = CFDataGetLength(imageData.get()); 67 68 printPNG(static_cast<const unsigned char*>(data), static_cast<size_t>(dataLength)); 69 } 70 71 void computeMD5HashStringForBitmapContext(BitmapContext* context, char hashString[33]) 72 { 73 CGContextRef bitmapContext = context->cgContext(); 74 75 ASSERT(CGBitmapContextGetBitsPerPixel(bitmapContext) == 32); // ImageDiff assumes 32 bit RGBA, we must as well. 76 size_t pixelsHigh = CGBitmapContextGetHeight(bitmapContext); 77 size_t pixelsWide = CGBitmapContextGetWidth(bitmapContext); 78 size_t bytesPerRow = CGBitmapContextGetBytesPerRow(bitmapContext); 79 80 // We need to swap the bytes to ensure consistent hashes independently of endianness 81 MD5_CTX md5Context; 82 MD5_Init(&md5Context); 83 unsigned char* bitmapData = static_cast<unsigned char*>(CGBitmapContextGetData(bitmapContext)); 84 #if PLATFORM(MAC) 85 if ((CGBitmapContextGetBitmapInfo(bitmapContext) & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Big) { 86 for (unsigned row = 0; row < pixelsHigh; row++) { 87 uint32_t buffer[pixelsWide]; 88 for (unsigned column = 0; column < pixelsWide; column++) 89 buffer[column] = OSReadLittleInt32(bitmapData, 4 * column); 90 MD5_Update(&md5Context, buffer, 4 * pixelsWide); 91 bitmapData += bytesPerRow; 92 } 93 } else 94 #endif 95 { 96 for (unsigned row = 0; row < pixelsHigh; row++) { 97 MD5_Update(&md5Context, bitmapData, 4 * pixelsWide); 98 bitmapData += bytesPerRow; 99 } 100 } 101 unsigned char hash[16]; 102 MD5_Final(hash, &md5Context); 103 104 hashString[0] = '\0'; 105 for (int i = 0; i < 16; i++) 106 snprintf(hashString, 33, "%s%02x", hashString, hash[i]); 107 } 108 109 void dumpBitmap(BitmapContext* context) 110 { 111 RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context->cgContext())); 112 printPNG(image.get()); 113 } 114