static void fail (PIC_PARM *pp, long error_code) { //terminates Pegasus and sets error code Pegasus (pp, REQ_TERM); pp->Status = error_code; if (inhandle != -1) { close (inhandle); inhandle = -1; } if (outhandle != -1) { close (outhandle); outhandle = -1; } remove (outfilename); printf ("!!!!Error -- code %ld\n", error_code); return; }
static long palettize_file (char *file1, char *file2, char *file3) { long error = 1; long n_input_colors; int i; RESPONSE res; BITMAPFILEHEADER bf; BITMAPINFOHEADER bi; inhandle = -1; outhandle = -1; palhandle = -1; //open the 3 files inhandle = open (file1, O_RDONLY | O_BINARY); if (inhandle == -1) { printf ("***** unable to open input image %s\n", file1); goto ehandler; } outhandle = open (file2, O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); if (outhandle == -1) { printf ("***** unable to create output file %s\n", file2); goto ehandler; } palhandle = open (file3, O_RDONLY | O_BINARY); if (palhandle == -1) { printf ("***** unable to open palette file %s\n", file3); goto ehandler; } //skip the bitmapfileheader of the palette file, and read the // bitmapinfoheader if (filelength (palhandle) < sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER)) { printf ("***** invalid input palette file\n"); goto ehandler; } lseek (palhandle, sizeof (BITMAPFILEHEADER), SEEK_SET); read (palhandle, &bi, sizeof (BITMAPINFOHEADER)); if (bi.biBitCount != 1 && bi.biBitCount != 4 && bi.biBitCount != 8) { printf ("***** input palette file is not 1, 4, or 8 bits per pixel\n"); goto ehandler; } palbuf.ncolors = (int)bi.biClrUsed; if (palbuf.ncolors == 0) { palbuf.ncolors = 1 << bi.biBitCount; } else { if (palbuf.ncolors > (1 << bi.biBitCount) || palbuf.ncolors < 2) { printf ("***** palette file error -- bad number of colors\n"); goto ehandler; } } //read those colors read (palhandle, &palbuf.rgb[0], palbuf.ncolors << 2); for (i=0; i<palbuf.ncolors; i++) { //clear reserved bits for safety palbuf.rgb[i].rgbReserved = 0; } infilesize = filelength (inhandle); total_bytes_read = 0; //write a dummy bitmapfileheader for now write (outhandle, &bf, sizeof (BITMAPFILEHEADER)); //write a dummy bitmapinfoheader for now write (outhandle, &bi, sizeof (BITMAPINFOHEADER)); //write the new palette write (outhandle, &palbuf.rgb[0], palbuf.ncolors << 2); //now set up for opcode 82 memset (&pp, 0, sizeof (pp)); //VERY IMPORTANT! pp.Op = OP_UTL; //Utility opcode (82) pp.ParmSize = sizeof (pp); pp.ParmVer = CURRENT_PARMVER; //from pic.h //get the input file's bitmapinfoheader into pp.Head // -- skip the BITMAPFILEHEADER lseek (inhandle, sizeof (BITMAPFILEHEADER), SEEK_SET); read (inhandle, &pp.Head, sizeof (BITMAPINFOHEADER)); seek_adder = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER); //if the input file is < 24bpp, read in that palette if (pp.Head.biBitCount <= 8) { if (pp.Head.biClrUsed == 0) { //0 means max colors n_input_colors = (1 << pp.Head.biBitCount); } else { n_input_colors = pp.Head.biClrUsed; } if (n_input_colors < 2 || n_input_colors > (1 << pp.Head.biBitCount)) { printf ("***** input palette has bad color count\n"); goto ehandler; } read (inhandle, pp.ColorTable, (unsigned short)n_input_colors << 2); seek_adder += (n_input_colors << 2); } //NOTE: at this point, seek_adder is the offset in the input file of // the dib bits pp.u.UTL.Subcode = 8; //"Palettize to given palette" pp.u.UTL.ptr1 = NULL; //actually, already null pp.u.UTL.ptr2 = NULL; //ditto pp.u.UTL.OutBpp = 8; //output bit depth -- could also be 1 or 4 if (do_dither) { pp.u.UTL.PicFlags = PF_Dither; } pp.u.UTL.ptr3 = ((BYTE PICHUGE *)&palbuf) + 2; //the palette to reduce to pp.u.UTL.NumColors = palbuf.ncolors; //number of colors to reduce to pp.u.UTL.AllocType = 0; //we will not allocate full buffers for the //input and output files -- we will just process in serial "chunks" pp.Get.Start = input_queue; pp.Get.Front = pp.Get.Rear = pp.Get.Start; pp.Get.End = pp.Get.Start + inbufsize + 1; pp.Put.Start = output_queue; pp.Put.Front = pp.Put.Rear = pp.Put.Start; pp.Put.End = pp.Put.Start + outbufsize + 1; getdata_already_called = 0; lseek (inhandle, seek_adder, SEEK_SET); //seek to the beginning of the dib bits //the Pegasus loops res = Pegasus (&pp, REQ_INIT); while (res != RES_DONE) { if (res == RES_GET_NEED_DATA || res == RES_GET_DATA_YIELD) { getdata (&pp); } else if (res == RES_PUT_DATA_YIELD || res == RES_PUT_NEED_SPACE) { putdata (&pp); } //NOTE: RES_SEEK is never requested for subcode 8 else { if (res != RES_ERR) { pp.Status = ERR_UNKNOWN_RESPONSE; } fail (&pp, pp.Status); return FALSE; } //actually, for this subcode, INIT does basicallay nothing res = Pegasus (&pp, REQ_CONT); } res = Pegasus (&pp, REQ_EXEC); while (res != RES_DONE) { if (res == RES_GET_NEED_DATA || res == RES_GET_DATA_YIELD) { getdata (&pp); } else if (res == RES_PUT_DATA_YIELD || res == RES_PUT_NEED_SPACE) { putdata (&pp); } //NOTE RES_SEEK is never requested for subcode 8 else { if (res != RES_ERR) { pp.Status = ERR_UNKNOWN_RESPONSE; } fail (&pp, pp.Status); return FALSE; } res = Pegasus (&pp, REQ_CONT); } //flush the output if (pp.Put.Front != pp.Put.Rear) { putdata (&pp); } //write the bitmapfileheader out lseek (outhandle, 0, SEEK_SET); bf.bfType = 'B' + ('M' << 8); bf.bfReserved1 = 0; bf.bfReserved2 = 0; bf.bfSize = filelength (outhandle); //where the bitmap image is: bf.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + (palbuf.ncolors << 2); write (outhandle, &bf, sizeof (BITMAPFILEHEADER)); //write the bitmapinfoheader out //but first, set the number of colors -- color reduction might use // less than we request, and bi must match the palette we previously // output pp.u.UTL.BiOut.biClrUsed = pp.u.UTL.BiOut.biClrImportant = palbuf.ncolors; write (outhandle, &pp.u.UTL.BiOut, sizeof (BITMAPINFOHEADER)); Pegasus (&pp, REQ_TERM); error = 0; ehandler: if (inhandle != -1) { close (inhandle); inhandle = -1; } if (outhandle != -1) { close (outhandle); outhandle = -1; } if (palhandle != -1) { close (palhandle); palhandle = -1; } if (error) { remove (file2); } else { filecount++; } return error; }
/* �����������������������������������������������������������������������ͼ */ PRIVATE LONG expand (void) { PIC_PARM p; RESPONSE res; LONG len; LONG ct; LONG local_status; LONG join_offset = 0; LONG k, region_x,region_y,region_endx,region_endy, region_w,region_h; BYTE *bptr; BYTE *region_info_ptr; REGION_INFO *region_info; /****/ src_file = src_file_join = des_file = NULL; join_offset = 0; memset(&p, 0, sizeof(PIC_PARM)); /* important: set all default values 0 */ /* ALSO important -- following must be set even for PegasusQuery */ /* beginning version 13 */ p.ParmSize = sizeof(PIC_PARM); p.ParmVer = CURRENT_PARMVER; p.ParmVerMinor = 1; #if NOCO defer_status = 0; p.DeferFn = &defer_function; #endif if(src_name_join != NULL) if(check1(!orient && !requant && !crop_flg,"Can't reorient, requant or crop while joining")) goto quit; /* Open the JPEG file */ src_file = fopen(src_name, "rb"); if(check1(src_file != NULL, "Could not open %s", src_name)) goto quit; printf("Opened file %s.\n", src_name); /* Open other JPEG file if joining */ if(src_name_join != NULL) { src_file_join = fopen(src_name_join, "rb"); if(check1(src_file_join != NULL, "Could not open %s", src_name_join)) goto quit; printf("Opened file %s.\n", src_name_join); } /* Allocate GetBuff and place into it the information to be queried */ if(num_loops > 1) { /* allocate a full_size buffer */ get_buff_size = file_size(src_file) + 2; if(put_buff_size < get_buff_size << 1) put_buff_size = get_buff_size << 1; } if(src_name_join != NULL) { join_offset = file_size(src_file_join); get_buff_size += join_offset; } p.Get.Start = (BYTE *) malloc(get_buff_size); if(check1(p.Get.Start != NULL, "Out of memory for get buffer")) goto quit; p.Get.End = p.Get.Start + get_buff_size; /* read in first file if joining */ if(src_name_join != NULL) { len = fread(p.Get.Start, sizeof(BYTE), get_buff_size, src_file_join); if(check1(ferror(src_file_join) == 0, "Error reading join file")) goto quit; if(check1(len == join_offset, "Error reading join file")) goto quit; } /* read in header data, at least (of second file if joining) */ len = fread(p.Get.Start + join_offset, sizeof(BYTE), get_buff_size - join_offset, src_file); if(check1(ferror(src_file) == 0, "Error reading input file")) goto quit; if(len < get_buff_size - join_offset) p.Get.QFlags |= Q_EOF; /* setup output buff */ p.Put.Start = (BYTE *) malloc(put_buff_size); if(check1(p.Put.Start != NULL, "Out of memory for put buff")) goto quit; p.Put.End = p.Put.Start + put_buff_size; /* setup output file */ #if PC_WATCOM des_file = _fsopen(des_name, "wb", SH_DENYWR); /* ^ use _fsopen in watcom so we can make sure the input file isn't the same file as the output file. If it is the same, _fsopen will fail with a sharing violation error */ #else des_file = fopen(des_name, "wb"); #endif if(check1(des_file != NULL,"Could not create %s", des_name)) goto quit; p.u.ROR.RegionInfo = NULL; for(ct = 0;ct < num_loops;++ct) { p.Get.Rear = p.Get.Start + len + join_offset; p.Get.Front = p.Get.Start; p.Put.Front = p.Put.Rear = p.Put.Start; #if USE_PEG_QRY /* note: PegasusQuery is not ANSI */ p.u.QRY.BitFlagsReq = QBIT_BICOMPRESSION; if(check1(PegasusQuery(&p), "Invalid PegasusQuery")) goto quit; memset(&p.u.QRY, 0, sizeof(p.u.QRY)); if(check1(p.Head.biCompression == BI_PICJ || #if PIC2_IN p.Head.biCompression == BI_PC2J || #endif #if ELS_CODER_IN p.Head.biCompression == BI_JPGE || #if PIC2_IN p.Head.biCompression == BI_PC2E || #endif #endif p.Head.biCompression == BI_JPEG, "Unsupported file type")) goto quit; #endif /* Set up the output image characteristics. */ p.ParmSize = sizeof(PIC_PARM); p.ParmVer = CURRENT_PARMVER; p.ParmVerMinor = 1; #if ELS_CODER_OUT p.Op = OP_RORE; #else p.Op = OP_ROR; #endif p.u.ROR.PicFlags = 0; p.VisualOrient = orient; p.u.ROR.PicFlags = 0; if(num_loops == 1) p.u.ROR.PicFlags |= PF_YieldPut; p.u.ROR.Pad = pad; p.u.ROR.KeepColors = keep_colors; #if ELS_CODER_OUT if(els_coder_out) p.u.ROR.PicFlags |= PF_ElsCoder; #endif p.u.ROR.JpegType = JT_RAW; #if PIC2_OUT if(pic2_out) p.u.ROR.JpegType = JT_PIC2; #endif memcpy(p.KeyField, key, 8); memcpy(p.u.ROR.OutputKeyField, outputkey, 8); if(requant || ((src_name_join != NULL) && (join_use_requested_quantization))) { p.u.ROR.Requantize = requant; if (QTableName[0] != '\0') p.u.ROR.QTableReq = (BYTE PICHUGE *) qtable; else { p.u.ROR.LumFactorReq = lum_opt; p.u.ROR.ChromFactorReq = chrom_opt; } } p.u.ROR.AppsToKeep = apps_to_keep; p.u.ROR.RemoveComments = remove_comments; if(src_name_join != NULL) { p.u.ROR.JoinFlags |= JF_DoJoin; p.u.ROR.JoinOffset = join_offset; if(join_use_requested_quantization) p.u.ROR.JoinFlags |= JF_UseRequestedQuantization; if(join_left_right) p.u.ROR.JoinFlags |= JF_LeftRight; if(join_insert) { p.u.ROR.JoinFlags |= JF_Insert; p.u.ROR.InsertTransparencyLum = insert_transparency_lum; p.u.ROR.InsertTransparencyChrom = insert_transparency_chrom; } if(join_second_on_top_left) p.u.ROR.JoinFlags |= JF_SecondOnTopLeftInsert; if(join_subsampling_from_second) p.u.ROR.JoinFlags |= JF_UseSecondSubsampling; if(join_quantization_from_second) p.u.ROR.JoinFlags |= JF_UseSecondQuantization; } #if(USE_PEG_QRY) if(p.Head.biHeight < 1) { p.Head.biHeight = -p.Head.biHeight; /* from now on,p.Head.biHeight is positive. */ } if(regions) { p.u.ROR.NumRegions = 2; p.u.ROR.RegionMapWidth = (p.Head.biWidth + 7) >> 3; p.u.ROR.RegionMapHeight = (p.Head.biHeight + 7) >> 3; region_x = crop_x >> 3; region_y = crop_y >> 3; region_endx = (crop_x + crop_w + 7) >> 3; region_endy = (crop_y + crop_h + 7) >> 3; if(check1(region_x < p.u.ROR.RegionMapWidth && region_y < p.u.ROR.RegionMapHeight && region_endx <= p.u.ROR.RegionMapWidth && region_endy <= p.u.ROR.RegionMapHeight, "Bad region rectangle")) goto quit; region_w = region_endx - region_x; region_h = region_endy - region_y; p.u.ROR.RegionInfo = malloc(8*p.u.ROR.NumRegions + 128*num_tables + p.u.ROR.RegionMapWidth * p.u.ROR.RegionMapHeight ); if(check1(p.u.ROR.RegionInfo != NULL, "Out of memory for RegionInfo")) goto quit; region_info_ptr = p.u.ROR.RegionInfo; region_info = (REGION_INFO *)region_info_ptr; region_info->NumTbls = 255; /* indicates to use qtables from input jpeg for region 0 */ region_info_ptr += 8; /* word for Lum.,word for Chrom, dword for NumTbls */ region_info = (REGION_INFO *)region_info_ptr; region_info->LumFactor = lum_opt; region_info->ChromFactor = chrom_opt; region_info->NumTbls = num_tables; if (num_tables != 0) memcpy(&(region_info->QTbls[0]),region_qtable,num_tables*128); p.u.ROR.RegionMapOffset = 8*p.u.ROR.NumRegions + 128*num_tables; bptr = p.u.ROR.RegionInfo + p.u.ROR.RegionMapOffset; memset(bptr,1,p.u.ROR.RegionMapWidth * p.u.ROR.RegionMapHeight); /* background has index 1 */ bptr += (region_y * p.u.ROR.RegionMapWidth) + region_x; for(k = 0;k < region_h;++k) { memset(bptr,0,region_w); /* rectangle of interest has index 0 */ bptr += p.u.ROR.RegionMapWidth; } } #endif /*p.Head.biBitCount = 24; // temp, while not using PegasusQuery */ if(crop_flg) { p.Flags |= F_Crop; if(crop_w == 0) crop_w = 65535; /* init will cut this back to full width */ if(crop_h == 0) crop_h = 65535; p.CropWidth = crop_w; p.CropHeight = crop_h; } p.CropXoff = crop_x; /* used also for inserting */ p.CropYoff = crop_y; #if NOCO /* Initialize Jpeg decompression */ res = Pegasus(&p, REQ_INIT); if(check1(defer_status >= 0, "Error %d in DeferFn.", defer_status)) goto quit; if(check1(res != RES_ERR, "Error number %d in Pegasus.",p.Status)) goto quit; if(check1(p.Status >= 0, "Error %d in Pegasus.", p.Status)) goto quit; if (p.Status > 0) printf("Status %d in Pegasus Init.\n", p.Status); if(p.Status == ERR_JUNK_BYTES_IN_HEADER) printf("Junk bytes found in header were skipped over.\n"); /* Decompress the file. */ res = Pegasus(&p, REQ_EXEC); /* if(check1(defer_status >= 0, "Error %d in DeferFn.", defer_status)) goto quit; */ /* check1(res != RES_ERR, "Error number %d in Pegasus.",p.Status); output what you can */ /* Let Pegasus close things(in seq. jpeg, everything is already closed, */ /* but this would not necessarily be true for progressive) */ /* res = Pegasus(&p,REQ_TERM); // This can only return RES_DONE, and */ /* does not change p->Status. Not needed in seq. */ if (p.Status) printf("Status %d in Pegasus.\n", p.Status); #else /* Initialize Jpeg decompression */ local_status = 0; res = Pegasus(&p, REQ_INIT); while (res != RES_DONE) { if (res == RES_GET_NEED_DATA) { local_status = read_file(&p); } else if (res == RES_PUT_DATA_YIELD) { if(num_loops == 1) local_status = copy_to_file(&p); } else if (res == RES_PUT_NEED_SPACE) { if(check1(num_loops == 1,"output buffer too small to do loops")) goto quit; local_status = copy_to_file(&p); } else if (res == RES_ERR) { if(check1(FALSE, "Error number %d ",p.Status)) goto quit; } else { if(check1(FALSE, "Unexpected or unknown response %d ", res)) goto quit; } if(check1(p.Status >= 0, "Error %d in Pegasus", p.Status)) goto quit; if(check1(local_status >= 0, "Error %d in Pegasus", local_status)) goto quit; if (p.Status > 0) printf("Status %d in Pegasus.\n", p.Status); res = Pegasus(&p, REQ_CONT); } if(check1(p.Status >= 0, "Error %d in Pegasus", p.Status)) goto quit; if (p.Status > 0) printf("Status %d in Pegasus Init.\n", p.Status); if(p.Status == ERR_JUNK_BYTES_IN_HEADER) printf("Junk bytes found in header were skipped over.\n"); /* Convert the file. */ res = Pegasus(&p, REQ_EXEC); while (res != RES_DONE) { if (res == RES_GET_NEED_DATA) local_status = read_file(&p); else if (res == RES_PUT_NEED_SPACE) { if(check1(num_loops == 1,"output buffer too small to do loops")) goto quit; local_status = copy_to_file(&p); } else if (res == RES_PUT_DATA_YIELD) { if(num_loops == 1) local_status = copy_to_file(&p); } else if (res == RES_POKE) { /* write out remainder of put buffer, if any -- there won't be a poke until after pack has output everything. flushing here saves us having to remember the current file position so we can seek back for the final write */ if ( p.Put.Rear > p.Put.Front ) { len = p.Put.Rear - p.Put.Front; if(check1(fwrite(p.Put.Front,sizeof(BYTE),len,des_file) == len, "output file write error")) goto quit; p.Put.Front = p.Put.Rear; /* it's empty now */ } else if ( p.Put.Rear < p.Put.Front ) { len = p.Put.End - p.Put.Front; if(check1(fwrite(p.Put.Front,sizeof(BYTE),len,des_file) == len, "output file write error")) goto quit; len = p.Put.Rear - p.Put.Start; if(check1(fwrite(p.Put.Start,sizeof(BYTE),len,des_file) == len, "output file write error")) goto quit; p.Put.Front = p.Put.Rear; /* it's empty now */ } /* else Rear == Front and there's nothing left to write */ if(check1(fseek(des_file, p.SeekInfo, SEEK_SET) == 0, "output file seek error")) goto quit; len = p.Put.RearEnd - p.Put.FrontEnd; if(check1(fwrite(p.Put.FrontEnd, sizeof(BYTE), len, des_file) == len, "output file write error")) goto quit; } else if (res == RES_YIELD) ; else if (res == RES_ERR) break; /* output what you can. check(FALSE, "Error number %d ",p.Status); */ else if(check1(FALSE, "Unexpected or unknown response %d ", res)) goto quit; if(local_status < 0) break; res = Pegasus(&p, REQ_CONT); } if (p.Status) printf("Status %d in Pegasus.\n", p.Status); Pegasus(&p, REQ_TERM); #endif if(p.u.ROR.RegionInfo != NULL) { free(p.u.ROR.RegionInfo); p.u.ROR.RegionInfo = NULL; } } if(p.Status == ERR_JUNK_BYTES_IN_HEADER) printf("Junk bytes found in header were skipped over.\n"); if(p.Status == ERR_JUNK_BYTES_BEFORE_RESTART) printf("Junk bytes found before restart marker(s) were skipped over.\n"); if(p.Status == ERR_RESTART_ATTEMPT_AFTER_BAD_DATA) printf("Bad data or unexpected end of data in entropy segment, restart attempted.\n"); #if NOCO if (defer_status) printf("defer status %d in Pegasus.\n", defer_status); #else if (local_status) printf("local status %d in Pegasus.\n", local_status); #endif #if REQUANT if(p.u.ROR.Requantize && !p.u.ROR.RequantizationDone) printf("\nFile was not requantized.\n"); #endif /* copy output buffer to file (if not already done) */ /* We are not wrapping queue, so Rear >= Front always. */ if( (len = p.Put.Rear - p.Put.Front) > 0) if (fwrite(p.Put.Front, sizeof(BYTE), len, des_file) < len) if(check1(FALSE, "error writing output file")) goto quit; printf("Converted file %s to %s.\n", src_name, des_name); /* Close files, free memory. */ quit: if (src_file != NULL) fclose(src_file); if (src_file_join != NULL) fclose(src_file_join); if (des_file != NULL) fclose(des_file); if(p.Put.Start != NULL) { free(p.Put.Start); p.Put.Start = NULL; } if(p.Get.Start != NULL) { free(p.Get.Start); p.Get.Start = NULL; } if(p.u.ROR.RegionInfo != NULL) { free(p.u.ROR.RegionInfo); p.u.ROR.RegionInfo = NULL; } return (p.Status); }