sixel 0.1.0.0 → 0.1.1.0
raw patch · 4 files changed
+147/−4 lines, 4 filesdep +vectorPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: vector
API changes (from Hackage documentation)
+ Data.Sixel: SixelImage :: String -> SixelImage
+ Data.Sixel: [toSixelString] :: SixelImage -> String
+ Data.Sixel: c_bufsize :: CInt -> CInt -> IO CInt
+ Data.Sixel: c_img2sixel :: Ptr () -> Ptr () -> CInt -> CInt -> IO CInt
+ Data.Sixel: img2sixel :: Image PixelRGB8 -> String
+ Data.Sixel: instance Data.Sixel.ToSixel [Data.Sixel.SixelCmd]
+ Data.Sixel: instance GHC.Classes.Eq Data.Sixel.SixelImage
+ Data.Sixel: instance GHC.Show.Show Data.Sixel.SixelImage
+ Data.Sixel: newtype SixelImage
+ Data.Sixel: toSixelCmds :: Image PixelRGB8 -> [SixelCmd]
- Data.Sixel: toSixel :: ToSixel a => a -> [SixelCmd]
+ Data.Sixel: toSixel :: ToSixel a => a -> SixelImage
Files
- README.md +25/−0
- csrc/sixel.c +83/−0
- sixel.cabal +4/−1
- src/Data/Sixel.hs +35/−3
+ README.md view
@@ -0,0 +1,25 @@+# SIXEL Library for Haskell++SIXEL, short for "six pixels", is a bitmap graphics format supported by terminals and printers from DEC. +It can show graphics in a terminal emulator.++[libsixel](https://saitoha.github.io/libsixel/) provides various demos using SIXEL.++This library is developed for displaying images on ghci.++# Usage++This library provides "Show-intances of Sixel-Commands" and "ToSixel type class to change image data into Sixel-Cmmands".+To render image data on ghci, just run 'toSixel image-data'.+'putImage' is a wrapper of "readImage 'image-file' >>= putStr.show.toSixel".++See following demo.+++++# References++* https://en.wikipedia.org/wiki/Sixel+* https://saitoha.github.io/libsixel+
+ csrc/sixel.c view
@@ -0,0 +1,83 @@+int+bufsize(int width,int height){+ return 256+((5+3*3+2+1)*width + 1)*height;+}++void putnum(unsigned char* buf,int* p, unsigned int r) {+ int v100 = (r)/100;+ int v10 = ((r)%100)/10;+ int v1 = (r)%10;+ if(v100)+ buf[(*p)++] = '0' + v100;+ if(v100 || v10)+ buf[(*p)++] = '0' + v10;+ buf[(*p)++] = '0' + v1;+}++int+img2sixel(unsigned char* buf, unsigned char* img,int width,int height){+ int i,j;+ int p=0;+ int c;+ int prev = (100 << 16 ) | (100 << 8 ) | 100;+ buf[p++] = 033; // ESC+ buf[p++] = 'P';+ buf[p++] = '8';+ buf[p++] = ';';+ buf[p++] = '1';+ buf[p++] = ';';+ buf[p++] = '0';+ buf[p++] = 'q';+ buf[p++] = '"';+ buf[p++] = '1';+ buf[p++] = ';';+ buf[p++] = '1';+ buf[p++] = ';';+ putnum(buf,&p,width);+ buf[p++] = ';';+ putnum(buf,&p,height);+ buf[p++] = '#';+ buf[p++] = '0';+ buf[p++] = ';';+ buf[p++] = '2';+ buf[p++] = ';';+ putnum(buf,&p,100);+ buf[p++] = ';';+ putnum(buf,&p,100);+ buf[p++] = ';';+ putnum(buf,&p,100);+ buf[p++] = '#';+ buf[p++] = '0';+ for(j=0;j<height;j++){+ for(i=0;i<width;i++){+ int pix = (j*width+i)*3;+ int r = img[pix]*101/256;+ int g = img[pix+1]*101/256;+ int b = img[pix+2]*101/256;+ int cur = (r << 16) | (g << 8) | b;+ if (prev != cur){+ buf[p++] = '#';+ buf[p++] = '0';+ buf[p++] = ';';+ buf[p++] = '2';+ buf[p++] = ';';+ putnum(buf,&p,r);+ buf[p++] = ';';+ putnum(buf,&p,g);+ buf[p++] = ';';+ putnum(buf,&p,b);+ }+ buf[p++] = (1 << (j%6))+0x3f;+ prev = cur;+ }+ if(j%6 ==5){+ buf[p++] = '-'; // LR+ }else{+ buf[p++] = '$'; // CR+ }+ }+ buf[p++] = 033; // END+ buf[p++] = '\\'; // END+ return p;+}+
sixel.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: sixel-version: 0.1.0.0+version: 0.1.1.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@@ -13,6 +13,7 @@ build-type: Simple extra-source-files: CHANGELOG.md , demo.png+ , README.md library exposed-modules: Data.Sixel@@ -20,6 +21,8 @@ default-language: Haskell2010 build-depends: base >= 4.7 && < 5 , JuicyPixels+ , vector+ c-sources: csrc/sixel.c executable sixel-exe main-is: Main.hs
src/Data/Sixel.hs view
@@ -6,7 +6,32 @@ import Codec.Picture import Data.Char (chr) import Data.Word (Word8)+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.C.String+import System.IO.Unsafe+import qualified Data.Vector.Storable as V +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 = unsafePerformIO $ do+ let (Image w h vec) = img+ bsize <- c_bufsize (fromIntegral w) (fromIntegral h)+ dptr <- mallocForeignPtrBytes (fromIntegral bsize)+ let (sptr,_) = V.unsafeToForeignPtr0 vec+ withForeignPtr dptr $ \dst -> do+ withForeignPtr sptr $ \src -> do+ len <- c_img2sixel (castPtr dst) (castPtr src) (fromIntegral w) (fromIntegral h)+ peekCStringLen (castPtr dst, fromIntegral len)++newtype SixelImage = SixelImage { toSixelString :: String } deriving (Eq)++instance Show SixelImage where+ show (SixelImage img) = img+ type ColorNumber = Word8 type PixelPattern = Word8@@ -50,13 +75,20 @@ | otherwise = numDigits (n `div` 10) + 1 class ToSixel a where- toSixel :: a -> [SixelCmd]+ toSixel :: a -> SixelImage +instance ToSixel [SixelCmd] where+ toSixel xs = SixelImage (concat $ map show xs)+ instance ToSixel DynamicImage where toSixel dimg = toSixel $ convertRGB8 dimg instance ToSixel (Image PixelRGB8) where- toSixel img =+ toSixel img = SixelImage (img2sixel img)+-- toSixel img = SixelImage (show (toSixelCmds img))++toSixelCmds :: Image PixelRGB8 -> [SixelCmd]+toSixelCmds img = let width = imageWidth img -1 height = imageHeight img -1 header =@@ -104,7 +136,7 @@ putImage file = do readImage file >>= \case Left err -> print err- Right img -> putStr $ show $ toSixel img+ Right img -> putStr $ toSixelString $ toSixel img demo :: [SixelCmd] demo =