我使用 X-H1 無反
破解到一半,可以執行與出圖,但效果可能不是很好
未完待續…
using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class Decoder : MonoBehaviour
{
// Use this for initialization
void Start()
{
byte[] b = File.ReadAllBytes("C:/A/_DSF0719.RAF");
// ---
string identify = "";
for (int i = 0; i < 16; i++)
{
identify += (char)b[i];
}
// ---
string version = "";
for (int i = 16; i < 20; i++)
{
version += (char)b[i];
}
// ---
string CameraNumberID = "";
for (int i = 20; i < 28; i++)
{
CameraNumberID += (char)b[i];
}
// ---
string CameraBodyName = "";
for (int i = 28; i < 60; i++)
{
CameraBodyName += (char)b[i];
}
// ---
string DirectoryVersion = "";
for (int i = 60; i < 64; i++)
{
DirectoryVersion += (char)b[i];
}
// ---
int JpegImageOffset = b[84] << 24 | b[85] << 16 | b[86] << 8 | b[87];
int JpegImageLength = b[88] << 24 | b[89] << 16 | b[90] << 8 | b[91];
int CFAHeaderOffset = b[92] << 24 | b[93] << 16 | b[94] << 8 | b[95];
int CFAHeaderLength = b[96] << 24 | b[97] << 16 | b[98] << 8 | b[99];
int CFAOffset = b[100] << 24 | b[101] << 16 | b[102] << 8 | b[103];
int CFALength = b[104] << 24 | b[105] << 16 | b[106] << 8 | b[107];
// ---
//int A = b[CFAHeaderOffset] << 24 | b[CFAHeaderOffset+1] << 16 | b[CFAHeaderOffset+2] << 8 | b[CFAHeaderOffset+3];
string A = "";
for (int i = CFAOffset; i < CFAOffset + 2047; i++)
{
A += (char)b[i];
}
// ---
print("Magic Word ( Identify ) : " + identify);
// 0200: Fuji S2
// 0201: Fuji S3
print("Format Version : " + version);
print("Camera number ID : " + CameraNumberID);
print("Camera Body Name : " + CameraBodyName);
print("Directory Version : " + DirectoryVersion);
print("Jpeg Image Offset : " + JpegImageOffset);
print("Jpeg Image Length : " + JpegImageLength);
print("CFA Header Offset : " + CFAHeaderOffset);
print("CFA Header Length : " + CFAHeaderLength);
print("CFA Offset : " + CFAOffset);
print("CFA Length : " + CFALength);
print(A);
// ------------------------------
// 保存 JPG 預覽圖 :
//byte[] PreviewImageByte = new byte[PreviewImageLength];
//for (int i = PreviewImageIndex, k = 0; i < PreviewImageIndex + PreviewImageLength; i++, k++) {
// PreviewImageByte[k] = b[i];
//}
//File.WriteAllBytes("C:/A/My.jpg", PreviewImageByte);
// ------------------------------
CFAOffset += 2047; // 有可能是 : CFALength - ( RAW_Width * RAW_Height ) - 1
Texture2D t = new Texture2D(6160, 4032);
int BlackLevel = 1023; // 黑電平數值
int colorMaxValue = 16383;
int i2 = 0;
for (int y = t.height - 1; y > 0; y--)
{
for (int x = 0; x < t.width; x++)
{
//int k2 = (x + t.width * y ) * 2;
//int c = b[CFAOffset + k2] << 8 | b[CFAOffset + k2 + 1];
int c = b[CFAOffset + i2] << 8 | b[CFAOffset + i2 + 1];
// 黑電平校正-----
c -= BlackLevel;
c = (int)(c * (colorMaxValue + BlackLevel) / (float)colorMaxValue);
//----------------
i2 += 2;
float c2 = c / (float)colorMaxValue;
//c2 *= 3f;
t.SetPixel(x, y, new Color(c2, c2, c2, 1));
}
}
t.Apply();
// ------------------------------
// RBGBRG/GGRGGB/GGBGGR/BRGRBG/GGBGGR/GGRGGB
// if (false)
for (int y = 0, y2 = t.height - 1; y2 > 0; y++, y2--)
{
for (int x = 0; x < t.width; x++)
{
int x2 = x + 1;
Color c = t.GetPixel(x2, y2);
// Red Balance : 2.059603
// Blue Balance : 2.294702
// c = new Color(c.r * 2.059603f, c.g, c.b * 2.294702f);
//c = new Color(c.r * 1.963576f, c.g, c.b * 1.976821f);
// c = new Color(c.r * 1.33333f, c.g, c.b * 1.46478f);
c = new Color(c.r * 1.7258f, c.g, c.b * 1.7258f);
if (y % 6 == 0) // 第一行 RBGBRG
{
if (x % 6 == 0 || x % 6 == 4)
{
t.SetPixel(x2, y2, new Color(c.r, 0, 0, 1));
}
else if (x % 6 == 1 || x % 6 == 3)
{
t.SetPixel(x2, y2, new Color(0, 0, c.b, 1));
}
else if (x % 6 == 2 || x % 6 == 5)
{
t.SetPixel(x2, y2, new Color(0, c.g, 0, 1));
}
}
else if (y % 6 == 1 || y % 6 == 5) // 第二行 GGRGGB
{
if (x % 6 == 2)
{
t.SetPixel(x2, y2, new Color(c.r, 0, 0, 1));
}
else if (x % 6 == 5)
{
t.SetPixel(x2, y2, new Color(0, 0, c.b, 1));
}
else if (x % 6 == 0 || x % 6 == 1 || x % 6 == 3 || x % 6 == 4)
{
t.SetPixel(x2, y2, new Color(0, c.g, 0, 1));
}
}
else if (y % 6 == 2 || y % 6 == 4) // 第三行 GGBGGR
{
if (x % 6 == 5)
{
t.SetPixel(x2, y2, new Color(c.r, 0, 0, 1));
}
else if (x % 6 == 2)
{
t.SetPixel(x2, y2, new Color(0, 0, c.b, 1));
}
else if (x % 6 == 0 || x % 6 == 1 || x % 6 == 3 || x % 6 == 4)
{
t.SetPixel(x2, y2, new Color(0, c.g, 0, 1));
}
}
else if (y % 6 == 3) // 第四行 BRGRBG
{
if (x % 6 == 1 || x % 6 == 3)
{
t.SetPixel(x2, y2, new Color(c.r, 0, 0, 1));
}
else if (x % 6 == 0 || x % 6 == 4)
{
t.SetPixel(x2, y2, new Color(0, 0, c.b, 1));
}
else if (x % 6 == 2 || x % 6 == 5)
{
t.SetPixel(x2, y2, new Color(0, c.g, 0, 1));
}
}
}
}
t.Apply();
// ------------------------------
// B G G R G G
// R G G B G G
// G B R G R B
// R G G B G G
// B G G R G G
// G R B G B R
//if (false)
for (int y = 0; y < t.height; y++)
{
int y2 = t.height - y - 1;
for (int x = 0; x < t.width; x++)
{
int x2 = x + 1;
float R = 0, G = 0, B = 0;
// if (y == 0 && x == 0)
if (y % 6 == 0)
{
if (x % 6 == 0)
{
B = (t.GetPixel(x2 + 1, y2).b + t.GetPixel(x2 + 2, y2 - 2).b) / 2f;
R = (t.GetPixel(x2, y2).r + t.GetPixel(x2 + 2, y2 - 1).r) / 2f;
G = (t.GetPixel(x2 + 2, y2).g
+ t.GetPixel(x2, y2 - 1).g
+ t.GetPixel(x2 + 1, y2 - 1).g
+ t.GetPixel(x2, y2 - 2).g
+ t.GetPixel(x2 + 1, y2 - 2).g) / 5f;
Color color = new Color(R, G, B);
t.SetPixel(x2, y2, color);
t.SetPixel(x2 + 1, y2, color);
t.SetPixel(x2 + 2, y2, color);
t.SetPixel(x2, y2 - 1, color);
t.SetPixel(x2 + 1, y2 - 1, color);
t.SetPixel(x2 + 2, y2 - 1, color);
t.SetPixel(x2, y2 - 2, color);
t.SetPixel(x2 + 1, y2 - 2, color);
t.SetPixel(x2 + 2, y2 - 2, color);
}
if (x % 6 == 3)
{
R = (t.GetPixel(x2 + 1, y2).r + t.GetPixel(x2 + 2, y2 - 2).r) / 2f;
B = (t.GetPixel(x2, y2).b + t.GetPixel(x2 + 2, y2 - 1).b) / 2f;
G = (t.GetPixel(x2 + 2, y2).g
+ t.GetPixel(x2, y2 - 1).g
+ t.GetPixel(x2 + 1, y2 - 1).g
+ t.GetPixel(x2, y2 - 2).g
+ t.GetPixel(x2 + 1, y2 - 2).g) / 5f;
Color color = new Color(R, G, B);
t.SetPixel(x2, y2, color);
t.SetPixel(x2 + 1, y2, color);
t.SetPixel(x2 + 2, y2, color);
t.SetPixel(x2, y2 - 1, color);
t.SetPixel(x2 + 1, y2 - 1, color);
t.SetPixel(x2 + 2, y2 - 1, color);
t.SetPixel(x2, y2 - 2, color);
t.SetPixel(x2 + 1, y2 - 2, color);
t.SetPixel(x2 + 2, y2 - 2, color);
}
}
else if (y % 6 == 3)
{
if (x % 6 == 0)
{
R = (t.GetPixel(x2 + 1, y2).r + t.GetPixel(x2 + 2, y2 - 2).r) / 2f;
B = (t.GetPixel(x2, y2).b + t.GetPixel(x2 + 2, y2 - 1).b) / 2f;
G = (t.GetPixel(x2 + 2, y2).g
+ t.GetPixel(x2, y2 - 1).g
+ t.GetPixel(x2 + 1, y2 - 1).g
+ t.GetPixel(x2, y2 - 2).g
+ t.GetPixel(x2 + 1, y2 - 2).g) / 5f;
Color color = new Color(R, G, B);
t.SetPixel(x2, y2, color);
t.SetPixel(x2 + 1, y2, color);
t.SetPixel(x2 + 2, y2, color);
t.SetPixel(x2, y2 - 1, color);
t.SetPixel(x2 + 1, y2 - 1, color);
t.SetPixel(x2 + 2, y2 - 1, color);
t.SetPixel(x2, y2 - 2, color);
t.SetPixel(x2 + 1, y2 - 2, color);
t.SetPixel(x2 + 2, y2 - 2, color);
}
if (x % 6 == 3)
{
B = (t.GetPixel(x2 + 1, y2).b + t.GetPixel(x2 + 2, y2 - 2).b) / 2f;
R = (t.GetPixel(x2, y2).r + t.GetPixel(x2 + 2, y2 - 1).r) / 2f;
G = (t.GetPixel(x2 + 2, y2).g
+ t.GetPixel(x2, y2 - 1).g
+ t.GetPixel(x2 + 1, y2 - 1).g
+ t.GetPixel(x2, y2 - 2).g
+ t.GetPixel(x2 + 1, y2 - 2).g) / 5f;
Color color = new Color(R, G, B);
t.SetPixel(x2, y2, color);
t.SetPixel(x2 + 1, y2, color);
t.SetPixel(x2 + 2, y2, color);
t.SetPixel(x2, y2 - 1, color);
t.SetPixel(x2 + 1, y2 - 1, color);
t.SetPixel(x2 + 2, y2 - 1, color);
t.SetPixel(x2, y2 - 2, color);
t.SetPixel(x2 + 1, y2 - 2, color);
t.SetPixel(x2 + 2, y2 - 2, color);
}
}
}
}
t.Apply();
outputImg.texture = t;
File.WriteAllBytes("C:/A/My.png", t.EncodeToPNG());
}
public RawImage outputImg;
}
參考 :
http://fileformats.archiveteam.org/wiki/Fujifilm_RAF
https://libopenraw.freedesktop.org/wiki/Fuji_RAF/
https://pixinsight.com/forum/index.php?topic=7242.0
https://web.archive.org/web/20090214101740/http://crousseau.free.fr/imgfmt_raw.htm
http://www.rawsamples.ch/index.php/en/fuji