sixel 0.1.1.1 → 0.1.2.0
raw patch · 5 files changed
+111/−54 lines, 5 filesdep +processdep +temporaryPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: process, temporary
API changes (from Hackage documentation)
- Data.Sixel: demo :: [SixelCmd]
- Data.Sixel: img2sixel' :: Image PixelRGB8 -> ByteString
- Data.Sixel: numDigits :: (Integral a, Ord a, Num a) => a -> Int
- Data.Sixel: pixel2colorMap :: Image PixelRGB8 -> Int -> Int -> SixelCmd
+ Data.Sixel: LatexStr :: String -> Float -> LatexStr
+ Data.Sixel: [strSize] :: LatexStr -> Float
+ Data.Sixel: [toLatexStr] :: LatexStr -> String
+ Data.Sixel: data LatexStr
+ Data.Sixel: instance Data.Sixel.ToSixel Data.Sixel.LatexStr
+ Data.Sixel: instance Data.Sixel.ToSixel Data.Sixel.SixelImage
+ Data.Sixel: instance GHC.Classes.Eq Data.Sixel.LatexStr
+ Data.Sixel: instance GHC.Show.Show Data.Sixel.LatexStr
+ Data.Sixel: instance GHC.Show.Show a => Data.Sixel.ToSixel a
+ Data.Sixel: latex :: String -> LatexStr
+ Data.Sixel: latexStr :: String -> Float -> String
+ Data.Sixel: math :: String -> LatexStr
+ Data.Sixel: putSixel :: ToSixel a => a -> IO ()
- Data.Sixel: ColorMapHLS :: ColorNumber -> Int -> Int -> Int -> SixelCmd
+ Data.Sixel: ColorMapHLS :: ColorNumber -> Int -> Word8 -> Word8 -> SixelCmd
- Data.Sixel: Size :: Int -> Int -> Int -> Int -> SixelCmd
+ Data.Sixel: Size :: Int -> Int -> Width -> Height -> SixelCmd
- Data.Sixel: img2sixel :: Image PixelRGB8 -> String
+ Data.Sixel: img2sixel :: Image PixelRGB8 -> ByteString
Files
- CHANGELOG.md +4/−0
- csrc/sixel.c +19/−1
- demo.png binary
- sixel.cabal +3/−1
- src/Data/Sixel.hs +85/−52
CHANGELOG.md view
@@ -3,3 +3,7 @@ ## 0.1.0.0 -- 2020-05-17 * First version.++## 0.1.2.0 -- 2020-05-19++* Support for Latex
csrc/sixel.c view
@@ -16,7 +16,7 @@ int img2sixel(unsigned char* buf, unsigned char* img,int width,int height){- int i,j;+ int i,j,k; int p=0; int c; int prev = (100 << 16 ) | (100 << 8 ) | 100;@@ -66,6 +66,24 @@ putnum(buf,&p,g); buf[p++] = ';'; putnum(buf,&p,b);+ } else {+ int num;+ for(k=i+1;k<width;k++){+ int pix = (j*width+k)*3;+ int r = img[pix]*101/256;+ int g = img[pix+1]*101/256;+ int b = img[pix+2]*101/256;+ int nxt = (r << 16) | (g << 8) | b;+ if(nxt!=cur){+ break;+ }+ }+ num = (k-i)-1;+ if(num > 3){+ buf[p++] = '!';+ putnum(buf,&p,num+1);+ i=k-1;+ } } buf[p++] = (1 << (j%6))+0x3f; prev = cur;
demo.png view
binary file changed (94084 → 127588 bytes)
sixel.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: sixel-version: 0.1.1.1+version: 0.1.2.0 synopsis: Sixel library to show images in a terminal emulator description: Sixel can show graphics on a terminal emulator. This library is developed to showing images on ghci. license: BSD3@@ -23,6 +23,8 @@ , JuicyPixels , vector , bytestring+ , process+ , temporary c-sources: csrc/sixel.c executable sixel-exe
src/Data/Sixel.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE LambdaCase #-} module Data.Sixel where@@ -14,30 +15,35 @@ import Foreign.C.Types import Foreign.ForeignPtr import Foreign.Ptr-import System.IO.Unsafe+import System.IO.Temp (withSystemTempDirectory)+import System.IO.Unsafe (unsafePerformIO)+import System.Process (readProcessWithExitCode) foreign import ccall "bufsize" c_bufsize :: CInt -> CInt -> IO CInt foreign import ccall "img2sixel" c_img2sixel :: Ptr () -> Ptr () -> CInt -> CInt -> IO CInt -img2sixel :: Image PixelRGB8 -> String-img2sixel img = BC.unpack $ img2sixel' img+newtype SixelImage = SixelImage {toSixelString :: String} deriving (Eq) -img2sixel' :: Image PixelRGB8 -> ByteString-img2sixel' img = unsafePerformIO $ do- let (Image w h vec) = img- bsize <- c_bufsize (fromIntegral w) (fromIntegral h)- let (sptr, _) = V.unsafeToForeignPtr0 vec- B.createAndTrim (fromIntegral bsize) $ \dst -> do- withForeignPtr sptr $ \src -> do- len <- c_img2sixel (castPtr dst) (castPtr src) (fromIntegral w) (fromIntegral h)- return (fromIntegral len)+data LatexStr+ = LatexStr+ { toLatexStr :: String,+ strSize :: Float+ }+ deriving (Eq) -newtype SixelImage = SixelImage {toSixelString :: String} deriving (Eq)+latex :: String -> LatexStr+latex str = LatexStr str 2.5 +math :: String -> LatexStr+math str = LatexStr ("$"++str++"$") 2.5+ instance Show SixelImage where show (SixelImage img) = img +instance Show LatexStr where+ show str = show $ toSixel str+ type ColorNumber = Word8 type PixelPattern = Word8@@ -49,9 +55,9 @@ data SixelCmd = Start Int Int Int | End- | Size Int Int Int Int+ | Size Int Int Width Height | ColorMapRGB ColorNumber Word8 Word8 Word8- | ColorMapHLS ColorNumber Int Int Int+ | ColorMapHLS ColorNumber Int Word8 Word8 | Color ColorNumber | Sixel PixelPattern | Repeat Int PixelPattern@@ -75,23 +81,57 @@ instance {-# OVERLAPS #-} Show [SixelCmd] where show xs = concat $ map show xs -numDigits :: (Integral a, Ord a, Num a) => a -> Int-numDigits n- | n < 10 = 1- | otherwise = numDigits (n `div` 10) + 1- class ToSixel a where toSixel :: a -> SixelImage+ putSixel :: a -> IO () -instance ToSixel [SixelCmd] where+instance {-# OVERLAPS #-} (Show a) => ToSixel a where+ toSixel xs = SixelImage $ show xs+ putSixel xs = putStrLn $ show xs++instance {-# OVERLAPS #-} ToSixel [SixelCmd] where toSixel xs = SixelImage (concat $ map show xs)+ putSixel xs = putStr $ concat $ map show xs -instance ToSixel DynamicImage where+instance {-# OVERLAPS #-} ToSixel DynamicImage where toSixel dimg = toSixel $ convertRGB8 dimg+ putSixel img = BC.putStr $ img2sixel $ convertRGB8 img -instance ToSixel (Image PixelRGB8) where- toSixel img = SixelImage (img2sixel img)+instance {-# OVERLAPS #-} ToSixel (Image PixelRGB8) where+ toSixel img = SixelImage (BC.unpack $ img2sixel img)+ putSixel img = BC.putStr $ img2sixel img +instance {-# OVERLAPS #-} ToSixel SixelImage where+ toSixel = id+ putSixel img = putStr $ show img++latexStr :: String -> Float -> String+latexStr str size =+ "\\documentclass[border=2pt]{standalone}"+ ++ "\\usepackage{amsmath}"+ ++ "\\usepackage{graphicx}"+ ++ "\\usepackage{varwidth}"+ ++ "\\begin{document}"+ ++ "\\begin{varwidth}{\\linewidth}"+ ++ "\\scalebox{"+ ++ show size+ ++ "}{"+ ++ str+ ++ "}"+ ++ "\\end{varwidth}"+ ++ "\\end{document}"++instance ToSixel LatexStr where+ toSixel (LatexStr str size) = unsafePerformIO $ do+ withSystemTempDirectory "sixel" $ \dir -> do+ writeFile (dir ++ "/sixel.tex") (latexStr str size)+ (_,outlog,errlog) <- readProcessWithExitCode "pdflatex" ["-output-directory="++dir ,dir ++ "/sixel.tex"] ""+ readProcessWithExitCode "convert" [dir ++ "/sixel.pdf", "-quality", "90", dir ++ "/sixel.png"] ""+ readImage (dir ++ "/sixel.png") >>= \case+ Left err -> error $ "can not read sixel.png. // " ++ errlog ++ " // " ++ outlog+ Right img -> return $ toSixel img+ putSixel img = putStr $ show $ toSixel img+ -- toSixel img = SixelImage (show (toSixelCmds img)) toSixelCmds :: Image PixelRGB8 -> [SixelCmd]@@ -130,37 +170,30 @@ [footer] ] in pixels--pixel2colorMap :: Image PixelRGB8 -> Int -> Int -> SixelCmd-pixel2colorMap img i j =- let p@(PixelRGB8 r g b) = pixelAt img i j- rr = fromIntegral $ ((fromIntegral r :: Int) * 101) `div` 256- gg = fromIntegral $ ((fromIntegral g :: Int) * 101) `div` 256- bb = fromIntegral $ ((fromIntegral b :: Int) * 101) `div` 256- in ColorMapRGB 0 rr gg bb+ where+ pixel2colorMap :: Image PixelRGB8 -> Int -> Int -> SixelCmd+ pixel2colorMap img i j =+ let p@(PixelRGB8 r g b) = pixelAt img i j+ rr = fromIntegral $ ((fromIntegral r :: Int) * 101) `div` 256+ gg = fromIntegral $ ((fromIntegral g :: Int) * 101) `div` 256+ bb = fromIntegral $ ((fromIntegral b :: Int) * 101) `div` 256+ in ColorMapRGB 0 rr gg bb --- putImage :: FilePath -> IO ()--- putImage file = do--- readImage file >>= \case--- Left err -> print err--- Right img -> putStr $ toSixelString $ toSixel img+img2sixel :: Image PixelRGB8 -> ByteString+img2sixel img = unsafePerformIO $ do+ let (Image w h vec) = img+ bsize <- c_bufsize (fromIntegral w) (fromIntegral h)+ let (sptr, _) = V.unsafeToForeignPtr0 vec+ B.createAndTrim (fromIntegral bsize) $ \dst -> do+ withForeignPtr sptr $ \src -> do+ len <- c_img2sixel (castPtr dst) (castPtr src) (fromIntegral w) (fromIntegral h)+ return (fromIntegral len) +-- | Display sixel image via ByteString+-- putStr of String is really slow on ghci. (Compiled version is not so slow.)+-- To improve perfomance of rendering on ghci, this function uses putStr of ByteString. putImage :: FilePath -> IO () putImage file = do readImage file >>= \case Left err -> print err- Right img -> BC.putStr $ img2sixel' $ convertRGB8 img--demo :: [SixelCmd]-demo =- [ Start 0 0 8,- Size 1 1 100 100,- ColorMapRGB 0 50 0 0,- Color 0,- Sixel 1,- Sixel 2,- Sixel 4,- Sixel 8,- Sixel 16,- End- ]+ Right img -> putSixel img