Haskell X Screenshot Program - image

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.

Related

How can I edit pixels of DynamicImage using JuicyPixels (Haskell)?

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.

Where is 's' defined in https://github.com/Workiva/go-datastructures/tree/master/bitarray?

I do not see where s is defined. Guru will not tell me. All I get is "no object for identifier" but it knows about the k right beside it. Here is a snippet that is typical of the linked code:
func getIndexAndRemainder(k uint64) (uint64, uint64) {
return k / s, k % s
}
The one letter variable name definitely makes it harder to grep around for. I have looked for the usual suspects: var s uint64, s := ..., and nothing. Clearly it needs to be a global value defined somewhere.
This leaves me with two questions:
Where is s coming from?
How would I find it without asking here?
EDIT:
For others who stumble on this.
Guru failed me because I did not checkout the source for the package under a proper Go workspace by placing the git clone under /some/path/src and setting the GOPATH to /some/path. So while I thought GOPATH=. guru definition s would work, the GOPATH was ignored. guru could find k because it is in the file but it did not know how to look in other files.
My grep failed cause const uses a simple = not a :=. I will remember this when grepping in the future.
It is defined in go-datastructures/bitarray/block.go:
// s denotes the size of any element in the block array.
// For a block of uint64, s will be equal to 64
// For a block of uint32, s will be equal to 32
// and so on...
const s = uint64(unsafe.Sizeof(block(0)) * 8)
As the variable s was not defined in the function, and it was not prefixed by a package name or alias, it had to be a global (variable or constant) of the bitarray package.
Once that was known, I went through every file in the folder go-datastructures/bitarray that was not suffixed with _test and I looked for a top-level declaration for s.
It's defined in go-datastructures/bitarray/block.go, line #33:
const s = uint64(unsafe.Sizeof(block(0)) * 8)
"Modern" IDEs with Go support usually have the ability to go to the definition of a symbol / identifier your cursor is at or what you click on. For example in Atom with the Go-plus plugin you can go to the definition by holding down the CTRL key while clicking.
These IDEs use the godef open source tool to find the definition source file and line, you may also use it directly. You can find the godef documentation here: https://godoc.org/github.com/rogpeppe/godef
Another tool, guru is also capable of tracking the definition of it. Both guru and godef works in Atom, and were able to jump to block.go, to the definition of s. But it's much easier to use an "armored" IDE and just do a simple click.
Also note that the success of using grep and patterns is limited, as variable and constant declarations can be grouped, and the following are also valid declarations:
var (
longer = 3
s = uint64(3)
)
Or:
var (
s = someExpression
longer = 3
)
Or:
const (
p = uint64(iota)
s
x
)

MATLAB ConnectedComponentLabeler does not work in for loop

I am trying to get a set of binary images' eccentricity and solidity values using the regionprops function. I obtain the label matrix using the vision.ConnectedComponentLabeler function.
This is the code I have so far:
files = getFiles('images');
ecc = zeros(length(files)); %eccentricity values
sol = zeros(length(files)); %solidity values
ccl = vision.ConnectedComponentLabeler;
for i=1:length(files)
I = imread(files{i});
[L NUM] = step(ccl, I);
for j=1:NUM
L = changem(L==j, 1, j); %*
end
stats = regionprops(L, 'all');
ecc(i) = stats.Eccentricity;
sol(i) = stats.Solidity;
end
However, when I run this, I get an error says indicating the line marked with *:
Error using ConnectedComponentLabeler/step
Variable-size input signals are not supported when the OutputDataType property is set to 'Automatic'.'
I do not understand what MATLAB is talking about and I do not have any idea about how to get rid of it.
Edit
I have returned back to bwlabel function and have no problems now.
The error is a bit hard to understand, but I can explain what exactly it means. When you use the CVST Connected Components Labeller, it assumes that all of your images that you're going to use with the function are all the same size. That error happens because it looks like the images aren't... hence the notion about "Variable-size input signals".
The "Automatic" property means that the output data type of the images are automatic, meaning that you don't have to worry about whether the data type of the output is uint8, uint16, etc. If you want to remove this error, you need to manually set the output data type of the images produced by this labeller, or the OutputDataType property to be static. Hopefully, the images in the directory you're reading are all the same data type, so override this field to be a data type that this function accepts. The available types are uint8, uint16 and uint32. Therefore, assuming your images were uint8 for example, do this before you run your loop:
ccl = vision.ConnectedComponentLabeler;
ccl.OutputDataType = 'uint8';
Now run your code, and it should work. Bear in mind that the input needs to be logical for this to have any meaningful output.
Minor comment
Why are you using the CVST Connected Component Labeller when the Image Processing Toolbox bwlabel function works exactly the same way? As you are using regionprops, you have access to the Image Processing Toolbox, so this should be available to you. It's much simpler to use and requires no setup: http://www.mathworks.com/help/images/ref/bwlabel.html

JuicyPixels can't load PNG files

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.)

Returning an array of tuples

func timesForDepartureStation(departureStation: Station, #arrivalStation: Station) -> Array<(departureTime: NSDate, arrivalTime: NSDate)>{
For some reason, the Xcode LINT tool completely stop me from compiling this line of code. It notes that the # is Extraneous (even though it's not and I just want the arrivalStation to be an external parameter as well), and when calling from an external class... it doesn't even recognize the second parameter. I have no clue why, but I've restarted Xcode numerous times and am very tempted to do a reinstall. Has anyone found a similar issue?
By default every parameter except the first uses the parameter name as the external name there is no need to force the second argument. So this func signature should give you what you want:
func timesForDepartureStation(departureStation: Station, arrivalStation: Station) -> Array<(departureTime: NSDate, arrivalTime: NSDate)>
Then you can call this function like this:
timesForDepartureStation(departStation, arrivalStation: arrStation)
If you want to force the first argument to use an external name you can use the # infront of departureStation, but that is not necessary based on the name of the function.
As well if you are looking to not use named parameters for a function you must put an _ in front of the parameter in the definition like so:
func timesForDepartureStation(departureStation: Station, _ arrivalStation: Station) -> Array<(departureTime: NSDate, arrivalTime: NSDate)>
Then it can be called like so:
timesForDepartureStation(departStation, arrStation)
Restarting my computer and Xcode fixed everything. Silly betas

Resources