X-Git-Url: https://git.sesse.net/index.cgi/?a=blobdiff_plain;f=stinger%2Fblur.cpp;fp=stinger%2Fblur.cpp;h=76c9ca8ebbb04636cd08d951cac6b78eb94dac6c;hb=780f5f18be8d28389a6ac9433aa6d8e5d5b80338;hp=0000000000000000000000000000000000000000;hpb=e5ca9f8c9d6277669bbb8ae244172cfe547e56a4;p=ultimatescore diff --git a/stinger/blur.cpp b/stinger/blur.cpp new file mode 100644 index 0000000..76c9ca8 --- /dev/null +++ b/stinger/blur.cpp @@ -0,0 +1,218 @@ +#define NO_SDL_GLEXT 1 + +#define WIDTH 1280 +#define HEIGHT 720 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace movit; + +unsigned char result[WIDTH * HEIGHT * 4]; + +unsigned char *load_image(const char *filename, unsigned *w, unsigned *h) +{ + SDL_Surface *img = IMG_Load(filename); + if (img == nullptr) { + fprintf(stderr, "Load of '%s' failed\n", filename); + exit(1); + } + + SDL_PixelFormat rgba_fmt; + rgba_fmt.palette = nullptr; + rgba_fmt.BitsPerPixel = 32; + rgba_fmt.BytesPerPixel = 8; + rgba_fmt.Rloss = rgba_fmt.Gloss = rgba_fmt.Bloss = rgba_fmt.Aloss = 0; + + // NOTE: Assumes little endian. + rgba_fmt.Rmask = 0x00ff0000; + rgba_fmt.Gmask = 0x0000ff00; + rgba_fmt.Bmask = 0x000000ff; + rgba_fmt.Amask = 0xff000000; + + rgba_fmt.Rshift = 16; + rgba_fmt.Gshift = 8; + rgba_fmt.Bshift = 0; + rgba_fmt.Ashift = 24; + + SDL_Surface *converted = SDL_ConvertSurface(img, &rgba_fmt, SDL_SWSURFACE); + + *w = img->w; + *h = img->h; + + SDL_FreeSurface(img); + + unsigned char *crop_img = new unsigned char[1280 * 720 * 4]; + + int img_w = *w; + int img_h = *h; + + int xoffs = (1280 - int(img_w)) / 2; + int yoffs = (720 - int(img_h)) / 2; + + for (unsigned y = 0; y < 720; ++y) { + unsigned char *dptr = crop_img + y * 1280 * 4; + int ysrc = y - yoffs; + if (ysrc < 0 || ysrc >= int(img_h)) { + memset(dptr, 0, 1280 * 4); + continue; + } + unsigned char *sptr = (unsigned char *)converted->pixels + ysrc * img_w * 4; + if (img_w >= 1280) { + memcpy(dptr, sptr - xoffs * 4, 1280 * 4); + } else { + memset(dptr, 0, 1280 * 4); + memcpy(dptr + xoffs * 4, sptr, img_w * 4); + } + } + + SDL_FreeSurface(converted); + + *w = 1280; + *h = 720; + + return crop_img; +} + +void write_png(const char *filename, unsigned char *screenbuf) +{ + FILE *fp = fopen(filename, "wb"); + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (setjmp(png_jmpbuf(png_ptr))) { + fclose(fp); + fprintf(stderr, "Write to %s failed; exiting.\n", filename); + exit(1); + } + + png_set_IHDR(png_ptr, info_ptr, WIDTH, HEIGHT, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_bytep *row_pointers = new png_bytep[HEIGHT]; + for (unsigned y = 0; y < HEIGHT; ++y) { + row_pointers[y] = screenbuf + ((HEIGHT - y - 1) * WIDTH) * 4; + } + + png_init_io(png_ptr, fp); + png_set_rows(png_ptr, info_ptr, row_pointers); + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, nullptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + + delete[] row_pointers; +} + +class BouncingIdentityEffect : public Effect { +public: + BouncingIdentityEffect() {} + std::string effect_type_id() const override { return "IdentityEffect"; } + std::string output_fragment_shader() override { return read_file("identity.frag"); } + bool needs_texture_bounce() const override { return true; } + AlphaHandling alpha_handling() const override { return DONT_CARE_ALPHA_TYPE; } +}; + + +int main(int argc, char **argv) +{ + if (SDL_Init(SDL_INIT_EVERYTHING) == -1) { + fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); + exit(1); + } + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + // SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); + SDL_Window *window = SDL_CreateWindow("OpenGL window", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + WIDTH, HEIGHT, + SDL_WINDOW_OPENGL); + SDL_GLContext context = SDL_GL_CreateContext(window); + assert(context != nullptr); + + CHECK(init_movit("/usr/share/movit", MOVIT_DEBUG_OFF)); + + EffectChain chain(WIDTH, HEIGHT); + glViewport(0, 0, WIDTH, HEIGHT); + + ImageFormat inout_format; + inout_format.color_space = COLORSPACE_sRGB; + inout_format.gamma_curve = GAMMA_sRGB; + + Effect *last_effect = nullptr; + for (int i = 1; i < argc; ++i) { + fprintf(stderr, "%s...\n", argv[i]); + unsigned img_w, img_h; + unsigned char *src_img = load_image(argv[i], &img_w, &img_h); + + FlatInput *input = new FlatInput(inout_format, FORMAT_BGRA_POSTMULTIPLIED_ALPHA, GL_UNSIGNED_BYTE, img_w, img_h); + input->set_pixel_data(src_img); + chain.add_input(input); + + if (i == 1) { + last_effect = input; + } else { + Effect *mix_effect = chain.add_effect(new MixEffect(), last_effect, input); + float z = 1.0f / i; + CHECK(mix_effect->set_float("strength_first", 1.0f - z)); + CHECK(mix_effect->set_float("strength_second", z)); + last_effect = mix_effect; + } + + if (i % 10 == 0) { + last_effect = chain.add_effect(new BouncingIdentityEffect()); + } + } + + chain.add_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED); + chain.set_dither_bits(8); + chain.finalize(); + + // generate a PBO to hold the data we read back with glReadPixels() + // (Intel/DRI goes into a slow path if we don't read to PBO) + GLuint pbo; + glGenBuffers(1, &pbo); + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); + glBufferData(GL_PIXEL_PACK_BUFFER_ARB, WIDTH * HEIGHT * 4, nullptr, GL_STREAM_READ); + + chain.render_to_screen(); + + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); + check_error(); + glReadPixels(0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER_OFFSET(0)); + check_error(); + + unsigned char *screenbuf = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); + write_png("blurout.png", screenbuf); + + return 0; +}