/// <summary> /// /// </summary> /// <param name="frame">If the frame being constructed is a link frame, this parameter should be the linked frame.</param> /// <param name="index"></param> /// <param name="linkFrameIndex"></param> public FrameMetadata(FrameInfo frame, int index, int? linkFrameIndex) { _index = index; _width = frame.Width; _height = frame.Height; _x = frame.LocationX; _y = frame.LocationY; _linkFrameIndex = linkFrameIndex; }
/// <summary> /// Converts the raw pixel data of a frame into 32-bit RGBA format. /// </summary> /// <param name="rawPixelData"></param> /// <param name="frameData"></param> /// <returns></returns> /// <exception cref="NpkException">The raw pixel data is not the expected size.</exception> private byte[] ExpandPixelData(byte[] rawPixelData, FrameInfo frameData) { byte[] expandedPixelData = new byte[frameData.Width * frameData.Height * 4]; switch (frameData.PixelFormat) { case PixelDataFormat.OneFiveFiveFive: // Make sure sizes match if (rawPixelData.Length != frameData.Width * frameData.Height * 2) { throw new NpkException( "Raw pixel data in 1555 format is {0} bytes. Expected it to be {1} bytes." .F(rawPixelData.Length, frameData.Width * frameData.Height * 2)); } for (int rawIndex = 0; rawIndex < frameData.Width * frameData.Height * 2; rawIndex += 2) { byte byte0 = rawPixelData[rawIndex]; byte byte1 = rawPixelData[rawIndex + 1]; byte a = (byte)(((byte1 & 0x80) >> 7) * 0xFF); byte r = (byte)(((byte1 & 0x7C) << 1) | ((byte1 & 0x7C) >> 4)); byte g = (byte)(((byte1 & 0x03) << 6) | ((byte0 & 0xE0) >> 2)); g = (byte)(g | (g >> 5)); byte b = (byte)(((byte0 & 0x1F) << 3) | ((byte0 & 0x1F) >> 2)); int pixelIndex = rawIndex / 2; int expandedIndex = pixelIndex * 4; expandedPixelData[expandedIndex] = r; expandedPixelData[expandedIndex + 1] = g; expandedPixelData[expandedIndex + 2] = b; expandedPixelData[expandedIndex + 3] = a; } break; case PixelDataFormat.FourFourFourFour: if (rawPixelData.Length != frameData.Width * frameData.Height * 2) { throw new NpkException( "Raw pixel data in 4444 format is {0} bytes. Expected it to be {1} bytes." .F(rawPixelData.Length, frameData.Width * frameData.Height * 2)); } for (int rawIndex = 0; rawIndex < frameData.Width * frameData.Height * 2; rawIndex += 2) { byte byte0 = rawPixelData[rawIndex]; byte byte1 = rawPixelData[rawIndex + 1]; byte a = (byte)(byte1 & 0xF0); a = (byte)(a | (a >> 4)); byte r = (byte)(byte1 & 0x0F); r = (byte)(r | (r << 4)); byte g = (byte)(byte0 & 0xF0); g = (byte)(g | (g >> 4)); byte b = (byte)(byte0 & 0x0F); b = (byte)(b | (b << 4)); int pixelIndex = rawIndex / 2; int expandedIndex = pixelIndex * 4; expandedPixelData[expandedIndex] = r; expandedPixelData[expandedIndex + 1] = g; expandedPixelData[expandedIndex + 2] = b; expandedPixelData[expandedIndex + 3] = a; } break; case PixelDataFormat.EightEightEightEight: if (rawPixelData.Length != frameData.Width * frameData.Height * 4) { throw new NpkException( "Raw pixel data in 8888 format is {0} bytes. Expected it to be {1} bytes." .F(rawPixelData.Length, frameData.Width * frameData.Height * 4)); } for (int rawIndex = 0; rawIndex < frameData.Width * frameData.Height * 4; rawIndex += 4) { byte r = rawPixelData[rawIndex + 2]; byte g = rawPixelData[rawIndex + 1]; byte b = rawPixelData[rawIndex]; byte a = rawPixelData[rawIndex + 3]; expandedPixelData[rawIndex] = r; expandedPixelData[rawIndex + 1] = g; expandedPixelData[rawIndex + 2] = b; expandedPixelData[rawIndex + 3] = a; } break; } return expandedPixelData; }
/// <summary> /// /// </summary> /// <param name="imgPath"></param> /// <param name="frameIndex"></param> /// <param name="pngFilePath"></param> /// <exception cref="DFOToolbox.DFOToolboxException">Something went wrong while editing. Message is suitable for UI display.</exception> /// <exception cref="System.Exception">Other errors resulting from incorrect usage of this function, such as passing null arguments or trying to edit a frame while no file is open.</exception> public void EditFrame(string imgPath, int frameIndex, string pngFilePath) { // validate that we have a file open for editing, that it has the img, that it has the frame index, that the file exists imgPath.ThrowIfNull("imgPath"); pngFilePath.ThrowIfNull("pngFileName"); if (!_editor.IsOpen) { throw new InvalidOperationException("Cannot edit a frame because no file is currently open."); } NpkPath npkPath = imgPath; if (!_editor.Frames.ContainsKey(npkPath)) { throw new KeyNotFoundException("There is no img with path {0}.".F(imgPath)); } if (frameIndex >= _editor.Frames[npkPath].Count) { throw new ArgumentOutOfRangeException("{0} does not have a frame with index {1}.".F(imgPath, frameIndex)); } FrameInfo uneditedFrameMetadata = _editor.Frames[npkPath][frameIndex]; // Use same pixel format as original. // If it's a link frame, we're turning it into a non-link frame, so use 8888 as that will preserve the colors of the new image. PixelDataFormat pixelFormatToUse = uneditedFrameMetadata.PixelFormat; if (pixelFormatToUse == PixelDataFormat.Link) { pixelFormatToUse = PixelDataFormat.EightEightEightEight; } if (!File.Exists(pngFilePath)) { throw new DFOToolboxException("{0} does not exist.".F(pngFilePath)); } byte[] newImageBytesInCorrectFormat; int newImageWidth; int newImageHeight; // Load image pixels into memory // TODO: catch exceptions using (System.Drawing.Bitmap inputImage = new System.Drawing.Bitmap(pngFilePath)) { // need to get pixels into format used by image newImageBytesInCorrectFormat = PixelConversion.Convert(inputImage, pixelFormatToUse); newImageWidth = inputImage.Width; newImageHeight = inputImage.Height; } using (MemoryStream newImageBytesInCorrectFormatStream = new MemoryStream(newImageBytesInCorrectFormat)) { FrameInfo newFrameMetadata = new FrameInfo( isCompressed: uneditedFrameMetadata.IsCompressed, compressedLength: -1, // not used pixelFormat: pixelFormatToUse, width: newImageWidth, height: newImageHeight, locationX: uneditedFrameMetadata.LocationX, locationY: uneditedFrameMetadata.LocationY, maxWidth: uneditedFrameMetadata.MaxWidth, maxHeight: uneditedFrameMetadata.MaxHeight ); _editor.EditFrame(npkPath, frameIndex, newFrameMetadata, newImageBytesInCorrectFormatStream); } // XXX: This code assumes the imgPath passed in is currently selected RefreshFrameList(); FrameList.MoveCurrentToPosition(frameIndex); }
public Image(byte[] pixelData, FrameInfo attributes) { PixelData = pixelData; Attributes = attributes; }