static void DrawBackground(void) { // Whole window cleared with clear color, checkerboard rendered on top of it. glClear(GL_COLOR_BUFFER_BIT); DrawCheckerBoard(); // ANIM background color rendered (blend) on top. Default is white for still // images (without ANIM chunk). glClear() can't be used for that (no blend). if (kParams.draw_anim_background_color) { glPushMatrix(); glLoadIdentity(); glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec GetColorf(kParams.bg_color, 8), GetColorf(kParams.bg_color, 0), GetColorf(kParams.bg_color, 24)); glRecti(-1, -1, +1, +1); glPopMatrix(); } }
static void StartDisplay(void) { const int width = kParams.canvas_width; const int height = kParams.canvas_height; glutInitDisplayMode(GLUT_RGBA); glutInitWindowSize(width, height); glutCreateWindow("WebP viewer"); glutDisplayFunc(HandleDisplay); glutIdleFunc(NULL); glutKeyboardFunc(HandleKey); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glClearColor(GetColorf(kParams.bg_color, 0), GetColorf(kParams.bg_color, 8), GetColorf(kParams.bg_color, 16), GetColorf(kParams.bg_color, 24)); HandleReshape(width, height); glClear(GL_COLOR_BUFFER_BIT); DrawCheckerBoard(); }
static void HandleDisplay(void) { const WebPDecBuffer* const pic = kParams.pic; const WebPIterator* const curr = &kParams.curr_frame; WebPIterator* const prev = &kParams.prev_frame; GLfloat xoff, yoff; if (pic == NULL) return; glPushMatrix(); glPixelZoom(1, -1); xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width); yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height); glRasterPos2f(-1.f + xoff, 1.f - yoff); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND || curr->blend_method == WEBP_MUX_NO_BLEND) { // TODO(later): these offsets and those above should factor in window size. // they will be incorrect if the window is resized. // glScissor() takes window coordinates (0,0 at bottom left). int window_x, window_y; if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { // Clear the previous frame rectangle. window_x = prev->x_offset; window_y = kParams.canvas_height - prev->y_offset - prev->height; } else { // curr->blend_method == WEBP_MUX_NO_BLEND. // We simulate no-blending behavior by first clearing the current frame // rectangle (to a checker-board) and then alpha-blending against it. window_x = curr->x_offset; window_y = kParams.canvas_height - curr->y_offset - curr->height; } glEnable(GL_SCISSOR_TEST); // Only update the requested area, not the whole canvas. glScissor(window_x, window_y, prev->width, prev->height); glClear(GL_COLOR_BUFFER_BIT); // use clear color DrawCheckerBoard(); glDisable(GL_SCISSOR_TEST); } *prev = *curr; glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pic->u.RGBA.rgba); if (kParams.print_info) { char tmp[32]; glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.90f); PrintString(kParams.file_name); snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.80f); PrintString(tmp); if (curr->x_offset != 0 || curr->y_offset != 0) { snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", curr->x_offset, curr->y_offset); glRasterPos2f(-0.95f, 0.70f); PrintString(tmp); } } glPopMatrix(); glFlush(); }
static void HandleDisplay(void) { const WebPDecBuffer* const pic = kParams.pic; const WebPIterator* const iter = &kParams.frameiter; GLfloat xoff, yoff; if (pic == NULL) return; glPushMatrix(); glPixelZoom(1, -1); xoff = (GLfloat)(2. * iter->x_offset / kParams.canvas_width); yoff = (GLfloat)(2. * iter->y_offset / kParams.canvas_height); glRasterPos2f(-1.f + xoff, 1.f - yoff); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); if (kParams.prev_frame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { // TODO(later): these offsets and those above should factor in window size. // they will be incorrect if the window is resized. // glScissor() takes window coordinates (0,0 at bottom left). const int window_x = kParams.prev_frame.x_offset; const int window_y = kParams.canvas_height - kParams.prev_frame.y_offset - kParams.prev_frame.height; glEnable(GL_SCISSOR_TEST); // Only updated the requested area, not the whole canvas. glScissor(window_x, window_y, kParams.prev_frame.width, kParams.prev_frame.height); glClear(GL_COLOR_BUFFER_BIT); // use clear color DrawCheckerBoard(); glDisable(GL_SCISSOR_TEST); } kParams.prev_frame.width = iter->width; kParams.prev_frame.height = iter->height; kParams.prev_frame.x_offset = iter->x_offset; kParams.prev_frame.y_offset = iter->y_offset; kParams.prev_frame.dispose_method = iter->dispose_method; glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pic->u.RGBA.rgba); if (kParams.print_info) { char tmp[32]; glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.90f); PrintString(kParams.file_name); snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.80f); PrintString(tmp); if (iter->x_offset != 0 || iter->y_offset != 0) { snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", iter->x_offset, iter->y_offset); glRasterPos2f(-0.95f, 0.70f); PrintString(tmp); } } glPopMatrix(); glFlush(); }