Manim / Cairo : color discrepancies - colors

I have some discrepancies in terms of brightness, saturation and hue when using a jpg picture in Manim.
I have a picture which color profile/space is Adobe RGB. I create it, edit it and save it that way. All of my apps previewing the picture are more, or less consistent with the original (enough to be acceptable). Including a movie export test from After effects. Even the image previewer of VS Code shows the image correctly. But when I render it with Manim, it's no good. Way too bright, oversaturated with a slight shift in hue and as if it was downgraded in terms of quality (some subtle but weird color artifacts are showing). You can tell something is off.
Granted, the picture I try to use is an abstract background with subtle gradients of color and light but still. The overall difference and loss in quality are sufficiently there not to be acceptable.
I know that managing color spaces and profiles is a bit tricky and is an art in and on itself but the problem here is that the image is consistent everywhere so far but in Manim's rendered MP4 file.
The only thing I've seen in the doc related to color spaces is this parameter "image_mode". I tried to set it both to RGB and RGBA (only two options available) in the Manim script but it doesn't change anything.
I suspect it's a feature that is more related to the renderer (Cairo) or the MP4 export parameters than Manim itself or maybe it downgrades jpg to gif/png before it renders the picture in Mp4 ? I don't know and I don't know what to do with that anyway since I don't know how to parameter any of this within Manim itself. I can't see any parameters that allow to edit any of this in the doc.
Maybe a plugin could add some functionalities or something ?
Any help would be appreciated.
PS: the picture is 4k and I render it in 4k in Manim, so it should be a pixel to pixel match.
Here is my Manim script:
from manim import *
class Graph(Scene):
def construct(self):
bg = ImageMobject("media/background/13.jpg")
self.add(bg)
self.wait()
And here are the relevant parts of my manim.cfg
[CLI]
write_to_movie = True
format = mp4
save_last_frame = False
write_all = False
save_pngs = False
save_as_gif = False
preview = False
background_color = #212021
background_opacity = 1
renderer = cairo
use_webgl_renderer = False
webgl_renderer_path =
use_opengl_renderer = False
enable_gui = False
gui_location = 0,0
fullscreen = False
window_size = default
window_monitor = 0
force_window = False
use_projection_fill_shaders = False
use_projection_stroke_shaders = False
movie_file_extension = .mp4
frame_rate = 60
frame_size = 3664,1980
pixel_height = 1980
pixel_width = 3664
max_files_cached = 100
flush_cache = True
disable_caching = True
disable_caching_warning = False
enable_wireframe = False
dry_run = False
tex_template =
plugins =

TL;DR: Some random pointers, but no answer to the question.
I have no clue about manim, so I just went searching for "JPEG" in its source code. That brought me to https://github.com/3b1b/manim/blob/3c7a38660af41478e1561073a5319b23fb6b7787/docs/source/documentation/custom_config.rst#L59 which says
The directory for storing raster images to be used in the code (including .jpg, .jpeg, .png and .gif), which will be read by ImageMobject.
Okay, what's ImageMobject? Another search found the place where it loads images and apparently this just uses the Python library PIL to call PIL.Image.open: https://github.com/3b1b/manim/blob/669182944da040c227ccfd018250ee2bbc49649d/manimlib/mobject/types/image_mobject.py#L31
Okay, so does this support color profiles? I don't know. What does this question even mean? You are loading some color image that contains a color profile and it ends up being part of a movie... Should the movie now use that color profile?
Another random pointer that I found is PIL/Pillow decode icc profile information but that didn't really help. All I can say is: The manim code that I found doesn't do anything fancy with color profiles.

Related

How do I carry over identical texture mapping when exporting to DAE?

I am able to open a 3DS file in MeshLab and when I export to Collada DAE format the textures are visible but they are not being projected onto the mesh in the same way as the preview in MeshLab. For example, the front/back faces of a cube would have the proper texture (suppose it's a polka dot) but the top and bottom have a striped look. How can I apply a single texture and have it appear as intended on all faces, like the imported model before I convert it?
This problem is a result of the end software being used to view the DAE file. It's not a problem with MeshLab.
For example, if loading the file into Away3D be sure to handle the texture materials using the TextureMaterial class instead of the simpler SinglePassMaterialBase such as what you might find in their example code. Here is what I use now, and it displays texture properly:
var material:TextureMaterial = cast(asset, TextureMaterial);
material.ambientColor = 0xffffff;
material.lightPicker = _lightPicker;
material.shadowMethod = new FilteredShadowMapMethod(_light);
material.lightPicker = _lightPicker;
material.gloss = 30;
material.specular = 1;
material.ambient = 1;
material.repeat = true;

I want segment the patches of size 32x32px or more using python's opencv

Here I have a image:
Then I have generated threshold image using the code below.
img = cv2.imread('Image_Original.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
lower_gr = np.array([40,0,0])
upper_gr = np.array([90,255,255])
mask = cv2.inRange(hsv,lower_gr,upper_gr)
mask=~mask
res = cv2.bitwise_and(img,img,mask = ~mask)
cv2.imshow('Masked',mask)
cv2.imshow('Result',res)
Then the following images (masked):
and (result):
Now what I want is to remove the black pixels(FROM THE ORiGINAL IMAGE ONLY) by making them zero and I want to extract only patches of size 32x32px or more.
Use cv2.findContours() to find the boundaries of the white patches in your mask image.
Each boundary is returned as a list of 2D points.
Use cv2.boundingRect() to get the width/height of each patch and filter accordingly.
You could also use cv2.minAreaRect(), or cv2.contourArea() to filter based on actual area of the patch.
https://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.htm
Once you have determined which patches should be discarded, overwrite them with black on the colour image using cv2.fillPoly().

Mapnik 2.2 disappearing markers (MarkerSymbolizer)

I'm using Mapnik v2.2.0 from Python 2.7 in an Ubuntu 16.04 environment. The application generates maps with a set of MarkerSymbolizers at various coordinates. In one map, when the MarkerSymbolizers are set to 25x25 pixels, one of the markers does not appear. If the marker size is set to 15x15, all of the markers appear.
The markers are loaded from a csv file:
layer = mapnik.Layer('GPS_tracking_points')
layer.datasource = mapnik.CSV(file=leak_file_name, layer_by_index=0)
The styling is below:
point_style = mapnik.Style()
point_rule = mapnik.Rule()
point_filter = mapnik.Filter ("[val] > 10")
point_rule.filter = point_filter
point_point_symbolizer = mapnik.MarkersSymbolizer()
point_point_symbolizer.width = mapnik.Expression ('25')
point_point_symbolizer.height = mapnik.Expression ('25')
point_point_symbolizer.fill = mapnik.Color ('#ff0000')
point_point_symbolizer.allow_overlap = True
point_point_symbolizer.opacity = 0.5 # semi-transparent
point_rule.symbols.append(point_point_symbolizer)
point_style.rules.append(point_rule)
map_canvas.append_style('high', point_style)
Screenshots are below.
Any help is appreciated.
Thanks.
The problem appears to be related to the way Mapnik 2.2 handles styling in code vs xml. I moved the styling specification to an xml file and everything works as expected.
The answer was found here: https://github.com/mapnik/python-mapnik/issues/117

SKIA - Inaccurate value returned by measureText()

I have a problem measuring text using skia measureText() function.
The value returned is inaccurate.
SkPaint *skPaint = new SkPaint();
SkTypeface* myFont = SkTypeface::CreateFromName("Impact", SkTypeface::kNormal);
skPaint->setTypeface(myFont);
skPaint->setAntiAlias(true);
skPaint->setTextAlign(SkPaint::kLeft_Align);
skPaint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
skPaint->setTextSize(SkIntToScalar(120));
skPaint->setColor(0xff000001);
canvas->drawText(text, length, SkIntToScalar(x) , SkIntToScalar(y) , *skPaint);
SkScalar width = skPaint->measureText(text, length);
The width returned by measureText() is 451.
I checked the generated bitmap text via a photo editor app, the actual width is only 438.
Any thoughts on getting the accurate width of text in SKIA?
Thank you!
I believe what you are trying to match will come from "bounds"
SkRect bounds;
SkScalar textWidth = paint.measureText("some", 4, &bounds);
which is a minimum rectangle to fit a given text, whereas textWidth is slightly larger than that.
I faced this issue too. Dont know why exactly it happens, maybe because of kerning differences, but i came to this:
SizeF RenderTextAndroid::GetStringSizeF() {
UpdateFont();
const base::string16& text = GetLayoutText();
std::vector<SkScalar> widths(text.length());
paint_.getTextWidths(text.c_str(), GetStrByteLen(text), &widths[0], NULL);
return SizeF(std::accumulate(widths.begin(), widths.end(), 0),
font_metrics_.fBottom - font_metrics_.fTop);
}
Where UpdateFont just sets new parameters to SkPaint

view RGBA image

Can someone tell me how can I view an RGBA image? I just want a tool that I can display an RGBA image with!
I have written a code, which outputs only RGBA format. I just want to verify if my code worked, and just want to find a simple tool to view this image.
I wasn't able to come across a software to be able to display a RGBA image.
Thanks in advance.
RGBA files only contain raw channel data. The binary data will not have enough information to display an image (ie. width,height,depth, &tc).
If you know the image dimensions of each .rgba file, you should be able to work with the data. Here's an example of viewing raw date in javascript.
var fr = new FileReader(),
myWidth = 200,
myHeight = 200;
fr.onload = function(frEvent) {
var canvasElement = document.getElementById("myCanvas"),
ctx = canvasElement.getContext("2d"),
blob = ctx.createImageData(myWidth,myHeight),
index = 0;
while(index < frEvent.target.result.length)
blob.data[index] = frEvent.target.result.charCodeAt(index++);
ctx.putImageData(blob,0,0);
}
Imagemagick will be able to display raw RGBA data. Assuming that each color sample is 8 bits.
display -size 200x200 -depth 8 mySimpleData.rgba

Resources