mirror of
https://github.com/arsenetar/dupeguru.git
synced 2026-01-22 06:37:17 +00:00
Merge core_{se,me,pe} into core.{se,me,pe}
This commit is contained in:
253
core/pe/modules/block.c
Normal file
253
core/pe/modules/block.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/* Created By: Virgil Dupras
|
||||
* Created On: 2010-01-30
|
||||
* Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "BSD" 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/bsd_license
|
||||
*/
|
||||
|
||||
#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;
|
||||
|
||||
/* Returns a 3 sized tuple containing the mean color of 'image'.
|
||||
* image: a PIL image or crop.
|
||||
*/
|
||||
static PyObject* getblock(PyObject *image)
|
||||
{
|
||||
int i, totr, totg, totb;
|
||||
Py_ssize_t pixel_count;
|
||||
PyObject *ppixels;
|
||||
|
||||
totr = totg = totb = 0;
|
||||
ppixels = PyObject_CallMethod(image, "getdata", NULL);
|
||||
if (ppixels == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixel_count = PySequence_Length(ppixels);
|
||||
for (i=0; i<pixel_count; i++) {
|
||||
PyObject *ppixel, *pr, *pg, *pb;
|
||||
int r, g, b;
|
||||
|
||||
ppixel = PySequence_ITEM(ppixels, i);
|
||||
pr = PySequence_ITEM(ppixel, 0);
|
||||
pg = PySequence_ITEM(ppixel, 1);
|
||||
pb = PySequence_ITEM(ppixel, 2);
|
||||
Py_DECREF(ppixel);
|
||||
r = PyLong_AsLong(pr);
|
||||
g = PyLong_AsLong(pg);
|
||||
b = PyLong_AsLong(pb);
|
||||
Py_DECREF(pr);
|
||||
Py_DECREF(pg);
|
||||
Py_DECREF(pb);
|
||||
|
||||
totr += r;
|
||||
totg += g;
|
||||
totb += b;
|
||||
}
|
||||
|
||||
Py_DECREF(ppixels);
|
||||
|
||||
if (pixel_count) {
|
||||
totr /= pixel_count;
|
||||
totg /= pixel_count;
|
||||
totb /= pixel_count;
|
||||
}
|
||||
|
||||
return inttuple(3, totr, totg, totb);
|
||||
}
|
||||
|
||||
/* Returns the difference between the first block and the second.
|
||||
* It returns an absolute sum of the 3 differences (RGB).
|
||||
*/
|
||||
static int diff(PyObject *first, PyObject *second)
|
||||
{
|
||||
int r1, g1, b1, r2, b2, g2;
|
||||
PyObject *pr, *pg, *pb;
|
||||
pr = PySequence_ITEM(first, 0);
|
||||
pg = PySequence_ITEM(first, 1);
|
||||
pb = PySequence_ITEM(first, 2);
|
||||
r1 = PyLong_AsLong(pr);
|
||||
g1 = PyLong_AsLong(pg);
|
||||
b1 = PyLong_AsLong(pb);
|
||||
Py_DECREF(pr);
|
||||
Py_DECREF(pg);
|
||||
Py_DECREF(pb);
|
||||
|
||||
pr = PySequence_ITEM(second, 0);
|
||||
pg = PySequence_ITEM(second, 1);
|
||||
pb = PySequence_ITEM(second, 2);
|
||||
r2 = PyLong_AsLong(pr);
|
||||
g2 = PyLong_AsLong(pg);
|
||||
b2 = PyLong_AsLong(pb);
|
||||
Py_DECREF(pr);
|
||||
Py_DECREF(pg);
|
||||
Py_DECREF(pb);
|
||||
|
||||
return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(block_getblocks2_doc,
|
||||
"Returns a list of blocks (3 sized tuples).\n\
|
||||
\n\
|
||||
image: A PIL image to base the blocks on.\n\
|
||||
block_count_per_side: This integer determine the number of blocks the function will return.\n\
|
||||
If it is 10, for example, 100 blocks will be returns (10 width, 10 height). The blocks will not\n\
|
||||
necessarely cover square areas. The area covered by each block will be proportional to the image\n\
|
||||
itself.\n");
|
||||
|
||||
static PyObject* block_getblocks2(PyObject *self, PyObject *args)
|
||||
{
|
||||
int block_count_per_side, width, height, block_width, block_height, ih;
|
||||
PyObject *image;
|
||||
PyObject *pimage_size, *pwidth, *pheight;
|
||||
PyObject *result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oi", &image, &block_count_per_side)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pimage_size = PyObject_GetAttrString(image, "size");
|
||||
pwidth = PySequence_ITEM(pimage_size, 0);
|
||||
pheight = PySequence_ITEM(pimage_size, 1);
|
||||
width = PyLong_AsLong(pwidth);
|
||||
height = PyLong_AsLong(pheight);
|
||||
Py_DECREF(pimage_size);
|
||||
Py_DECREF(pwidth);
|
||||
Py_DECREF(pheight);
|
||||
|
||||
if (!(width && height)) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
|
||||
block_width = max(width / block_count_per_side, 1);
|
||||
block_height = max(height / block_count_per_side, 1);
|
||||
|
||||
result = PyList_New(block_count_per_side * block_count_per_side);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ih=0; ih<block_count_per_side; ih++) {
|
||||
int top, bottom, iw;
|
||||
top = min(ih*block_height, height-block_height);
|
||||
bottom = top + block_height;
|
||||
for (iw=0; iw<block_count_per_side; iw++) {
|
||||
int left, right;
|
||||
PyObject *pbox;
|
||||
PyObject *pmethodname;
|
||||
PyObject *pcrop;
|
||||
PyObject *pblock;
|
||||
|
||||
left = min(iw*block_width, width-block_width);
|
||||
right = left + block_width;
|
||||
pbox = inttuple(4, left, top, right, bottom);
|
||||
pmethodname = PyUnicode_FromString("crop");
|
||||
pcrop = PyObject_CallMethodObjArgs(image, pmethodname, pbox, NULL);
|
||||
Py_DECREF(pmethodname);
|
||||
Py_DECREF(pbox);
|
||||
if (pcrop == NULL) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
pblock = getblock(pcrop);
|
||||
Py_DECREF(pcrop);
|
||||
if (pblock == NULL) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyList_SET_ITEM(result, ih*block_count_per_side+iw, pblock);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(block_avgdiff_doc,
|
||||
"Returns the average diff between first blocks and seconds.\n\
|
||||
\n\
|
||||
If the result surpasses limit, limit + 1 is returned, except if less than min_iterations\n\
|
||||
iterations have been made in the blocks.\n");
|
||||
|
||||
static PyObject* block_avgdiff(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *first, *second;
|
||||
int limit, min_iterations;
|
||||
Py_ssize_t count;
|
||||
int sum, i, result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OOii", &first, &second, &limit, &min_iterations)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
count = PySequence_Length(first);
|
||||
if (count != PySequence_Length(second)) {
|
||||
PyErr_SetString(DifferentBlockCountError, "");
|
||||
return NULL;
|
||||
}
|
||||
if (!count) {
|
||||
PyErr_SetString(NoBlocksError, "");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
for (i=0; i<count; i++) {
|
||||
int iteration_count;
|
||||
PyObject *item1, *item2;
|
||||
|
||||
iteration_count = i + 1;
|
||||
item1 = PySequence_ITEM(first, i);
|
||||
item2 = PySequence_ITEM(second, i);
|
||||
sum += diff(item1, item2);
|
||||
Py_DECREF(item1);
|
||||
Py_DECREF(item2);
|
||||
if ((sum > limit*iteration_count) && (iteration_count >= min_iterations)) {
|
||||
return PyLong_FromLong(limit + 1);
|
||||
}
|
||||
}
|
||||
|
||||
result = sum / count;
|
||||
if (!result && sum) {
|
||||
result = 1;
|
||||
}
|
||||
return PyLong_FromLong(result);
|
||||
}
|
||||
|
||||
static PyMethodDef BlockMethods[] = {
|
||||
{"getblocks2", block_getblocks2, METH_VARARGS, block_getblocks2_doc},
|
||||
{"avgdiff", block_avgdiff, METH_VARARGS, block_avgdiff_doc},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static struct PyModuleDef BlockDef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_block",
|
||||
NULL,
|
||||
-1,
|
||||
BlockMethods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyObject *
|
||||
PyInit__block(void)
|
||||
{
|
||||
PyObject *m = PyModule_Create(&BlockDef);
|
||||
if (m == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NoBlocksError = PyErr_NewException("_block.NoBlocksError", NULL, NULL);
|
||||
PyModule_AddObject(m, "NoBlocksError", NoBlocksError);
|
||||
DifferentBlockCountError = PyErr_NewException("_block.DifferentBlockCountError", NULL, NULL);
|
||||
PyModule_AddObject(m, "DifferentBlockCountError", DifferentBlockCountError);
|
||||
|
||||
return m;
|
||||
}
|
||||
303
core/pe/modules/block_osx.m
Normal file
303
core/pe/modules/block_osx.m
Normal file
@@ -0,0 +1,303 @@
|
||||
/* Created By: Virgil Dupras
|
||||
* Created On: 2010-02-04
|
||||
* Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
**/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define RADIANS( degrees ) ( degrees * M_PI / 180 )
|
||||
|
||||
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*)PyBytes_AS_STRING(encoded);
|
||||
size = PyBytes_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;
|
||||
long 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 = PyLong_FromLong(width);
|
||||
if (pwidth == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
pheight = PyLong_FromLong(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,
|
||||
(CGBitmapInfo)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<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;
|
||||
totalR /= pixelCount;
|
||||
totalG /= pixelCount;
|
||||
totalB /= pixelCount;
|
||||
|
||||
return inttuple(3, totalR, totalG, totalB);
|
||||
}
|
||||
|
||||
static PyObject* block_osx_getblocks(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *path, *result;
|
||||
CFStringRef image_path;
|
||||
CFURLRef image_url;
|
||||
CGImageSourceRef source;
|
||||
CGImageRef image;
|
||||
size_t width, height, image_width, image_height;
|
||||
int block_count, block_width, block_height, orientation, i;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oii", &path, &block_count, &orientation)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PySequence_Length(path) == 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "empty path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((orientation > 8) || (orientation < 0)) {
|
||||
orientation = 0; // simplifies checks later since we can only have values in 0-8
|
||||
}
|
||||
|
||||
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) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
image = CGImageSourceCreateImageAtIndex(source, 0, NULL);
|
||||
if (image == NULL) {
|
||||
CFRelease(source);
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
|
||||
width = image_width = CGImageGetWidth(image);
|
||||
height = image_height = CGImageGetHeight(image);
|
||||
if (orientation >= 5) {
|
||||
// orientations 5-8 rotate the photo sideways, so we have to swap width and height
|
||||
width = image_height;
|
||||
height = image_width;
|
||||
}
|
||||
|
||||
CGContextRef context = MyCreateBitmapContext(width, height);
|
||||
|
||||
if (orientation == 2) {
|
||||
// Flip X
|
||||
CGContextTranslateCTM(context, width, 0);
|
||||
CGContextScaleCTM(context, -1, 1);
|
||||
}
|
||||
else if (orientation == 3) {
|
||||
// Rot 180
|
||||
CGContextTranslateCTM(context, width, height);
|
||||
CGContextRotateCTM(context, RADIANS(180));
|
||||
}
|
||||
else if (orientation == 4) {
|
||||
// Flip Y
|
||||
CGContextTranslateCTM(context, 0, height);
|
||||
CGContextScaleCTM(context, 1, -1);
|
||||
}
|
||||
else if (orientation == 5) {
|
||||
// Flip X + Rot CW 90
|
||||
CGContextTranslateCTM(context, width, 0);
|
||||
CGContextScaleCTM(context, -1, 1);
|
||||
CGContextTranslateCTM(context, 0, height);
|
||||
CGContextRotateCTM(context, RADIANS(-90));
|
||||
}
|
||||
else if (orientation == 6) {
|
||||
// Rot CW 90
|
||||
CGContextTranslateCTM(context, 0, height);
|
||||
CGContextRotateCTM(context, RADIANS(-90));
|
||||
}
|
||||
else if (orientation == 7) {
|
||||
// Rot CCW 90 + Flip X
|
||||
CGContextTranslateCTM(context, width, 0);
|
||||
CGContextScaleCTM(context, -1, 1);
|
||||
CGContextTranslateCTM(context, width, 0);
|
||||
CGContextRotateCTM(context, RADIANS(90));
|
||||
}
|
||||
else if (orientation == 8) {
|
||||
// Rot CCW 90
|
||||
CGContextTranslateCTM(context, width, 0);
|
||||
CGContextRotateCTM(context, RADIANS(90));
|
||||
}
|
||||
CGRect myBoundingBox = CGRectMake(0, 0, image_width, image_height);
|
||||
CGContextDrawImage(context, myBoundingBox, image);
|
||||
unsigned char *bitmapData = CGBitmapContextGetData(context);
|
||||
CGContextRelease(context);
|
||||
|
||||
CGImageRelease(image);
|
||||
CFRelease(source);
|
||||
if (bitmapData == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
block_width = max(width/block_count, 1);
|
||||
block_height = max(height/block_count, 1);
|
||||
|
||||
result = PyList_New(block_count * block_count);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0; i<block_count; i++) {
|
||||
int j, top;
|
||||
top = min(i*block_height, height-block_height);
|
||||
for(j=0; j<block_count; j++) {
|
||||
int left;
|
||||
left = min(j*block_width, width-block_width);
|
||||
PyObject *block = getblock(bitmapData, width, height, left, top, block_width, block_height);
|
||||
if (block == NULL) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyList_SET_ITEM(result, i*block_count+j, block);
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmapData);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyMethodDef BlockOsxMethods[] = {
|
||||
{"get_image_size", block_osx_get_image_size, METH_VARARGS, ""},
|
||||
{"getblocks", block_osx_getblocks, METH_VARARGS, ""},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static struct PyModuleDef BlockOsxDef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_block_osx",
|
||||
NULL,
|
||||
-1,
|
||||
BlockOsxMethods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyObject *
|
||||
PyInit__block_osx(void)
|
||||
{
|
||||
PyObject *m = PyModule_Create(&BlockOsxDef);
|
||||
if (m == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
95
core/pe/modules/cache.c
Normal file
95
core/pe/modules/cache.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Created By: Virgil Dupras
|
||||
* Created On: 2010-01-30
|
||||
* Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "BSD" 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/bsd_license
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* I know that there strtol out there, but it requires a pointer to
|
||||
* a char, which would in turn require me to buffer my chars around,
|
||||
* making the whole process slower.
|
||||
*/
|
||||
static long
|
||||
xchar_to_long(char c)
|
||||
{
|
||||
if ((c >= 48) && (c <= 57)) { /* 0-9 */
|
||||
return c - 48;
|
||||
}
|
||||
else if ((c >= 65) && (c <= 70)) { /* A-F */
|
||||
return c - 55;
|
||||
}
|
||||
else if ((c >= 97) && (c <= 102)) { /* a-f */
|
||||
return c - 87;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
cache_string_to_colors(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *s;
|
||||
Py_ssize_t char_count, color_count, i;
|
||||
PyObject *result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#", &s, &char_count)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_count = (char_count / 6);
|
||||
result = PyList_New(color_count);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i=0; i<color_count; i++) {
|
||||
long r, g, b;
|
||||
Py_ssize_t ci;
|
||||
PyObject *color_tuple;
|
||||
|
||||
ci = i * 6;
|
||||
r = (xchar_to_long(s[ci]) << 4) + xchar_to_long(s[ci+1]);
|
||||
g = (xchar_to_long(s[ci+2]) << 4) + xchar_to_long(s[ci+3]);
|
||||
b = (xchar_to_long(s[ci+4]) << 4) + xchar_to_long(s[ci+5]);
|
||||
|
||||
color_tuple = inttuple(3, r, g, b);
|
||||
if (color_tuple == NULL) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyList_SET_ITEM(result, i, color_tuple);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyMethodDef CacheMethods[] = {
|
||||
{"string_to_colors", cache_string_to_colors, METH_VARARGS,
|
||||
"Transform the string 's' in a list of 3 sized tuples."},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static struct PyModuleDef CacheDef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_cache",
|
||||
NULL,
|
||||
-1,
|
||||
CacheMethods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyObject *
|
||||
PyInit__cache(void)
|
||||
{
|
||||
PyObject *m = PyModule_Create(&CacheDef);
|
||||
if (m == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
45
core/pe/modules/common.c
Normal file
45
core/pe/modules/common.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Created By: Virgil Dupras
|
||||
* Created On: 2010-02-04
|
||||
* Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "BSD" 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/bsd_license
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
int max(int a, int b)
|
||||
{
|
||||
return b > 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<n; i++) {
|
||||
pnumber = PyLong_FromLong(va_arg(numbers, long));
|
||||
if (pnumber == NULL) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(result, i, pnumber);
|
||||
}
|
||||
|
||||
va_end(numbers);
|
||||
return result;
|
||||
}
|
||||
20
core/pe/modules/common.h
Normal file
20
core/pe/modules/common.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* Created By: Virgil Dupras
|
||||
* Created On: 2010-02-04
|
||||
* Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
*
|
||||
* This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
* which should be included with this package. The terms are also available at
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
|
||||
/* It seems like MS VC defines min/max already */
|
||||
#ifndef _MSC_VER
|
||||
int max(int a, int b);
|
||||
int min(int a, int b);
|
||||
#endif
|
||||
|
||||
/* Create a tuple out of an array of integers. */
|
||||
PyObject* inttuple(int n, ...);
|
||||
Reference in New Issue
Block a user