#python 2.7
#coding=utf-8

__author__ = "Terry.Ren"

#try:
#    import Image
#except ImportError:
#    from PIL import Image

from PIL import Image
from PIL import ImageDraw
import ImageEnhance
import os
import urllib
import StringIO
import uuid
import pytesseract #open source

class Captcha(object):    
    def __init__(self, isDebug = False):
        self.__isDebug = isDebug
        self.__currentStepId = 1
        self.__tempFileList = []

    def __BuildTempFileFullName(self, localDir, extName):
        fname = str(uuid.uuid1()) + "_" + str(self.__currentStepId) + "." + extName
        fname = os.path.join(localDir,fname)
        self.__currentStepId += 1
        self.__tempFileList.append(fname)

        return fname

    '''
    Store remote image to local dir
    '''
    def __StoreImage2LocalDir(self, imageUrl , localDir , extName):
        response = urllib.urlopen(imageUrl)
        tempFileFullName = self.__BuildTempFileFullName(localDir, extName)
        with open(tempFileFullName, 'wb') as f: 
            f.write(response.read())         
        
        return  tempFileFullName

    def Clearup(self):
        for filename in self.__tempFileList:
            if os.path.isfile(filename):
                os.remove(filename)
    
    '''
    image enhance
    '''
    def __imageEnhance(self, image):
        enhancer = ImageEnhance.Contrast(image) 
        image_enhancer = enhancer.enhance(4)

        return image_enhancer

    '''
    two value
    '''
    def __twoValue(self, image):
        img = image.convert('RGBA')  # convert to RGBA
        pix = img.load()  #read pix

        for x in range(img.size[0]):  #remove [top-bottom] border
            pix[x, 0] = pix[x, img.size[1] - 1] = (255, 255, 255, 255)

        for y in range(img.size[1]):  #remove [left-right] border
            pix[0, y] = pix[img.size[0] - 1, y] = (255, 255, 255, 255)

        for y in range(img.size[1]):  # two value: R=95，G=95，B=95
            for x in range(img.size[0]):
                if pix[x, y][0] < 95 or pix[x, y][1] < 95 or pix[x, y][2] < 95:
                    pix[x, y] = (0, 0, 0, 255)
                else:
                    pix[x, y] = (255, 255, 255, 255)
        return img

    '''
    Get Captcha Code from on-line web site
    '''
    def GetOnlineCaptchaCode(self, imageUrl, isStoreOriginalImage = False, localDir = '', extName = 'jpg'):

        if isStoreOriginalImage == True:
            if not os.path.isdir(localDir):
                raise ValueError("please validate the argument GetOnlineCaptchaCode.localDir...")
            
            localFileName = self.__StoreImage2LocalDir(imageUrl , localDir , extName)
            img = Image.open(localFileName)
        else:
            imgBuf = StringIO.StringIO(urllib.urlopen(imageUrl).read())
            img = Image.open(imgBuf)
            
        print img.format, img.size, img.mode

        # image Enhance
        img = self.__imageEnhance(img)
        if self.__isDebug:       
            img.save(self.__BuildTempFileFullName(localDir, extName))

        img = self.__twoValue(img)        
        
        tempFileFullName = self.__BuildTempFileFullName(localDir, extName)        
        img.save(tempFileFullName)  # must use local file via tesseract-orc

        text = pytesseract.image_to_string(Image.open(tempFileFullName))
                
        return text 

    '''
    Get Captcha Code from local
    '''
    def GetLocalCaptchaCode(self, imagePath, extName = 'jpg'):

        localDir = os.path.dirname(imagePath)
        img = Image.open(imagePath)
                    
        print img.format, img.size, img.mode

        # image Enhance
        img = self.__imageEnhance(img)
        if self.__isDebug:       
            img.save(self.__BuildTempFileFullName(localDir, extName))

        img = img.convert('RGBA')  # convert to RGBA
        pix = img.load()  #read pix

        for x in range(img.size[0]):  #remove [top-bottom] border
            pix[x, 0] = pix[x, img.size[1] - 1] = (255, 255, 255, 255)

        for y in range(img.size[1]):  #remove [left-right] border
            pix[0, y] = pix[img.size[0] - 1, y] = (255, 255, 255, 255)

        for y in range(img.size[1]):  # two value: R=95，G=95，B=95
            for x in range(img.size[0]):
                if pix[x, y][0] < 90 or pix[x, y][1] < 90 or pix[x, y][2] < 90:
                    pix[x, y] = (0, 0, 0, 255)
                else:
                    pix[x, y] = (255, 255, 255, 255)
        
        tempFileFullName = self.__BuildTempFileFullName(localDir, extName)        
        img.save(tempFileFullName)  # must use local file via tesseract-orc

        text = pytesseract.image_to_string(Image.open(tempFileFullName))
                
        return text 

    def TestImage(self):
        data = [(1,0),(0,1)]
        size = (2,2)
        image = Image.new("1",size)  
        draw = ImageDraw.Draw(image)  
  
        for x in xrange(0,size[0]):  
            for y in xrange(0,size[1]):  
                draw.point((x,y),data[x][y])  
  
        image.save("D:\\GitHub\\TrPython\\NetLib\\Test\\1.gif")  



class SmartCaptcha(object):
    def __init__(self, isDebug = False):
        self.__isDebug = isDebug
        self.__currentStepId = 1
        self.__tempFileList = []

    def __BuildTempFileFullName(self, localDir, extName):
        fname = str(uuid.uuid1()) + "_" + str(self.__currentStepId) + "." + extName
        fname = os.path.join(localDir,fname)
        self.__currentStepId += 1
        self.__tempFileList.append(fname)

        return fname

    '''
    Store remote image to local dir
    '''
    def __StoreImage2LocalDir(self, imageUrl , localDir , extName):
        response = urllib.urlopen(imageUrl)
        tempFileFullName = self.__BuildTempFileFullName(localDir, extName)
        with open(tempFileFullName, 'wb') as f: 
            f.write(response.read())         
        
        return  tempFileFullName

    def Clearup(self):
        for filename in self.__tempFileList:
            if os.path.isfile(filename):
                os.remove(filename)
    
    '''
    image enhance
    '''
    def __imageEnhance(self, image):
        enhancer = ImageEnhance.Contrast(image) 
        image_enhancer = enhancer.enhance(4)

        return image_enhancer

    '''
    two value
    '''
    def __twoValue(self, image):
        img = image.convert('RGBA')  # convert to RGBA
        pix = img.load()  #read pix

        for x in range(img.size[0]):  #remove [top-bottom] border
            pix[x, 0] = pix[x, img.size[1] - 1] = (255, 255, 255, 255)

        for y in range(img.size[1]):  #remove [left-right] border
            pix[0, y] = pix[img.size[0] - 1, y] = (255, 255, 255, 255)

        for y in range(img.size[1]):  # two value: R=100，G=100，B=120
            for x in range(img.size[0]):
                if pix[x, y][0] < 100 and pix[x, y][1] < 100:
                    pix[x, y] = (0, 0, 0, 255)
                else:
                    pix[x, y] = (255, 255, 255, 255)
        return img


    def __getEffectivePoint(self, pix, x , y):
        point, sx , sy = 0, x-1, y-1
        #print sx+3 , sy +3 ,x , y
        for i in xrange(3):
            for j in xrange(3):
                if sx+i == x and sy+j == y:
                    continue
                if pix[sx+i,sy+j] == pix[x,y]:
                    point += 1

        return point;

    '''
    1111111
    1011101
    1011101
    1111111
    '''
    def __clearNoise(self, img, effectivePoint ,processCount):
        
        for ct in xrange(0, processCount):
            pix = img.load()  #read pix
            for x in xrange(1,img.size[0] - 1):
                for y in xrange(1, img.size[1] - 1):
                    point = self.__getEffectivePoint(pix , x , y)
                    if point < effectivePoint:
                        pix[x, y] = (255, 255, 255, 255) # set to Noise
            
        return img

    '''
    Get Captcha Code from local
    '''
    def GetLocalCaptchaCode(self, imagePath, extName = 'jpg'):

        localDir = os.path.dirname(imagePath)
        img = Image.open(imagePath)
                    
        print img.format, img.size, img.mode

        # image Enhance
        img = self.__imageEnhance(img)
        if self.__isDebug:       
            img.save(self.__BuildTempFileFullName(localDir, extName))
        # two value
        img = self.__twoValue(img) 
        if self.__isDebug:
            img.save(self.__BuildTempFileFullName(localDir, extName))
        # clear Noise
        img = self.__clearNoise(img, 3 , 1)

        # orc
        tempFileFullName = self.__BuildTempFileFullName(localDir, extName)        
        img.save(tempFileFullName)  # must use local file via tesseract-orc

        text = pytesseract.image_to_string(Image.open(tempFileFullName))
                
        return text 

if __name__ == "__main__":
    print '[unit test]'

    #validate1 = Captcha()
    #print validate1.GetOnlineCaptchaCode("http://202.119.81.113:8080/verifycode.servlet")

    #validate2 = Captcha(True)
    #print validate2.GetOnlineCaptchaCode("http://202.119.81.113:8080/verifycode.servlet",True,"D:\\GitHub\\TrPython\\NetLib\\Test")
    #validate2.Clearup()

    #validate3 = Captcha(True)
    #print validate3.GetLocalCaptchaCode("D:\\GitHub\\TrPython\\NetLib\\Test\\1400.gif","gif")
    #validate3.TestImage()

    validate4 = SmartCaptcha(True)
    print validate4.GetLocalCaptchaCode("D:\\GitHub\\TrPython\\NetLib\\Test\\xxf2.jpg","jpg")
    #print validate4.GetLocalCaptchaCode("D:\\GitHub\\TrPython\\NetLib\\Test\\queaa.jpg","jpg")

    print pytesseract.image_to_string(Image.open("D:\\GitHub\\TrPython\\NetLib\\Test\\xxf2.jpg"))

















