Merge "res: Embed FPS into icon_installing.png."
@@ -12,42 +12,69 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Script to take a set of frames (PNG files) for a recovery animation
|
"""
|
||||||
and turn it into a single output image which contains the input frames
|
Script to take a set of frames (PNG files) for a recovery animation and turn
|
||||||
interlaced by row. Run with the names of all the input frames on the
|
it into a single output image which contains the input frames interlaced by
|
||||||
command line, in order, followed by the name of the output file."""
|
row. Run with the names of all the input frames on the command line. Specify
|
||||||
|
the name of the output file with -o (or --output), and optionally specify the
|
||||||
|
number of frames per second (FPS) with --fps (default: 20).
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
interlace-frames.py --fps 20 --output output.png frame0.png frame1.png frame3.png
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
try:
|
try:
|
||||||
import Image
|
import Image
|
||||||
import PngImagePlugin
|
import PngImagePlugin
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "This script requires the Python Imaging Library to be installed."
|
print("This script requires the Python Imaging Library to be installed.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
frames = [Image.open(fn).convert("RGB") for fn in sys.argv[1:-1]]
|
|
||||||
assert len(frames) > 0, "Must have at least one input frame."
|
|
||||||
sizes = set()
|
|
||||||
for fr in frames:
|
|
||||||
sizes.add(fr.size)
|
|
||||||
|
|
||||||
assert len(sizes) == 1, "All input images must have the same size."
|
def interlace(output, fps, inputs):
|
||||||
w, h = sizes.pop()
|
frames = [Image.open(fn).convert("RGB") for fn in inputs]
|
||||||
N = len(frames)
|
assert len(frames) > 0, "Must have at least one input frame."
|
||||||
|
sizes = set()
|
||||||
|
for fr in frames:
|
||||||
|
sizes.add(fr.size)
|
||||||
|
|
||||||
out = Image.new("RGB", (w, h*N))
|
assert len(sizes) == 1, "All input images must have the same size."
|
||||||
for j in range(h):
|
w, h = sizes.pop()
|
||||||
for i in range(w):
|
N = len(frames)
|
||||||
for fn, f in enumerate(frames):
|
|
||||||
out.putpixel((i, j*N+fn), f.getpixel((i, j)))
|
|
||||||
|
|
||||||
# When loading this image, the graphics library expects to find a text
|
out = Image.new("RGB", (w, h*N))
|
||||||
# chunk that specifies how many frames this animation represents. If
|
for j in range(h):
|
||||||
# you post-process the output of this script with some kind of
|
for i in range(w):
|
||||||
# optimizer tool (eg pngcrush or zopflipng) make sure that your
|
for fn, f in enumerate(frames):
|
||||||
# optimizer preserves this text chunk.
|
out.putpixel((i, j*N+fn), f.getpixel((i, j)))
|
||||||
|
|
||||||
meta = PngImagePlugin.PngInfo()
|
# When loading this image, the graphics library expects to find a text
|
||||||
meta.add_text("Frames", str(N))
|
# chunk that specifies how many frames this animation represents. If
|
||||||
|
# you post-process the output of this script with some kind of
|
||||||
|
# optimizer tool (eg pngcrush or zopflipng) make sure that your
|
||||||
|
# optimizer preserves this text chunk.
|
||||||
|
|
||||||
|
meta = PngImagePlugin.PngInfo()
|
||||||
|
meta.add_text("Frames", str(N))
|
||||||
|
meta.add_text("FPS", str(fps))
|
||||||
|
|
||||||
|
out.save(output, pnginfo=meta)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--fps', default=20)
|
||||||
|
parser.add_argument('--output', '-o', required=True)
|
||||||
|
parser.add_argument('input', nargs='+')
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
interlace(args.output, args.fps, args.input)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv[1:])
|
||||||
|
|
||||||
out.save(sys.argv[-1], pnginfo=meta)
|
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ int res_create_display_surface(const char* name, GRSurface** pSurface);
|
|||||||
// should have a 'Frames' text chunk whose value is the number of
|
// should have a 'Frames' text chunk whose value is the number of
|
||||||
// frames this image represents. The pixel data itself is interlaced
|
// frames this image represents. The pixel data itself is interlaced
|
||||||
// by row.
|
// by row.
|
||||||
int res_create_multi_display_surface(const char* name,
|
int res_create_multi_display_surface(const char* name, int* frames,
|
||||||
int* frames, GRSurface*** pSurface);
|
int* fps, GRSurface*** pSurface);
|
||||||
|
|
||||||
// Load a single alpha surface from a grayscale PNG image.
|
// Load a single alpha surface from a grayscale PNG image.
|
||||||
int res_create_alpha_surface(const char* name, GRSurface** pSurface);
|
int res_create_alpha_surface(const char* name, GRSurface** pSurface);
|
||||||
|
|||||||
@@ -237,14 +237,14 @@ int res_create_display_surface(const char* name, GRSurface** pSurface) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res_create_multi_display_surface(const char* name, int* frames, GRSurface*** pSurface) {
|
int res_create_multi_display_surface(const char* name, int* frames, int* fps,
|
||||||
|
GRSurface*** pSurface) {
|
||||||
GRSurface** surface = NULL;
|
GRSurface** surface = NULL;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
png_structp png_ptr = NULL;
|
png_structp png_ptr = NULL;
|
||||||
png_infop info_ptr = NULL;
|
png_infop info_ptr = NULL;
|
||||||
png_uint_32 width, height;
|
png_uint_32 width, height;
|
||||||
png_byte channels;
|
png_byte channels;
|
||||||
int i;
|
|
||||||
png_textp text;
|
png_textp text;
|
||||||
int num_text;
|
int num_text;
|
||||||
unsigned char* p_row;
|
unsigned char* p_row;
|
||||||
@@ -257,14 +257,23 @@ int res_create_multi_display_surface(const char* name, int* frames, GRSurface***
|
|||||||
if (result < 0) return result;
|
if (result < 0) return result;
|
||||||
|
|
||||||
*frames = 1;
|
*frames = 1;
|
||||||
|
*fps = 20;
|
||||||
if (png_get_text(png_ptr, info_ptr, &text, &num_text)) {
|
if (png_get_text(png_ptr, info_ptr, &text, &num_text)) {
|
||||||
for (i = 0; i < num_text; ++i) {
|
for (int i = 0; i < num_text; ++i) {
|
||||||
if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) {
|
if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) {
|
||||||
*frames = atoi(text[i].text);
|
*frames = atoi(text[i].text);
|
||||||
break;
|
} else if (text[i].key && strcmp(text[i].key, "FPS") == 0 && text[i].text) {
|
||||||
|
*fps = atoi(text[i].text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(" found frames = %d\n", *frames);
|
printf(" found frames = %d\n", *frames);
|
||||||
|
printf(" found fps = %d\n", *fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frames <= 0 || fps <= 0) {
|
||||||
|
printf("bad number of frames (%d) and/or FPS (%d)\n", *frames, *fps);
|
||||||
|
result = -10;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height % *frames != 0) {
|
if (height % *frames != 0) {
|
||||||
@@ -278,7 +287,7 @@ int res_create_multi_display_surface(const char* name, int* frames, GRSurface***
|
|||||||
result = -8;
|
result = -8;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
for (i = 0; i < *frames; ++i) {
|
for (int i = 0; i < *frames; ++i) {
|
||||||
surface[i] = init_display_surface(width, height / *frames);
|
surface[i] = init_display_surface(width, height / *frames);
|
||||||
if (surface[i] == NULL) {
|
if (surface[i] == NULL) {
|
||||||
result = -8;
|
result = -8;
|
||||||
@@ -307,7 +316,7 @@ exit:
|
|||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
if (surface) {
|
if (surface) {
|
||||||
for (i = 0; i < *frames; ++i) {
|
for (int i = 0; i < *frames; ++i) {
|
||||||
if (surface[i]) free(surface[i]);
|
if (surface[i]) free(surface[i]);
|
||||||
}
|
}
|
||||||
free(surface);
|
free(surface);
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 127 KiB |
@@ -73,7 +73,7 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
|
|||||||
menu_items(0),
|
menu_items(0),
|
||||||
menu_sel(0),
|
menu_sel(0),
|
||||||
file_viewer_text_(nullptr),
|
file_viewer_text_(nullptr),
|
||||||
animation_fps(20),
|
animation_fps(-1),
|
||||||
installing_frames(-1),
|
installing_frames(-1),
|
||||||
stage(-1),
|
stage(-1),
|
||||||
max_stage(-1) {
|
max_stage(-1) {
|
||||||
@@ -367,8 +367,9 @@ void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, GRSurface*** surface) {
|
void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, int* fps,
|
||||||
int result = res_create_multi_display_surface(filename, frames, surface);
|
GRSurface*** surface) {
|
||||||
|
int result = res_create_multi_display_surface(filename, frames, fps, surface);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
|
LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
|
||||||
}
|
}
|
||||||
@@ -405,7 +406,7 @@ void ScreenRecoveryUI::Init() {
|
|||||||
text_top_ = 1;
|
text_top_ = 1;
|
||||||
|
|
||||||
backgroundIcon[NONE] = nullptr;
|
backgroundIcon[NONE] = nullptr;
|
||||||
LoadBitmapArray("icon_installing", &installing_frames, &installation);
|
LoadBitmapArray("icon_installing", &installing_frames, &animation_fps, &installation);
|
||||||
backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : nullptr;
|
backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : nullptr;
|
||||||
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
|
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
|
||||||
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
|
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
|
|
||||||
pthread_t progress_thread_;
|
pthread_t progress_thread_;
|
||||||
|
|
||||||
|
// The following two are parsed from the image file
|
||||||
|
// (e.g. '/res/images/icon_installing.png').
|
||||||
int animation_fps;
|
int animation_fps;
|
||||||
int installing_frames;
|
int installing_frames;
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
void DrawTextLines(int* y, const char* const* lines);
|
void DrawTextLines(int* y, const char* const* lines);
|
||||||
|
|
||||||
void LoadBitmap(const char* filename, GRSurface** surface);
|
void LoadBitmap(const char* filename, GRSurface** surface);
|
||||||
void LoadBitmapArray(const char* filename, int* frames, GRSurface*** surface);
|
void LoadBitmapArray(const char* filename, int* frames, int* fps, GRSurface*** surface);
|
||||||
void LoadLocalizedBitmap(const char* filename, GRSurface** surface);
|
void LoadLocalizedBitmap(const char* filename, GRSurface** surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,10 +61,10 @@ WearRecoveryUI::WearRecoveryUI() :
|
|||||||
menu_unusable_rows(0),
|
menu_unusable_rows(0),
|
||||||
intro_frames(22),
|
intro_frames(22),
|
||||||
loop_frames(60),
|
loop_frames(60),
|
||||||
|
animation_fps(30),
|
||||||
currentIcon(NONE),
|
currentIcon(NONE),
|
||||||
intro_done(false),
|
intro_done(false),
|
||||||
current_frame(0),
|
current_frame(0),
|
||||||
animation_fps(30),
|
|
||||||
rtl_locale(false),
|
rtl_locale(false),
|
||||||
progressBarType(EMPTY),
|
progressBarType(EMPTY),
|
||||||
progressScopeStart(0),
|
progressScopeStart(0),
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ class WearRecoveryUI : public RecoveryUI {
|
|||||||
int intro_frames;
|
int intro_frames;
|
||||||
int loop_frames;
|
int loop_frames;
|
||||||
|
|
||||||
|
// Number of frames per sec (default: 30) for both of intro and loop.
|
||||||
|
int animation_fps;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Icon currentIcon;
|
Icon currentIcon;
|
||||||
|
|
||||||
@@ -86,8 +89,6 @@ class WearRecoveryUI : public RecoveryUI {
|
|||||||
|
|
||||||
int current_frame;
|
int current_frame;
|
||||||
|
|
||||||
int animation_fps;
|
|
||||||
|
|
||||||
bool rtl_locale;
|
bool rtl_locale;
|
||||||
|
|
||||||
pthread_mutex_t updateMutex;
|
pthread_mutex_t updateMutex;
|
||||||
|
|||||||