/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d Y U V I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method ReadYUVImage reads an image with digital YUV (CCIR 601 4:1:1) bytes % and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadYUVImage method is: % % Image *ReadYUVImage(const ImageInfo *image_info) % % A description of each parameter follows: % % o image: Method ReadYUVImage returns a pointer to the image after % reading. A null image is returned if there is a memory shortage or % if the image cannot be read. % % o image_info: Specifies a pointer to an ImageInfo structure. % % */ Export Image *ReadYUVImage(const ImageInfo *image_info) { Image *chroma_image, *image, *zoom_image; int count, y; register int i, x; register PixelPacket *q, *r; register unsigned char *p; unsigned char *scanline; unsigned int status; /* Allocate image structure. */ image=AllocateImage(image_info); if (image == (Image *) NULL) return((Image *) NULL); if ((image->columns == 0) || (image->rows == 0)) ReaderExit(OptionWarning,"Must specify image size",image); image->depth=8; if (image_info->interlace != PartitionInterlace) { /* Open image file. */ status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); for (i=0; i < image->offset; i++) (void) ReadByte(image); } /* Allocate memory for a scanline. */ scanline=(unsigned char *) AllocateMemory(image->columns*sizeof(unsigned char)); if (scanline == (unsigned char *) NULL) ReaderExit(ResourceLimitWarning,"Memory allocation failed",image); do { /* Convert raster image to pixel packets. */ if (image_info->interlace == PartitionInterlace) { AppendImageFormat("Y",image->filename); status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) image->rows; y++) { if ((y > 0) || (image->previous == (Image *) NULL)) (void) ReadBlob(image,image->columns,scanline); p=scanline; q=SetPixelCache(image,0,y,image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) image->columns; x++) { q->red=UpScale(*p++); q->green=0; q->blue=0; q++; } if (!SyncPixelCache(image)) break; if (image->previous == (Image *) NULL) ProgressMonitor(LoadImageText,y,image->rows); } if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("U",image->filename); status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); } chroma_image=CloneImage(image,image->columns/2,image->rows/2,True); if (chroma_image == (Image *) NULL) ReaderExit(ResourceLimitWarning,"Memory allocation failed",image); for (y=0; y < (int) chroma_image->rows; y++) { (void) ReadBlob(image,chroma_image->columns,scanline); p=scanline; q=SetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { q->red=0; q->green=UpScale(*p++); q->blue=0; q++; } if (!SyncPixelCache(chroma_image)) break; } if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("V",image->filename); status=OpenBlob(image_info,image,ReadBinaryType); if (status == False) ReaderExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) chroma_image->rows; y++) { (void) ReadBlob(image,chroma_image->columns,scanline); p=scanline; q=GetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (q == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { q->blue=UpScale(*p++); q++; } if (!SyncPixelCache(chroma_image)) break; } /* Scale image. */ chroma_image->orphan=True; zoom_image=SampleImage(chroma_image,image->columns,image->rows); DestroyImage(chroma_image); if (zoom_image == (Image *) NULL) ReaderExit(ResourceLimitWarning,"Memory allocation failed",image); for (y=0; y < (int) image->rows; y++) { q=GetPixelCache(image,0,y,image->columns,1); r=GetPixelCache(zoom_image,0,y,zoom_image->columns,1); if ((q == (PixelPacket *) NULL) || (r == (PixelPacket *) NULL)) break; for (x=0; x < (int) image->columns; x++) { q->green=r->green; q->blue=r->blue; r++; q++; } if (!SyncPixelCache(image)) break; } DestroyImage(zoom_image); TransformRGBImage(image,YCbCrColorspace); if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); /* Proceed to next image. */ if (image_info->subrange != 0) if (image->scene >= (image_info->subimage+image_info->subrange-1)) break; count=ReadBlob(image,image->columns,(char *) scanline); if (count > 0) { /* Allocate next image structure. */ AllocateNextImage(image_info,image); if (image->next == (Image *) NULL) { DestroyImages(image); return((Image *) NULL); } image=image->next; ProgressMonitor(LoadImagesText,TellBlob(image),image->filesize); } } while (count > 0); FreeMemory(scanline); while (image->previous != (Image *) NULL) image=image->previous; CloseBlob(image); return(image); }
int tc_filter(frame_list_t *ptr_, char *options) { vframe_list_t *ptr = (vframe_list_t *)ptr_; int instance = ptr->filter_id; Image *pattern, *resized, *orig = 0; ImageInfo *image_info; PixelPacket *pixel_packet; pixelsMask *pixel_last; ExceptionInfo exception_info; if(ptr->tag & TC_FILTER_GET_CONFIG) { char buf[128]; optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYMO", "1"); tc_snprintf(buf, 128, "/dev/null"); optstr_param(options, "pattern", "Pattern image file path", "%s", buf); tc_snprintf(buf, 128, "results.dat"); optstr_param(options, "results", "Results file path" , "%s", buf); tc_snprintf(buf, 128, "%f", compare[instance]->delta); optstr_param(options, "delta", "Delta error", "%f",buf,"0.0", "100.0"); return 0; } //---------------------------------- // // filter init // //---------------------------------- if(ptr->tag & TC_FILTER_INIT) { unsigned int t,r,index; pixelsMask *temp; compare[instance] = tc_malloc(sizeof(compareData)); if(compare[instance] == NULL) return (-1); compare[instance]->vob = tc_get_vob(); if(compare[instance]->vob ==NULL) return(-1); compare[instance]->delta=DELTA_COLOR; compare[instance]->step=1; compare[instance]->width=0; compare[instance]->height=0; compare[instance]->frames = 0; compare[instance]->pixel_mask = NULL; pixel_last = NULL; compare[instance]->width = compare[instance]->vob->ex_v_width; compare[instance]->height = compare[instance]->vob->ex_v_height; if (options != NULL) { char pattern_name[PATH_MAX]; char results_name[PATH_MAX]; memset(pattern_name,0,PATH_MAX); memset(results_name,0,PATH_MAX); if(verbose) tc_log_info(MOD_NAME, "options=%s", options); optstr_get(options, "pattern", "%[^:]", pattern_name); optstr_get(options, "results", "%[^:]", results_name); optstr_get(options, "delta", "%f", &compare[instance]->delta); if (verbose > 1) { tc_log_info(MOD_NAME, "Compare Image Settings:"); tc_log_info(MOD_NAME, " pattern = %s\n", pattern_name); tc_log_info(MOD_NAME, " results = %s\n", results_name); tc_log_info(MOD_NAME, " delta = %f\n", compare[instance]->delta); } if (strlen(results_name) == 0) { // Ponemos el nombre del fichero al original con extension dat strlcpy(results_name, "/tmp/compare.dat", sizeof(results_name)); } if (!(compare[instance]->results = fopen(results_name, "w"))) { tc_log_perror(MOD_NAME, "could not open file for writing"); } InitializeMagick(""); if (verbose > 1) tc_log_info(MOD_NAME, "Magick Initialized successfully"); GetExceptionInfo(&exception_info); image_info = CloneImageInfo ((ImageInfo *) NULL); strlcpy(image_info->filename, pattern_name, MaxTextExtent); if (verbose > 1) tc_log_info(MOD_NAME, "Trying to open image"); orig = ReadImage(image_info, &exception_info); if (orig == (Image *) NULL) { MagickWarning(exception_info.severity, exception_info.reason, exception_info.description); strlcpy(pattern_name, "/dev/null", sizeof(pattern_name)); }else{ if (verbose > 1) tc_log_info(MOD_NAME, "Image loaded successfully"); } } else{ tc_log_perror(MOD_NAME, "Not image provided"); } if (options != NULL) if (optstr_lookup (options, "help")) { help_optstr(); } fprintf(compare[instance]->results,"#fps:%f\n",compare[instance]->vob->fps); if (orig != NULL){ // Flip and resize if (compare[instance]->vob->im_v_codec == CODEC_YUV) TransformRGBImage(orig,YCbCrColorspace); if (verbose > 1) tc_log_info(MOD_NAME, "Resizing the Image"); resized = ResizeImage(orig, compare[instance]->width, compare[instance]->height, GaussianFilter, 1, &exception_info); if (verbose > 1) tc_log_info(MOD_NAME, "Flipping the Image"); pattern = FlipImage(resized, &exception_info); if (pattern == (Image *) NULL) { MagickError (exception_info.severity, exception_info.reason, exception_info.description); } // Filling the matrix with the pixels values not // alpha if (verbose > 1) tc_log_info(MOD_NAME, "GetImagePixels"); pixel_packet = GetImagePixels(pattern,0,0, pattern->columns, pattern->rows); if (verbose > 1) tc_log_info(MOD_NAME, "Filling the Image matrix"); for (t = 0; t < pattern->rows; t++) for (r = 0; r < pattern->columns; r++){ index = t*pattern->columns + r; if (pixel_packet[index].opacity == 0){ temp=tc_malloc(sizeof(struct pixelsMask)); temp->row=t; temp->col=r; temp->r = (uint8_t)ScaleQuantumToChar(pixel_packet[index].red); temp->g = (uint8_t)ScaleQuantumToChar(pixel_packet[index].green); temp->b = (uint8_t)ScaleQuantumToChar(pixel_packet[index].blue); temp->next=NULL; if (pixel_last == NULL){ pixel_last = temp; compare[instance]->pixel_mask = temp; }else{ pixel_last->next = temp; pixel_last = temp; } } } if (verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP); } return(0); } //---------------------------------- // // filter close // //---------------------------------- if(ptr->tag & TC_FILTER_CLOSE) { if (compare[instance] != NULL) { fclose(compare[instance]->results); free(compare[instance]); } DestroyMagick(); compare[instance]=NULL; return(0); } /* filter close */ //---------------------------------- // // filter frame routine // //---------------------------------- // tag variable indicates, if we are called before // transcodes internal video/audio frame processing routines // or after and determines video/audio context if((ptr->tag & TC_POST_M_PROCESS) && (ptr->tag & TC_VIDEO)) { // For now I only support RGB color space pixelsMask *item = NULL; double sr,sg,sb; double avg_dr,avg_dg,avg_db; if (compare[instance]->vob->im_v_codec == CODEC_RGB){ int r,g,b,c; double width_long; if (compare[instance]->pixel_mask != NULL) { item = compare[instance]->pixel_mask; c = 0; sr = 0.0; sg = 0.0; sb = 0.0; width_long = compare[instance]->width*3; while(item){ r = item->row*width_long + item->col*3; g = item->row*width_long + item->col*3 + 1; b = item->row*width_long + item->col*3 + 2; // diff between points // Interchange RGB values if necesary sr = sr + (double)abs((unsigned char)ptr->video_buf[r] - item->r); sg = sg + (double)abs((unsigned char)ptr->video_buf[g] - item->g); sb = sb + (double)abs((unsigned char)ptr->video_buf[b] - item->b); item = item->next; c++; } avg_dr = sr/(double)c; avg_dg = sg/(double)c; avg_db = sb/(double)c; if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta)) fprintf(compare[instance]->results,"1"); else fprintf(compare[instance]->results,"n"); fflush(compare[instance]->results); } compare[instance]->frames++; return(0); }else{ // The colospace is YUV // FIXME: Doesn't works, I need to code all this part // again int Y,Cr,Cb,c; if (compare[instance]->pixel_mask != NULL) { item = compare[instance]->pixel_mask; c = 0; sr = 0.0; sg = 0.0; sb = 0.0; while(item){ Y = item->row*compare[instance]->width + item->col; Cb = compare[instance]->height*compare[instance]->width + (int)((item->row*compare[instance]->width + item->col)/4); Cr = compare[instance]->height*compare[instance]->width + (int)((compare[instance]->height*compare[instance]->width)/4) + (int)((item->row*compare[instance]->width + item->col)/4); // diff between points // Interchange RGB values if necesary sr = sr + (double)abs((unsigned char)ptr->video_buf[Y] - item->r); sg = sg + (double)abs((unsigned char)ptr->video_buf[Cb] - item->g); sb = sb + (double)abs((unsigned char)ptr->video_buf[Cr] - item->b); item = item->next; c++; } avg_dr = sr/(double)c; avg_dg = sg/(double)c; avg_db = sb/(double)c; if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta)) fprintf(compare[instance]->results,"1"); else fprintf(compare[instance]->results,"n"); } compare[instance]->frames++; return(0); } } return(0); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e Y U V I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method WriteYUVImage writes an image to a file in the digital YUV % (CCIR 601 4:1:1) format. % % The format of the WriteYUVImage method is: % % unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o status: Method WriteYUVImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ Export unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image) { Image *chroma_image, *yuv_image; int y; register int x; register PixelPacket *p; unsigned int height, scene, status, width; if (image_info->interlace != PartitionInterlace) { /* Open output image file. */ status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } if (image_info->interlace == PartitionInterlace) { AppendImageFormat("Y",image->filename); status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } scene=0; do { /* Sample image to an even width and height. */ TransformRGBImage(image,RGBColorspace); width=image->columns+(image->columns & 0x01); height=image->rows+(image->rows & 0x01); image->orphan=True; yuv_image=SampleImage(image,width,height); if (yuv_image == (Image *) NULL) WriterExit(ResourceLimitWarning,"Unable to zoom image",image); RGBTransformImage(yuv_image,YCbCrColorspace); /* Initialize Y channel. */ for (y=0; y < (int) yuv_image->rows; y++) { p=GetPixelCache(yuv_image,0,y,yuv_image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) yuv_image->columns; x++) { (void) WriteByte(image,DownScale(p->red)); p++; } if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) ProgressMonitor(SaveImageText,y,image->rows); } DestroyImage(yuv_image); /* Downsample image. */ image->orphan=True; chroma_image=SampleImage(image,width/2,height/2); if (chroma_image == (Image *) NULL) WriterExit(ResourceLimitWarning,"Unable to zoom image",image); RGBTransformImage(chroma_image,YCbCrColorspace); /* Initialize U channel. */ if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("U",image->filename); status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) chroma_image->rows; y++) { p=GetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { (void) WriteByte(image,DownScale(p->green)); p++; } } /* Initialize V channel. */ if (image_info->interlace == PartitionInterlace) { CloseBlob(image); AppendImageFormat("V",image->filename); status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); } for (y=0; y < (int) chroma_image->rows; y++) { p=GetPixelCache(chroma_image,0,y,chroma_image->columns,1); if (p == (PixelPacket *) NULL) break; for (x=0; x < (int) chroma_image->columns; x++) { (void) WriteByte(image,DownScale(p->blue)); p++; } } DestroyImage(chroma_image); if (image_info->interlace == PartitionInterlace) (void) strcpy(image->filename,image_info->filename); if (image->next == (Image *) NULL) break; image=GetNextImage(image); ProgressMonitor(SaveImagesText,scene++,GetNumberScenes(image)); } while (image_info->adjoin); if (image_info->adjoin) while (image->previous != (Image *) NULL) image=image->previous; CloseBlob(image); return(True); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e H T M L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method WriteHTMLImage writes an image in the HTML encoded image format. % % The format of the WriteHTMLImage method is: % % unsigned int WriteHTMLImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o status: Method WriteHTMLImage return True if the image is written. % False is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to an ImageInfo structure. % % o image: A pointer to a Image structure. % % */ Export unsigned int WriteHTMLImage(const ImageInfo *image_info,Image *image) { char buffer[MaxTextExtent], filename[MaxTextExtent], mapname[MaxTextExtent], url[MaxTextExtent]; Image *next; ImageInfo *local_info; int x, y; register char *p; register PixelPacket *q; unsigned int height, status, width; /* Open image. */ status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); CloseBlob(image); TransformRGBImage(image,RGBColorspace); *url='\0'; if ((Latin1Compare(image_info->magick,"FTP") == 0) || (Latin1Compare(image_info->magick,"HTTP") == 0)) { /* Extract URL base from filename. */ p=strrchr(image->filename,'/'); if (p) { p++; (void) strcpy(url,image_info->magick); (void) strcat(url,":"); url[Extent(url)+p-image->filename]='\0'; (void) strncat(url,image->filename,p-image->filename); (void) strcpy(image->filename,p); } } /* Refer to image map file. */ (void) strcpy(filename,image->filename); AppendImageFormat("map",filename); (void) strcpy(mapname,BaseFilename(filename)); (void) strcpy(image->filename,image_info->filename); (void) strcpy(filename,image->filename); local_info=CloneImageInfo(image_info); if (local_info == (ImageInfo *) NULL) WriterExit(FileOpenWarning,"Unable to allocate memory",image); local_info->adjoin=True; status=True; if (Latin1Compare(image_info->magick,"SHTML") != 0) { /* Open output image file. */ status=OpenBlob(image_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); /* Write the HTML image file. */ (void) strcpy(buffer,"<html version=\"2.0\">\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<head>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer,"<title>%.1024s</title>\n", image->label ? image->label : BaseFilename(image->filename)); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"</head>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<body>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<center>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer,"<h1>%.1024s</h1>\n",image->filename); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"<br><br>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(filename,image->filename); AppendImageFormat("gif",filename); (void) sprintf(buffer, "<img ismap usemap=#%.1024s src=\"%.1024s\" border=0>\n", mapname,filename); (void) WriteBlob(image,strlen(buffer),buffer); /* Determine the size and location of each image tile. */ width=image->columns; height=image->rows; x=0; y=0; if (image->montage != (char *) NULL) (void) ParseGeometry(image->montage,&x,&y,&width,&height); /* Write an image map. */ (void) sprintf(buffer,"<map name=%.1024s>\n",mapname); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); if (image->directory == (char *) NULL) { (void) sprintf(buffer,"%.1024s shape=rect coords=0,0,%u,%u>\n", image->filename,width-1,height-1); (void) WriteBlob(image,strlen(buffer),buffer); } else for (p=image->directory; *p != '\0'; p++) if (*p != '\n') (void) WriteByte(image,*p); else { (void) sprintf(buffer," shape=rect coords=%d,%d,%d,%d>\n", x,y,x+(int) width-1,y+(int) height-1); (void) WriteBlob(image,strlen(buffer),buffer); if (*(p+1) != '\0') { (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); } x+=width; if (x >= (int) image->columns) { x=0; y+=height; } } (void) strcpy(buffer,"</map>\n"); (void) WriteBlob(image,strlen(buffer),buffer); if (image->montage != (char *) NULL) { char color[MaxTextExtent] = "#000"; /* Make montage background transparent. */ q=GetPixelCache(image,0,0,1,1); if (q != (PixelPacket *) NULL) FormatString(color,HexColorFormat,q->red,q->green,q->blue); TransparentImage(image,color); } (void) strcpy(filename,image->filename); (void) strcpy(buffer,"</center>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"</body>\n"); (void) WriteBlob(image,strlen(buffer),buffer); (void) strcpy(buffer,"</html>\n"); status=WriteBlob(image,strlen(buffer),buffer); CloseBlob(image); /* Write the image as transparent GIF. */ (void) strcpy(image->filename,filename); AppendImageFormat("gif",image->filename); next=image->next; image->next=(Image *) NULL; status|=WriteGIFImage(local_info,image); image->next=next; /* Determine image map filename. */ (void) strcpy(image->filename,filename); for (p=filename+Extent(filename)-1; p > (filename+1); p--) if (*p == '.') { (void) strncpy(image->filename,filename,p-filename); image->filename[p-filename]='\0'; break; } (void) strcat(image->filename,"_map.shtml"); } /* Open image map. */ status=OpenBlob(local_info,image,WriteBinaryType); if (status == False) WriterExit(FileOpenWarning,"Unable to open file",image); DestroyImageInfo(local_info); /* Determine the size and location of each image tile. */ width=image->columns; height=image->rows; x=0; y=0; if (image->montage != (char *) NULL) (void) ParseGeometry(image->montage,&x,&y,&width,&height); /* Write an image map. */ (void) sprintf(buffer,"<map name=%.1024s>\n",mapname); (void) WriteBlob(image,strlen(buffer),buffer); (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); if (image->directory == (char *) NULL) { (void) sprintf(buffer,"%.1024s shape=rect coords=0,0,%u,%u>\n", image->filename,width-1,height-1); (void) WriteBlob(image,strlen(buffer),buffer); } else for (p=image->directory; *p != '\0'; p++) if (*p != '\n') (void) WriteByte(image,*p); else { (void) sprintf(buffer," shape=rect coords=%d,%d,%d,%d>\n",x,y, x+(int) width-1,y+(int) height-1); (void) WriteBlob(image,strlen(buffer),buffer); if (*(p+1) != '\0') { (void) sprintf(buffer," <area href=""%.1024s""",url); (void) WriteBlob(image,strlen(buffer),buffer); } x+=width; if (x >= (int) image->columns) { x=0; y+=height; } } (void) strcpy(buffer,"</map>\n"); (void) WriteBlob(image,strlen(buffer),buffer); CloseBlob(image); (void) strcpy(image->filename,filename); return(status); }