Thread: eMonitor
View Single Post
Old 04-26-2012, 03:50 PM   #42
jmseight
Zealot
jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'jmseight knows the difference between 'who' and 'whom'
 
Posts: 130
Karma: 10000
Join Date: Mar 2012
Device: Kindle 3G, Kindle Touch 3G, iRiver Story HD, Sony Reader
Hi All,

I found that for dithered screen, PNG is the smallest file size. For grayscale, PNG is smaller is there is only text windows on the screen, and JPEG is smaller is there is any photos or video.

I modified the Python program so hat for grayscale, it writes two files, both the jpeg and png. It then determine which is smaller and then updates with the smaller file. Since file transfer remains the largest time component, this results in faster updates.

I have found that with Python, to run fast I need to reduce the over number of operations in the critical loop. So in this version I pre-multiply the dither table by 2, so I can remove the last division by 2 or shift. Also, I used 1:2:1 r:g:b instead of 3:6:1 as this will result in less operations.

Code:
#!/usr/bin/python
#eMonitor
#Version 4 modified by jmseight for Kindle/Story (4-26-2012)
#  Rotate screen 90 deg
#  Support Dithering if turned on (no flash on videos)
#    support cropping of dithering table
#    pre-multiple dither table for faster run time
#    saves as png for dithered
#    saves as jpeg and png for grayscale, compare file sizes, then send the smaller file
#  Reduce quality for faster load
#  Uses GeekMaster's Dithering Formula (MIT license)
#  Set to Story HD resolution

#based on eMonitor by Kranu
#Version 2 (9-1-2011)

#Tested on Windows 7 x64, Python 2.7.2, wxPython 2.8
#For more information, see: http://goo.gl/rJoLp

#BEGIN SETUP

#HTTP Server
port=8000              #port of http server (http://127.0.0.1:8000/)

#capture region
#l,t=(1680,1050-800)
l,t=(0,0)              #left and right offset from primary monitor
w,h=(1024,768)          #width and height of capture region
fn1 ='shot1.png'         #file name of screenshot
fn2 ='shot1.jpg'
fn = 'shot.png'
quality = "50"

dt = [
    3,129,34,160,10,136,42,168,192,66,223,97,200,73,231,105,50,
    176,18,144,58,184,26,152,239,113,207,81,247,121,215,89,14,
    140,46,180,7,133,38,164,203,77,235,109,196,70,227,101,62,188,
    30,156,54,180,22,148,251,125,219,93,243,117,211,85 ] # 0-255 dither table

white = 255     #white threshold
black = 0       #black threshold
dithered = False  #dithered or not

#//END SETUP

import wx,socket,os
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

class serv(BaseHTTPRequestHandler):
  def do_GET(self):
    self.send_response(200)
    if self.path.startswith('/'+fn):
      self.send_header('Content-type','image/jpeg')
      self.end_headers()
  
      app=wx.PySimpleApp()
      context=wx.ScreenDC()
      bitmap=wx.EmptyBitmap(w, h, -1)
 
      memory=wx.MemoryDC()
      memory.SelectObject(bitmap)
      memory.Blit(0, 0, w, h, context, l, t)
      memory.SelectObject(wx.NullBitmap)
 
      image=wx.ImageFromBitmap(bitmap)
      data=list(image.GetData())

#      for i in xrange(0,len(data),3):
#        data[i]=data[i+1]=data[i+2]=chr(int(0.2989*float(ord(data[i]))+0.5870*float(ord(data[i+1]))+0.1140*float(ord(data[i+2]))))

      i=0

      if dithered:
        for y in xrange(0,h-1,1):
          yy=(y&7)<<3
          for x in xrange(0,w-1,1):
#            i = (y*w + x)*3
#            j = ((y&7)<<3)|x&7
#            if dt[yy|x&7] < (ord(data[i])+(ord(data[i+1])<<1)+ord(data[i+2]))>>2:
#            if dt[((y&7)*8)|x&7] < (299*ord(data[i])+587*ord(data[i+1])+114*ord(data[i+2]))/1000 :
            if dt[yy|x&7] < (ord(data[i])+(ord(data[i+1])<<1)+ord(data[i+2])):
              data[i] = '\xff'
            else:
              data[i] = '\x00'
            i=i+3
      else:
        for y in xrange(0,h-1,1):
          for x in xrange(0,w-1,1):
#            i = (y*w + x)*3
#            j = ((y&7)<<3)|x&7
            data[i+2]=data[i+1]=data[i]= chr((ord(data[i])+(ord(data[i+1])<<1)+ord(data[i+2]))>>2)
#            data[i] = chr((ord(data[i])+(ord(data[i+1])<<1)+ord(data[i+2]))>>2)
#            data[i] = chr(int((299*ord(data[i])+587*ord(data[i+1])+144*ord(data[i+2]))/1000))
            i=i+3

      image.SetData("".join(data))
      image = image.Rotate90(False)

      image.SetOption(wx.IMAGE_OPTION_PNG_FORMAT, str(wx.PNG_TYPE_GREY_RED))
      image.SetOption(wx.IMAGE_OPTION_PNG_BITDEPTH, "8")

      if dithered:
        image.SaveFile(fn,wx.BITMAP_TYPE_PNG)
      else:
        image.SaveFile(fn1,wx.BITMAP_TYPE_PNG)
        image.SetOption("quality", quality)
        image.SaveFile(fn2,wx.BITMAP_TYPE_JPEG)
        size1 = os.stat(fn1).st_size
        size2 = os.stat(fn2).st_size
        if size2 < size1:
          image.SaveFile(fn,wx.BITMAP_TYPE_JPEG)
        else:
          image.SaveFile(fn,wx.BITMAP_TYPE_PNG)

      f=open(fn,'rb')
      self.wfile.write(f.read())
    else:
      self.send_header('Content-type','text/html')
      self.end_headers()
      self.wfile.write('<!doctype html>'\
        '<html lang="en">'\
        '<head>'\
        '<title>eMonitor by Kranu</title>'\
        '</head>'\
        '<body style="margin:0px;">'\
        '<img id="pic" src="'+fn+'" style="float:left;width:100%;height:100%;">'\
        '<script type="text/javascript">'\
        'document.getElementById("pic").onload=function() {'\
        '  document.getElementById("pic").src="'+fn+'?"+(new Date()).getTime();'\
        '}'\
        '</script>'\
        '</body>'\
        '</html>')
try:
  print 'eMonitor by jmseight (based on Kranu)'

  for j in xrange(0, len(dt)-1, 1):
    if dt[j] < black:
      dt[j] = black
    if dt[j] > white:
      dt[j] = white
  for j in xrange(0, len(dt)-1, 1):
    dt[j] = dt[j] << 2
    
  #Amazon's website is used here for its reliablity. Feel free to change it.
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  s.connect(("amazon.com",80))

  print 'Starting.. ',
  server=HTTPServer(('',port),serv)
  print 'Press Ctrl+C to stop'
  print

  print 'On your Kindle/Story, visit http://'+s.getsockname()[0]+':'+str(port)+'/'

  server.serve_forever()
except KeyboardInterrupt:
  print 'Stopping.. ',
  server.socket.close()
  print 'Have a nice day!'
Attached Files
File Type: zip webserver_v4.zip (2.3 KB, 446 views)
jmseight is offline   Reply With Quote