static PyObject * flea_get_gamma(PyObject *self, PyObject *args) { int handle = -1; fleaCamera* cam = NULL; float gamma; if (!PyArg_ParseTuple(args, "i", &handle)) return NULL; if (handle >= 0 && handle < NUM_CAMERA_HANDLES && cameras[handle]) { cam = cameras[handle]; gamma = get_gamma(cam); } else { PyErr_SetString(FleaError, "Invalid Handle"); return NULL; } return Py_BuildValue("f",gamma); }
/* really_load_png: * Worker routine, used by load_png and load_memory_png. */ static BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr, RGB *pal) { BITMAP *bmp; PALETTE tmppal; png_uint_32 width, height, rowbytes; int bit_depth, color_type, interlace_type; double image_gamma, screen_gamma; int intent; int bpp, dest_bpp; int tRNS_to_alpha = FALSE; int number_passes, pass; ASSERT(png_ptr && info_ptr && rgb); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) png_set_expand(png_ptr); /* Adds a full alpha channel if there is transparency information * in a tRNS chunk. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); tRNS_to_alpha = TRUE; } /* Convert 16-bits per colour component to 8-bits per colour component. */ if (bit_depth == 16) png_set_strip_16(png_ptr); /* Convert grayscale to RGB triplets */ if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_gray_to_rgb(png_ptr); /* Optionally, tell libpng to handle the gamma correction for us. */ if (_png_screen_gamma != 0.0) { screen_gamma = get_gamma(); if (png_get_sRGB(png_ptr, info_ptr, &intent)) png_set_gamma(png_ptr, screen_gamma, 0.45455); else { if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) png_set_gamma(png_ptr, screen_gamma, image_gamma); else png_set_gamma(png_ptr, screen_gamma, 0.45455); } } /* Turn on interlace handling. */ number_passes = png_set_interlace_handling(png_ptr); /* Call to gamma correct and add the background to the palette * and update info structure. */ png_read_update_info(png_ptr, info_ptr); /* Even if the user doesn't supply space for a palette, we want * one for the load process. */ if (!pal) pal = tmppal; /* Palettes. */ if (color_type & PNG_COLOR_MASK_PALETTE) { int num_palette, i; png_colorp palette; if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { /* We don't actually dither, we just copy the palette. */ for (i = 0; ((i < num_palette) && (i < 256)); i++) { pal[i].r = palette[i].red >> 2; /* 256 -> 64 */ pal[i].g = palette[i].green >> 2; pal[i].b = palette[i].blue >> 2; } for (; i < 256; i++) pal[i].r = pal[i].g = pal[i].b = 0; } }
void video_menu (Game *game) { int choice = -1; bool done = false; int i, width, height, bpp, fs, native_res, native_bpp; DIALOG old_settings[sizeof(video_dialog)/sizeof(video_dialog[0])]; tw_set_config_file(home_ini_full_path("client.ini")); if (get_config_int("Video", "NativeResolution", 1)) { i = static_get_native_resolution_index(); } else { sprintf(dialog_string[3], "%dx%d", videosystem.width, videosystem.height); for (i = 0; i< sizeof(resolution)/sizeof(resolution[0]); i++) { if (strcmp(resolution[i], dialog_string[3]) == 0) { break; } } if (i == sizeof(resolution)/sizeof(resolution[0])) { i = static_get_native_resolution_index(); } } video_dialog[DIALOG_VIDEO_RESLIST].d1 = i; if (get_config_int("Video", "NativeBpp", 1)) { i = static_get_native_bpp_index(); } else { for (i = 0; i< sizeof(color_depth)/sizeof(color_depth[0]); i++) { if (atoi(color_depth[i]) == videosystem.bpp) { break; } if (i == sizeof(color_depth)/sizeof(color_depth[0])) { i = static_get_native_bpp_index(); } } } video_dialog[DIALOG_VIDEO_BPPLIST].d1 = i; //set button for fullscreen video_dialog[DIALOG_VIDEO_FULLSCREEN].flags = videosystem.fullscreen ? D_SELECTED : 0; int startfs = video_dialog[DIALOG_VIDEO_FULLSCREEN].flags; //set gamma correction video_dialog[DIALOG_VIDEO_GAMMA_SLIDER].d2 = get_gamma(); memcpy(old_settings, video_dialog, sizeof(video_dialog)); while ( (choice != DIALOG_VIDEO_EXIT) && (!done) ) { //do the dialog choice = tw_popup_dialog(NULL, video_dialog, 0); if (choice == -1) choice = DIALOG_VIDEO_EXIT; static_video_dialog_to_params(video_dialog, &width, &height, &bpp, &fs, &native_res, &native_bpp); switch (choice) { case DIALOG_VIDEO_GET_DEFAULT: set_config_int("Video", "BitsPerPixel", 16); set_config_int("Video", "ScreenWidth", 640); set_config_int("Video", "ScreenHeight", 480); set_config_int("Video", "FullScreen", 1); set_config_int("Video", "Gamma", 128); set_config_int("Video", "NativeResolution", 1); set_config_int("Video", "NativeBpp", 1); if (tw_get_desktop_resolution(&width, &height)) { tw_error("Unable to get desktop resolution!!!"); } videosystem.set_resolution(width, height, tw_desktop_color_depth(), 1); return; break; case DIALOG_VIDEO_OK: set_gamma(video_dialog[DIALOG_VIDEO_GAMMA_SLIDER].d2); if (videosystem.set_resolution(width, height, bpp, fs)) { if (confirmVideoChanges()) { set_config_int("Video", "BitsPerPixel", bpp); set_config_int("Video", "ScreenWidth", width); set_config_int("Video", "ScreenHeight", height); set_config_int("Video", "FullScreen", fs); set_config_int("Video", "Gamma", get_gamma()); if (video_dialog[DIALOG_VIDEO_RESLIST].d1 == static_get_native_resolution_index()) { set_config_int("Video", "NativeResolution", 1); } else { set_config_int("Video", "NativeResolution", 0); } if (video_dialog[DIALOG_VIDEO_BPPLIST].d1 == static_get_native_bpp_index()) { set_config_int("Video", "NativeBpp", 1); } else { set_config_int("Video", "NativeBpp", 0); } return; } else { static_video_dialog_to_params(old_settings, &width, &height, &bpp, &fs, &native_res, &native_bpp); videosystem.set_resolution(width, height, bpp, fs); memcpy(video_dialog, old_settings, sizeof(video_dialog)); } } break; case DIALOG_VIDEO_GAMMA_SLIDER: set_gamma(video_dialog[DIALOG_VIDEO_GAMMA_SLIDER].d2); break; case DIALOG_VIDEO_EXIT: case -1: return; break; } } return; }
int main(int argc, char *const argv[]) { char *map_output_file = NULL; if (argc < 3) { usage(argv[0]); return 1; } opterr = 0; int c; while((c = getopt(argc, argv, "ho:")) != -1) { switch (c) { case 'h': usage(argv[0]); return 0; case 'o': map_output_file = optarg; break; default: fprintf(stderr, "Unknown option\n"); return 1; } } if (optind+1 >= argc) { fprintf(stderr, "You must specify at least 2 files to compare\n"); return 1; } const char *file1 = argv[optind]; png24_image image1 = {}; int retval = read_image(file1, &image1); if (retval) { fprintf(stderr, "Can't read %s\n", file1); return retval; } dssim_attr *attr = dssim_create_attr(); dssim_image *original = dssim_create_image(attr, image1.row_pointers, DSSIM_RGBA, image1.width, image1.height, get_gamma(&image1)); free(image1.row_pointers); free(image1.rgba_data); for (int arg = optind+1; arg < argc; arg++) { const char *file2 = argv[arg]; png24_image image2 = {}; retval = read_image(file2, &image2); if (retval) { fprintf(stderr, "Can't read %s\n", file2); break; } if (image1.width != image2.width || image1.height != image2.height) { fprintf(stderr, "Image %s has different size than %s\n", file2, file1); break; } dssim_image *modified = dssim_create_image(attr, image2.row_pointers, DSSIM_RGBA, image2.width, image2.height, get_gamma(&image2)); free(image2.row_pointers); free(image2.rgba_data); if (map_output_file) { dssim_set_save_ssim_maps(attr, 1, 1); } double dssim = dssim_compare(attr, original, modified); dssim_dealloc_image(modified); printf("%.6f\t%s\n", dssim, file2); if (map_output_file) { dssim_ssim_map map_meta = dssim_pop_ssim_map(attr, 0, 0); dssim_px_t *map = map_meta.data; dssim_rgba *out = (dssim_rgba*)map; for(int i=0; i < map_meta.width*map_meta.height; i++) { const dssim_px_t max = 1.0 - map[i]; const dssim_px_t maxsq = max * max; out[i] = (dssim_rgba) { .r = to_byte(max * 3.0), .g = to_byte(maxsq * 6.0), .b = to_byte(max / ((1.0 - map_meta.dssim) * 4.0)), .a = 255, }; } if (write_image(map_output_file, out, map_meta.width, map_meta.height)) { fprintf(stderr, "Can't write %s\n", map_output_file); free(map); return 1; } free(map); } } dssim_dealloc_image(original); dssim_dealloc_attr(attr); return retval; }
/* really_load_png: * Worker routine, used by load_png and load_memory_png. */ static ALLEGRO_BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr, int flags) { ALLEGRO_BITMAP *bmp; png_uint_32 width, height, rowbytes, real_rowbytes; int bit_depth, color_type, interlace_type; double image_gamma, screen_gamma; int intent; int bpp; int number_passes, pass; int num_trans = 0; PalEntry pal[256]; png_bytep trans; ALLEGRO_LOCKED_REGION *lock; unsigned char *buf; unsigned char *dest; bool premul = !(flags & ALLEGRO_NO_PREMULTIPLIED_ALPHA); bool index_only; ALLEGRO_ASSERT(png_ptr && info_ptr); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) png_set_expand(png_ptr); /* Adds a full alpha channel if there is transparency information * in a tRNS chunk. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { if (!(color_type & PNG_COLOR_MASK_PALETTE)) png_set_tRNS_to_alpha(png_ptr); png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); } /* Convert 16-bits per colour component to 8-bits per colour component. */ if (bit_depth == 16) png_set_strip_16(png_ptr); /* Convert grayscale to RGB triplets */ if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_gray_to_rgb(png_ptr); /* Optionally, tell libpng to handle the gamma correction for us. */ if (_al_png_screen_gamma != 0.0) { screen_gamma = get_gamma(); if (png_get_sRGB(png_ptr, info_ptr, &intent)) png_set_gamma(png_ptr, screen_gamma, 0.45455); else { if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) png_set_gamma(png_ptr, screen_gamma, image_gamma); else png_set_gamma(png_ptr, screen_gamma, 0.45455); } } /* Turn on interlace handling. */ number_passes = png_set_interlace_handling(png_ptr); /* Call to gamma correct and add the background to the palette * and update info structure. */ png_read_update_info(png_ptr, info_ptr); /* Palettes. */ if (color_type & PNG_COLOR_MASK_PALETTE) { int num_palette, i; png_colorp palette; if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { /* We don't actually dither, we just copy the palette. */ for (i = 0; ((i < num_palette) && (i < 256)); i++) { pal[i].r = palette[i].red; pal[i].g = palette[i].green; pal[i].b = palette[i].blue; } for (; i < 256; i++) pal[i].r = pal[i].g = pal[i].b = 0; } } rowbytes = png_get_rowbytes(png_ptr, info_ptr); /* Allocate the memory to hold the image using the fields of info_ptr. */ bpp = rowbytes * 8 / width; /* Allegro cannot handle less than 8 bpp. */ if (bpp < 8) bpp = 8; if ((bpp == 24) || (bpp == 32)) { #ifdef ALLEGRO_BIG_ENDIAN png_set_bgr(png_ptr); png_set_swap_alpha(png_ptr); #endif } bmp = al_create_bitmap(width, height); if (!bmp) { ALLEGRO_ERROR("al_create_bitmap failed while loading PNG.\n"); return NULL; } // TODO: can this be different from rowbytes? real_rowbytes = ((bpp + 7) / 8) * width; if (interlace_type == PNG_INTERLACE_ADAM7) buf = al_malloc(real_rowbytes * height); else buf = al_malloc(real_rowbytes); if (bpp == 8 && (color_type & PNG_COLOR_MASK_PALETTE) && (flags & ALLEGRO_KEEP_INDEX)) { lock = al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8, ALLEGRO_LOCK_WRITEONLY); index_only = true; } else { lock = al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE, ALLEGRO_LOCK_WRITEONLY); index_only = false; } /* Read the image, one line at a time (easier to debug!) */ for (pass = 0; pass < number_passes; pass++) { png_uint_32 y; unsigned int i; unsigned char *ptr; dest = lock->data; for (y = 0; y < height; y++) { unsigned char *dest_row_start = dest; /* For interlaced pictures, the row needs to be initialized with * the contents of the previous pass. */ if (interlace_type == PNG_INTERLACE_ADAM7) ptr = buf + y * real_rowbytes; else ptr = buf; png_read_row(png_ptr, NULL, ptr); switch (bpp) { case 8: if (index_only) { for (i = 0; i < width; i++) { *(dest++) = *(ptr++); } } else if (color_type & PNG_COLOR_MASK_PALETTE) { for (i = 0; i < width; i++) { int pix = ptr[0]; ptr++; dest[0] = pal[pix].r; dest[1] = pal[pix].g; dest[2] = pal[pix].b; if (pix < num_trans) { int a = trans[pix]; dest[3] = a; if (premul) { dest[0] = dest[0] * a / 255; dest[1] = dest[1] * a / 255; dest[2] = dest[2] * a / 255; } } else { dest[3] = 255; } dest += 4; } } else { for (i = 0; i < width; i++) { int pix = ptr[0]; ptr++; *(dest++) = pix; *(dest++) = pix; *(dest++) = pix; *(dest++) = 255; } } break; case 24: for (i = 0; i < width; i++) { uint32_t pix = _AL_READ3BYTES(ptr); ptr += 3; *(dest++) = pix & 0xff; *(dest++) = (pix >> 8) & 0xff; *(dest++) = (pix >> 16) & 0xff; *(dest++) = 255; } break; case 32: for (i = 0; i < width; i++) { uint32_t pix = *(uint32_t*)ptr; int r = pix & 0xff; int g = (pix >> 8) & 0xff; int b = (pix >> 16) & 0xff; int a = (pix >> 24) & 0xff; ptr += 4; if (premul) { r = r * a / 255; g = g * a / 255; b = b * a / 255; } *(dest++) = r; *(dest++) = g; *(dest++) = b; *(dest++) = a; } break; default: ALLEGRO_ASSERT(bpp == 8 || bpp == 24 || bpp == 32); break; } dest = dest_row_start + lock->pitch; } } al_unlock_bitmap(bmp); al_free(buf); /* Read rest of file, and get additional chunks in info_ptr. */ png_read_end(png_ptr, info_ptr); return bmp; }