void jpeg_out() { int x,y; int xp; int p=0; int i,j; int m; int mincount; int* maskcount=(int*)malloc(g_numimages*sizeof(int)); int* masklimit=(int*)malloc(g_numimages*sizeof(int)); int* mask=(int*)malloc(g_numimages*sizeof(int)); struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row=(JSAMPROW)malloc(g_workwidth*3); uint32 temp; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo,g_jpeg); cinfo.image_width=g_workwidth; cinfo.image_height=g_workheight; cinfo.input_components=3; cinfo.in_color_space=JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo,g_jpegquality,true); jpeg_start_compress(&cinfo,true); if (g_nomask) { for (y=0; y<g_workheight; y++) { xp=0; for (x=0; x<g_workwidth; x++) { ((uint8*)row)[xp++]=((uint8*)g_out_channels[0])[p]; ((uint8*)row)[xp++]=((uint8*)g_out_channels[1])[p]; ((uint8*)row)[xp++]=((uint8*)g_out_channels[2])[p]; p++; } jpeg_write_scanlines(&cinfo,&row,1); } } else { for (y=0; y<g_workheight; y++) { for (i=0; i<g_numimages; i++) { mask[i]=MASKOFF; if (y>=g_images[i].ypos && y<g_images[i].ypos+g_images[i].height) { maskcount[i]=g_images[i].xpos; masklimit[i]=g_images[i].xpos+g_images[i].width; g_images[i].binary_mask.pointer=&g_images[i].binary_mask.data[g_images[i].binary_mask.rows[y-g_images[i].ypos]]; } else { maskcount[i]=g_workwidth; masklimit[i]=g_workwidth; } } x=0; xp=0; while (x<g_workwidth) { m=MASKOFF; mincount=g_workwidth-x; for (i=0; i<g_numimages; i++) { if (maskcount[i]==0) { if (x<masklimit[i]) { NEXTiMASK(i); } else { mask[i]=MASKOFF; maskcount[i]=mincount; } } if (maskcount[i]<mincount) mincount=maskcount[i]; if (mask[i]!=MASKOFF) m=MASKON; } if (m==MASKON) { for (j=0; j<mincount; j++) { ((uint8*)row)[xp++]=((uint8*)g_out_channels[0])[p]; ((uint8*)row)[xp++]=((uint8*)g_out_channels[1])[p]; ((uint8*)row)[xp++]=((uint8*)g_out_channels[2])[p]; p++; } } else { memset(&((uint8*)row)[xp],0,mincount*3); xp+=mincount*3; p+=mincount; } for (i=0; i<g_numimages; i++) maskcount[i]-=mincount; x+=mincount; } jpeg_write_scanlines(&cinfo,&row,1); } } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); fclose(g_jpeg); }
void tiff_out() { int i,j; int m; int mincount; int* maskcount=(int*)malloc(g_numimages*sizeof(int)); int* masklimit=(int*)malloc(g_numimages*sizeof(int)); int* mask=(int*)malloc(g_numimages*sizeof(int)); int rowsperstrip=64; int p=0; int strips; int remaining; int strip_p; int x,y=0,s; int stripy; int rows; uint16 out[1]; uint32 temp; int mul; mul=3; if (!g_nomask) mul=4; if (g_workbpp==16) mul=mul<<1; mul=mul*g_workwidth; for (i=0; i<g_numimages; i++) g_images[i].binary_mask.pointer=g_images[i].binary_mask.data; void* strip=malloc((rowsperstrip*g_workwidth)<<(g_workbpp>>2)); TIFFSetField(g_tiff, TIFFTAG_IMAGEWIDTH, g_workwidth); TIFFSetField(g_tiff, TIFFTAG_IMAGELENGTH, g_workheight); TIFFSetField(g_tiff, TIFFTAG_COMPRESSION, g_compression); TIFFSetField(g_tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(g_tiff, TIFFTAG_ROWSPERSTRIP, rowsperstrip); TIFFSetField(g_tiff, TIFFTAG_BITSPERSAMPLE, g_workbpp); if (g_nomask) { TIFFSetField(g_tiff, TIFFTAG_SAMPLESPERPIXEL, 3); } else { TIFFSetField(g_tiff, TIFFTAG_SAMPLESPERPIXEL, 4); out[0] = EXTRASAMPLE_UNASSALPHA; TIFFSetField(g_tiff, TIFFTAG_EXTRASAMPLES, 1, &out); } TIFFSetField(g_tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); if (g_xres!=-1) { TIFFSetField(g_tiff, TIFFTAG_XRESOLUTION, g_xres); TIFFSetField(g_tiff, TIFFTAG_XPOSITION, (float)(g_min_left/g_xres)); } if (g_yres!=-1) { TIFFSetField(g_tiff, TIFFTAG_YRESOLUTION, g_yres); TIFFSetField(g_tiff, TIFFTAG_YPOSITION, (float)(g_min_top/g_yres)); } if (g_images[0].geotiff.set) { // if we got a georeferenced input, store the geotags in the output GeoTIFFInfo info(g_images[0].geotiff); info.XGeoRef = g_min_left * g_images[0].geotiff.XCellRes; info.YGeoRef = -g_min_top * g_images[0].geotiff.YCellRes; output(1,"Output georef: UL: %f %f, pixel size: %f %f\n",info.XGeoRef, info.YGeoRef, info.XCellRes, info.YCellRes); geotiff_write(g_tiff, &info); } strips=(int)((g_workheight+rowsperstrip-1)/rowsperstrip); remaining=g_workheight; for (s=0; s<strips; s++) { rows=min(remaining,rowsperstrip); strip_p=0; for (stripy=0; stripy<rows; stripy++) { if (g_nomask) { if (g_workbpp==8) { for (x=0; x<g_workwidth; x++) { ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[0])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[1])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[2])[p]; p++; } } else { for (x=0; x<g_workwidth; x++) { ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[0])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[1])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[2])[p]; p++; } } } else { for (i=0; i<g_numimages; i++) { mask[i]=MASKOFF; if (y>=g_images[i].ypos && y<g_images[i].ypos+g_images[i].height) { maskcount[i]=g_images[i].xpos; masklimit[i]=g_images[i].xpos+g_images[i].width; g_images[i].binary_mask.pointer=&g_images[i].binary_mask.data[g_images[i].binary_mask.rows[y-g_images[i].ypos]]; } else { maskcount[i]=g_workwidth; masklimit[i]=g_workwidth; } } x=0; while (x<g_workwidth) { m=MASKOFF; mincount=g_workwidth-x; for (i=0; i<g_numimages; i++) { if (maskcount[i]==0) { if (x<masklimit[i]) { NEXTiMASK(i); } else { mask[i]=MASKOFF; maskcount[i]=mincount; } } if (maskcount[i]<mincount) mincount=maskcount[i]; if (mask[i]!=MASKOFF) m=MASKON; } if (m==MASKON) { if (g_workbpp==8) { for (j=0; j<mincount; j++) { ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[0])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[1])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[2])[p]; ((uint8*)strip)[strip_p++]=0xff; p++; } } else { for (j=0; j<mincount; j++) { ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[0])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[1])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[2])[p]; if (!g_nomask) ((uint16*)strip)[strip_p++]=0xffff; p++; } } } else { if (g_workbpp==8) { memset(&((uint8*)strip)[strip_p],0,mincount<<2); } else { memset(&((uint16*)strip)[strip_p],0,mincount<<3); } strip_p+=mincount<<2; p+=mincount; } /* if (m==MASKON || g_nomask) { if (g_workbpp==8) { for (j=0; j<mincount; j++) { ((uint8*)strip)[strip_p++]=((uint8**)g_out_channels)[0][p]; ((uint8*)strip)[strip_p++]=((uint8**)g_out_channels)[1][p]; ((uint8*)strip)[strip_p++]=((uint8**)g_out_channels)[2][p]; if (!g_nomask) ((uint8*)strip)[strip_p++]=0xff; p++; } } else { for (j=0; j<mincount; j++) { ((uint16*)strip)[strip_p++]=((uint16**)g_out_channels)[0][p]; ((uint16*)strip)[strip_p++]=((uint16**)g_out_channels)[1][p]; ((uint16*)strip)[strip_p++]=((uint16**)g_out_channels)[2][p]; if (!g_nomask) ((uint16*)strip)[strip_p++]=0xffff; p++; } } } else { if (g_workbpp==8) { if (g_nomask) blank=mincount*3; else blank=mincount<<2; memset(&((uint8*)strip)[strip_p],0,blank); strip_p+=mincount<<2; } else { if (g_nomask) blank=mincount*6; else blank=mincount<<3; memset(&((uint16*)strip)[strip_p],0,blank); strip_p+=mincount<<2; } p+=mincount; } */ for (i=0; i<g_numimages; i++) maskcount[i]-=mincount; x+=mincount; } } y++; } TIFFWriteEncodedStrip(g_tiff,s,strip,rows*mul); remaining-=rows; } TIFFClose(g_tiff); }
void seam_png(int mode, const char *filename) { int x; int y; int count, i; int *maskcount = (int *)malloc(g_numimages * sizeof(int)); int *masklimit = (int *)malloc(g_numimages * sizeof(int)); int *mask = (int *)malloc(0x100 * sizeof(int)); int mincount; int xorcount; int xorimage; int stop; uint32 temp; uint32 *seam_p; png_structp png_ptr; png_infop info_ptr; double base = 2; double rad; double r, g, b; FILE *f; if (!g_palette) { g_palette = (png_color *)malloc(256 * sizeof(png_color)); for (i = 0; i < 255; i++) { rad = base; r = max<double>(0, min<double>(1.0, min<double>(rad, 4 - rad))); rad += 2; if (rad >= 6) rad -= 6; g = max<double>(0, min<double>(1.0, min<double>(rad, 4 - rad))); rad += 2; if (rad >= 6) rad -= 6; b = max<double>(0, min<double>(1.0, min<double>(rad, 4 - rad))); base += 6 * 0.618033988749895; if (base >= 6) base -= 6; g_palette[i].red = (int)(r * 255 + 0.5); g_palette[i].green = (int)(g * 255 + 0.5); g_palette[i].blue = (int)(b * 255 + 0.5); } g_palette[i].red = 0; g_palette[i].green = 0; g_palette[i].blue = 0; } switch (mode) { case 0: output(1, "saving xor map...\n"); break; case 1: output(1, "saving seams...\n"); break; } fopen_s(&f, filename, "wb"); if (!f) { output(0, "WARNING: couldn't save seam file\n"); return; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { output(0, "WARNING: PNG create failed\n"); return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return; } png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, g_workwidth, g_workheight, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_PLTE(png_ptr, info_ptr, g_palette, 256); png_write_info(png_ptr, info_ptr); if (mode == 0) { for (y = 0; y < g_workheight; y++) { for (i = 0; i < g_numimages; i++) { mask[i] = MASKOFF; if (y >= g_images[i].ypos && y < g_images[i].ypos + g_images[i].height) { maskcount[i] = g_images[i].xpos; masklimit[i] = g_images[i].xpos + g_images[i].width; g_images[i].binary_mask.pointer = &g_images[i] .binary_mask .data[g_images[i].binary_mask.rows[y - g_images[i].ypos]]; } else { maskcount[i] = g_workwidth; masklimit[i] = g_workwidth; } } x = 0; while (x < g_workwidth) { mincount = g_workwidth - x; xorcount = 0; for (i = 0; i < g_numimages; i++) { if (maskcount[i] == 0) { if (x < masklimit[i]) { NEXTiMASK(i); } else { mask[i] = MASKOFF; maskcount[i] = mincount; } } if (maskcount[i] < mincount) mincount = maskcount[i]; if (mask[i] != MASKOFF) { xorcount++; xorimage = i; } } stop = x + mincount; if (xorcount != 1) xorimage = 255; while (x < stop) { ((uint8 *)g_line0)[x++] = xorimage; } for (i = 0; i < g_numimages; i++) maskcount[i] -= mincount; } png_write_row(png_ptr, (uint8 *)g_line0); } } else if (mode == 1) { seam_p = g_seams; for (y = 0; y < g_workheight; y++) { x = 0; while (x < g_workwidth) { i = *seam_p & 0xff; count = *seam_p++ >> 8; memset(&((uint8 *)g_line0)[x], i, count); x += count; } png_write_row(png_ptr, (uint8 *)g_line0); } }