diff --git a/TBO/Program.cs b/TBO/Program.cs
index 373c2b0..e1a4a4f 100644
--- a/TBO/Program.cs
+++ b/TBO/Program.cs
@@ -1,8 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows.Forms;
+using Microsoft.Win32;
+using System;
+using System.Reflection;
using TBO.UI;
+using XWolf;
namespace TBO
{
@@ -14,8 +14,11 @@
[STAThread]
static void Main()
{
+ //ShellNotification.NotifyOfChange();
+ //if (!FileAssociation.IsAssociatedWithMe("tbo"))
+ // FileAssociation.AssociateMe("tbo", "XWolfTebeo", "Tebeo", 0);
+ //AssociateMe("tbo", "XWolfTebeo", "Tebeo", 0,null);
UIManager.Manager.EnterStudio();
-
}
}
}
diff --git a/TBO/TBO.csproj b/TBO/TBO.csproj
index 9097062..3e8159d 100644
--- a/TBO/TBO.csproj
+++ b/TBO/TBO.csproj
@@ -47,6 +47,9 @@
+
+ FileAssociationNT6.cs
+
xIO2.cs
diff --git a/TBO/TBOFile.cs b/TBO/TBOFile.cs
index 621632f..40b81df 100644
--- a/TBO/TBOFile.cs
+++ b/TBO/TBOFile.cs
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
+using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
+using TBO.Properties;
using XWolf.IO;
namespace TBO
@@ -13,15 +15,18 @@
private const string FILEHEADER = "TBO";
private const int EOF = 0x1A;
private const int FILEVERSION = 0;
+ private const uint ENDIANMARK = 0xFEEDFACE;
private static ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
private static EncoderParameters eParams = new EncoderParameters(1);
private FileStream fs;
+ private long tboStart;
private bool readOnly;
- private bool empty;
+ private bool changed;
private long metapos;
- private long[] pagepos;
+ private bool sameEndian;
+ private List pagepos = new List();
static TBOFile()
{
@@ -33,6 +38,7 @@
try
{
fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
+ readOnly = false;
}
catch
{
@@ -41,16 +47,116 @@
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
readOnly = true;
}
- catch { throw new Exception("No se pudo abrir ni crear el archivo"); }
+ catch { throw new Exception("No se pudo abrir ni crear el tebeo"); }
}
if (fs.Length == 0)
WriteHeader();
else
- ReadHeader();
+ ReadHeader(false);
ReadDirectory();
ReadMetadata();
}
+ public void Dispose()
+ {
+ if (changed)
+ Commit();
+ fs.Close();
+ }
+
+ #region I/O
+
+ private void ReadHeader(bool hard = true)
+ {
+ fs.Position = tboStart;
+ if (Encoding.ASCII.GetString(fs.Read(FILEHEADER.Length)) != FILEHEADER)
+ if (hard)
+ throw new Exception("El arhivo no es un tebeo");
+ else
+ {
+ // Search enveloped TBO
+ fs.Position = fs.Length - FILEHEADER.Length;
+ if (Encoding.ASCII.GetString(fs.Read(FILEHEADER.Length)) != FILEHEADER)
+ throw new Exception("El arhivo no contiene un tebeo");
+ fs.Position = fs.Length - (FILEHEADER.Length + sizeof(int));
+ tboStart = fs.ReadInt32();
+ ReadHeader();
+ return;
+ }
+ if (fs.ReadByte() != EOF)
+ throw new Exception("Error al leer el tebeo");
+ if (fs.ReadByte() != FILEVERSION)
+ throw new Exception("No se puede leer esta versión del tebeo");
+ sameEndian = fs.ReadUInt32() == ENDIANMARK;
+ }
+
+ private void WriteHeader()
+ {
+ fs.Position = tboStart;
+ fs.Write(Encoding.ASCII.GetBytes(FILEHEADER));
+ fs.WriteByte(EOF);
+ fs.WriteByte(FILEVERSION);
+ fs.WriteUInt32(ENDIANMARK);
+ }
+
+ private void ReadDirectory()
+ {
+ pagepos.Clear();
+ if (fs.Position >= fs.Length)
+ {
+ metapos = fs.Position + sizeof(int);
+ }
+ else
+ {
+ long pos = fs.Position;
+ int lng;
+ while ((lng = fs.ReadInt32()) > 0)
+ {
+ pagepos.Add(pos);
+ fs.Position = pos = fs.Position + lng;
+ }
+ metapos = fs.Position;
+ }
+ }
+
+ private void ReadMetadata()
+ {
+ fs.Position = metapos;
+ if (fs.Position >= fs.Length)
+ return;
+ fs.DeserializeTo(this);
+ }
+
+ private Image ReadImage()
+ {
+ MemoryStream ms = new MemoryStream(fs.ReadBlock());
+ return Image.FromStream(ms);
+ }
+
+ private void WriteImage(Image i)
+ {
+ fs.WriteBlock(ImageJPEG(i));
+ }
+
+ private void Commit()
+ {
+ if (readOnly)
+ throw new Exception("Tebeo de solo lectura, no se puede escribir");
+ fs.Position = metapos - sizeof(int);
+ fs.WriteInt32(0); // End of directory mark
+ fs.Serialize(this);
+ if (tboStart > 0)
+ {
+ fs.WriteInt32((int)tboStart);
+ fs.Write(Encoding.ASCII.GetBytes(FILEHEADER));
+ }
+ changed = false;
+ }
+
+ #endregion
+
+ #region Image Processing
+
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
@@ -64,107 +170,15 @@
return null;
}
- public void Dispose()
- {
- fs.Close();
- }
-
- private void ReadDirectory()
- {
- List poses = new List();
- long pos = fs.Position;
- int lng;
- while ((lng = fs.ReadInt32()) > 0)
- {
- poses.Add(pos);
- fs.Position = pos = fs.Position + lng;
- }
- pagepos = poses.ToArray();
- }
-
- private void ReadMetadata()
- {
- metapos = fs.Position;
- if (fs.Position >= fs.Length)
- return;
- string metaJSON = fs.ReadString();
- }
-
- #region I/O
-
- private void ReadHeader()
- {
- empty = false;
- fs.Position = 0;
- if (Encoding.ASCII.GetString(fs.Read(FILEHEADER.Length)) != FILEHEADER)
- throw new Exception("El arhivo no es un tebeo");
- if (fs.ReadByte() != EOF)
- throw new Exception("Error al leer el tebeo");
- if (fs.ReadByte() != FILEVERSION)
- throw new Exception("No se puede leer esta versión del tebeo");
- }
-
- private void WriteHeader()
- {
- empty = true;
- fs.Position = 0;
- fs.Write(Encoding.ASCII.GetBytes(FILEHEADER));
- fs.WriteByte(EOF);
- fs.WriteByte(FILEVERSION);
- }
-
- private Image ReadImage()
- {
- MemoryStream ms = new MemoryStream(fs.ReadBlock());
- return Image.FromStream(ms);
- }
-
- private void WriteImage(Image i)
- {
- fs.WriteBlock(ImageJPEG(i));
- }
-
- public void AppendImage(string filename)
- {
- byte[] image;
- FileInfo fi = new FileInfo(filename);
- Image i;
- try
- {
- i = Image.FromFile(filename);
- }
- catch
- {
- return;
- }
- using (i)
- {
- image = GetImageBytes(i);
- if (image.Length > fi.Length)
- image = File.ReadAllBytes(filename);
- }
- fs.WriteBlock(image);
- }
-
- ///
- /// Closes the TBO writing procedure
- ///
- public void Commit()
- {
-
- }
-
- #endregion
-
- private byte[] GetImageBytes(Image i)
+ private byte[] GetImageBytes(Image i, int grayscale, bool keepColors)
{
byte[] img = ImageJPEG(i);
- if (Grayscale == 0)
+ if (grayscale == 0)
return img;
- if (KeepColors && !ImageWorks.IsGray(i))
+ if (keepColors && !ImageWorks.IsGray(i))
return img;
byte[] gimg;
- switch (Grayscale)
+ switch (grayscale)
{
case 256:
gimg = ImagePNG8bpp(i);
@@ -249,6 +263,87 @@
return ImagePNG(bmp);
}
+ #endregion
+
+ ///
+ /// Reset the file starting like new
+ ///
+ public void Reset()
+ {
+ changed = true;
+ fs.Position = tboStart;
+ fs.SetLength(tboStart);
+ WriteHeader();
+ ReadDirectory();
+ }
+
+ ///
+ /// Reset the TBO with a thumbnail image
+ ///
+ ///
+ public void Reset(Image i)
+ {
+ tboStart = 0;
+ if (i != null)
+ {
+ using (Bitmap bmp = new Bitmap(256, 256))
+ using (Graphics g = Graphics.FromImage(bmp))
+ {
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+ g.InterpolationMode = InterpolationMode.High;
+ int w = (i.Width * 256) / i.Height;
+ g.DrawImage(i, (256 - w) / 2, 0, w, 256);
+ g.DrawImage(Resources.tbo_logo, 128, 170, 128, 88);
+ fs.Position = 0;
+ bmp.Save(fs, ImageFormat.Png);
+ tboStart = fs.Position;
+ }
+ }
+ Reset();
+ }
+
+ ///
+ /// Adds an image to the TBO
+ ///
+ ///
+ public void AppendImage(string filename, int grayscale = 0, bool keepColors = true)
+ {
+ if (readOnly)
+ throw new Exception("Tebeo de solo lectura, no se puede escribir");
+ Image i;
+ try
+ {
+ i = Image.FromFile(filename);
+ }
+ catch
+ {
+ return;
+ }
+ changed = true;
+ fs.Position = metapos - sizeof(int);
+ byte[] image;
+ FileInfo fi = new FileInfo(filename);
+ using (i)
+ {
+ image = GetImageBytes(i, grayscale, keepColors);
+ if (image.Length > fi.Length)
+ image = File.ReadAllBytes(filename);
+ }
+ pagepos.Add(fs.Position);
+ fs.WriteBlock(image);
+ metapos = fs.Position + sizeof(int);
+ }
+
+ ///
+ /// Save the metadata of the file
+ ///
+ public void SaveMetadata()
+ {
+ Commit();
+ }
+
+ #region Metadata Properteis
+
[xIO.Serializable("Titl")]
public string Title { get; set; }
@@ -270,9 +365,9 @@
[xIO.Serializable("Com")]
public string Comments { get; set; }
- public int Grayscale { get; set; } = 16;
- public bool KeepColors { get; set; } = true;
+ #endregion
public long Size => fs.Length;
+ public int PageCount => pagepos.Count;
}
}
diff --git a/TBO/UI/Windows/Studio.Designer.cs b/TBO/UI/Windows/Studio.Designer.cs
index fc247f0..ae20c52 100644
--- a/TBO/UI/Windows/Studio.Designer.cs
+++ b/TBO/UI/Windows/Studio.Designer.cs
@@ -58,6 +58,7 @@
this.cbDepth = new System.Windows.Forms.ComboBox();
this.label12 = new System.Windows.Forms.Label();
this.cbColor = new System.Windows.Forms.CheckBox();
+ this.cbThumb = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.nudYear)).BeginInit();
this.SuspendLayout();
//
@@ -147,7 +148,7 @@
//
this.pbGo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.pbGo.Location = new System.Drawing.Point(12, 410);
+ this.pbGo.Location = new System.Drawing.Point(12, 431);
this.pbGo.Name = "pbGo";
this.pbGo.Size = new System.Drawing.Size(292, 23);
this.pbGo.TabIndex = 8;
@@ -155,7 +156,7 @@
// btGo
//
this.btGo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.btGo.Location = new System.Drawing.Point(310, 410);
+ this.btGo.Location = new System.Drawing.Point(310, 431);
this.btGo.Name = "btGo";
this.btGo.Size = new System.Drawing.Size(75, 23);
this.btGo.TabIndex = 14;
@@ -167,7 +168,7 @@
//
this.lbInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.lbInfo.AutoSize = true;
- this.lbInfo.Location = new System.Drawing.Point(12, 394);
+ this.lbInfo.Location = new System.Drawing.Point(12, 415);
this.lbInfo.Name = "lbInfo";
this.lbInfo.Size = new System.Drawing.Size(16, 13);
this.lbInfo.TabIndex = 10;
@@ -318,6 +319,7 @@
this.cbGrayscale.TabIndex = 11;
this.cbGrayscale.Text = "Usar";
this.cbGrayscale.UseVisualStyleBackColor = true;
+ this.cbGrayscale.CheckedChanged += new System.EventHandler(this.cbGrayscale_CheckedChanged);
//
// cbDepth
//
@@ -357,12 +359,25 @@
this.cbColor.Text = "Excepto las de color.";
this.cbColor.UseVisualStyleBackColor = true;
//
+ // cbThumb
+ //
+ this.cbThumb.AutoSize = true;
+ this.cbThumb.Checked = true;
+ this.cbThumb.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.cbThumb.Location = new System.Drawing.Point(15, 389);
+ this.cbThumb.Name = "cbThumb";
+ this.cbThumb.Size = new System.Drawing.Size(225, 17);
+ this.cbThumb.TabIndex = 28;
+ this.cbThumb.Text = "Generar un thumbnail de la primera página";
+ this.cbThumb.UseVisualStyleBackColor = true;
+ //
// Studio
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
- this.ClientSize = new System.Drawing.Size(397, 445);
+ this.ClientSize = new System.Drawing.Size(397, 466);
+ this.Controls.Add(this.cbThumb);
this.Controls.Add(this.cbColor);
this.Controls.Add(this.label12);
this.Controls.Add(this.cbDepth);
@@ -437,5 +452,6 @@
private System.Windows.Forms.ComboBox cbDepth;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.CheckBox cbColor;
+ private System.Windows.Forms.CheckBox cbThumb;
}
}
\ No newline at end of file
diff --git a/TBO/UI/Windows/Studio.cs b/TBO/UI/Windows/Studio.cs
index 29378d3..5eef6cf 100644
--- a/TBO/UI/Windows/Studio.cs
+++ b/TBO/UI/Windows/Studio.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Drawing;
using System.IO;
using System.Windows.Forms;
@@ -55,7 +56,7 @@
if (fbd.ShowDialog() == DialogResult.OK)
{
tbInputDir.Text = fbd.SelectedPath;
- tbTBO.Text = Path.Combine(Path.GetDirectoryName(fbd.SelectedPath), Path.GetFileNameWithoutExtension(fbd.SelectedPath)) + ".tbo";
+ tbTBO.Text = Path.Combine(Path.GetDirectoryName(fbd.SelectedPath), Path.GetFileNameWithoutExtension(fbd.SelectedPath)) + ".tebeo.png";
}
}
@@ -67,8 +68,8 @@
fd.FileName = tbTBO.Text;
}
catch { }
- fd.Filter = "Tebeo|*.tbo";
- fd.DefaultExt = "tbo";
+ fd.Filter = "Tebeo|*.tebeo.png";
+ fd.DefaultExt = "tebeo.png";
if (fd.ShowDialog() == DialogResult.OK)
{
tbTBO.Text = fd.FileName;
@@ -94,27 +95,39 @@
try
{
btGo.Enabled = false;
- TBOFile tbo = new TBOFile(tbTBO.Text);
- tbo.Title = tbTitle.Text;
- tbo.Variant = tbVar.Text;
- tbo.Volume = tbVolume.Text;
- tbo.Author = tbAuthor.Text;
- tbo.Publisher = tbPublisher.Text;
- tbo.Year = (int)nudYear.Value;
- tbo.Comments = tbCom.Text;
- if (cbGrayscale.Checked)
- tbo.Grayscale = new int[] { 256, 16, 8, 6, 4, 2 }[cbDepth.SelectedIndex];
- else
- tbo.Grayscale = 0;
- tbo.KeepColors = cbColor.Checked;
- for (int i = 0; i < files.Count; i++)
+ int grayscale = new int[] { 256, 16, 8, 6, 4, 2 }[cbDepth.SelectedIndex];
+ bool keepcolors = cbColor.Checked;
+ using (TBOFile tbo = new TBOFile(tbTBO.Text))
{
- pbGo.Value = i;
- tbo.AppendImage(files[i]);
- lbInfo.Text = FBytes(tbo.Size);
- Application.DoEvents();
+ if (cbThumb.Checked)
+ {
+ Image i = null;
+ foreach (string f in files)
+ try
+ {
+ i = Image.FromFile(f);
+ break;
+ }
+ catch { };
+ using (i) { tbo.Reset(i); }
+ }
+ else
+ tbo.Reset();
+ tbo.Title = tbTitle.Text;
+ tbo.Variant = tbVar.Text;
+ tbo.Volume = tbVolume.Text;
+ tbo.Author = tbAuthor.Text;
+ tbo.Publisher = tbPublisher.Text;
+ tbo.Year = (int)nudYear.Value;
+ tbo.Comments = tbCom.Text;
+ for (int i = 0; i < files.Count; i++)
+ {
+ pbGo.Value = i;
+ tbo.AppendImage(files[i], grayscale, keepcolors);
+ lbInfo.Text = tbo.PageCount + " páginas (" + FBytes(tbo.Size) + ")";
+ Application.DoEvents();
+ }
}
- tbo.W
}
//catch (Exception ex)
//{
@@ -123,13 +136,20 @@
finally
{
btGo.Enabled = true;
+ pbGo.Value = pbGo.Maximum;
}
-
+ MessageBox.Show("Tebeo creado correctamente", "Tebeo", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void Studio_Load(object sender, EventArgs e)
{
cbDepth.SelectedIndex = 1;
}
+
+ private void cbGrayscale_CheckedChanged(object sender, EventArgs e)
+ {
+ cbDepth.Enabled = cbGrayscale.Checked;
+ cbColor.Enabled = cbGrayscale.Checked;
+ }
}
}