Skip to content

Commit

Permalink
Upload of GetPsdLayers VS2013 Final Release
Browse files Browse the repository at this point in the history
A simple example web page to extract psd layers as png and display in
html
  • Loading branch information
daamdaam committed May 14, 2014
0 parents commit 78da6c2
Show file tree
Hide file tree
Showing 20 changed files with 3,211 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Default.aspx
@@ -0,0 +1,19 @@
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GetPsdLayers.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:FileUpload runat="server" ToolTip="give me a layered psd" ID="fupGiveMeAPsd" />
<asp:Button ID="btnGivePsd" runat="server" Text="Submit"/>
<p>Your layers will appear here as PNGs</p>
<asp:Literal ID="litPsdLayerImages" runat="server" />
</div>
</form>
</body>
</html>
30 changes: 30 additions & 0 deletions Web.config
@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.5" />
</system.Web>
-->
<system.web>
<compilation targetFramework="4.5"/>
<httpRuntime/>
<pages controlRenderingCompatibilityVersion="4.0"/>
</system.web>
<appSettings>
<add key="psdLayersOutput" value="~\psdLayersOutput\" />
</appSettings>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" compilerOptions="/unsafe" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v4.0" />
</compiler>
</compilers>
</system.codedom>
</configuration>
227 changes: 227 additions & 0 deletions bin/App_Code/1bpp.cs
@@ -0,0 +1,227 @@
using System;


namespace PhotoshopFiles
{
internal class ImageBitChanger
{
//static void Main(string[] args)
//{
// System.Drawing.Bitmap b = new System.Drawing.Bitmap("test.jpg");
// SplashImage(b, 0, 0);
// //
// DateTime dtFaq = DateTime.Now;
// System.Drawing.Bitmap b0 = CopyToBpp(b, 1);
// TimeSpan tsFaq = DateTime.Now - dtFaq;
// Console.WriteLine("GDI conversion time: " + tsFaq.ToString());
// SplashImage(b0, 200, 100);
// //
// DateTime dtLu = DateTime.Now;
// System.Drawing.Bitmap b1 = FaqCopyTo1bpp(b);
// TimeSpan tsLu = DateTime.Now - dtLu;
// Console.WriteLine("FAQ conversion time: " + tsLu.ToString());
// SplashImage(b1, 400, 200);
// //
// System.Threading.Thread.Sleep(1000);
// InvalidateRect(IntPtr.Zero, IntPtr.Zero, 1);
//}


/// <summary>
/// Copies a bitmap into a 1bpp/8bpp bitmap of the same dimensions, fast
/// </summary>
/// <param name="b">original bitmap</param>
/// <param name="bpp">1 or 8, target bpp</param>
/// <returns>a 1bpp copy of the bitmap</returns>
internal static System.Drawing.Bitmap CopyToBpp(System.Drawing.Bitmap b, int bpp)
{
//System.Drawing.Bitmap b = new System.Drawing.Bitmap(img);

if (bpp != 1 && bpp != 8) throw new System.ArgumentException("1 or 8", "bpp");

// Plan: built into Windows GDI is the ability to convert
// bitmaps from one format to another. Most of the time, this
// job is actually done by the graphics hardware accelerator card
// and so is extremely fast. The rest of the time, the job is done by
// very fast native code.
// We will call into this GDI functionality from C#. Our plan:
// (1) Convert our Bitmap into a GDI hbitmap (ie. copy unmanaged->managed)
// (2) Create a GDI monochrome hbitmap
// (3) Use GDI "BitBlt" function to copy from hbitmap into monochrome (as above)
// (4) Convert the monochrone hbitmap into a Bitmap (ie. copy unmanaged->managed)

int w = b.Width, h = b.Height;
IntPtr hbm = b.GetHbitmap(); // this is step (1)
//
// Step (2): create the monochrome bitmap.
// "BITMAPINFO" is an interop-struct which we define below.
// In GDI terms, it's a BITMAPHEADERINFO followed by an array of two RGBQUADs
BITMAPINFO bmi = new BITMAPINFO();
bmi.biSize = 40; // the size of the BITMAPHEADERINFO struct
bmi.biWidth = w;
bmi.biHeight = h;
bmi.biPlanes = 1; // "planes" are confusing. We always use just 1. Read MSDN for more info.
bmi.biBitCount = (short)bpp; // ie. 1bpp or 8bpp
bmi.biCompression = BI_RGB; // ie. the pixels in our RGBQUAD table are stored as RGBs, not palette indexes
bmi.biSizeImage = (uint)(((w + 7) & 0xFFFFFFF8) * h / 8);
bmi.biXPelsPerMeter = 1000000; // not really important
bmi.biYPelsPerMeter = 1000000; // not really important
// Now for the colour table.
uint ncols = (uint)1 << bpp; // 2 colours for 1bpp; 256 colours for 8bpp
bmi.biClrUsed = ncols;
bmi.biClrImportant = ncols;
bmi.cols = new uint[256]; // The structure always has fixed size 256, even if we end up using fewer colours
if (bpp == 1) { bmi.cols[0] = MAKERGB(0, 0, 0); bmi.cols[1] = MAKERGB(255, 255, 255); }
else { for (int i = 0; i < ncols; i++) bmi.cols[i] = MAKERGB(i, i, i); }
// For 8bpp we've created an palette with just greyscale colours.
// You can set up any palette you want here. Here are some possibilities:
// greyscale: for (int i=0; i<256; i++) bmi.cols[i]=MAKERGB(i,i,i);
// rainbow: bmi.biClrUsed=216; bmi.biClrImportant=216; int[] colv=new int[6]{0,51,102,153,204,255};
// for (int i=0; i<216; i++) bmi.cols[i]=MAKERGB(colv[i/36],colv[(i/6)%6],colv[i%6]);
// optimal: a difficult topic: http://en.wikipedia.org/wiki/Color_quantization
//
// Now create the indexed bitmap "hbm0"
IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
IntPtr hbm0 = CreateDIBSection(IntPtr.Zero, ref bmi, DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0);
//
// Step (3): use GDI's BitBlt function to copy from original hbitmap into monocrhome bitmap
// GDI programming is kind of confusing... nb. The GDI equivalent of "Graphics" is called a "DC".
IntPtr sdc = GetDC(IntPtr.Zero); // First we obtain the DC for the screen
// Next, create a DC for the original hbitmap
IntPtr hdc = CreateCompatibleDC(sdc); SelectObject(hdc, hbm);
// and create a DC for the monochrome hbitmap
IntPtr hdc0 = CreateCompatibleDC(sdc); SelectObject(hdc0, hbm0);
// Now we can do the BitBlt:
BitBlt(hdc0, 0, 0, w, h, hdc, 0, 0, SRCCOPY);
// Step (4): convert this monochrome hbitmap back into a Bitmap:
System.Drawing.Bitmap b0 = System.Drawing.Bitmap.FromHbitmap(hbm0);
//
// Finally some cleanup.
DeleteDC(hdc);
DeleteDC(hdc0);
ReleaseDC(IntPtr.Zero, sdc);
DeleteObject(hbm);
DeleteObject(hbm0);
//
return b0;
}

/// <summary>
/// Draws a bitmap onto the screen. Note: this will be overpainted
/// by other windows when they come to draw themselves. Only use it
/// if you want to draw something quickly and can't be bothered with forms.
/// </summary>
/// <param name="b">the bitmap to draw on the screen</param>
/// <param name="x">x screen coordinate</param>
/// <param name="y">y screen coordinate</param>
static void SplashImage(System.Drawing.Bitmap b, int x, int y)
{ // Drawing onto the screen is supported by GDI, but not by the Bitmap/Graphics class.
// So we use interop:
// (1) Copy the Bitmap into a GDI hbitmap
IntPtr hbm = b.GetHbitmap();
// (2) obtain the GDI equivalent of a "Graphics" for the screen
IntPtr sdc = GetDC(IntPtr.Zero);
// (3) obtain the GDI equivalent of a "Graphics" for the hbitmap
IntPtr hdc = CreateCompatibleDC(sdc);
SelectObject(hdc, hbm);
// (4) Draw from the hbitmap's "Graphics" onto the screen's "Graphics"
BitBlt(sdc, x, y, b.Width, b.Height, hdc, 0, 0, SRCCOPY);
// and do boring GDI cleanup:
DeleteDC(hdc);
ReleaseDC(IntPtr.Zero, sdc);
DeleteObject(hbm);
}


[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int InvalidateRect(IntPtr hwnd, IntPtr rect, int bErase);

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hwnd);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int DeleteDC(IntPtr hdc);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int BitBlt(IntPtr hdcDst, int xDst, int yDst, int w, int h, IntPtr hdcSrc, int xSrc, int ySrc, int rop);
static int SRCCOPY = 0x00CC0020;

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
static uint BI_RGB = 0;
static uint DIB_RGB_COLORS = 0;
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct BITMAPINFO
{
public uint biSize;
public int biWidth, biHeight;
public short biPlanes, biBitCount;
public uint biCompression, biSizeImage;
public int biXPelsPerMeter, biYPelsPerMeter;
public uint biClrUsed, biClrImportant;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 256)]
public uint[] cols;
}

static uint MAKERGB(int r, int g, int b)
{
return ((uint)(b & 255)) | ((uint)((r & 255) << 8)) | ((uint)((g & 255) << 16));
}


/// <summary>
/// Copies a bitmap into a 1bpp bitmap of the same dimensions, slowly, using code from Bob Powell's GDI+ faq http://www.bobpowell.net/onebit.htm
/// </summary>
/// <param name="b">original bitmap</param>
/// <returns>a 1bpp copy of the bitmap</returns>
static System.Drawing.Bitmap FaqCopyTo1bpp(System.Drawing.Bitmap b)
{
int w = b.Width, h = b.Height; System.Drawing.Rectangle r = new System.Drawing.Rectangle(0, 0, w, h);
if (b.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
{
System.Drawing.Bitmap temp = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(temp);
g.DrawImage(b, r, 0, 0, w, h, System.Drawing.GraphicsUnit.Pixel);
g.Dispose(); b = temp;
}
System.Drawing.Imaging.BitmapData bdat = b.LockBits(r, System.Drawing.Imaging.ImageLockMode.ReadOnly, b.PixelFormat);
System.Drawing.Bitmap b0 = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
System.Drawing.Imaging.BitmapData b0dat = b0.LockBits(r, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int index = y * bdat.Stride + (x * 4);
if (System.Drawing.Color.FromArgb(System.Runtime.InteropServices.Marshal.ReadByte(bdat.Scan0, index + 2), System.Runtime.InteropServices.Marshal.ReadByte(bdat.Scan0, index + 1), System.Runtime.InteropServices.Marshal.ReadByte(bdat.Scan0, index)).GetBrightness() > 0.5f)
{
int index0 = y * b0dat.Stride + (x >> 3);
byte p = System.Runtime.InteropServices.Marshal.ReadByte(b0dat.Scan0, index0);
byte mask = (byte)(0x80 >> (x & 0x7));
System.Runtime.InteropServices.Marshal.WriteByte(b0dat.Scan0, index0, (byte)(p | mask));
}
}
}
b0.UnlockBits(b0dat);
b.UnlockBits(bdat);
return b0;
}


//internal static void CopyToBpp(string p, int p_2)
//{
// CopyToBpp(p, p_2);
//}
}
}
78 changes: 78 additions & 0 deletions bin/App_Code/AlphaChannels.cs
@@ -0,0 +1,78 @@
/////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2006, Frank Blumenberg
//
// See License.txt for complete licensing and attribution information.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
/////////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;

namespace PhotoshopFiles
{
/// <summary>
/// The names of the alpha channels
/// </summary>
public class AlphaChannels : ImageResource
{
private List<string> m_channelNames = new List<string>();
public List<string> ChannelNames
{
get { return m_channelNames; }
}

public AlphaChannels()
: base((short)ResourceIDs.AlphaChannelNames)
{
}

public AlphaChannels(ImageResource imgRes)
: base(imgRes)
{

BinaryReverseReader reader = imgRes.DataReader;
// the names are pascal strings without padding!!!
while ((reader.BaseStream.Length - reader.BaseStream.Position) > 0)
{
byte stringLength = reader.ReadByte();
string s = new string(reader.ReadChars(stringLength));
if (s.Length > 0)
m_channelNames.Add(s);
}
reader.Close();
}

protected override void StoreData()
{
System.IO.MemoryStream stream = new System.IO.MemoryStream();
BinaryReverseWriter writer = new BinaryReverseWriter(stream);

foreach (string name in m_channelNames)
{
writer.Write((byte)name.Length);
writer.Write(name.ToCharArray());
}

writer.Close();
stream.Close();

Data = stream.ToArray();
}
}
}

0 comments on commit 78da6c2

Please sign in to comment.