Merge "res: Embed FPS into icon_installing.png."
am: 29b0fbe160
* commit '29b0fbe160f815a142fa0d056c1ce10186cea516':
res: Embed FPS into icon_installing.png.
@@ -12,42 +12,69 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# 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
|
||||
interlaced by row. Run with the names of all the input frames on the
|
||||
command line, in order, followed by the name of the output file."""
|
||||
"""
|
||||
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 interlaced by
|
||||
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
|
||||
try:
|
||||
import Image
|
||||
import PngImagePlugin
|
||||
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)
|
||||
|
||||
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."
|
||||
w, h = sizes.pop()
|
||||
N = len(frames)
|
||||
def interlace(output, fps, inputs):
|
||||
frames = [Image.open(fn).convert("RGB") for fn in inputs]
|
||||
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))
|
||||
for j in range(h):
|
||||
for i in range(w):
|
||||
for fn, f in enumerate(frames):
|
||||
out.putpixel((i, j*N+fn), f.getpixel((i, j)))
|
||||
assert len(sizes) == 1, "All input images must have the same size."
|
||||
w, h = sizes.pop()
|
||||
N = len(frames)
|
||||
|
||||
# When loading this image, the graphics library expects to find a text
|
||||
# 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.
|
||||
out = Image.new("RGB", (w, h*N))
|
||||
for j in range(h):
|
||||
for i in range(w):
|
||||
for fn, f in enumerate(frames):
|
||||
out.putpixel((i, j*N+fn), f.getpixel((i, j)))
|
||||
|
||||
meta = PngImagePlugin.PngInfo()
|
||||
meta.add_text("Frames", str(N))
|
||||
# When loading this image, the graphics library expects to find a text
|
||||
# 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
|
||||
// frames this image represents. The pixel data itself is interlaced
|
||||
// by row.
|
||||
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);
|
||||
|
||||
// Load a single alpha surface from a grayscale PNG image.
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
int result = 0;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
png_uint_32 width, height;
|
||||
png_byte channels;
|
||||
int i;
|
||||
png_textp text;
|
||||
int num_text;
|
||||
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;
|
||||
|
||||
*frames = 1;
|
||||
*fps = 20;
|
||||
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) {
|
||||
*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 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) {
|
||||
@@ -278,7 +287,7 @@ int res_create_multi_display_surface(const char* name, int* frames, GRSurface***
|
||||
result = -8;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < *frames; ++i) {
|
||||
for (int i = 0; i < *frames; ++i) {
|
||||
surface[i] = init_display_surface(width, height / *frames);
|
||||
if (surface[i] == NULL) {
|
||||
result = -8;
|
||||
@@ -307,7 +316,7 @@ exit:
|
||||
|
||||
if (result < 0) {
|
||||
if (surface) {
|
||||
for (i = 0; i < *frames; ++i) {
|
||||
for (int i = 0; i < *frames; ++i) {
|
||||
if (surface[i]) free(surface[i]);
|
||||
}
|
||||
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_sel(0),
|
||||
file_viewer_text_(nullptr),
|
||||
animation_fps(20),
|
||||
animation_fps(-1),
|
||||
installing_frames(-1),
|
||||
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) {
|
||||
int result = res_create_multi_display_surface(filename, frames, surface);
|
||||
void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, int* fps,
|
||||
GRSurface*** surface) {
|
||||
int result = res_create_multi_display_surface(filename, frames, fps, surface);
|
||||
if (result < 0) {
|
||||
LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
|
||||
}
|
||||
@@ -405,7 +406,7 @@ void ScreenRecoveryUI::Init() {
|
||||
text_top_ = 1;
|
||||
|
||||
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[ERASING] = backgroundIcon[INSTALLING_UPDATE];
|
||||
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
|
||||
|
||||
@@ -109,6 +109,8 @@ class ScreenRecoveryUI : public RecoveryUI {
|
||||
|
||||
pthread_t progress_thread_;
|
||||
|
||||
// The following two are parsed from the image file
|
||||
// (e.g. '/res/images/icon_installing.png').
|
||||
int animation_fps;
|
||||
int installing_frames;
|
||||
|
||||
@@ -135,7 +137,7 @@ class ScreenRecoveryUI : public RecoveryUI {
|
||||
void DrawTextLines(int* y, const char* const* lines);
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -61,10 +61,10 @@ WearRecoveryUI::WearRecoveryUI() :
|
||||
menu_unusable_rows(0),
|
||||
intro_frames(22),
|
||||
loop_frames(60),
|
||||
animation_fps(30),
|
||||
currentIcon(NONE),
|
||||
intro_done(false),
|
||||
current_frame(0),
|
||||
animation_fps(30),
|
||||
rtl_locale(false),
|
||||
progressBarType(EMPTY),
|
||||
progressScopeStart(0),
|
||||
|
||||
@@ -79,6 +79,9 @@ class WearRecoveryUI : public RecoveryUI {
|
||||
int intro_frames;
|
||||
int loop_frames;
|
||||
|
||||
// Number of frames per sec (default: 30) for both of intro and loop.
|
||||
int animation_fps;
|
||||
|
||||
private:
|
||||
Icon currentIcon;
|
||||
|
||||
@@ -86,8 +89,6 @@ class WearRecoveryUI : public RecoveryUI {
|
||||
|
||||
int current_frame;
|
||||
|
||||
int animation_fps;
|
||||
|
||||
bool rtl_locale;
|
||||
|
||||
pthread_mutex_t updateMutex;
|
||||
|
||||