I'm trying to learn how load, modify and save images using JuicyPixels version 3.2.5.1. I have the following code:
{-# LANGUAGE OverloadedStrings #-}
import Codec.Picture
imageCreator :: String -> IO ()
imageCreator path = writePng path $ generateImage pixelRenderer 250 300
where pixelRenderer x y = PixelRGB8 (fromIntegral x) (fromIntegral y) 128
loadSampleImage path = case decodePng path of
Left errorMsg -> putStrLn errorMsg
Right sampleImage -> putStrLn "Loaded Successfully"
main = do
imageCreator "test.png"
loadSampleImage "test.png"
The imageCreator function is taken with a slight modification from the JuicyPixels documentation: https://hackage.haskell.org/package/JuicyPixels-3.2.5.1/docs/Codec-Picture.html The modification was the addition of the two calls to fromIntegral, as this example did not compile without them. (It seems strange to me that an example in the documentation wouldn't compile, so if I'm doing something stupid, please let me know)
Running this program will create an image called "test.png" and will print:
Invalid PNG file, signature broken
which is presumably the error message coming from the call to decodePng. I have tried this with a few other PNGs, one that I created in Gimp, and another that I created in MS paint. I did so by removing the imageCreator "test.png" line from my main function, to avoid overwriting the images I wanted to test.
What should I change in order to load PNG images?
loadSampleImage path = case decodePng path of
You're trying to literally decode the string "test.png" as a PNG. You want readPng, not decodePng. (Or you can just use readImage and not care about what format the file is in.)
Related
I'm trying to make this welcome card thingy in discord.py and I'm running my bot on replit.com as of now.
font = ImageFont.truetype("arial.ttf", 28)
I got some examples and it worked great as long as I'm running it on my PC but wen I get to replit.com it gives the error saying
Command raised an exception: OSError: cannot open resource
How should I go about correcting this?
I don't know discord or replit but presume the issue is that you can't upload your binary font file.
If so, you have a couple of options:
find your desired font online somewhere and use requests.get(URL) to grab it in your code on replit, or
make a base64 variable in your code and decode it
The first option is covered here.
Let's look at the second. Say your font is called /Fonts/funky.ttf on your PC. Now you want that in base64 which you can do with a commandline tool on your local PC:
base64 < /Fonts/funky.txt
That will make a long string of characters. Copy it, and in your Python code add a string called font64 and set it equal to the pasted string, i.e.
font64 = 'PASTED STRING'
Now in your code you can convert the string back from base64 to binary, then wrap it in a BytesIO to make it look like a file and load it:
import base64
import io
from PIL import ImageFont
font64 = 'PASTED STRING'
# decode from base64 to binary
binary = base64.b64decode(font64)
# wrap in BytesIO to make file-like object
FileLike = io.BytesIO(binary)
# load font
font = ImageFont.truetype(FileLike, 28)
How can I do similar thing but with DynamicImage (the result of example <- readImage "/filepath.png"):
negative :: Image PixelRGBA8 -> Image PixelRGBA8
negative = pixelMap $ \(PixelRGBA8 r g b a) -> PixelRGBA8 (255 - r) (255 - g) (255 - b) a
And how it's working without any arguments despite signature?
I guess that's what I need, because there's no writeJpg function provided that does work with Image (not Dynamic) type.
I know about dynamicPixelMap function provided by JuicyPixels, but I do not actually understand how to work with it. It will be good if someone can explain it.
UPD:
I've found simple solution:
negative :: Image PixelRGBA8 -> Image PixelRGBA8
dynamicImage <- readImage filepath
let image = convertRGBA8 <$> dynamicImage
let modified = negative <$> image
case modified of
Left err -> print err
Right image -> saveJpgImage 100 outputFile $ ImageRGBA8 image
It's an example, my code is more complicated.
Let's start by looking at why DynamicImage exists. Just looking at the definition is sufficient to make that clear: There are lot of different formats for color data in images. The input routines JuicyPixels provides preserve the color data the way it was stored in the file. But the Image type puts the color data format into the type. This is a problem in Haskell - if you make a function polymorphic, the caller gets to choose the concrete type, not the function itself. There's no way to say "this returns some Image type, depending on the input". So DynamicImage exists - it has a different constructor for each supported color data format. Matching on the constructor tells you the type of Image you're working with, so you can't get the data without also knowing what type it is.
Since the constructors are public, you can match on them to get an Image and use pixelMap on it... But I wouldn't. JPEG files are sometimes in CMYK space, not RGB. Logic in that space is entirely different - it's a subtractive space, rather than additive. And JuicyPixels provides tools to help you out here. The convertRGBA8 function takes a DynamicImage and does whatever colorspace conversion is necessary to give you an Image PixelRBGA8. The conversion will lose details in some cases, but it will get you the format in the example you provided.
I just used this code to convert a picture to binary:
import io
tme = input("Name: ")
with io.open(tme, "rb") as se:
print(se.read())
se.close()
Now it looks like this:
5MEMMMMMMMMMMMMM777777777777777777777777777777777\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95MEEMMMMEEMM\x96\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97
And now I want to be able to interpret what this binary code is telling me exactly... I know it ruffly but not enough to be able to do anything on purpose. I searched the web but I didn't find anything that could help me on that point. Can you tell me how is it working or send me a link where I can read how it's done?
You can't just change random bytes in an image. There's a header at the start with the height and width, probably the date and a palette and information about the number of channels and bits per pixel. Then there is the image data which is often padded, and/or compressed.
So you need an imaging library like PIL/Pillow and code something like this:
from PIL import Image
im = Image.open('image.bmp').convert('RGB')
px = im.load()
# Look at pixel[4,4]
print (px[4,4])
# Make it red
px[4,4] = (255,0,0)
# Save to disk
im.save('result.bmp')
Documentation and examples available here.
The output should be printed in hexadecimal format. The first bytes in bitmap file are 'B' and 'M'.
You are attempting to print the content in ASCII. Moreover, it doesn't show the first bytes because the content has scrolled further down. Add print("start\n") to make sure you see the start of the output.
import io
import binascii
tme = 'path.bmp'
print("start") # make sure this line appears in console output
with io.open(tme, "rb") as se:
content = se.read()
print(binascii.hexlify(content))
Now you should see something like
start
b'424d26040100000000003...
42 is hex value for B
4d is hex value for M ...
The first 14 bytes in the file are BITMAPFILEHEADER
The next 40 bytes are BITMAPINFOHEADER
The bytes after that are color table (if any) and finally the actual pixels.
See BITMAPFILEHEADER and BITMAPINFOHEADER
I'm trying to make a program that will get me some data structure that contains the pixels currently on screen. I tried to compile This example I found on google, but ghc complained that X.getImage isn't in scope. I checked the library on hackage and it doesn't seem to contain a function by that name. But I did find a function by that name in The xhb package.
getImage :: Connection -> GetImage -> IO (Receipt GetImageReply)
So it takes a Connection and a GetImage. I looked up the type and it has a constructor MkGetImage
MkGetImage
format_getImage :: ImageFormat
drawable_getImage :: DRAWABLE
x_getImage :: Int16
y_getImage :: Int16
width_getImage :: Word16
height_getImage :: Word16
plane_mask_GetImage :: Word32
Most of these look familiar from the man page of xgetimage, but I'd never seen DRAWABLE before. Looking in the source on hackage, I find
newtype DRAWABLE = MkDRAWABLE Xid
Now this MkDRAWABLE I can't find any info on whatsoever.
I just want to get the pixels on the screen or in some range. It doesn't have to be with a particular library. But if anyone knows how to get this to work that would be great.
I am trying to create png images from dnd file for better understanding of dnd file.I have seen some software which convert dnd files to image format and I have around 2000 dnd file and I want to convert those file into image file for better understanding
Is it possible to create phylogenetic tree image from clusterw dnd file?
one example of the dnd file is like bellow:
(
(
A:0.336889,
(
(
B:0.204161,
(
(
(
C:0.112841,
(
D:0.0605849,
E:0.0605849):0.112841):0.133598,
(
F:0.0946236,
G:0.0946236):0.133598):0.148107,
H:0.148107):0.204161):0.285724,
I:0.285724):0.336889):0.338734,
J:0.338734):0.338734;
you may use ape library in R, dnd file is a type of Newick format
install.packages("ape")
library(ape)
MyTree <- read.tree("my_file.dnd")
png("my_file.png")
plot(MyTree)
dev.off()
you get:
or, if you prefer use phytools library, Note: before, you must first remove line breaks to input file
((A:0.336889,((B:0.204161,(((C:0.112841,(D:0.0605849,E:0.0605849):0.112841):0.133598,(F:0.0946236,G:0.0946236):0.133598):0.148107,H:0.148107):0.204161):0.285724,I:0.285724):0.336889):0.338734,J:0.338734):0.338734;
install.packages("phytools")
library(phytools)
MyTree <- read.newick("my_file.dnd")
png("my_file2.png")
plot(MyTree)
dev.off()
you get