Spinning circle with transloadit. Is it possible with watermark or image rotation? - transloadit

I'm trying to achieve a spinning circle with artwork as a mask.
From what I've seen there is no way to use a moving watermark or an automatic rotation of an image. Is it possible with transloadit?
The result should be a "vinyl" spinning.

This question is quite complex to answer, but it's very much do-able with Transloadit. I'll be using python to answer it primarily for OpenCV, but of course you can use a language that you prefer - I'll try and make it as language agnostic as possible.
I used 4 different templates to get the result we want, as well as some local python magic to tie everything together - here goes.
First we need to resize the image so it fits nicely onto the vinyl record.
{
"steps": {
":original": {
"robot": "/upload/handle"
},
"resize": {
"use": ":original",
"robot": "/image/resize",
"format": "png",
"resize_strategy": "fillcrop",
"width": 350,
"height": 350,
"imagemagick_stack": "v2.0.7"
}
}
}
Now, we want to mask this image using OpenCV and NumPy like so:
# Mask the image
# Reads the input image
img = cv2.imread(img_path)
# Creates a mask with the same size as the image
mask = np.zeros(img.shape, dtype=np.uint8)
# Creates a white circle in the centre
mask = cv2.circle(mask, (175, 175), 175, (255, 255, 255), -1)
# Makes a small whole in the centre of the mask
mask = cv2.circle(mask, (175, 175), 20, (0, 0, 0), -1)
result = cv2.bitwise_and(img, mask)
This will take an image, and create a mask for it that should look like a donut.
Then, using a bitwise and operation between the image and the mask you end up with a cookie cutter of the original image
Yet we still need to remove the black background - which is what we use this template for:
{
"steps": {
":original": {
"robot": "/upload/handle"
},
"trimmed": {
"use": ":original",
"robot": "/image/resize",
"alpha": "Activate",
"type": "TrueColor",
"transparent": "0,0,0",
"imagemagick_stack": "v2.0.7"
}
}
}
This will just make all black pixels transparent.
We can now use Transloadit's watermark feature to overlay this image onto our vinyl record
{
"steps": {
":original": {
"robot": "/upload/handle"
},
"watermark": {
"use": ":original",
"robot": "/image/resize",
"watermark_size": "33%",
"watermark_position": "center",
"imagemagick_stack": "v2.0.7"
}
}
}
Now, all that is left is to make it spin. What we can do is create say 60 frames, and have the image rotate, then using the /video/merge robot - to stitch it all together into a seamless GIF.
{
"steps": {
":original": {
"robot": "/upload/handle"
},
"rotate_image": {
"use": ":original",
"robot": "/image/resize",
"rotation": "${file.basename}",
"resize_strategy": "crop",
"imagemagick_stack": "v2.0.7"
},
"animated": {
"robot": "/video/merge",
"use": {
"steps": [
{
"name": "rotate_image",
"as": "image"
}
],
"bundle_steps": true
},
"result": true,
"ffmpeg_stack": "v4.3.1",
"ffmpeg": {
"f": "gif",
"pix_fmt": "rgb24"
}
}
}
}
Here I use the image's name to determine how many degrees to rotate it by - so when I'm uploading the files to the robot I will name the image based on its index in an array using this python code:
# Now we make a list of images that represent each frame
no_of_frames = 60
assembly = tl.new_assembly({'template_id': [SPINNING_VINYL_TEMPLATE_ID]})
directory = 'Assets/Frames/{image}'.format(image=img_name)
# Length of our animation in seconds
length = 2
for i in range(no_of_frames):
if not os.path.exists(directory):
os.mkdir(directory)
# Creates an image based on the index in the animation
# We pass this to the robot so it knows how many degrees to rotate the image by
location = '{directory}/{index}.png'.format(directory=directory, index=round(i*360/no_of_frames))
cv2.imwrite(location, finished_vinyl)
assembly.add_file(open(location, 'rb'))
This is my end result

Related

Altair Y-Axis Label Left-Alignment & Spacing Edits Possible?

I'm trying to recreate this chart in Altair but can't figure out how to make a few minor edits: https://datawrapper.dwcdn.net/E0jaK/1/
Here's my current progress: https://imgur.com/RMuTU7h
The three edits I'm trying to figure out are:
How to left-align y-axis labels
How to add spacing between the labels and the y-axis
How to move bar number labels to the base of the bars instead of the ends
Any insight on how to implement these edits would be great.
Here's the raw data:
Crime,Count
Larceny/Theft,739
Assault,177
Burglary/Breaking & Entering,133
Destruction of Property/Vandalism,128
Drugs,107
Motor Vehicle Theft,95
Fraud,71
Sex Offenses,57
Suspicious Activity,45
Trespassing,23
Family Offenses,22
Weapons Violations,21
This is the theme I used:
def chart_theme():
font = "Calibri"
return {
"width": 700,
"height": 300,
"background": "white",
"config": {
"title": {
"fontSize": 20,
"anchor": "start"
},
"axisY": {
"labelFont": font,
"labelFontSize": 13,
"labelLimit":200,
"ticks": False,
"titleFont": font,
"titleFontSize": 12,
"titleAlign":"right",
"titleAngle": 0,
"titleY": -10,
"titleX": 25,
},
"view":{"stroke": "transparent",
},
}
}
And here's the chart code:
base = alt.Chart(df, title='San Francisco Crime (11/05 - 11/11)').encode(
x=alt.X('Count', axis=None),
y=alt.Y('Crime', title='Crimes reported to SFPD, by top complaint',
sort=list(df.Crime.values)))
bars = base.mark_bar(size=22).encode(color=alt.condition(
alt.datum.Count > 700,
alt.value('#e17700'),
alt.value('#00648e')))
text = base.mark_text(
color='white',
align='right',
size=12,
dx=-3
).encode(
text='Count')
chart = bars + text
chart
Any guidance/suggestions would be greatly appreciated.
How about something like this
import pandas as pd
import altair as alt
data = {'Larceny/Theft':739,
'Assault':177,
'Burglary/Breaking & Entering':133,
'Destruction of Property/Vandalism':128,
'Drugs':107,
'Motor Vehicle Theft':95,
'Fraud':71,
'Sex Offenses':57,
'Suspicious Activity':45,
'Trespassing':23,
'Family Offenses':22,
'Weapons Violations':21}
df = pd.DataFrame(list(data.items()), columns=['Crime', 'Count'])
base = alt.Chart(df, title='San Francisco Crime (11/05 - 11/11)').encode(
x=alt.X('Count', axis=None),
y=alt.Y('Crime', title='Crimes reported to SFPD, by top complaint',
sort=list(df.Crime.values)))
bars = base.mark_bar(size=22).encode(color=alt.condition(
alt.datum.Count > 700,
alt.value('#e17700'),
alt.value('#00648e')))
text = alt.Chart(df).mark_text(
color='white',
align='left',
x=3
).encode(alt.Text('Count:N'), alt.Y('Crime', sort=list(df.Crime.values)))
chart = bars + text
chart.properties(width=700).configure_axisY(
titleAngle=0,
titleY=-10,
titleX=-60,
labelPadding=160,
labelAlign='left'
)

Adding watermark to images in Laravel

I am trying to add a text (as watermark) to images. I am using Image/Intervention package. The text shows but I want it to be at top right hand corner of the image and I also want the size increased. The text is currently at top-left corner and the size is extremely small.
This is my code
if($request->hasFile('file')) {
foreach ($request->file('file') as $photo) {
$file = $photo;
$img = Image::make($file);
$img->text('12345 ', 120, 100, function($font) {
$font->size(45);
$font->color('#e1e1e1');
$font->align('center');
$font->valign('top');
});
$img->save(public_path('images/hardik3.jpg'));
}
}
How do I solve this?
From the documentation:
Font sizing is only available if a font file is set and will be ignored otherwise. Default: 12
So you have to specify a custom font just like in the below example:
$img->text('foo', 0, 0, function($font) {
$font->file('foo/bar.ttf');
$font->size(24);
$font->color('#fdf6e3');
$font->align('center');
$font->valign('top');
$font->angle(45);
});
Update
The text alignment is relative to the size of the textbox, but the positioning is given by the x and y coordinates (2nd and 3rd parameters of the text method). To put the text on the right top corner you can do:
$img->text('foo', $img->width(), 100, function($font) {
$font->file('foo/bar.ttf');
$font->size(24);
$font->color('#e1e1e1');
$font->align('right');
$font->valign('top');
});
The text function accepts the X and Y coordinates of the position to insert the text. The text is being printed into the shown position because you used the coordinates 120 and 100.
Try the following:
if($request->hasFile('file')) {
foreach ($request->file('file') as $photo) {
$file = $photo;
$img = Image::make($file);
$img->text('12345 ', $img->width() - 120, 100, function($font) {
$font->size(45);
$font->color('#e1e1e1');
$font->align('center');
$font->valign('top');
});
$img->save(public_path('images/hardik3.jpg'));
}
}
Source: http://image.intervention.io/api/text

Setting a window's background to an unusual pattern before drawing into it

I have a window (CWnd object), into which I am drawing a bitmap image.
Before doing so, I would like to set the window's background to a specific pattern.
The pattern may change from time to time.
If I understand correctly, then I need to override the window's OnCtlColor function, and return a brush compatible with my desired pattern (recalculated according to internal data-structure).
Am I on the right track?
The pattern is rather irregular. It consists of "zebra stripes", all of which are of the same width, but (may be) of different heights. Here is an illustrated example:
Is it even possible to create a brush with such pattern?
If yes, then which of the following functions would be the most appropriate:
CBrush::CreateBrushIndirect
CBrush::CreateDIBPatternBrush
CBrush::CreateHatchBrush
CBrush::CreatePatternBrush
Thank you.
I wouldn't even bother with brushes. This example draws a bunch of stripes using FillSolidRect and stripe heights in screen height percentages. Should be easy to adjust if you're using absolutes.
BOOL CChildView::OnEraseBkgnd(CDC* pDC)
{
CRect clientRect;
GetClientRect(clientRect);
const auto savedDC = pDC->SaveDC();
// Make the co-ordinates system behave like percentages
{
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(100, 100);
pDC->SetViewportExt(clientRect.right, clientRect.bottom);
}
// pair requires #include <utility>
std::pair<int, COLORREF> stripeData[] =
{
{ 8, RGB(220,220,220) }, // 8% of window height, light grey
{ 17, RGB(165,165,165) }, // 17% of window height, dark grey
{ 12, RGB(220,220,220) }, // etc. These should total 100%
{ 7, RGB(165,165,165) },
{ 23, RGB(220,220,220) },
{ 33, RGB(165,165,165) }
};
// NOTE: FillSolidRect changes the background color, so restore it at the
// end of the function. RestoreDC will handle this; otherwise save the
// GetBkColor return value and restore it by calling SetBkColor
//auto oldBkColor = pDC->GetBkColor();
// Draw the stripes
CRect stripeRect{0,0,100,0};
for (auto const& data : stripeData)
{
stripeRect.bottom = stripeRect.top + data.first;
pDC->FillSolidRect(stripeRect, data.second);
stripeRect.OffsetRect(0, data.first);
}
//pDC->SetBkColor(oldBkColor);
pDC->RestoreDC(savedDC);
return TRUE;
}

How to rotate part of a 3D model about its center, not the model's centre with LIBGDX

I have a model created in Blender with a ship with one turret, and the turret has 1 gun.
Just to be clear these are 3 separate objects in blender.
In the g3dj file this appears as 3 nodes: one for the ship, one for the turret, one for the gun.
"nodes": [
{
"id": "gun1",
"rotation": [ 0.000000, 0.000000, 0.707107, 0.707107],
"scale": [ 0.100000, 0.984755, 0.100000],
"translation": [-3.526966, 1.428384, 0.191505],
"parts": [
{
"meshpartid": "Cylinder_part1",
"materialid": "gunMaterial"
}
]
},
{
"id": "turret1",
"scale": [ 1.000000, 0.300000, 0.395389],
"translation": [-1.603167, 1.406584, 0.000000],
"parts": [
{
"meshpartid": "Cube.001_part1",
"materialid": "turretMaterial"
}
]
},
{
"id": "ship",
"scale": [ 3.000000, 1.000000, 1.000000],
"parts": [
{
"meshpartid": "Cube_part1",
"materialid": "shipMaterial",
"uvMapping": [[]]
}
]
}
],
"animations": []
}
Using Libgdx I try to rotate the turret through say 30 degrees (rotAngle=30).
So I translate to what I think is the model's origin (I presume that is the origin of the ship?).
Then I rotate. Then finally I would translate back.
But I have taken that translate out because the rotate is not around the correct point?
Code is as follows (based on a xoppa tutorial):
Vector3 dimensions = new Vector3();
for (int i = 0; i < model.nodes.size; i++) {
String id = model.nodes.get(i).id;
ModelInstance instance = new ModelInstance(model, id);
instance.transform.getTranslation(position);
Node node = instance.getNode(id);
node.calculateLocalTransform();
node.localTransform.getTranslation(position);
node.calculateBoundingBox(bounds).mul(node.localTransform);
node.localTransform.getScale(scale);
bounds.getDimensions(dimensions);
centre=bounds.getCenter(centre);
//float radius;
//radius = dimensions.x / 2f;
if (id.equals("ship")) {
///instance.transform.rotate(Vector3.Y,rotAngle);
ship = instance;
instances.add(ship);
continue;
}
if (id.startsWith("gun")) {
guns.add(instance);
instances.add(instance);
continue;
}
if (id.startsWith("turret")) {
//movement on Y is based on Z from blender
instance.transform.trn(-centre.x,-centre.z,0).
rotate(Vector3.Y,rotAngle); // ???z???
turrets.add(instance);
instances.add(instance);
continue;
}
}
What is wrong?
The basic idea was right, but I needed to translate using the position (translation) of the node not the centre, and take into account the scale factor from blender, and the apparent random switching of some y/z values.
Here is the modified code for the turret:
Vector3 turretMove = new Vector3();
turretMove.x = position.x*scale.x;
//scale.z is what was the blender scale.y and vice versa
turretMove.y = -position.y*scale.z; //using opposite sign of position
turretMove.z = position.z*scale.y;
instance.transform.translate(turretMove.x,turretMove.y,turretMove.z).
rotate(Vector3.Y,dt).
translate(-turretMove.x,-turretMove.y,-turretMove.z);
This code now includes the translate back to the original position.
It took several hours of trial and error to get here!
In Blender Z-up was from the bottom to the top of the ship, and Y from the left side of the ship (and turret) to the right.
In Libgdx, Z was from the left side of the ship to the right (looking into the screen) with Y being from the bottom to the top of the ship (up the screen).
Export from Blender was to FBX with -Z forward and Y Up with only selected objects exported.
I guess some of this explains the flipping of the Z and Y scale values?

as3 Click thumbnail to tween large image

I'm using Greensock's LoaderMax to parse an XML doc and load thumbnails and large images onto the stage - the large images are hidden off screen initially.
What I'd like to do is click on a thumbnail and have the large image tween into place, I have assigned the same name to the relevant thumbnail and image, ie 0 in thumbs corresponds to the 0 image
Thumbnails have been added to a movieclip named mc2, images are in a mc called bigDocWrap
Here's my attempt:
function callFull(event:MouseEvent):void
{
var clicked = [event.target.name];
if (isUp == true) {
// Do some stuff
fadeOut.addEventListener(TweenEvent.MOTION_FINISH, end);
function end(event:TweenEvent) {
// Some more stuff
// Animate large image in
mcDocIn = new Tween (clicked, "y", Strong.easeOut, clicked.y, -650, 1, true);
}
}
}
This didn't work - undefined reference error
mcDocIn = new Tween (bigDocWrap.clicked, "y", Strong.easeOut, bigDocWrap.clicked.y, -650, 1, true);
You are passing Name of object and not object to new Tween(). Use event.currentTarget or event.target, depends on your need.
I have updated your code like so:
function callFull(event:MouseEvent):void
{
if (isUp == true) {
// Do some stuff
fadeOut.addEventListener(TweenEvent.MOTION_FINISH, end);
function end(event:TweenEvent) {
// Some more stuff
// Animate large image in
mcDocIn = new Tween (event.currentTarget, "y", Strong.easeOut, clicked.y, -650, 1, true);
}
}
}

Resources