// ========================================================================== // stage 2 of the decompression of the direction frames // return 0 on success, non-zero if error List <Image> dcc_make_frame(int d) { List <Image> bitmaps = new List <Image>(); DCC_DIRECTION_HEADER_S dir = dcc_direction_headers[d]; int pbei = 0; DCC_PB_ENTRY_S pbe = dir.pixel_buffer[pbei++]; DCC_CELL_S buff_cell, cell; uint pix; int nb_cell, nb_bit, cell_x, cell_y, cell_idx, x, y, c; //Bitmap frm_bmp; //char add_error[256]; BitArray pixelCodesAndDisplacementBits = new BitArray(dcc_direction_headers[d].PixelCodesAndDisplacementBitstream); int pixelCodesAndDisplacementBitsOffset = dcc_direction_headers[d].pco; // initialised the last_w & last_h of the buffer cells for (c = 0; c < dir.nb_cells_w * dir.nb_cells_h; c++) { dir.cells[c].last_w = -1; dir.cells[c].last_h = -1; } // for all frames for (int f = 0; f < dcc_header.frames_per_dir; f++) { // create the temp frame bitmap (size = current direction box) //DCC_FRAME_HEADER_S frame = dir.frame_headers[f]; var frm_bmp = new Bitmap(dir.box.width, dir.box.height); using (var g = Graphics.FromImage(frm_bmp)) { g.Clear(Color.Transparent); } //clear(frm_bmp); // clear the final frame bitmap (to index 0) nb_cell = dir.frame_headers[f].nb_cells_w * dir.frame_headers[f].nb_cells_h; // for all cells of this frame for (c = 0; c < nb_cell; c++) { // frame cell cell = dir.frame_headers[f].cells[c]; // buffer cell cell_x = cell.x0 / 4; cell_y = cell.y0 / 4; cell_idx = cell_x + (cell_y * (dir.nb_cells_w - 1)); buff_cell = dir.cells[cell_idx]; // equal cell checks if ((pbe.frame != f) || (pbe.frame_cell_index != c)) { // this buffer cell have an equalcell bit set to 1 // so either copy the frame cell or clear it if ((cell.w != buff_cell.last_w) || (cell.h != buff_cell.last_h)) { // different sizes //clear(cell.bmp); // set all pixels of the frame cell to 0 using (var g = Graphics.FromImage(dir.frame_headers[f].cells[c].bmp)) { g.Clear(Color.Magenta); } } else { // same sizes //// copy the old frame cell into its new position //blit(dir.bmp, dir.bmp, // buff_cell.last_x0, buff_cell.last_y0, // cell.x0, cell.y0, // cell.w, cell.h //); using (var fg = Graphics.FromImage(dcc_direction_headers[d].bmp)) { fg.DrawImage(dcc_direction_headers[d].bmp, cell.x0, cell.y0); } //// copy it again, into the final frame bitmap //blit(cell.bmp, frm_bmp, // 0, 0, // cell.x0, cell.y0, // cell.w, cell.h //); using (var fg = Graphics.FromImage(frm_bmp)) { fg.DrawImage(dir.frame_headers[f].cells[c].bmp, cell.x0, cell.y0); } } } else { // fill the frame cell with pixels if (pbe.val[0] == pbe.val[1]) { // fill FRAME cell to color val[0] //clear_to_color(cell.bmp, pbe.val[0]); byte color = pbe.val[0]; using (var g = Graphics.FromImage(dir.frame_headers[f].cells[c].bmp)) { g.Clear(palette[color]); } } else { if (pbe.val[1] == pbe.val[2]) { nb_bit = 1; } else { nb_bit = 2; } //// fill FRAME cell with pixels for (y = 0; y < cell.h; y++) { for (x = 0; x < cell.w; x++) { //if (dcc_read_bits( //& dcc.direction[d].pixel_code_and_displacment_bitstream, //nb_bit, FALSE, & pix)) //{ //sprintf(add_error, "dcc_make_frame() :\n " // "pixel_code_and_displacment bitstream, direction %i, frame %i, " // "curr_cell %i\n", //d, pbe.frame, pbe.frame_cell_index); //strcat(dcc_error, add_error); //return 1; //} pix = pixelCodesAndDisplacementBits.ToUInt32(ref pixelCodesAndDisplacementBitsOffset, (uint)nb_bit); byte color = pbe.val[pix]; //if (pix < 3) { dir.frame_headers[f].cells[c].bmp.SetPixel(x, y, palette[color]); } //putpixel(cell.bmp, x, y, pbe.val[pix]); } } } //// copy the frame cell into the frame bitmap //blit(cell.bmp, frm_bmp, // 0, 0, // cell.x0, cell.y0, // cell.w, cell.h //); using (var fg = Graphics.FromImage(frm_bmp)) { fg.DrawImage(dir.frame_headers[f].cells[c].bmp, cell.x0, cell.y0); } // next pixelbuffer entry pbe = dir.pixel_buffer[pbei++]; } // for the buffer cell that was used by this frame cell, // save the width & size of the current frame cell // (needed for further tests about equalcell) buff_cell.last_w = cell.w; buff_cell.last_h = cell.h; // and save its origin, for further copy when equalcell buff_cell.last_x0 = cell.x0; buff_cell.last_y0 = cell.y0; } // save frame bitmaps.Add(frm_bmp); //return frm_bmp; } return(bitmaps); }
void LoadHeader() { long nb, s; int size = Marshal.SizeOf(typeof(DCC_Header_S)); IntPtr buffer = Marshal.AllocHGlobal(size); try { Marshal.Copy(dc6_file, 0, buffer, size); dcc_header = (DCC_Header_S)Marshal.PtrToStructure(buffer, typeof(DCC_Header_S)); } finally { Marshal.FreeHGlobal(buffer); } //nb = dcc_header.directions; // *dcc_header.frames_per_dir; dcc_direction_ptr = new int[dcc_header.directions]; dcc_direction_headers = new DCC_DIRECTION_HEADER_S[dcc_header.directions]; s = sizeof(int) * dcc_header.directions; size = Marshal.SizeOf(s); buffer = Marshal.AllocHGlobal(size); try { //Marshal.Copy(dc6_file, Marshal.SizeOf(typeof(DC6_Header_S)), buffer, (int)s); //var dptr = (int)Marshal.PtrToStructure(buffer, typeof(int)); for (int i = 0; i < dcc_header.directions; i++) { var ptr = BitConverter.ToInt32(dc6_file, Marshal.SizeOf(typeof(DCC_Header_S)) + (i * 4)); dcc_direction_ptr[i] = ptr; } } finally { Marshal.FreeHGlobal(buffer); } int bitOffset = (int)((Marshal.SizeOf(typeof(DCC_Header_S)) + ((dcc_header.directions) * 4)) * 8); BitArray bits = new BitArray(dc6_file); uint[] widthTable = { 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32 }; for (int i = 0; i < dcc_header.directions; i++) { int offsetStart = bitOffset; int directionBufferSize; if (i == dcc_header.directions - 1) { directionBufferSize = 8 * (dc6_file.Length - dcc_direction_ptr[i]); } else { directionBufferSize = 8 * (dcc_direction_ptr[i + 1] - dcc_direction_ptr[i]); } var directionHeader = new DCC_DIRECTION_HEADER_S(); directionHeader.PixelValues = new byte[256]; directionHeader.frame_headers = new DCC_FRAME_HEADER_S[dcc_header.frames_per_dir]; directionHeader.OutSizeCoded = bits.ToInt32(ref bitOffset); directionHeader.CompressionFlags = bits.ToByte(ref bitOffset, 2); directionHeader.Variable0Bits = bits.ToUInt32(ref bitOffset, 4); directionHeader.WidthBits = bits.ToUInt32(ref bitOffset, 4); directionHeader.HeightBits = bits.ToUInt32(ref bitOffset, 4); directionHeader.XOffsetBits = bits.ToUInt32(ref bitOffset, 4); directionHeader.YOffsetBits = bits.ToUInt32(ref bitOffset, 4); directionHeader.OptionalDataBits = bits.ToUInt32(ref bitOffset, 4); directionHeader.CodedBytesBits = bits.ToUInt32(ref bitOffset, 4); // Calculate box sizes // init direction box min & max (NOT ZERO !) directionHeader.box.xmin = directionHeader.box.ymin = int.MaxValue; directionHeader.box.xmax = directionHeader.box.ymax = int.MinValue; for (int j = 0; j < dcc_header.frames_per_dir; j++) { var frameHeader = new DCC_FRAME_HEADER_S(); frameHeader.Variable0 = bits.ToUInt32(ref bitOffset, widthTable[directionHeader.Variable0Bits]); frameHeader.width = bits.ToUInt32(ref bitOffset, widthTable[directionHeader.WidthBits]); frameHeader.height = bits.ToUInt32(ref bitOffset, widthTable[directionHeader.HeightBits]); frameHeader.offset_x = bits.ToInt32(ref bitOffset, widthTable[directionHeader.XOffsetBits]); frameHeader.offset_y = bits.ToInt32(ref bitOffset, widthTable[directionHeader.YOffsetBits]); frameHeader.optionalData = bits.ToUInt32(ref bitOffset, widthTable[directionHeader.OptionalDataBits]); frameHeader.codedBytes = bits.ToUInt32(ref bitOffset, widthTable[directionHeader.CodedBytesBits]); frameHeader.FrameBottomUp = bits.ToBool(ref bitOffset); // frame box frameHeader.box.xmin = frameHeader.offset_x; frameHeader.box.xmax = (int)(frameHeader.box.xmin + frameHeader.width - 1); if (frameHeader.FrameBottomUp) // bottom-up { frameHeader.box.ymin = frameHeader.offset_y; frameHeader.box.ymax = (int)(frameHeader.box.ymin + frameHeader.height - 1); } else // top-down { frameHeader.box.ymax = frameHeader.offset_y; frameHeader.box.ymin = (int)(frameHeader.box.ymax - frameHeader.height + 1); } frameHeader.box.width = frameHeader.box.xmax - frameHeader.box.xmin + 1; frameHeader.box.height = frameHeader.box.ymax - frameHeader.box.ymin + 1; // direction box if (frameHeader.box.xmin < directionHeader.box.xmin) { directionHeader.box.xmin = frameHeader.box.xmin; } if (frameHeader.box.ymin < directionHeader.box.ymin) { directionHeader.box.ymin = frameHeader.box.ymin; } if (frameHeader.box.xmax > directionHeader.box.xmax) { directionHeader.box.xmax = frameHeader.box.xmax; } if (frameHeader.box.ymax > directionHeader.box.ymax) { directionHeader.box.ymax = frameHeader.box.ymax; } directionHeader.frame_headers[j] = frameHeader; } directionHeader.box.width = directionHeader.box.xmax - directionHeader.box.xmin + 1; directionHeader.box.height = directionHeader.box.ymax - directionHeader.box.ymin + 1; //TODO OptionalData if (directionHeader.OptionalDataBits > 0) { throw new NotImplementedException(); } if ((directionHeader.CompressionFlags & 0x02) == 0x02) { directionHeader.EqualCellsBitstreamSize = bits.ToUInt32(ref bitOffset, 20); } directionHeader.PixelMaskBitstreamSize = bits.ToUInt32(ref bitOffset, 20); if ((directionHeader.CompressionFlags & 0x01) == 0x01) { directionHeader.EncodingTypeBitsreamSize = bits.ToUInt32(ref bitOffset, 20); directionHeader.RawPixelCodesBitstreamSize = bits.ToUInt32(ref bitOffset, 20); } directionHeader.PixelValuesKey = bits.ToBitArray(ref bitOffset, 256); int pi = 0; for (int p = 0; p < 256; p++) { if (directionHeader.PixelValuesKey[p]) { directionHeader.PixelValues[pi++] = (byte)p; } } directionHeader.EqualCellsBitstream = bits.ToBytes(ref bitOffset, directionHeader.EqualCellsBitstreamSize); directionHeader.PixelMaskBitstream = bits.ToBytes(ref bitOffset, directionHeader.PixelMaskBitstreamSize); directionHeader.EncodingTypeBitsream = bits.ToBytes(ref bitOffset, directionHeader.EncodingTypeBitsreamSize); directionHeader.RawPixelCodesBitstream = bits.ToBytes(ref bitOffset, directionHeader.RawPixelCodesBitstreamSize); directionHeader.PixelCodesAndDisplacementBitstream = bits.ToBytes(ref bitOffset, (uint)(directionBufferSize - (bitOffset - offsetStart))); dcc_direction_headers[i] = directionHeader; //size = Marshal.SizeOf(typeof(DC6_FRAME_HEADER_S)); //buffer = Marshal.AllocHGlobal(size); //try //{ // Marshal.Copy(dc6_file, dcc_frame_ptr[i], buffer, size); // var dc6_frame_header = (DC6_FRAME_HEADER_S)Marshal.PtrToStructure(buffer, typeof(DC6_FRAME_HEADER_S)); // dcc_frame_headers[i] = dc6_frame_header; //} //finally //{ // Marshal.FreeHGlobal(buffer); //} } }