2014-04-04 4 views
3

과제에 대해 실행 길이 이미지 인코더를 쓰고 있습니다. 내 코드는 매우 잘 이진 및 8 비트 이미지를 작동하지만 4 비트 이미지를 인코딩 할 때 제대로 작동하지 않습니다. 나는 우분투 13.10, 파이썬 3.3.4 및 베개를 사용하고 있습니다. 다음 코드를 실행하면 TrueTrue이 인쇄되지만 TrueFalse이 인쇄됩니다.이미지의 길이 인코딩 실행

내 코드를 테스트하기 위해 랜덤 목록을 생성하여 이미지를 시뮬레이트합니다. 그것은 작동, 첫 번째 가치는 그것을 선물하지만,이 image가 작동하지 않습니다. 이런 이미지가 4 개 더 있지만 그 중 아무 것도 작동하지 않습니다. 나는 어떤 점을 놓치고 있는가? 완전한 참조 4 판 26 페이지

가 다시 한 번 비트는 각 바이트에 전념 알고리즘 데이터 압축에서

from PIL import Image 
import random 

def _encodeImage4bit(imagePixels, width, height): 
    encodedImage = bytearray() 

    count = 0 

    prev = imagePixels[0] 
    tempmap = "" 

    for pixel in imagePixels: 
     if count >= 15: 
      encodedImage.append(15) 
      encodedImage.append(pixel) 
      tempmap += "1" 
      tempmap += "0" 
      count = 0 

     if pixel == prev: 
      count += 1 
     else: 
      if count > 1: 
       encodedImage.append(count) 
       tempmap += "1" 
      encodedImage.append(prev) 
      tempmap += "0" 
      count = 1 
      prev = pixel 

    if count > 1: 
     encodedImage.append(count) 
     tempmap += "1" 

    encodedImage.append(prev) 
    tempmap += "0" 

    encodedImage.extend([0] * _remaining(len(encodedImage))) 
    tempmap += "1"*_remaining(len(tempmap)) 

    encodedImage = _set4bitMap(tempmap, encodedImage) 

    return encodedImage 

def _set4bitMap(imgMap, encodedImage): 
    newImgMap = _divideByRow(imgMap, 8) 

    tempImg = [_merge4bitTo8bit(encodedImage[i], encodedImage[i + 1]) for i in range(0, len(encodedImage), 2)] 
    tempImg = _divideByRow(list(tempImg), 4) 

    return bytearray(_flattenListOfList(_mergeMap(tempImg, newImgMap))) 

def _decodeImage4bit(encodedImage, width, height): 
    decodedImage = [] 

    imgMap, encImg = _get4bitMap(encodedImage) 

    for index, i in enumerate(imgMap): 
     if i == '1' and encImg[index] == 0: 
      break 

     if i == '1': 
      decodedImage.extend([encImg[index + 1]] * encImg[index]) 
     elif imgMap[index - 1] != '1' or index == 0: 
      decodedImage.append(encImg[index]) 

    return decodedImage 

def _get4bitMap(encodedImage): 
    imgMap = "" 

    newEncodedImage = list(encodedImage) 

    I = range(0, len(newEncodedImage), 5) 

    for i in I: 
     imgMap += '{0:08b}'.format(newEncodedImage[i]) 

    for i in sorted(list(I), reverse = True): 
     del newEncodedImage[i] 

    newEncodedImage = _flattenListOfList([_split8bitTo4bit(i) for i in newEncodedImage]) 

    return (imgMap, newEncodedImage) 

def _split8bitTo4bit(eightbit): 
    leftmask = 240 
    rightmask = 15 
    left = (eightbit & leftmask) >> 4 
    right = eightbit & rightmask 

    return (left, right) 

def _merge4bitTo8bit(left, right): 
    return (left << 4) | right 

_remaining = lambda x, y = 8: 0 if x % y == 0 else y - (x % y) 
_mergeMap = lambda z, x:[[int(x[index], 2)] + i for index, i in enumerate(z)] 
_flattenListOfList = lambda flat:[item for sublist in flat for item in sublist] 
_divideByRow = lambda flat, size: [flat[i:i + size] for i in range(0, len(flat), size)] 


if __name__ == "__main__": 
    img = [15] * 100 
    img.extend([random.randrange(0, 16) for n in range(300)]) 
    encImg = _encodeImage4bit(img, 20, 20) 
    decImg = _decodeImage4bit(encImg, 20, 20) 
    print(str(decImg == img)) 

    imgpath = "../../images/4bit/baboon_4bit.bmp" 
    img2 = Image.open(imgpath) 
    encImg2 = _encodeImage4bit(list(img2.getdata(0)), img2.size[0], img2.size[1]) 
    decImg2 = _decodeImage4bit(encImg2, img2.size[0], img2.size[1]) 
    print(str(decImg2 == list(img2.getdata(0)))) 

바이트 은 그레이 값 또는 수를 포함하는지 여부를 표시한다. 이번에는, 그러나, 이들 여분 비트 (8)의 그룹이 축적되고, 각 그룹은 8 바이트 위 (또는 아래)에 출력 스트림에 기록되는 " 에 대응한다."

그것을 변경 4 비트 이미지를 지원합니다.

예 원본 이미지 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 3, 7, 10, 10, 10, 10, 5, 5, 5, 5 , 5, 5, 1,. . .

첫 번째 단계 : 반복 찾기 9, 12, 14, 3, 7, 4, 10, 6, 5, 1,. . .

두 번째 단계 : 어떤 요소가 픽셀 값 (0)인지 확인하기 위해지도를 생성합니다. 반복 번호는 (1) 1 0 0 0 0 1 0 1 0입니다. . .

세 번째 단계 : 길이를 8의 배수로 만들려면 0으로 채우십시오. 길이가 8의 배수가되도록 맵을 채 웁니다.

네 번째 단계 : 지도를 8 개로 나누고 모든 조각을 정수로 변환합니다. 133,. . .

다섯 번째 단계 : 두 쌍을 하나씩 8 비트로 만듭니다. 왼쪽으로 4 번 왼쪽으로 이동하고 오른쪽으로 이동합니다. 156, 226, 166, 81,. . .

여섯 번째 단계 : 값으로 맵을 병합하십시오. 맵의 모든 정수는 이제 값에 4 개의 값을 제공합니다. 133, 156, 227, 116, 166 ,. . .

디코딩은이 작업과 반대입니다.

답변

2

내 문제가 발견되었습니다. 반복 횟수가 15에 도달하면 목록에 추가 값이 추가됩니다. 이를 방지하기 위해 코드를 변경했습니다.

for pixel in imagePixels: 
    if count >= 15: 
     encodedImage.append(15) 
     encodedImage.append(prev) #changed line 
     tempmap += "1" 
     tempmap += "0" 
     count = 0 
     prev = pixel #new line