Trivial calculation related to computer displays v0.3.1

Here's a simple program I wrote to aid in comparing basic data about standard computer displays. Enjoy! I will upload it to it's regular place later, but I need a bit more time than usual this time.
Edited to version v0.3.1 on 2010.04.07

-- Calculates basic LCD monitor parameters from diagonals.
--
-- Copyright (c) bkil, 2009
-- License: GNU GPL v2 (or later), see the
--  attached gpl-2.0.txt for details.
--
--Changelog:
-- 2009.01.20 v0.0 first release
-- 2009.01.22 v0.1 refactoring: cleanup, typo in comments
-- 2009.01.29 v0.2 refactoring: friendlier names, Html type
-- 2009.02.04 v0.3 refactoring: tidied comments, improved formatting,
--            fixed a few names (CamelCase), used html more
-- 2010.04.07 v0.3.1 DPI, EEE, widescreens added
--


--HTML substring type
newtype HtmlChar = HtmlChar Char
type Html = [HtmlChar]

instance Show HtmlChar where
         show (HtmlChar ch) = [ch]

showHtml :: Html -> String
showHtml = concat . map show

--does conversion with simple HTML escaping of main body text
toHtml :: String -> Html
toHtml = concat . map code  where
   code '&' = html "&"
   code '<' = html "&lt;"
   code '>' = html "&gt;"
   code c   = html [c]

--constructor for constants (no conversion!)
html :: String -> Html
html = map HtmlChar

--similar to unlines
unlinesHtml :: [Html] -> Html
unlinesHtml s = concat . zipWith (++) s $ repeat $ html ['\n']


--the type of the data structure used by the parameter routine
data UnionParameter =
      ParamInt   Int       String | -- an Int  with a measure
      ParamFloat Float Int String | -- a Float with a measure
      ParamRatio Int Int            -- a ratio

instance Show UnionParameter where
         show (ParamInt   i        s) = show i ++ s
         show (ParamFloat x digits s) = showPrecision x digits ++ s
         show (ParamRatio a b)        = show a ++ ":" ++ show b


--an optional (ugly) routine for outputting in limited precision
showPrecision :: Float -> Int -> String
showPrecision x digits
 | digits == 0 = show $ myRound x
 | otherwise   = int ++ "." ++ frac  where
    (int,frac) = if shifted_x < shift   -- almost: x < 1
       then replacehd0 $ int_to_2str (shifted_x + shift)
       else              int_to_2str shifted_x
    shift     = 10 ^ digits
    shifted_x = myRound $ x * fromIntegral shift
    replacehd0 ([],b)    = ([],b)  -- never happens
    replacehd0 ((_:a),b) = (('0':a),b)
    int_to_2str y = splitAt (length sy - digits) sy  where
       sy = show y

--a helper for showPrecision
myRound :: Float -> Int
myRound = floor . (0.5+)


--the routine that calculates all the parameters
-- input: diagonal in inches, horizontal pixels, vertical pixels
--
getParams :: (Float, Int, Int) -> [UnionParameter]
getParams (diag_inch, xi, yi) =
 [ParamFloat diag_inch 1 "in",  ParamRatio a b,
  ParamInt   xi          "px",  ParamInt   yi        "px",
  ParamFloat dpi       0 "dpi", ParamFloat dotPitch 3 "mm",
  ParamFloat megaPix 2 "Mpx",
  ParamFloat area_cm  0 "cm^2",
  ParamFloat w        1 "mm",   ParamFloat h        1 "mm"
 ]  where
   a        = xi `div` gcd xi yi ;  b  = yi `div` gcd xi yi
   x        = fromIntegral xi    ;  y  = fromIntegral yi
   diag_mm  = diag_inch * inch_mm
   inch_mm  = 25.4
   aspect   = x/y
   calcDiag = sqrt $ aspect*aspect + 1*1
   scale    = diag_mm/calcDiag
   w        = scale*aspect       ;  h = scale*1
   area_cm  = w*h / 1e2
   megaPix  = x*y / 1e6
   dotPitch = w/x
   dpi      = x / (w/inch_mm)


--presentation alternative #1: list format in plain text
listTable :: Show a=> [[a]] -> String
listTable   = unlines . map (listSemi . map show)  where
   listSemi = foldl1 (\a b -> a ++ "; " ++ b)

--presentation alternative #2: HTML (uses toHtml, html, unlinesHtml)
-- (you could use concat instead of unlines to suppress line breaks)
htmlTable :: Show a=> [[a]] -> Html
htmlTable table = unlinesHtml lines  where
   lines = [html "<table>"] ++ rows table ++ [html "</table>"]
   rows  = map (\r-> html " <tr>" ++ (concat . cols)r ++ html "</tr>")
   cols  = map (\c-> html " <td>" ++ (toHtml . show)c ++ html "</td>")

--outputs a few parameters of common computer displays
main       = putStr result  where
   result  = ( showHtml $ htmlTable results ) ++ listTable results
   results = map getParams modes
   modes   = [
      (7,    800, 480),
      (13,   640, 480), (13, 800, 600),
      (15,  1024, 768),
      (17,  1280,1024),
      (18.5,1360, 768),
      (19,  1440, 900), (19,1280,1024),
      (20,  1680,1050), (20,1600,1200),
      (22,  1680,1050), (22,1920,1080), (22,1600,1200)
      ]

Output:
7.0in 5:3 800px 480px 133dpi 0.191mm 0.38Mpx 139cm^2 152.5mm 91.5mm
13.0in 4:3 640px 480px 62dpi 0.413mm 0.31Mpx 523cm^2 264.2mm 198.1mm
13.0in 4:3 800px 600px 77dpi 0.330mm 0.48Mpx 523cm^2 264.2mm 198.1mm
15.0in 4:3 1024px 768px 85dpi 0.298mm 0.79Mpx 697cm^2 304.8mm 228.6mm
17.0in 5:4 1280px 1024px 96dpi 0.263mm 1.31Mpx 910cm^2 337.2mm 269.7mm
18.5in 85:48 1360px 768px 84dpi 0.301mm 1.04Mpx 945cm^2 409.2mm 231.1mm
19.0in 8:5 1440px 900px 89dpi 0.284mm 1.30Mpx 1047cm^2 409.2mm 255.8mm
19.0in 5:4 1280px 1024px 86dpi 0.294mm 1.31Mpx 1136cm^2 376.8mm 301.5mm
20.0in 8:5 1680px 1050px 99dpi 0.256mm 1.76Mpx 1160cm^2 430.8mm 269.2mm
20.0in 4:3 1600px 1200px 100dpi 0.254mm 1.92Mpx 1239cm^2 406.4mm 304.8mm
22.0in 8:5 1680px 1050px 90dpi 0.282mm 1.76Mpx 1403cm^2 473.9mm 296.2mm
22.0in 16:9 1920px 1080px 100dpi 0.254mm 2.07Mpx 1334cm^2 487.0mm 274.0mm
22.0in 4:3 1600px 1200px 91dpi 0.279mm 1.92Mpx 1499cm^2 447.0mm 335.3mm

Comments

Post a Comment

Popular posts from this blog

Tftp secret of TL-WR740N uncovered

Hidden TFTP of TP-Link routers

Haskell for embedded: C output, compilers, monads, Timber