PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Uhr einblenden (Lösung)


Sweeeet
10. October 2005, 09:30
Hallo! Ich hoffe, was ich teilen möchte, verdient das Attribut "fortgeschritten".

Folgende Problemstellung: Ich hab meine Digicam aufs Fenstersims gestellt und alle 30 Sekunden ein Bild vom Himmel gemacht, insgesamt ein paarhundert. Daraus habe ich einen Zeitrafferfilm zusammengebastelt. Dann wollte ich die Zeit eingeblendet haben. Als Text war's natürlich überhaupt kein Problem dank ScriptClip(), aber ich wollte es als analoge Uhr haben. Es hat mich einige Zeit gekostet, aber nun hab ich eine Lösung mit der ich sehr zufrieden bin.

Im Anhang ist ein Bildchen davon und ich hab mal eine kleine Demo (Megaupload, 658 kB) (http://www.megaupload.com/?d=1LMKR4UP) upgeloadet.

Hier die Vorgehensweise in Kürze:
Mit PHP (standalone) einen Satz Bilder (PNG) des Ziffernblatts mit Stundenzeiger in 60 verschiedenen Positionen erzeugt.
Ebenso einen Satz PNGs nur mit dem Minutenzeiger in 60 verschiedenen Positionen erzeugt.
Ein AviSynth-Script erstellt, das aus der Framenummer die jeweiligen Frames aus dem "Stunden"- und "Minuten"-Film herauspickt und übereinanderlegt.
Zusätzlich noch eine Funktion, um aus den Framenummern das amerikanische Zeitformat (AM/PM) erzeugt und mit Subtitle() darstellt.


Wer sich für das PHP-Script interessiert bitte melden (ist ausführlich kommentiert). Das AviSynth-Script pack ich hier mal rein, obwohl es leider noch wie Kraut und Rüben aussieht :ani_lol:. Fragen, Anregungen und vor allem Verbesserungsvorschläge nehme ich gerne entgegen. Eine kleine Frage habe ich selber auch: Gibt's einen verbreiteten Codec, mit dem man Filme mit sehr wenigen Farben (in diesem Fall 3) und Bewegung (nur der Zeiger) verlustfrei stark komprimieren kann? Früher gab's FLI für sowas, heute animated GIFs, aber die kann man schlecht weiterverarbeiten.

antialias = TRUE
global time_factor = 30
global time_offset = 39049
global clock_x = 160

# Load original clip.
cl1 = AviSource("Irgendeinpfad/himmel.avi").ConvertToRGB32
cl1 = cl1.trim(300, 0)

# Resize to double size if antialiasing on.
global cl2 = antialias ? cl1.BilinearResize(cl1.Width * 2, cl1.Height * 2) : cl1

cl_hour = ImageReader("Irgendeinpfad/clock_h_%02d.png", 0, 59).ConvertToRGB32
global cl_hour = ResetMask(cl_hour).ColorKeyMask($00ff00, 0)
cl_minute = ImageReader("Irgendeinpfad/clock_m_%02d.png", 0, 59).ConvertToRGB32
global cl_minute = ResetMask(cl_minute).ColorKeyMask($00ff00, 0)
cl5 = ScriptClip(cl2, "OverlayClock(cl2, current_frame)")
cl_out = antialias ? cl5.BilinearResize(cl5.Width / 2, cl5.Height / 2) : cl5
cl_out
AssumeFps(24)

Function OverlayClock(clip, frame) {
time = frame * time_factor + time_offset
minute_index = Round(time / 60) % 60
hour_index = Round(time / 720) % 60
cl7 = cl_hour.trim(hour_index, -1)
cl8 = cl_minute.trim(minute_index, -1)
cl5 = Layer(clip, cl7, "add", 255, clock_x)
cl6 = Layer(cl5, cl8, "add", 255, clock_x)
cl6 = cl6.Subtitle(sec2time(time), font="Arial", size=100, align=2, text_color=$ffffff)
return(cl6)
}

Function sec2time(s) {
minutes = s / 60
seconds = s % 60
hours = minutes / 60
minutes = minutes % 60
days = hours / 24
ampm = (hours % 24 > 11) ? "PM" : "AM"
hours = (hours - 1) % 12 + 1
minutes = minutes % 60
out = (days > 0) ? String(days) + " d " : ""
out = out + String(hours, "% 2.0f")
out = out + ":" + String(minutes, "%02.0f")
out = out + " " + ampm
return(out)
}

Eastermeyer
10. October 2005, 09:36
Ich hoffe, was ich teilen möchte, verdient das Attribut "fortgeschritten".Mit Sicherheit :daumen:

Kann ich das PHP-Script sehen ? :kuss:

Gibt's einen verbreiteten Codec, mit dem man Filme mit sehr wenigen Farben (in diesem Fall 3) und Bewegung (nur der Zeiger) verlustfrei stark komprimieren kann?
LCL ? (http://www.computerbase.de/lexikon/LCL-Codec)

katjarella
10. October 2005, 09:37
Ich wüßte zwar jetzt nicht, für was ich das breuchte, aber trotzdem ist das echt Klasse.

Sweeeet
10. October 2005, 09:45
Mit Sicherheit :daumen:Hurra! :)

Kann ich das PHP-Script sehen ? :kuss:
Klar, voilà:


#!/usr/bin/php
<?php
/***************************************************************\
| Clock Image Generation Script v1.0
|
| This PHP script generates a series of PNG image files
| depicting a clock face with hands. I used it for an
| overlay image in a time lapse video I did with AviSynth.
| It is not suitable for use on a webserver but with the
| standalone version of PHP.
|
| By default it generates 60 images with the clock face and
| an hour hand in various positions and 60 more images of
| the minute hand to be overlayed on top of that. Both
| contain transparency information.
|
| Usage:
| Call the PHP standalone executable with this script
|
| $> php -f clock_generator.php
|
| License:
| This script may be used and modified freely. However, you may
| not redistribute this script or derivations except it is
| publicly accessible free of charge and without any registration.
| If you do redistribute this script this text block must
| remain unchanged.
|
| Have fun!
|
| 10. Oct 2005, Sweeeet, <clock.20.santo@recursor.net>
\***************************************************************/

/***************************************************************\
| Configuration
\***************************************************************/

$out_directory_hour = "./";
$out_filename_hour_mask = $out_directory_hour . "clock_h_%02d.png";
$out_directory_minute = $out_directory_hour;
$out_filename_minute_mask = $out_directory_minute . "clock_m_%02d.png";
$image_width = 80;
$image_height = $image_width;

// The radius of the outer bounds of the clock.
$radius_outer = $image_width * 0.49;

// The radius of the inner bounds of the hour ticks.
$radius_inner = $image_width * 0.38;

// The length of the hour arm.
$radius_arm_hour = $image_width * 0.25;

// The length of the minute arm.
$radius_arm_minute = $image_width * 0.35;

// Center of the clock within the image.
$image_center_x = round($image_width / 2);
$image_center_y = round($image_height / 2);

// Thickness of outer ring, hour ticks and arms.
$line_thickness = $image_width / 20;

/***************************************************************\
| Functions
\***************************************************************/

/*
Draws a box radial to a center (like an arm of a clock).
$im: The image to draw on.
$center_x: X coordinate of the origin.
$center_y: Y coordinate of the origin.
$start_radius: Distance of side A from the origin.
$end_radius: Distance of side C from the origin.
$angle: Rotation of the box around the origin in degrees.
$thickness: Length of the tangential sides A and C.
$fill_color: Fill color of the box (must be allocated).
$border_color: Color of the border (must be allocated).
$what: Defines what to draw: Bit 1: Fill, Bit 2: Border.
$no_outer_line: Supresses drawing of the line farmost from origin.
*/
function draw_radial_box($im, $center_x, $center_y, $start_radius,
$end_radius, $angle, $thickness, $fill_color, $border_color,
$what = 3, $no_outer_line = FALSE)
{
$rad = deg2rad($angle);
// Save so we don't have to recalculate.
$cos = cos($rad);
$sin = sin($rad);

// End points of the radial axis in the middle of the box.
$x1 = ( $sin * $start_radius);
$y1 = (-$cos * $start_radius);
$x2 = ( $sin * $end_radius);
$y2 = (-$cos * $end_radius);

// Offset in tangential direction from the middle axis.
$xt = ($cos * $thickness / 2);
$yt = ($sin * $thickness / 2);
$points = array(
($center_x + $x2 - $xt), ($center_y + $y2 - $yt),
($center_x + $x1 - $xt), ($center_y + $y1 - $yt),
($center_x + $x1 + $xt), ($center_y + $y1 + $yt),
($center_x + $x2 + $xt), ($center_y + $y2 + $yt)
);
if($what & 1)
imagefilledpolygon($im, $points, 4, $fill_color);
if($what & 2)
{
if($no_outer_line)
{
imageline($im, $points[0], $points[1], $points[2], $points[3], $border_color);
imageline($im, $points[2], $points[3], $points[4], $points[5], $border_color);
imageline($im, $points[4], $points[5], $points[6], $points[7], $border_color);
}
else
imagepolygon($im, $points, 4, $border_color);
}
}


/***************************************************************\
| Image Generation
\***************************************************************/

$im1 = imagecreatetruecolor($image_width, $image_height);

// Define colors.
$co_white = imagecolorallocate($im1, 0xff, 0xff, 0xff);
$co_black = imagecolorallocate($im1, 0x00, 0x00, 0x00);
$co_green = imagecolorallocate($im1, 0x00, 0xff, 0x00);
$co_trans = $co_green;
imagecolortransparent($im1, $co_trans);
$co_basic = $co_white;
$co_basic_border = $co_black;
$co_arm_h = $co_white;
$co_arm_h_border = $co_black;
$co_arm_m = $co_white;
$co_arm_m_border = $co_black;

imagefilledrectangle($im1, 0, 0, $image_width, $image_height, $co_trans);

// Draw outer ring.
$r1 = $radius_outer * 2;
// Please don't ask me why the lines won't fit without the 1.5 pixels added here.
$r2 = ($radius_outer - $line_thickness) * 2 + 1.5;
$r3 = sqrt(pow($radius_outer - $line_thickness, 2) - pow($line_thickness / 2, 2));
imagefilledellipse($im1, $image_center_x, $image_center_y, $r1, $r1, $co_basic);
imageellipse($im1, $image_center_x, $image_center_y, $r1, $r1, $co_basic_border);
imagefilledellipse($im1, $image_center_x, $image_center_y, $r2, $r2, $co_trans);
imageellipse($im1, $image_center_x, $image_center_y, $r2, $r2, $co_basic_border);

// Draw hour ticks on outer ring.
for($angle = 0; $angle < 360; $angle += 30)
{
draw_radial_box($im1, $image_center_x, $image_center_y, $radius_inner,
$radius_outer - $line_thickness / 2, $angle, $line_thickness,
$co_basic, $co_basic_border, 1);

draw_radial_box($im1, $image_center_x, $image_center_y, $radius_inner,
$r3, $angle, $line_thickness,
$co_basic, $co_basic_border, 2, TRUE);
}

// Generate hour images.
$im2 = imagecreatetruecolor($image_width, $image_height);
imagecolortransparent($im2, $co_trans);
$count = 0;
for($angle_hour = 0; $angle_hour < 360; $angle_hour += 6)
{
imagecopy($im2, $im1, 0, 0, 0, 0, $image_width, $image_height);
draw_radial_box($im2, $image_center_x, $image_center_y, -$line_thickness,
$radius_arm_hour, $angle_hour, $line_thickness,
$co_basic, $co_basic_border, 3);
imagepng($im2, sprintf($out_filename_hour_mask, $count++));
}

// Generate minute images.
$count = 0;
for($angle_hour = 0; $angle_hour < 360; $angle_hour += 6)
{
imagefilledrectangle($im2, 0, 0, $image_width, $image_height, $co_trans);
draw_radial_box($im2, $image_center_x, $image_center_y, -$line_thickness,
$radius_arm_minute, $angle_hour, $line_thickness,
$co_basic, $co_basic_border, 3);
imagepng($im2, sprintf($out_filename_minute_mask, $count++));
}

imagedestroy($im2);
imagedestroy($im1);

// Thank you for reading to this point :-).
?>


Vielleicht wären auch die PNGs ganz nützlich für die, die kein PHP dahaben. Eine 320x320 Version hab ich mal angehängt. Wenn mir jemand meine Frage oben beantworten kann, könnte man die sicher auf wenige Bytes eindampfen :lol:.

Hoffentlich gibt's keinen Stress für den 300 kB Anhang.

Sweeeet
10. October 2005, 20:24
Oh, gerade habe ich den Filter gefunden, der mir dafür gefehlt hätte: Call.
Damit wäre weit mehr möglich gewesen, z.B. immer wenn ein Bild gebraucht wird die EXIF-Daten des Digicam-Bildes holen und ins Bild einblenden (z.B. Blende und Verschlusszeit).
Hmmm, ich hab zu wenig Zeit :(