diff --git a/cocoa/pe/PictureBlocks.h b/cocoa/pe/PictureBlocks.h deleted file mode 100644 index 47812e8a..00000000 --- a/cocoa/pe/PictureBlocks.h +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2010 Hardcoded Software (http://www.hardcoded.net) - -This software is licensed under the "HS" License as described in the "LICENSE" file, -which should be included with this package. The terms are also available at -http://www.hardcoded.net/licenses/hs_license -*/ - -#import - - -@interface PictureBlocks : NSObject { -} -+ (NSString *)getBlocksFromImagePath:(NSString *)imagePath blockCount:(NSNumber *)blockCount; -+ (NSSize)getImageSize:(NSString *)imagePath; -@end - - -NSString* GetBlocks(NSString *filePath, int blockCount); \ No newline at end of file diff --git a/cocoa/pe/PictureBlocks.m b/cocoa/pe/PictureBlocks.m deleted file mode 100644 index d29f70a0..00000000 --- a/cocoa/pe/PictureBlocks.m +++ /dev/null @@ -1,146 +0,0 @@ -/* -Copyright 2010 Hardcoded Software (http://www.hardcoded.net) - -This software is licensed under the "HS" License as described in the "LICENSE" file, -which should be included with this package. The terms are also available at -http://www.hardcoded.net/licenses/hs_license -*/ - -#import "PictureBlocks.h" -#import "Utils.h" - -@implementation PictureBlocks -+ (NSString *)getBlocksFromImagePath:(NSString *)imagePath blockCount:(NSNumber *)blockCount -{ - return GetBlocks(imagePath, n2i(blockCount)); -} - -+ (NSSize)getImageSize:(NSString *)imagePath -{ - CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)imagePath, kCFURLPOSIXPathStyle, FALSE); - CGImageSourceRef source = CGImageSourceCreateWithURL(fileURL, NULL); - if (source == NULL) - return NSMakeSize(0, 0); - CGImageRef image = CGImageSourceCreateImageAtIndex(source, 0, NULL); - if (image == NULL) - return NSMakeSize(0, 0); - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - CGImageRelease(image); - CFRelease(source); - CFRelease(fileURL); - return NSMakeSize(width, height); -} -@end - - CGContextRef MyCreateBitmapContext (int width, int height) - { - CGContextRef context = NULL; - CGColorSpaceRef colorSpace; - void * bitmapData; - int bitmapByteCount; - int bitmapBytesPerRow; - - bitmapBytesPerRow = (width * 4); - bitmapByteCount = (bitmapBytesPerRow * height); - - colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - - // calloc() must be used to allocate bitmapData here because the buffer has to be zeroed. - // If it's not zeroes, when images with transparency are drawn in the context, this buffer - // will stay with undefined pixels, which means that two pictures with the same pixels will - // most likely have different blocks (which is not supposed to happen). - bitmapData = calloc(bitmapByteCount, 1); - if (bitmapData == NULL) - { - fprintf (stderr, "Memory not allocated!"); - return NULL; - } - - context = CGBitmapContextCreate (bitmapData,width,height,8,bitmapBytesPerRow,colorSpace,kCGImageAlphaNoneSkipLast); - if (context== NULL) - { - free (bitmapData); - fprintf (stderr, "Context not created!"); - return NULL; - } - CGColorSpaceRelease( colorSpace ); - return context; - } - - // returns 0x00RRGGBB - int GetBlock(unsigned char *imageData, int imageWidth, int imageHeight, int boxX, int boxY, int boxW, int boxH) - { - int i,j; - int totalR = 0; - int totalG = 0; - int totalB = 0; - for(i = boxY; i < boxY + boxH; i++) - { - for(j = boxX; j < boxX + boxW; j++) - { - int offset = (i * imageWidth * 4) + (j * 4); - totalR += *(imageData + offset); - totalG += *(imageData + offset + 1); - totalB += *(imageData + offset + 2); - } - } - int pixelCount = boxH * boxW; - int result = 0; - result += (totalR / pixelCount) << 16; - result += (totalG / pixelCount) << 8; - result += (totalB / pixelCount); - return result; - } - - NSString* GetBlocks (NSString* filePath, int blockCount) - { - CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)filePath, kCFURLPOSIXPathStyle, FALSE); - CGImageSourceRef source = CGImageSourceCreateWithURL(fileURL, NULL); - if (source == NULL) - return NULL; - CGImageRef image = CGImageSourceCreateImageAtIndex(source, 0, NULL); - if (image == NULL) - return NULL; - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - CGContextRef myContext = MyCreateBitmapContext(width, height); - CGRect myBoundingBox = CGRectMake (0, 0, width, height); - CGContextDrawImage(myContext, myBoundingBox, image); - unsigned char *bitmapData = CGBitmapContextGetData(myContext); - if (bitmapData == NULL) - return NULL; - - int blockHeight = height / blockCount; - if (blockHeight < 1) - blockHeight = 1; - int blockWidth = width / blockCount; - if (blockWidth < 1) - blockWidth = 1; - //blockCount might have changed - int blockXCount = (width / blockWidth); - int blockYCount = (height / blockHeight); - - CFMutableArrayRef blocks = CFArrayCreateMutable(NULL, blockXCount * blockYCount, &kCFTypeArrayCallBacks); - int i,j; - for(i = 0; i < blockYCount; i++) - { - for(j = 0; j < blockXCount; j++) - { - int block = GetBlock(bitmapData, width, height, j * blockWidth, i * blockHeight, blockWidth, blockHeight); - CFStringRef strBlock = CFStringCreateWithFormat(NULL, NULL, CFSTR("%06x"), block); - CFArrayAppendValue(blocks, strBlock); - CFRelease(strBlock); - } - } - - CGContextRelease (myContext); - if (bitmapData) free(bitmapData); - CGImageRelease(image); - CFRelease(source); - CFRelease(fileURL); - - CFStringRef result = CFStringCreateByCombiningStrings(NULL, blocks, CFSTR("")); - CFRelease(blocks); - return (NSString *)result; - } \ No newline at end of file diff --git a/cocoa/pe/dupeguru.xcodeproj/project.pbxproj b/cocoa/pe/dupeguru.xcodeproj/project.pbxproj index 26176fd2..9d12a722 100644 --- a/cocoa/pe/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/pe/dupeguru.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ CE031751109B340A00517EE6 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031750109B340A00517EE6 /* Preferences.xib */; }; CE031754109B345200517EE6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE031753109B345200517EE6 /* MainMenu.xib */; }; CE073F6309CAE1A3005C1D2F /* dupeguru_pe_help in Resources */ = {isa = PBXBuildFile; fileRef = CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */; }; - CE0C46AA0FA0647E000BE99B /* PictureBlocks.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0C46A90FA0647E000BE99B /* PictureBlocks.m */; }; CE15C8A80ADEB8B50061D4A5 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; }; CE15C8C00ADEB8D40061D4A5 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */; }; CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; }; @@ -77,8 +76,6 @@ CE031750109B340A00517EE6 /* Preferences.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = ""; }; CE031753109B345200517EE6 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../../base/xib/MainMenu.xib; sourceTree = ""; }; CE073F5409CAE1A3005C1D2F /* dupeguru_pe_help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dupeguru_pe_help; path = ../../help_pe/dupeguru_pe_help; sourceTree = SOURCE_ROOT; }; - CE0C46A80FA0647E000BE99B /* PictureBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PictureBlocks.h; sourceTree = ""; }; - CE0C46A90FA0647E000BE99B /* PictureBlocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PictureBlocks.m; sourceTree = ""; }; CE15C8A70ADEB8B50061D4A5 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = ""; }; CE381C9409914ACE003581CE /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; }; CE381C9509914ACE003581CE /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; }; @@ -155,8 +152,6 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( - CE0C46A80FA0647E000BE99B /* PictureBlocks.h */, - CE0C46A90FA0647E000BE99B /* PictureBlocks.m */, CE381C9509914ACE003581CE /* AppDelegate.h */, CE381C9409914ACE003581CE /* AppDelegate.m */, CE848A1809DD85810004CB44 /* Consts.h */, @@ -409,7 +404,6 @@ CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */, CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */, CECA899D09DB132E00A3D774 /* DetailsPanel.m in Sources */, - CE0C46AA0FA0647E000BE99B /* PictureBlocks.m in Sources */, CE80DB2E0FC192D60086DCA6 /* Dialogs.m in Sources */, CE80DB2F0FC192D60086DCA6 /* HSErrorReportWindow.m in Sources */, CE80DB300FC192D60086DCA6 /* Outline.m in Sources */, diff --git a/core_pe/app_cocoa.py b/core_pe/app_cocoa.py index 54db2e14..8bf3f376 100644 --- a/core_pe/app_cocoa.py +++ b/core_pe/app_cocoa.py @@ -11,7 +11,7 @@ import logging import plistlib import re -from Foundation import NSBundle, NSUserDefaults, NSURL +from Foundation import NSUserDefaults, NSURL from appscript import app, k, CommandError from hsutil import io @@ -21,14 +21,9 @@ from hsutil.cocoa import as_fetch from core import fs from core import app_cocoa, directories -from . import data -from .cache import string_to_colors +from . import data, _block_osx from .scanner import ScannerPE -mainBundle = NSBundle.mainBundle() -PictureBlocks = mainBundle.classNamed_('PictureBlocks') -assert PictureBlocks is not None - class Photo(fs.File): INITIAL_INFO = fs.File.INITIAL_INFO.copy() INITIAL_INFO.update({ @@ -43,17 +38,16 @@ class Photo(fs.File): def _read_info(self, field): fs.File._read_info(self, field) if field == 'dimensions': - size = PictureBlocks.getImageSize_(unicode(self.path)) - self.dimensions = (size.width, size.height) + self.dimensions = _block_osx.get_image_size(unicode(self.path)) def get_blocks(self, block_count_per_side): try: - blocks = PictureBlocks.getBlocksFromImagePath_blockCount_(unicode(self.path), block_count_per_side) + blocks = _block_osx.getblocks(unicode(self.path), block_count_per_side) except Exception as e: raise IOError('The reading of "%s" failed with "%s"' % (unicode(self.path), unicode(e))) if not blocks: raise IOError('The picture %s could not be read' % unicode(self.path)) - return string_to_colors(blocks) + return blocks class IPhoto(Photo): diff --git a/core_pe/gen.py b/core_pe/gen.py index bbda1640..55b59512 100644 --- a/core_pe/gen.py +++ b/core_pe/gen.py @@ -23,5 +23,6 @@ os.system('python setup.py build_ext --inplace') os.chdir('..') move(op.join('modules', '_block.so'), '_block.so') move(op.join('modules', '_block.pyd'), '_block.pyd') +move(op.join('modules', '_block_osx.so'), '_block_osx.so') move(op.join('modules', '_cache.so'), '_cache.so') move(op.join('modules', '_cache.pyd'), '_cache.pyd') diff --git a/core_pe/modules/block.c b/core_pe/modules/block.c index 82930424..25a24727 100644 --- a/core_pe/modules/block.c +++ b/core_pe/modules/block.c @@ -7,59 +7,17 @@ * http://www.hardcoded.net/licenses/hs_license */ -#define PY_SSIZE_T_CLEAN -#include "Python.h" +#include "common.h" /* avgdiff/maxdiff has been called with empty lists */ static PyObject *NoBlocksError; /* avgdiff/maxdiff has been called with 2 block lists of different size. */ static PyObject *DifferentBlockCountError; -/* It seems like MS VC defines min/max already */ -#ifndef _MSC_VER -static int -max(int a, int b) -{ - return b > a ? b : a; -} - -static int -min(int a, int b) -{ - return b < a ? b : a; -} -#endif - -/* Create a tuple out of an array of integers. */ -static PyObject* -inttuple(int n, ...) -{ - int i; - PyObject *pnumber; - PyObject *result; - va_list numbers; - - va_start(numbers, n); - result = PyTuple_New(n); - - for (i=0; i + +static CFStringRef +pystring2cfstring(PyObject *pystring) +{ + PyObject *encoded; + UInt8 *s; + CFIndex size; + CFStringRef result; + + if (PyUnicode_Check(pystring)) { + encoded = PyUnicode_AsUTF8String(pystring); + if (encoded == NULL) { + return NULL; + } + } else { + encoded = pystring; + Py_INCREF(encoded); + } + + s = (UInt8*)PyString_AS_STRING(encoded); + size = PyString_GET_SIZE(encoded); + result = CFStringCreateWithBytes(NULL, s, size, kCFStringEncodingUTF8, FALSE); + Py_DECREF(encoded); + return result; +} + +static PyObject* block_osx_get_image_size(PyObject *self, PyObject *args) +{ + PyObject *path; + CFStringRef image_path; + CFURLRef image_url; + CGImageSourceRef source; + CGImageRef image; + size_t width, height; + PyObject *pwidth, *pheight; + PyObject *result; + + width = 0; + height = 0; + if (!PyArg_ParseTuple(args, "O", &path)) { + return NULL; + } + + image_path = pystring2cfstring(path); + if (image_path == NULL) { + return PyErr_NoMemory(); + } + image_url = CFURLCreateWithFileSystemPath(NULL, image_path, kCFURLPOSIXPathStyle, FALSE); + CFRelease(image_path); + + source = CGImageSourceCreateWithURL(image_url, NULL); + CFRelease(image_url); + if (source != NULL) { + image = CGImageSourceCreateImageAtIndex(source, 0, NULL); + if (image != NULL) { + width = CGImageGetWidth(image); + height = CGImageGetHeight(image); + CGImageRelease(image); + } + CFRelease(source); + } + + pwidth = PyInt_FromSsize_t(width); + if (pwidth == NULL) { + return NULL; + } + pheight = PyInt_FromSsize_t(height); + if (pheight == NULL) { + return NULL; + } + result = PyTuple_Pack(2, pwidth, pheight); + Py_DECREF(pwidth); + Py_DECREF(pheight); + return result; +} + +static CGContextRef +MyCreateBitmapContext(int width, int height) +{ + CGContextRef context = NULL; + CGColorSpaceRef colorSpace; + void *bitmapData; + int bitmapByteCount; + int bitmapBytesPerRow; + + bitmapBytesPerRow = (width * 4); + bitmapByteCount = (bitmapBytesPerRow * height); + + colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + + // calloc() must be used to allocate bitmapData here because the buffer has to be zeroed. + // If it's not zeroes, when images with transparency are drawn in the context, this buffer + // will stay with undefined pixels, which means that two pictures with the same pixels will + // most likely have different blocks (which is not supposed to happen). + bitmapData = calloc(bitmapByteCount, 1); + if (bitmapData == NULL) { + fprintf(stderr, "Memory not allocated!"); + return NULL; + } + + context = CGBitmapContextCreate(bitmapData, width, height, 8, bitmapBytesPerRow, colorSpace, + kCGImageAlphaNoneSkipLast); + if (context== NULL) { + free(bitmapData); + fprintf(stderr, "Context not created!"); + return NULL; + } + CGColorSpaceRelease(colorSpace); + return context; +} + +static PyObject* getblock(unsigned char *imageData, int imageWidth, int imageHeight, int boxX, int boxY, int boxW, int boxH) +{ + int i,j, totalR, totalG, totalB; + + totalR = totalG = totalB = 0; + for(i=boxY; i a ? b : a; +} + +int min(int a, int b) +{ + return b < a ? b : a; +} +#endif + +PyObject* inttuple(int n, ...) +{ + int i; + PyObject *pnumber; + PyObject *result; + va_list numbers; + + va_start(numbers, n); + result = PyTuple_New(n); + + for (i=0; i