/* ====================== = = HuffExpand = ====================== */ public static void HuffExpand(byte[] sourceBuffer, int sourceIndex, byte[] destBuffer, int destIndex, int length, huffnode hufftable) { memptr source = new memptr(sourceBuffer, sourceIndex); memptr dest = new memptr(destBuffer, destIndex); ushort bit, _byte, code; huffnode nodeon, headptr; headptr = new huffnode(hufftable, 254); // head node is allways node 254 // as: The disabled C code that was in this function appears to be the C version of the asm code // this came in handy during the conversion nodeon = new huffnode(headptr); // as: bugfix - refactored to prevent the out of bounds read that can occur occasionally with the final byte bit = 256; _byte = 0; while(length != 0) { if(bit == 256) { bit = 1; _byte = source.GetUInt8(0); source.Offset(1); } if((_byte & bit) != 0) code = nodeon.bit1; else code = nodeon.bit0; bit <<= 1; if(code < 256) { dest.SetUInt8(0, (byte) code); dest.Offset(1); nodeon = headptr; length--; } else { nodeon = new huffnode(hufftable, code - 256); } } }
/* =========================== = = MakeShape = = Takes a raw bit map of width bytes by height and creates a scaleable shape = = Returns the length of the shape in bytes = =========================== */ private void SC_MakeShape(memptr src, short width, short height, ref memptr shapeseg) { short pixwidth = (short) (width * 8); memptr tempseg_memptr = new memptr(); // as: added MMGetPtr(ref tempseg_memptr, pixwidth * (height + 20)); // larger than needed buffer scaleshape tempseg = new scaleshape(tempseg_memptr); tempseg.width = pixwidth; // pixel dimensions tempseg.height = height; // // convert ega pixels to byte color values in a temp buffer // // Stored in a collumn format, not rows! // memptr byteseg = new memptr(); MMGetPtr(ref byteseg, pixwidth * height); memptr byteptr = new memptr(byteseg); memptr plane0 = new memptr(src); memptr plane1 = new memptr(plane0, width * height); memptr plane2 = new memptr(plane1, width * height); memptr plane3 = new memptr(plane2, width * height); for(short x = 0; x < width; x++) { for(ushort b = 0; b < 8; b++) { ushort shift = (ushort) (8 - b); ushort offset = (ushort) x; for(short y = 0; y < height; y++) { byte by0 = plane0.GetUInt8(offset); byte by1 = plane1.GetUInt8(offset); byte by2 = plane2.GetUInt8(offset); byte by3 = plane3.GetUInt8(offset); offset += (ushort) width; ushort color = 0; // as: converted from asm color |= AsmRotate(by3, shift); color <<= 1; color |= AsmRotate(by2, shift); color <<= 1; color |= AsmRotate(by1, shift); color <<= 1; color |= AsmRotate(by0, shift); byteptr.SetUInt8(0, (byte) color); byteptr.Offset(1); } // Y } // B } // X // // convert byte map to sparse scaling format // memptr saveptr = tempseg.PointerTofirst(pixwidth); // start filling in data after all pointers to line segments byteptr = new memptr(byteseg); // first pixel in byte array for(short x = 0; x < pixwidth; x++) { // // each vertical line can have 0 or more segments of pixels in it // short y = 0; memptr segptr = tempseg.PointerTofirst(x); segptr.SetUInt16(0, 0); // in case there are no segments on line do { // scan for first pixel to be scaled while(y < height && byteptr.GetUInt8(0) == BACKGROUND) // as: bugfix - re-ordered to prevent out of bounds read { byteptr.Offset(1); y++; } if(y == height) // if not, the line is finished continue; // // start a segment by pointing the last link (either shape.first[x] if it // is the first segment, or a seg.next if not) to the current spot in // the tempseg, setting segptr to this segments next link, and copying // all the pixels in the segment // segptr.SetUInt16(0, _sys.FP_OFF(saveptr)); // pointer to start of this segment short start = y; short length = 0; scaleseg scale_seg = new scaleseg(saveptr); memptr dataptr = scale_seg.PointerToData(0); // // copy bytes in the segment to the shape // while(y < height && byteptr.GetUInt8(0) != BACKGROUND) // as: bugfix - re-ordered to prevent out of bounds read { length++; dataptr.SetUInt8(0, byteptr.GetUInt8(0)); dataptr.Offset(1); byteptr.Offset(1); y++; } scale_seg.start = start; scale_seg.length = length; scale_seg.next = 0; // get ready for next segment segptr = new memptr(saveptr, scaleseg.FieldOffset_next); saveptr = dataptr; // next free byte to be used } while(y < height); } // // allocate exact space needed and copy shape to it, then free buffers // MMGetPtr(ref shapeseg, _sys.FP_OFF(saveptr)); Array.Copy(tempseg.Pointer.Buffer, shapeseg.Buffer, _sys.FP_OFF(saveptr)); MMFreePtr(ref byteseg); MMFreePtr(ref tempseg_memptr); }