#include #include #include #include #include #include #include #define TAG 50839 #define OFFSET 16 #define ONE_ROW 1 #define bool_t uint8_t #define FALSE 0 #define TRUE 1 double diff_timespec(struct timespec *time1, struct timespec *time0) { return (time1->tv_sec - time0->tv_sec) + (time1->tv_nsec - time0->tv_nsec) / 1000000000.0; } bool_t color_zero(uint8_t* color1, size_t channels) { for (size_t idx = 0; idx < channels; idx++) { if (idx == 3) { break; } if (color1[idx] != 0) { return FALSE; } } return TRUE; } bool_t color_equal(uint8_t* color1, uint8_t* color2, size_t channels) { for (size_t idx = 0; idx < channels; idx++) { if (color1[idx] != color2[idx]) { return FALSE; } } return TRUE; } void print_color(uint8_t* color, size_t channels) { for (size_t index = 0; index < channels; index++) { printf("%hhu ", color[index]); } printf("\n"); } bool_t flood(uint8_t* image, uint16_t* mask, size_t width, size_t height, size_t channels, size_t x, size_t y, uint8_t* color_old, uint16_t label) { if ((x >= width) | (y >= height)) { return FALSE; } size_t coord = x + y*width; if (mask[coord] != 0) { return FALSE; } if (color_zero(&(image[coord*channels]), channels)) { return FALSE; } if (color_equal(&(image[coord*channels]), color_old, channels)) { mask[coord] = label; flood(image, mask, width, height, channels, x, y+1, color_old, label); flood(image, mask, width, height, channels, x, y-1, color_old, label); flood(image, mask, width, height, channels, x+1, y, color_old, label); flood(image, mask, width, height, channels, x-1, y, color_old, label); return TRUE; } return FALSE; } int main() { SetConfigFlags(FLAG_WINDOW_RESIZABLE); const char* gui_title = "Image Manip - Useful for segmentations!"; InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, gui_title); TIFF *tif = TIFFOpen("./data/test.tif", "r"); if (!tif) { fprintf(stderr, "Failed to open TIFF file\n"); return 1; } uint32_t width, height; size_t channels = 1; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); void* buffer; tmsize_t STRIP_LENGTH = TIFFStripSize(tif); tmsize_t STRIP_COUNT = TIFFNumberOfStrips(tif); if (width*height*3 == STRIP_LENGTH*STRIP_COUNT) { channels = 3; } else if (width*height*4 == STRIP_LENGTH*STRIP_COUNT) { channels = 4; } printf("%llu\n", STRIP_LENGTH*STRIP_COUNT); printf("%lu %hhu\n", width*height*channels, channels); assert(STRIP_LENGTH*STRIP_COUNT == width*height*channels); buffer = malloc(STRIP_LENGTH*sizeof(uint8_t)); uint8_t* raster_8 = calloc(width*height*channels,sizeof(uint8_t)); for (size_t y = 0; y < STRIP_COUNT; y++) { tmsize_t strip_size = TIFFReadRawStrip(tif, y, buffer, STRIP_LENGTH); assert(strip_size == STRIP_LENGTH); for (size_t x = 0; x < STRIP_LENGTH; x++) { raster_8[x + y*STRIP_LENGTH] = ((uint8_t*)buffer)[x]; } } free(buffer); struct timespec ts_start, ts_end; char buff[100]; timespec_get(&ts_start, TIME_UTC); strftime(buff, sizeof buff, "%D %T", gmtime(&ts_start.tv_sec)); printf("Current time: %s.%09ld UTC\n", buff, ts_start.tv_nsec); // Flood fill uint16_t starting_label = 1; uint16_t *labels = NULL; labels = (uint16_t*)calloc(width*height,sizeof(uint16_t)); for (size_t y = 0; y < height; y++) { for (size_t x = 0; x < width; x++) { size_t coord = x + y*width; if(flood(raster_8, labels, width, height, channels, x, y, &(raster_8[coord*channels]), starting_label)) { starting_label += 1; } } } for (size_t y = 0; y < height; y++) { for (size_t x = 0; x < width; x++) { labels[x + y*width] |= 0xFF000000; } } timespec_get(&ts_end, TIME_UTC); strftime(buff, sizeof buff, "%D %T", gmtime(&ts_end.tv_sec)); printf("Current time: %s.%09ld UTC\n", buff, ts_end.tv_nsec); printf("Time difference: %f\n", diff_timespec(&ts_end, &ts_start)); printf("N_labels: %u\n", starting_label-1); uint32_t *raster = (uint32_t*)_TIFFmalloc(width*height*sizeof(uint32_t)); if (raster == NULL) { fprintf(stderr, "Memory allocation error\n"); TIFFClose(tif); return 1; } if (!TIFFReadRGBAImage(tif, width, height, raster, 0)) { fprintf(stderr, "Failed to read TIFF image\n"); _TIFFfree(raster); TIFFClose(tif); return 1; } Image RaylibImage; //RaylibImage.data = raster; //RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; RaylibImage.data = raster_8; if (channels == 1) { RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; } else if (channels == 3) { RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8; } else if (channels == 4) { RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; } else { assert(0); } RaylibImage.data = labels; RaylibImage.format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4; RaylibImage.width = width; RaylibImage.height = height; RaylibImage.mipmaps = 1; Texture2D RaylibTexture = LoadTextureFromImage(RaylibImage); Rectangle sourceRec = { 0.0f, 0.0f, (float)width, (float)height }; Rectangle destRec = { 0.0f, 0.0f, (float)SCREEN_WIDTH, (float)(SCREEN_HEIGHT-OFFSET) }; Vector2 origin = { (float)0, (float)-OFFSET }; SetTargetFPS(60); Camera2D camera = { 0 }; camera.zoom = 1.0f; while (!WindowShouldClose()) { //----------------------------------------------- //-DRAWING--------------------------------------- //----------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); BeginMode2D(camera); EndMode2D(); DrawText("Image Manip", 0, 0, OFFSET, DARKGRAY); DrawTexturePro(RaylibTexture, sourceRec, destRec, origin, (float)0, RAYWHITE); uint32_t x = 0x49, y = 0x4A; uint32_t dx = 0x69 - x, dy = 0x6E - y; x = (SCREEN_WIDTH*x)/width; y = SCREEN_HEIGHT-((SCREEN_HEIGHT-OFFSET)*y)/height; dx = (SCREEN_WIDTH*dx)/width; dy = SCREEN_HEIGHT-((SCREEN_HEIGHT-OFFSET)*dy)/height; DrawRectangleGradientH(x, y, dx, dy, BLUE, PURPLE); EndDrawing(); //----------------------------------------------- } if (labels != NULL) { free(labels); } free(raster_8); _TIFFfree(raster); TIFFClose(tif); CloseWindow(); return 0; }