#!/usr/bin/env python # Copyright (c) 2010, Jonas Tullus # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Color vision deficiency simulator # # based on http://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html # Written by Jonas Tullus, 2010-11-28 from gimpfu import * from array import array # color vision deficiency simulation matrices # source: http://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html # dimensions: # severity [0.0, 0.1 .. 1.0] # protanomaly, deuteranomaly, tritanomaly # 3x3 RGB transformation matrix matrices = [[ # severity 0.0 [[1.000000, 0.000000, -0.000000] ,[0.000000, 1.000000, 0.000000] ,[-0.000000, -0.000000, 1.000000] ] , [[1.000000, 0.000000, -0.000000] ,[0.000000, 1.000000, 0.000000] ,[-0.000000, -0.000000, 1.000000] ] , [[1.000000, 0.000000, -0.000000] ,[0.000000, 1.000000, 0.000000] ,[-0.000000, -0.000000, 1.000000] ] ],[ # severity 0.1 [[0.856167, 0.182038, -0.038205] ,[0.029342, 0.955115, 0.015544] ,[-0.002880, -0.001563, 1.004443] ] , [[0.866435, 0.177704, -0.044139] ,[0.049567, 0.939063, 0.011370] ,[-0.003453, 0.007233, 0.996220] ] , [[0.926670, 0.092514, -0.019184] ,[0.021191, 0.964503, 0.014306] ,[0.008437, 0.054813, 0.936750] ] ],[ # severity 0.2 [[0.734766, 0.334872, -0.069637] ,[0.051840, 0.919198, 0.028963] ,[-0.004928, -0.004209, 1.009137] ] , [[0.760729, 0.319078, -0.079807] ,[0.090568, 0.889315, 0.020117] ,[-0.006027, 0.013325, 0.992702] ] , [[0.895720, 0.133330, -0.029050] ,[0.029997, 0.945400, 0.024603] ,[0.013027, 0.104707, 0.882266] ] ],[ # severity 0.3 [[0.630323, 0.465641, -0.095964] ,[0.069181, 0.890046, 0.040773] ,[-0.006308, -0.007724, 1.014032] ] , [[0.675425, 0.433850, -0.109275] ,[0.125303, 0.847755, 0.026942] ,[-0.007950, 0.018572, 0.989378] ] , [[0.905871, 0.127791, -0.033662] ,[0.026856, 0.941251, 0.031893] ,[0.013410, 0.148296, 0.838294] ] ],[ # severity 0.4 [[0.539009, 0.579343, -0.118352] ,[0.082546, 0.866121, 0.051332] ,[-0.007136, -0.011959, 1.019095] ] , [[0.605511, 0.528560, -0.134071] ,[0.155318, 0.812366, 0.032316] ,[-0.009376, 0.023176, 0.986200] ] , [[0.948035, 0.089490, -0.037526] ,[0.014364, 0.946792, 0.038844] ,[0.010853, 0.193991, 0.795156] ] ],[ # severity 0.5 [[0.458064, 0.679578, -0.137642] ,[0.092785, 0.846313, 0.060902] ,[-0.007494, -0.016807, 1.024301] ] , [[0.547494, 0.607765, -0.155259] ,[0.181692, 0.781742, 0.036566] ,[-0.010410, 0.027275, 0.983136] ] , [[1.017277, 0.027029, -0.044306] ,[-0.006113, 0.958479, 0.047634] ,[0.006379, 0.248708, 0.744913] ] ],[ # severity 0.6 [[0.385450, 0.769005, -0.154455] ,[0.100526, 0.829802, 0.069673] ,[-0.007442, -0.022190, 1.029632] ] , [[0.498864, 0.674741, -0.173604] ,[0.205199, 0.754872, 0.039929] ,[-0.011131, 0.030969, 0.980162] ] , [[1.104996, -0.046633, -0.058363] ,[-0.032137, 0.971635, 0.060503] ,[0.001336, 0.317922, 0.680742] ] ],[ # severity 0.7 [[0.319627, 0.849633, -0.169261] ,[0.106241, 0.815969, 0.077790] ,[-0.007025, -0.028051, 1.035076] ] , [[0.457771, 0.731899, -0.189670] ,[0.226409, 0.731012, 0.042579] ,[-0.011595, 0.034333, 0.977261] ] , [[1.193214, -0.109812, -0.083402] ,[-0.058496, 0.979410, 0.079086] ,[-0.002346, 0.403492, 0.598854] ] ],[ # severity 0.8 [[0.259411, 0.923008, -0.182420] ,[0.110296, 0.804340, 0.085364] ,[-0.006276, -0.034346, 1.040622] ] , [[0.422823, 0.781057, -0.203881] ,[0.245752, 0.709602, 0.044646] ,[-0.011843, 0.037423, 0.974421] ] , [[1.257728, -0.139648, -0.118081] ,[-0.078003, 0.975409, 0.102594] ,[-0.003316, 0.501214, 0.502102] ] ],[ # severity 0.9 [[0.203876, 0.990338, -0.194214] ,[0.112975, 0.794542, 0.092483] ,[-0.005222, -0.041043, 1.046265] ] , [[0.392952, 0.823610, -0.216562] ,[0.263559, 0.690210, 0.046232] ,[-0.011910, 0.040281, 0.971630] ] , [[1.278864, -0.125333, -0.153531] ,[-0.084748, 0.957674, 0.127074] ,[-0.000989, 0.601151, 0.399838] ] ],[ # severity 1.0 [[0.152286, 1.052583, -0.204868] ,[0.114503, 0.786281, 0.099216] ,[-0.003882, -0.048116, 1.051998] ] , [[0.367322, 0.860646, -0.227968] ,[0.280085, 0.672501, 0.047413] ,[-0.011820, 0.042940, 0.968881] ] , [[1.255528, -0.076749, -0.178779] ,[-0.078411, 0.930809, 0.147602] ,[0.004733, 0.691367, 0.303900] ] ]] def cvd(img, layer, anomaly, severity): # choose correct transformation matrix for anomaly and severity matrix = matrices[int(round(severity*10))][anomaly] pdb.gimp_image_undo_group_start(img) bpp = layer.bpp height = layer.height width = layer.width pr = layer.get_pixel_rgn(0, 0, width, height, dirty=True, shadow=False) # complete layer data read as array of unsigned char's data = array("B", pr[0:width, 0:height]) for y in range(height): for x in range(width): offset = bpp*(y*width + x) vector = data[offset:offset+3] for row in range(3): mr = matrix[row] data[offset+row] = min(255, max(0, int(mr[0] * vector[0] + mr[1] * vector[1] + mr[2] * vector[2]))) gimp.progress_update(float(y) / float(height)) anomaly_name = ["Protanomaly", "Deuteranomaly", "Tritanomaly"][anomaly] name = "%s - %0.1f" % (anomaly_name, severity) new_layer = gimp.Layer(img, name, width, height ,layer.type, layer.opacity, layer.mode) img.add_layer(new_layer, 0) out = new_layer.get_pixel_rgn(0, 0, width, height, dirty=True, shadow=False) out[0:width, 0:height] = data.tostring() new_layer.flush() new_layer.update(0,0,width,height) pdb.gimp_image_undo_group_end(img) # Register with The Gimp register( "python_fu_cvd", "Color Vision Deficiency Simulator", "Simulates different types of color vision deficiency with differing levels of severity.\nAt a level of 1.0, it simulates dichromacy, i.e. the complete absence of the relevant color receptor.\n Based on http://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html", "Jonas Tullus", "(c) 2010, Jonas Tullus", "2010", "/Python-Fu/Effects/Color Vision Deficiency", "RGB*", [ (PF_OPTION, "Anomaly", "Type of color vision anomaly", 0, ["Protanomaly (red weak)", "Deuteranomaly (green weak)", "Tritanomaly (blue weak)"]), (PF_SLIDER, "Severity", "Severity of the color vision anomaly", 0.5, (0,1,0.1)) ], [], cvd) main()