void imProcessFillHoles(const imImage* image, imImage* NewImage, int connect) { // finding regions in the inverted image will isolate only the holes. imProcessNegative(image, NewImage); imImage *region_image = imImageCreate(image->width, image->height, IM_GRAY, IM_USHORT); if (!region_image) return; int holes_count = imAnalyzeFindRegions(NewImage, region_image, connect, 0); if (!holes_count) { imImageCopy(image, NewImage); imImageDestroy(region_image); return; } imushort* region_data = (imushort*)region_image->data[0]; imbyte* dst_data = (imbyte*)NewImage->data[0]; for (int i = 0; i < image->count; i++) { if (*region_data) *dst_data = 1; else *dst_data = !(*dst_data); // Fix negative data. region_data++; dst_data++; } imImageDestroy(region_image); }
void imProcessRemoveByArea(const imImage* image, imImage* NewImage, int connect, int start_size, int end_size, int inside) { imImage *region_image = imImageCreate(image->width, image->height, IM_GRAY, IM_USHORT); if (!region_image) return; int region_count = imAnalyzeFindRegions(image, region_image, connect, 1); if (!region_count) { imImageClear(NewImage); imImageDestroy(region_image); return; } if (end_size == 0) end_size = image->width*image->height; int outside; if (inside) { /* remove from inside */ inside = 0; outside = 1; } else { /* remove from outside */ inside = 1; outside = 0; } int* area_data = (int*)malloc(region_count*sizeof(int)); imAnalyzeMeasureArea(region_image, area_data, region_count); imushort* region_data = (imushort*)region_image->data[0]; imbyte* img_data = (imbyte*)NewImage->data[0]; for (int i = 0; i < image->count; i++) { if (*region_data) { int area = area_data[(*region_data) - 1]; if (area < start_size || area > end_size) *img_data = (imbyte)outside; else *img_data = (imbyte)inside; } else *img_data = 0; region_data++; img_data++; } free(area_data); imImageDestroy(region_image); }
int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size) { imImage*temp = imImageClone(src_image); if (!temp) return 0; if (!imProcessGrayMorphDilate(src_image, temp, kernel_size)) {imImageDestroy(temp); return 0;} if (!imProcessGrayMorphErode(temp, dst_image, kernel_size)) {imImageDestroy(temp); return 0;} imImageDestroy(temp); return 1; }
int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size) { imImage*temp = imImageClone(src_image); if (!temp) return 0; if (!imProcessGrayMorphDilate(src_image, temp, kernel_size)) {imImageDestroy(temp); return 0;} if (!imProcessGrayMorphErode(src_image, dst_image, kernel_size)) {imImageDestroy(temp); return 0;} imProcessArithmeticOp(temp, dst_image, dst_image, IM_BIN_DIFF); imImageDestroy(temp); return 1; }
void imProcessCrossCorrelation(const imImage* src_image1, const imImage* src_image2, imImage* dst_image) { imImage *tmp_image = imImageCreate(src_image2->width, src_image2->height, src_image2->color_space, IM_COMPLEX); if (!tmp_image) return; if (src_image2->data_type != IM_COMPLEX) imConvertDataType(src_image2, tmp_image, 0, 0, 0, 0); else imImageCopy(src_image2, tmp_image); if (src_image1->data_type != IM_COMPLEX) imConvertDataType(src_image1, dst_image, 0, 0, 0, 0); else imImageCopy(src_image1, dst_image); imProcessFFTraw(tmp_image, 0, 1, 1); // forward, centered, normalized imProcessFFTraw(dst_image, 0, 1, 1); imProcessMultiplyConj(dst_image, tmp_image, dst_image); imProcessFFTraw(dst_image, 1, 1, 1); // inverse, uncentered, normalized imProcessSwapQuadrants(dst_image, 0); // from origin to center imImageDestroy(tmp_image); }
int item_paste_action_cb(Ihandle* item_paste) { if (save_check(item_paste)) { Ihandle* canvas = IupGetDialogChild(item_paste, "CANVAS"); imImage* old_image = (imImage*)IupGetAttribute(canvas, "IMAGE"); Ihandle *clipboard = IupClipboard(); imImage* image = IupGetNativeHandleImage(IupGetAttribute(clipboard, "NATIVEIMAGE")); IupDestroy(clipboard); if (!image) { show_error("Invalid Clipboard Data", 1); return IUP_DEFAULT; } /* we are going to support only RGB images with no alpha */ imImageRemoveAlpha(image); if (image->color_space != IM_RGB) { imImage* new_image = imImageCreateBased(image, -1, -1, IM_RGB, -1); imConvertColorSpace(image, new_image); imImageDestroy(image); image = new_image; } /* create OpenGL compatible data */ imImageGetOpenGLData(image, NULL); imImageSetAttribString(image, "FileFormat", "JPEG"); IupSetAttribute(canvas, "DIRTY", "Yes"); IupSetAttribute(canvas, "IMAGE", (char*)image); IupSetAttribute(canvas, "FILENAME", NULL); IupSetAttribute(IupGetDialog(canvas), "TITLE", "Untitled - Simple Paint"); IupUpdate(canvas); if (old_image) imImageDestroy(old_image); } return IUP_DEFAULT; }
int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size) { imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT); imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Dilate"); // Kernel is all zeros int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 1); imImageDestroy(kernel); return ret; }
void set_new_image(Ihandle* canvas, imImage* image, const char* filename, int dirty) { imImage* old_image = (imImage*)IupGetAttribute(canvas, "IMAGE"); Ihandle* size_lbl = IupGetDialogChild(canvas, "SIZELABEL"); Ihandle* zoom_val = IupGetDialogChild(canvas, "ZOOMVAL"); if (filename) { IupSetStrAttribute(canvas, "FILENAME", filename); IupSetfAttribute(IupGetDialog(canvas), "TITLE", "%s - Simple Paint", str_filetitle(filename)); } else { IupSetAttribute(canvas, "FILENAME", NULL); IupSetAttribute(IupGetDialog(canvas), "TITLE", "Untitled - Simple Paint"); } /* we are going to support only RGB images with no alpha */ imImageRemoveAlpha(image); if (image->color_space != IM_RGB) { imImage* new_image = imImageCreateBased(image, -1, -1, IM_RGB, -1); imConvertColorSpace(image, new_image); imImageDestroy(image); image = new_image; } /* default file format */ const char* format = imImageGetAttribString(image, "FileFormat"); if (!format) imImageSetAttribString(image, "FileFormat", "JPEG"); IupSetAttribute(canvas, "DIRTY", dirty? "Yes": "No"); IupSetAttribute(canvas, "IMAGE", (char*)image); IupSetfAttribute(size_lbl, "TITLE", "%d x %d px", image->width, image->height); if (old_image) imImageDestroy(old_image); IupSetDouble(zoom_val, "VALUE", 0); zoom_update(canvas, 0); }
/*****************************************************************************\ image:Destroy() \*****************************************************************************/ static int imluaImageDestroy (lua_State *L) { imImage** image_p = imlua_rawcheckimage(L, 1); if (!(*image_p)) luaL_argerror(L, 1, "destroyed imImage"); imImageDestroy(*image_p); *image_p = NULL; /* mark as destroyed */ return 0; }
/*****************************************************************************\ gc \*****************************************************************************/ static int imluaImage_gc (lua_State *L) { imImage** image_p = imlua_rawcheckimage(L, 1); if (*image_p) { imImageDestroy(*image_p); *image_p = NULL; /* mark as destroyed */ } return 0; }
int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage *kernel, int ismax) { int ret = 0; int counter = imProcessCounterBegin("Gray Morphological Convolution"); const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); if (!msg) msg = "Processing..."; imCounterTotal(counter, src_image->depth*src_image->height, msg); imImage* fkernel = NULL; if ((src_image->data_type == IM_FLOAT || src_image->data_type == IM_DOUBLE) && kernel->data_type != src_image->data_type) { fkernel = imImageCreate(kernel->width, kernel->height, IM_GRAY, src_image->data_type); imProcessConvertDataType(kernel, fkernel, 0, 0, 0, IM_CAST_DIRECT); kernel = fkernel; } for (int i = 0; i < src_image->depth; i++) { switch(src_image->data_type) { case IM_BYTE: ret = DoGrayMorphConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); break; case IM_SHORT: ret = DoGrayMorphConvolve((short*)src_image->data[i], (short*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); break; case IM_USHORT: ret = DoGrayMorphConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); break; case IM_INT: ret = DoGrayMorphConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); break; case IM_FLOAT: ret = DoGrayMorphConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (float)0); break; case IM_DOUBLE: ret = DoGrayMorphConvolve((double*)src_image->data[i], (double*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (double)0); break; } if (!ret) break; } if (fkernel) imImageDestroy(fkernel); imProcessCounterEnd(counter); return ret; }
static int cbDialogClose(Ihandle* iup_dialog) { cdCanvas* cd_canvas = (cdCanvas*)IupGetAttribute(iup_dialog, "cdCanvas"); imImage* image = (imImage*)IupGetAttribute(iup_dialog, "imImage"); if (cd_canvas) cdKillCanvas(cd_canvas); if (image) imImageDestroy(image); IupSetAttribute(iup_dialog, "cdCanvas", NULL); IupSetAttribute(iup_dialog, "imImage", NULL); return IUP_CLOSE; }
static void ShowImage(char* file_name, Ihandle* iup_dialog) { int error; imImage* image = (imImage*)IupGetAttribute(iup_dialog, "imImage"); if (image) imImageDestroy(image); IupSetAttribute(iup_dialog, "imImage", NULL); image = imFileImageLoadBitmap(file_name, 0, &error); if (error) PrintError(error); if (!image) return; IupSetAttribute(iup_dialog, "imImage", (char*)image); IupStoreAttribute(iup_dialog, "TITLE", file_name); cbCanvasRepaint(iup_dialog); /* we can do this because canvas inherit attributes from the dialog */ }
int item_exit_action_cb(Ihandle* item_exit) { Ihandle* dlg = IupGetDialog(item_exit); Ihandle* config = (Ihandle*)IupGetAttribute(dlg, "CONFIG"); Ihandle* canvas = IupGetDialogChild(dlg, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (!save_check(item_exit)) return IUP_IGNORE; /* to abort the CLOSE_CB callback */ if (image) imImageDestroy(image); IupConfigDialogClosed(config, dlg, "MainWindow"); IupConfigSave(config); IupDestroy(config); return IUP_CLOSE; }
static int bt1_cb(Ihandle* self) { imImage* image; int w, h; void* gldata; int ii = tabs_get_index(); IupGetIntInt(plot[ii], "DRAWSIZE", &w, &h); gldata = malloc(w*h*3); image = imImageCreate(w, h, IM_RGB, IM_BYTE); IupMglPlotPaintTo(plot[ii], "RGB", w, h, 0, gldata); imConvertPacking(gldata, image->data[0], w, h, 3, 3, IM_BYTE, 1); imProcessFlip(image, image); imFileImageSave("../mglplot.png", "PNG", image); free(gldata); imImageDestroy(image); (void)self; return IUP_DEFAULT; }
void new_file(Ihandle* ih, imImage* image) { Ihandle* dlg = IupGetDialog(ih); Ihandle* canvas = IupGetDialogChild(dlg, "CANVAS"); imImage* old_image = (imImage*)IupGetAttribute(canvas, "IMAGE"); IupSetAttribute(dlg, "TITLE", "Untitled - Simple Paint"); IupSetAttribute(canvas, "FILENAME", NULL); IupSetAttribute(canvas, "DIRTY", "NO"); IupSetAttribute(canvas, "IMAGE", (char*)image); /* create OpenGL compatible data */ imImageGetOpenGLData(image, NULL); IupUpdate(canvas); if (old_image) imImageDestroy(old_image); }
void open_file(Ihandle* ih, const char* filename) { imImage* image = read_file(filename); if (image) { Ihandle* dlg = IupGetDialog(ih); Ihandle* canvas = IupGetDialogChild(dlg, "CANVAS"); Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); imImage* old_image = (imImage*)IupGetAttribute(canvas, "IMAGE"); IupSetfAttribute(dlg, "TITLE", "%s - Simple Paint", str_filetitle(filename)); IupSetStrAttribute(canvas, "FILENAME", filename); IupSetAttribute(canvas, "DIRTY", "NO"); IupSetAttribute(canvas, "IMAGE", (char*)image); IupUpdate(canvas); if (old_image) imImageDestroy(old_image); IupConfigRecentUpdate(config, filename); } }
imImage* read_file(const char* filename) { int error; imImage* image = imFileImageLoadBitmap(filename, 0, &error); if (error) show_file_error(error); else { /* we are going to support only RGB images with no alpha */ imImageRemoveAlpha(image); if (image->color_space != IM_RGB) { imImage* new_image = imImageCreateBased(image, -1, -1, IM_RGB, -1); imConvertColorSpace(image, new_image); imImageDestroy(image); image = new_image; } /* create OpenGL compatible data */ imImageGetOpenGLData(image, NULL); } return image; }
int imConvertToBitmap(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int absolute, int cast_mode) #endif { assert(src_image); assert(dst_image); if (!imImageMatchSize(src_image, dst_image) || !imImageIsBitmap(dst_image)) return IM_ERR_DATA; #ifdef IM_PROCESS int counter = imProcessCounterBegin("Building Bitmap"); #else int counter = imCounterBegin("Building Bitmap"); #endif int ret; if (src_image->data_type == IM_BYTE) { // NO data type conversion, only color mode conversion #ifdef IM_PROCESS ret = imProcessConvertColorSpace(src_image, dst_image); #else ret = imConvertColorSpace(src_image, dst_image); #endif } else { if (src_image->color_space == IM_RGB || src_image->color_space == IM_GRAY) { // data type conversion, but NO color mode conversion #ifdef IM_PROCESS ret = imProcessConvertDataType(src_image, dst_image, cpx2real, gamma, absolute, cast_mode); #else ret = imConvertDataType(src_image, dst_image, cpx2real, gamma, absolute, cast_mode); #endif } else { // data type conversion AND color mode conversion imImage* temp_image = imImageCreate(src_image->width, src_image->height, dst_image->color_space, src_image->data_type); if (!temp_image) ret = IM_ERR_MEM; else { // first convert color_mode in the bigger precision #ifdef IM_PROCESS ret = imProcessConvertColorSpace(src_image, temp_image); #else ret = imConvertColorSpace(src_image, temp_image); #endif if (ret == IM_ERR_NONE) { // second just convert data type #ifdef IM_PROCESS ret = imProcessConvertDataType(temp_image, dst_image, cpx2real, gamma, absolute, cast_mode); #else ret = imConvertDataType(temp_image, dst_image, cpx2real, gamma, absolute, cast_mode); #endif } imImageDestroy(temp_image); } } } #ifdef IM_PROCESS imProcessCounterEnd(counter); #else imCounterEnd(counter); #endif return ret; }
void imAnalyzeMeasureHoles(const imImage* image, int connect, int* count_data, int* area_data, float* perim_data) { int i; imImage *inv_image = imImageCreate(image->width, image->height, IM_BINARY, IM_BYTE); imbyte* inv_data = (imbyte*)inv_image->data[0]; imushort* img_data = (imushort*)image->data[0]; // finds the holes in the inverted image for (i = 0; i < image->count; i++) { if (*img_data) *inv_data = 0; else *inv_data = 1; img_data++; inv_data++; } imImage *holes_image = imImageClone(image); if (!holes_image) return; int holes_count = imAnalyzeFindRegions(inv_image, holes_image, connect, 0); imImageDestroy(inv_image); if (!holes_count) { imImageDestroy(holes_image); return; } // measure the holes area int* holes_area = (int*)malloc(holes_count*sizeof(int)); imAnalyzeMeasureArea(holes_image, holes_area, holes_count); float* holes_perim = 0; if (perim_data) { holes_perim = (float*)malloc(holes_count*sizeof(int)); imAnalyzeMeasurePerimeter(holes_image, holes_perim, holes_count); } imushort* holes_data = (imushort*)holes_image->data[0]; img_data = (imushort*)image->data[0]; // holes do not touch the border for (int y = 1; y < image->height-1; y++) { int offset_up = (y+1)*image->width; int offset = y*image->width; int offset_dw = (y-1)*image->width; for (int x = 1; x < image->width-1; x++) { int hole_index = holes_data[offset+x]; if (hole_index && holes_area[hole_index-1]) // a hole not yet used { // if the hole has not been used, // it is the first time we encounter a pixel of this hole. // then it is a pixel from the hole border. // now find which region this hole is inside. // a 4 connected neighbour is necessarilly a valid region or 0. int region_index = 0; if (img_data[offset_up + x]) region_index = img_data[offset_up + x]; else if (img_data[offset + x+1]) region_index = img_data[offset + x+1]; else if (img_data[offset + x-1]) region_index = img_data[offset + x-1]; else if (img_data[offset_dw+x]) region_index = img_data[offset_dw+x]; if (!region_index) continue; if (count_data) count_data[region_index-1]++; if (area_data) area_data[region_index-1] += holes_area[hole_index-1]; if (perim_data) perim_data[region_index-1] += holes_perim[hole_index-1]; holes_area[hole_index-1] = 0; // mark hole as used } } } if (holes_perim) free(holes_perim); free(holes_area); imImageDestroy(holes_image); }