methods classes and objects - class

I don't know what my error is I am not understanding classes
I have read a java book but its not helpful
classes codes and methods confuse me and though you figuring out my code i will have a better understanding of what those things actually do
public double intoxicated(double weight)
{
double numDrinks;
numDrinks = (0.08 + 0.015) * weight /
(12 * 7.5 * alcohol);
return numDrinks;
}
public class Beer
{
private String name;
private double alcohol;
public String getName(){
return name;
}
public void setName(String n)
{
this.name= name;
}
public double getAlcohol()
{
return Alcohol;
}
public void setAlcohol(double a)
{
this.age = age;
}
public double intoxicated(double weight)
{
double numDrinks;
numDrinks = (0.08 + 0.015) * weight /
(12 * 7.5 * alcohol);
return numDrinks;
}
public static void main(String[] args)
{
Beer beer1 = new Beer();
Beer beer2 = new Beer();
beer1.setName("Cors Light");
beer1.setAlcohol(0.042);
beer2.setName("Heinaken");
beer2.setAlcohol(0.042);
double lightWeight = 100.0;
double heavyWeight = 250.0;
double lightDrinks1 = beer1.intoxicated(lightWeight);
System.out.println("The number of " + beer1.getName() +
" drinks needed to make\na person weighing " +
lightWeight + " pounds intoxicated is " + lightDrinks1);
System.out.println();
double heavyDrinks1 = beer1.intoxicated(heavyWeight);
System.out.println("The number of " + beer1.getName() +
" drinks needed to make\na person weighing " +
heavyWeight + " pounds intoxicated is " + heavyDrinks1);
System.out.println();
double lightDrinks2 = beer2.intoxicated(lightWeight);
System.out.println("The number of " + beer2.getName() +
" drinks needed to make\na person weighing " +
lightWeight + " pounds intoxicated is " + lightDrinks2);
System.out.println();
double heavyDrinks2 = beer2.intoxicated(heavyWeight);
System.out.println("The number of " + beer2.getName() +
" drinks needed to make\na person weighing " +
heavyWeight + " pounds intoxicated is " + heavyDrinks2);
System.out.println();
Beer beer3 = new Beer();
beer3.setName("Miller Genuine Draft Light");
beer3.setAlcohol(0.042); // 4.2% alcohol
lightWeight = 100.0;
heavyWeight = 250.0;
double lightDrinks3 = beer3.intoxicated(lightWeight);
System.out.println("The number of " + beer3.getName() +
" drinks needed to make\na person weighing " +
lightWeight + " pounds intoxicated is " + lightDrinks3);
System.out.println();
double heavyDrinks3 = beer3.intoxicated(heavyWeight);
System.out.println("The number of " + beer3.getName() +
" drinks needed to make\na person weighing " +
heavyWeight + " pounds intoxicated is " + heavyDrinks3);
System.out.println();
}
}

Related

Why does my plugin not give a name to the item?

I've tried everything, but with this code, the items I get for killing a player will have their base Minecraft name, why? I've tried everything. Could another plugin be blocking it? What could be the problem?
Java, intellijidea, 1.8 Code:
public class killitem implements Listener {
private random plugin = random.getPlugin(random.class);
#EventHandler
public void onPlayerDeath(PlayerDeathEvent e) {
Player player = e.getEntity();
Player killer = player.getKiller();
//Enderpearl
ItemStack is = new ItemStack(Material.ENDER_PEARL);
ItemMeta meta = is.getItemMeta();
meta.setDisplayName("" + ChatColor.GOLD + ChatColor.YELLOW + ChatColor.BOLD + "Véggyöngy");
ArrayList<String> lore = new ArrayList();
//Blaze rod
ItemStack is2 = new ItemStack(Material.BLAZE_ROD);
ItemMeta meta2 = is2.getItemMeta();
meta.setDisplayName("" + ChatColor.GOLD + ChatColor.DARK_RED + ChatColor.BOLD + "Mentőrúd");
ArrayList<String> lore2 = new ArrayList();
lore.add("|" + ChatColor.RED + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Feltölti " + ChatColor.RED + "teljesen " + ChatColor.GRAY + "az életedet!");
meta.setLore(lore2);
is2.setItemMeta(meta2);
//Csillag
ItemStack is3 = new ItemStack(Material.NETHER_STAR);
ItemMeta meta3 = is3.getItemMeta();
meta.setDisplayName("" + ChatColor.DARK_GREEN + ChatColor.BOLD + "Második Esély");
ArrayList<String> lore3 = new ArrayList();
lore.add("|" + ChatColor.GREEN + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Feldob " + ChatColor.RED + "60 " + ChatColor.GRAY + "blokk magasra!");
meta.setLore(lore3);
//Toll
ItemStack is4 = new ItemStack(Material.FEATHER);
ItemMeta meta4 = is4.getItemMeta();
meta.setDisplayName("" + ChatColor.AQUA + ChatColor.BOLD + "Speed");
ArrayList<String> lore4 = new ArrayList();
lore.add("|" + ChatColor.AQUA + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Speed 4-et kapsz " + ChatColor.AQUA + "10 " + ChatColor.GRAY + "másodpercre!");
meta.setLore(lore4);
//Quartz
ItemStack is5 = new ItemStack(Material.QUARTZ);
ItemMeta meta5 = is5.getItemMeta();
meta.setDisplayName("" + ChatColor.RED + ChatColor.BOLD + "Instant Health");
ArrayList<String> lore5 = new ArrayList();
lore.add("|" + ChatColor.RED + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Feltölti " + ChatColor.RED + "teljesen " + ChatColor.GRAY + "az életed!");
meta.setLore(lore5);
//Aranyalma
ItemStack is6 = new ItemStack(Material.GOLDEN_APPLE);
ItemMeta meta6 = is6.getItemMeta();
meta.setDisplayName("" + ChatColor.YELLOW + "Aranyalma");
ArrayList<String> lore6 = new ArrayList();
int upper = 5;
Random random = new Random();
random.nextInt(5 + (upper));
if (player.isDead()) {
player.getKiller();
if (player.getKiller() instanceof Player) {
random.nextInt(5 + (upper));
if (random.nextInt(5 + (upper)) == 6) {
killer.getInventory().addItem(is2);
is2.setItemMeta(meta2);
} else if (random.nextInt(5 + (upper)) == 7) {
killer.getInventory().addItem(is3);
is3.setItemMeta(meta3);
} else if (random.nextInt(5 + (upper)) == 8) {
killer.getInventory().addItem(is4);
is4.setItemMeta(meta4);
} else if (random.nextInt(5 + (upper)) == 9) {
killer.getInventory().addItem(is);
killer.getInventory().addItem(is6);
is6.setItemMeta(meta6);
is.setItemMeta(meta);
}
} else if (random.nextInt(5 + (upper)) == 10) {
}
}
}
}
okay try to first setItemMeta and then give it
if (random.nextInt(5 + (upper)) == 6) {
is2.setItemMeta(meta2);//like this
killer.getInventory().addItem(is2);
Try using this:
public class killitem implements Listener {
private random plugin = random.getPlugin(random.class);
#EventHandler
public void onPlayerDeath(PlayerDeathEvent e) {
bukkit.getscheduler().runTask(plugin, ()->giveItemForKiller(e));
}
private void giveItemForKiller(PlayerDeathEvent e) {
Player player = e.getEntity();
Player killer = player.getKiller();
//Enderpearl
ItemStack is = new ItemStack(Material.ENDER_PEARL);
ItemMeta meta = is.getItemMeta();
meta.setDisplayName("" + ChatColor.GOLD + ChatColor.YELLOW + ChatColor.BOLD + "Véggyöngy");
ArrayList<String> lore = new ArrayList();
//Blaze rod
ItemStack is2 = new ItemStack(Material.BLAZE_ROD);
ItemMeta meta2 = is2.getItemMeta();
meta.setDisplayName("" + ChatColor.GOLD + ChatColor.DARK_RED + ChatColor.BOLD + "Mentőrúd");
ArrayList<String> lore2 = new ArrayList();
lore.add("|" + ChatColor.RED + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Feltölti " + ChatColor.RED + "teljesen " + ChatColor.GRAY + "az életedet!");
meta.setLore(lore2);
is2.setItemMeta(meta2);
//Csillag
ItemStack is3 = new ItemStack(Material.NETHER_STAR);
ItemMeta meta3 = is3.getItemMeta();
meta.setDisplayName("" + ChatColor.DARK_GREEN + ChatColor.BOLD + "Második Esély");
ArrayList<String> lore3 = new ArrayList();
lore.add("|" + ChatColor.GREEN + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Feldob " + ChatColor.RED + "60 " + ChatColor.GRAY + "blokk magasra!");
meta.setLore(lore3);
//Toll
ItemStack is4 = new ItemStack(Material.FEATHER);
ItemMeta meta4 = is4.getItemMeta();
meta.setDisplayName("" + ChatColor.AQUA + ChatColor.BOLD + "Speed");
ArrayList<String> lore4 = new ArrayList();
lore.add("|" + ChatColor.AQUA + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Speed 4-et kapsz " + ChatColor.AQUA + "10 " + ChatColor.GRAY + "másodpercre!");
meta.setLore(lore4);
//Quartz
ItemStack is5 = new ItemStack(Material.QUARTZ);
ItemMeta meta5 = is5.getItemMeta();
meta.setDisplayName("" + ChatColor.RED + ChatColor.BOLD + "Instant Health");
ArrayList<String> lore5 = new ArrayList();
lore.add("|" + ChatColor.RED + "Jobb klikk: |" + ChatColor.DARK_GRAY + " ▪ " + ChatColor.GRAY + "Feltölti " + ChatColor.RED + "teljesen " + ChatColor.GRAY + "az életed!");
meta.setLore(lore5);
//Aranyalma
ItemStack is6 = new ItemStack(Material.GOLDEN_APPLE);
ItemMeta meta6 = is6.getItemMeta();
meta.setDisplayName("" + ChatColor.YELLOW + "Aranyalma");
ArrayList<String> lore6 = new ArrayList();
int upper = 5;
Random random = new Random();
random.nextInt(5 + (upper));
if (player.isDead()) {
player.getKiller();
if (player.getKiller() instanceof Player) {
random.nextInt(5 + (upper));
if (random.nextInt(5 + (upper)) == 6) {
killer.getInventory().addItem(is2);
is2.setItemMeta(meta2);
} else if (random.nextInt(5 + (upper)) == 7) {
killer.getInventory().addItem(is3);
is3.setItemMeta(meta3);
} else if (random.nextInt(5 + (upper)) == 8) {
killer.getInventory().addItem(is4);
is4.setItemMeta(meta4);
} else if (random.nextInt(5 + (upper)) == 9) {
killer.getInventory().addItem(is);
killer.getInventory().addItem(is6);
is6.setItemMeta(meta6);
is.setItemMeta(meta);
}
} else if (random.nextInt(5 + (upper)) == 10) {
}
}
}
}

Complex Class, mutliply & divide not working

I have first listed my class code, then my tester/driver code and have put my questions at the bottom. My code for my class is as follows :
class Complex {
//data values
private double real;
private double imag;
//constructors
public Complex () {
real = 0;
imag = 0;
}
public Complex (double realInput) {
real = realInput;
imag = 0;
}
public Complex (double realInput, double imagInput) {
real = realInput;
imag = imagInput;
}
//accessors
public double getReal () {
return real;
}
public double getImag () {
return imag;
}
//modifiers
public void setReal (double inputReal) {
real = inputReal;
}
public void setImag (double inputImag) {
imag = inputImag;
}
//toString method
public String toString() {
return real + " + " + imag + "i";
}
//instance methods
//addition methods
public Complex add (double realInput) {
real = real + realInput;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
public Complex add (Complex complex) {
double firstReal = complex.getReal();
double firstImag = complex.getImag();
double secondReal = this.getReal();
double secondImag = this.getImag();
real = firstReal + secondReal;
imag = firstImag + secondImag;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
//subtraction methods
public Complex subtract (double realInput) {
real = real - realInput;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
public Complex subtract (Complex complex) {
double newReal = complex.getReal();
double newImag = complex.getImag();
real = this.getReal() - newReal;
imag = this.getImag() - newImag;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
//multiplication methods
public Complex multiply (double realInput) {
real = real * realInput;
imag = imag * realInput;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
//****problem code****
public Complex multiply (Complex complex) {
double newReal = complex.getReal();
double newImag = complex.getImag();
real = ((real * newReal) - (imag * newImag));
imag = ((real * newImag) + (imag * newReal));
Complex newComplex = new Complex(real, imag);
return newComplex;
}
//division methods
public Complex divide (double realInput) {
real = real / realInput;
imag = imag / realInput;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
//****problem code****
public Complex divide (Complex complex) {
double newReal = complex.getReal();
double newImag = complex.getImag();
real = this.getReal();
imag = this.getImag();
double newRealNumerator = (real * newReal) + (imag * newImag);
double newRealDenominator = (Math.pow(newReal, 2) + Math.pow(newImag, 2));
real = newRealNumerator / newRealDenominator;
double newImagNumerator = (imag * newReal) - (real * newImag);
double newImagDenominator = newRealDenominator;
imag = newImagNumerator / newImagDenominator;
Complex newComplex = new Complex(real, imag);
return newComplex;
}
//equals method
public boolean equals (Complex complex) {
double firstReal = complex.getReal();
double firstImag = complex.getImag();
double secondReal = this.getReal();
double secondImag = this.getImag();
boolean testEquals = false;
if (firstReal == secondReal && firstImag == secondImag) {
testEquals = true;
}
return testEquals;
}
}//end class
My code for my tester/driver is as follows:
class ComplexTester {
public static void main(String[] args ) {
//declaring Complex objects
Complex one = new Complex ();
Complex two = new Complex (3);
Complex three = new Complex (1, 4);
Complex four = new Complex (2, 3);
//testing addition methods
System.out.println("Testing addition methods...");
System.out.println("(" + three.toString() + ") + (" + 3.0 + ") = " + three.add(3.0));
three.setReal(1);
three.setImag(4);
System.out.println("(" + three.toString() + ") + (" + four.toString() + ") = " + three.add(four));
three.setReal(1);
three.setImag(4);
//testing subtraction methods
System.out.println();
System.out.println("Testing subtraction methods...");
System.out.println("(" + three.toString() + ") - (" + 3.0 + ") = " + three.subtract(3.0));
three.setReal(1);
three.setImag(4);
System.out.println("(" + three.toString() + ") - (" + four.toString() + ") = " + three.subtract(four));
three.setReal(1);
three.setImag(4);
//testing multiplication methods
System.out.println();
System.out.println("Testing multiplication methods...");
System.out.println("(" + three.toString() + ") * (" + 3.0 + ") = " + three.multiply(3.0));
three.setReal(1);
three.setImag(4);
System.out.println("(" + three.toString() + ") * (" + four.toString() + ") = " + three.multiply(four));
three.setReal(6);
three.setImag(3);
//testing division method
System.out.println();
System.out.println("Testing division methods...");
System.out.println("(" + three.toString() + ") / (" + 3.0 + ") = " + three.divide(3.0));
three.setReal(4);
three.setImag(2);
Complex testDiv = new Complex(3, -1);
System.out.println("(" + three.toString() + ") / (" + testDiv.toString() + ") = " + three.divide(testDiv));
three.setReal(1);
three.setImag(4);
//testing equals method
System.out.println();
System.out.println("Testing equals method...");
if (three.equals(four) == true) {
System.out.println(three.toString() + " is equal to " + four.toString());
}
else {
System.out.println(three.toString() + " is not equal to " + four.toString());
}
Complex testEquals = new Complex(2, 3);
if (four.equals(testEquals) == true) {
System.out.println(four.toString() + " is equal to " + testEquals.toString());
}
else {
System.out.println(four.toString() + " is not equal to " + testEquals.toString());
}
}// end main method
}// end class
My first problem is that if I would call my add method on the three object [such as three.add(four) ] it completely changes the three object to the answer of three.add(four). What I did to get around that (and I'm assuming it's bad programming) is call the set methods to assign the three object back to what I needed.
My second problem is that the multiply and divide methods (that I have commented above with "****problem code****") are not reporting the correct complex number. The multiply problem code should show (-10.0 + 11.0i) in the tester but instead it shows (-10.0 + -22.0i) upon running. The divide problem code should show (1.0 + 1.0i) but instead it shows (1.0 + 0.7i) upon running.
To multiply a complex number by another complex number the formula is: (A + Bi) times (C + Di) = (AC - BD) + (AD + BC)i
To divide a complex number by another complex number the formula is: (A + Bi) divided by (C + Di) = (AC+BD)/(C2 + D2) + (BC-AD)/(C2 + D2)i
My key to convert from the letters of the formulas listed (A, B, C, D) and my own self-named variables is: A = real, B = imag, C = newReal, and D = newImag
real = ((real * newReal) - (imag * newImag));
imag = ((real * newImag) + (imag * newReal));
This updates your instance variable real and you are using this updated real variable in the calculation of imaginary part of the complex variable which is obviously wrong.
Your code should be like this.
public Complex multiply (Complex complex) {
double newReal = complex.getReal();
double newImag = complex.getImag();
double real = ((this.real * newReal) - (this.imag * newImag));
double imag = ((this.real * newImag) + (this.imag * newReal));
Complex newComplex = new Complex(real, imag);
return newComplex;
}

Netbeans Java illegal public static void with compiling?

The below throws an error for in public static void DemoMethod(). Why?
package demoblock;
/**
*
* #author coleen
*/
public class DemoBlock {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Demontrating block scope");
int x = 1111;
System.out.print("in first block x is" + x);
{
int y = 2222;
System.out.println(" In second block x is " + x);
System.out.println(" In seond block y is " + y);
}
{
int y = 3333;
System.out.println(" In third block x is " + x);
System.out.println(" In third block y is " + y);
DemoMethod();
System.out.println(" After method x is " + x);
System.out.println(" After method block y is " + y);
System.out.println(" At the end x is " + x);
public static void DemoMethod()
{
int x = 8888;
int y = 9999;
System.out.println(" In demoMethod x is " + x);
System.out.println(" In DemoMethod block y is " + y);
}
}
/** * * #author coleen */
public class DemoBlock
{
/**
* #param args
* the command line arguments
*/
public static void main( String[] args )
{
System.out.println( "Demontrating block scope" );
int x = 1111;
System.out.print( "in first block x is" + x );
{
int y = 2222;
System.out.println( " In second block x is " + x );
System.out.println( " In seond block y is " + y );
}
{
int y = 3333;
System.out.println( " In third block x is " + x );
System.out.println( " In third block y is " + y );
DemoMethod();
System.out.println( " After method x is " + x );
System.out.println( " After method block y is " + y );
System.out.println( " At the end x is " + x );
}
}
public static void DemoMethod()
{
int x = 8888;
int y = 9999;
System.out.println( " In demoMethod x is " + x );
System.out.println( " In DemoMethod block y is " + y );
}
}

User input with linear and binary searching in java

I'm trying to write a program that asks the user to input the size of the array the user wants to create, and then asks the user to fill the array with elements, and then it should display the array with its elements and, ask the user to conduct a search for an integer. It should conduct a linear and binary search, while displaying how many probes it took to determine is the element is in the array. So far the only output i have gotten is that the element has not been found. If you could look at my code and see what the problem is, because i have tried for hours and i have changed everything i can think of. Any help would be greatly appreciated.
import java.util.Scanner;
public class Searching
{
public static int[] anArray = new int[100];
private int numberOfElements;
public int arraySize = numberOfElements;
public String linearSearch(int value)
{
int count = 0;
boolean valueInArray = false;
String indexOfValue = "";
System.out.print("The Value was Found in: ");
for(int i = 0; i < arraySize; i++)
{
if(anArray[i] == value)
{
valueInArray = true;
System.out.print(i + " ");
indexOfValue += i + " ";
}
count ++;
}
if(!valueInArray)
{
indexOfValue = " None found";
System.out.print(indexOfValue);
}
System.out.println("\nIt took " + count + " probes with a linear search to find");
return indexOfValue;
}
public void binarySearch(int value)
{
int min = 0;
int max = arraySize - 1;
int count = 0;
while(min <= max)
{
int mid = (max + min) / 2;
if(anArray[mid] < value) min = mid + 1;
else if(anArray[mid] > value) max = mid - 1;
else
{
System.out.println("\nFound a Match for " + value + " at Index " + mid);
min = max + 1;
}
count ++;
}
System.out.println("It took " + count + " probes with a binary search to find");
}
public static void main(String[] args)
{
#SuppressWarnings("resource")
Scanner scan = new Scanner(System.in);
System.out.println("Input the number of elements in your Array");
int numberOfElements = scan.nextInt();
if(numberOfElements <= 0)
{
System.exit(0);
}
int[] anArray = new int[numberOfElements];
System.out.println("\nEnter " + numberOfElements + " Integers");
for(int i = 0; i < anArray.length; i ++)
{
System.out.println("Int # " + (i + 1) + ": ");
anArray[i] = scan.nextInt();
}
System.out.println("\nThe integers you entered are: ");
for(int i = 0; i < anArray.length; i ++) // for loop used to print out each element on a different line
{
System.out.println(anArray[i]);
}
System.out.println("Which element would you like to find?");
int value = scan.nextInt();
Wee3Q2JOSHBALBOA newArray = new Wee3Q2JOSHBALBOA();
newArray.linearSearch(3);
newArray.binarySearch(value);
}
}
hmm I am not sure you are using an array the correct way, you see an Array is a set size and I dont think you can expand like they way you are doing...
Instead try setting the size of the array to certain length.
Or use vectors

How to save an SDL surface to a PNG and get the colors right?

I wrote up a simple patch to add PNG-saving capabilities to the SDL_Image library. It almost works, too. Problem is, the colors come out all scrambled, and I don't know enough C to figure out what's wrong. Can anyone take a look at this and help me fix it up?
Use case:
Load a 256-color PNG image with IMG_LoadPNG_RW.
Save it with IMG_SavePNG_RW.
See if they're identical or not.
Patch:
Index: IMG_png.c
===================================================================
--- IMG_png.c (revision 4475)
+++ IMG_png.c (working copy)
## -76,17 +76,25 ##
png_infop (*png_create_info_struct) (png_structp png_ptr);
png_structp (*png_create_read_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn);
void (*png_destroy_read_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr);
+ png_structp (*png_create_write_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn);
+ void (*png_destroy_write_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr);
png_uint_32 (*png_get_IHDR) (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method);
+ void (*png_set_IHDR) (png_structp png_ptr, png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int interlace_method, int compression_method, int filter_method);
png_voidp (*png_get_io_ptr) (png_structp png_ptr);
png_uint_32 (*png_get_tRNS) (png_structp png_ptr, png_infop info_ptr, png_bytep *trans, int *num_trans, png_color_16p *trans_values);
png_uint_32 (*png_get_valid) (png_structp png_ptr, png_infop info_ptr, png_uint_32 flag);
void (*png_read_image) (png_structp png_ptr, png_bytepp image);
+ void (*png_write_image) (png_structp png_ptr, png_bytepp image);
void (*png_read_info) (png_structp png_ptr, png_infop info_ptr);
+ void (*png_write_info) (png_structp png_ptr, png_infop info_ptr);
+ void (*png_set_PLTE) (png_structp png_ptr, png_infop info_ptr, png_colorp palette, int num_palette);
+ void (*png_write_end) (png_structp png_ptr, png_infop info_ptr);
void (*png_read_update_info) (png_structp png_ptr, png_infop info_ptr);
void (*png_set_expand) (png_structp png_ptr);
void (*png_set_gray_to_rgb) (png_structp png_ptr);
void (*png_set_packing) (png_structp png_ptr);
void (*png_set_read_fn) (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn);
+ void (*png_set_write_fn) (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn);
void (*png_set_strip_16) (png_structp png_ptr);
int (*png_sig_cmp) (png_bytep sig, png_size_t start, png_size_t num_to_check);
} lib;
## -120,6 +128,20 ##
SDL_UnloadObject(lib.handle);
return -1;
}
+ lib.png_create_write_struct =
+ (png_structp (*) (png_const_charp, png_voidp, png_error_ptr, png_error_ptr))
+ SDL_LoadFunction(lib.handle, "png_create_write_struct");
+ if ( lib.png_create_write_struct == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
+ lib.png_destroy_write_struct =
+ (void (*) (png_structpp, png_infopp))
+ SDL_LoadFunction(lib.handle, "png_destroy_write_struct");
+ if ( lib.png_destroy_write_struct == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
lib.png_get_IHDR =
(png_uint_32 (*) (png_structp, png_infop, png_uint_32 *, png_uint_32 *, int *, int *, int *, int *, int *))
SDL_LoadFunction(lib.handle, "png_get_IHDR");
## -127,6 +149,13 ##
SDL_UnloadObject(lib.handle);
return -1;
}
+ lib.png_set_IHDR =
+ (void (*) (png_structp, png_infop, png_uint_32, png_uint_32, int, int, int, int, int))
+ SDL_LoadFunction(lib.handle, "png_set_IHDR");
+ if ( lib.png_set_IHDR == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
lib.png_get_io_ptr =
(png_voidp (*) (png_structp))
SDL_LoadFunction(lib.handle, "png_get_io_ptr");
## -155,6 +184,13 ##
SDL_UnloadObject(lib.handle);
return -1;
}
+ lib.png_write_image =
+ (void (*) (png_structp, png_bytepp))
+ SDL_LoadFunction(lib.handle, "png_write_image");
+ if ( lib.png_write_image == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
lib.png_read_info =
(void (*) (png_structp, png_infop))
SDL_LoadFunction(lib.handle, "png_read_info");
## -162,6 +198,27 ##
SDL_UnloadObject(lib.handle);
return -1;
}
+ lib.png_write_info =
+ (void (*) (png_structp, png_infop))
+ SDL_LoadFunction(lib.handle, "png_write_info");
+ if ( lib.png_write_info == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
+ lib.png_set_PLTE =
+ (void (*) (png_structp, png_infop, png_colorp, int))
+ SDL_LoadFunction(lib.handle, "png_set_PLTE");
+ if ( lib.png_set_PLTE == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
+ lib.png_write_end =
+ (void (*) (png_structp, png_infop))
+ SDL_LoadFunction(lib.handle, "png_write_end");
+ if ( lib.png_write_end == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
lib.png_read_update_info =
(void (*) (png_structp, png_infop))
SDL_LoadFunction(lib.handle, "png_read_update_info");
## -197,6 +254,13 ##
SDL_UnloadObject(lib.handle);
return -1;
}
+ lib.png_set_write_fn =
+ (void (*) (png_structp, png_voidp, png_rw_ptr))
+ SDL_LoadFunction(lib.handle, "png_set_write_fn");
+ if ( lib.png_set_write_fn == NULL ) {
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
lib.png_set_strip_16 =
(void (*) (png_structp))
SDL_LoadFunction(lib.handle, "png_set_strip_16");
## -472,7 +536,7 ##
palette->colors[i].g = i;
palette->colors[i].b = i;
}
- } else if (info_ptr->num_palette > 0 ) {
+ } else if (info_ptr->num_palette > 0 ) {
palette->ncolors = info_ptr->num_palette;
for( i=0; i<info_ptr->num_palette; ++i ) {
palette->colors[i].b = info_ptr->palette[i].blue;
## -505,18 +569,167 ##
return(surface);
}
-#else
+static void png_write_data(png_structp ctx, png_bytep area, png_size_t size)
+{
+ SDL_RWops *src;
-/* See if an image is contained in a data source */
-int IMG_isPNG(SDL_RWops *src)
+ src = (SDL_RWops *)lib.png_get_io_ptr(ctx);
+ SDL_RWwrite(src, area, size, 1);
+}
+/* write a png file */
+int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *src)
{
- return(0);
-}
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_colorp palette = NULL;
+ int start;
+ int colorType;
+ int i;
+ const char *error;
+ SDL_Palette *sdlPalette;
+ png_uint_32 height = surface->h;
+ png_uint_32 width = surface->w;
+ png_bytep *volatile row_pointers;
+ int row;
-/* Load a PNG type image from an SDL datasource */
-SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
-{
- return(NULL);
+ if ( !src ) {
+ /* The error message has been set in SDL_RWFromFile */
+ return -1;
+ }
+ start = SDL_RWtell(src);
+
+ if ( IMG_InitPNG() < 0 ) {
+ return -1;
+ }
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible with the one used at compile time,
+ * in case we are using dynamically linked libraries. REQUIRED.
+ */
+ png_ptr = NULL; info_ptr = NULL;
+
+ /* Create the PNG loading context structure */
+ png_ptr = lib.png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL,NULL,NULL);
+ if (png_ptr == NULL){
+ error = "Couldn't allocate memory for PNG file or incompatible PNG dll";
+ goto done;
+ }
+
+ /* Allocate/initialize the memory for image information. REQUIRED. */
+ info_ptr = lib.png_create_info_struct(png_ptr);
+ if (info_ptr == NULL) {
+ error = "Couldn't create image information for PNG file";
+ goto done;
+ }
+
+ /* Set error handling if you are using setjmp/longjmp method (this is
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in png_create_read_struct() earlier.
+ */
+ if ( setjmp(png_ptr->jmpbuf) ) {
+ error = "Error reading the PNG file.";
+ goto done;
+ }
+
+ /* Set up the output control */
+ lib.png_set_write_fn(png_ptr, src, png_write_data);
+
+ /* Set the image information here. Width and height are up to 2^31,
+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+ */
+ sdlPalette = surface->format->palette;
+ if (sdlPalette)
+ {
+ colorType = PNG_COLOR_TYPE_PALETTE;
+ } else if (surface->format->Amask)
+ {
+ colorType = PNG_COLOR_TYPE_RGB_ALPHA;
+ } else
+ {
+ colorType = PNG_COLOR_TYPE_RGB;
+ }
+ lib.png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, surface->format->BitsPerPixel, colorType,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ /* set the palette if there is one. REQUIRED for indexed-color images */
+ if (colorType == PNG_COLOR_TYPE_PALETTE)
+ {
+ palette = (png_colorp) malloc(sdlPalette->ncolors * sizeof(png_color));
+
+ for( i=0; i < sdlPalette->ncolors; ++i ) {
+ palette[i].blue = sdlPalette->colors[i].b;
+ palette[i].green = sdlPalette->colors[i].g;
+ palette[i].red = sdlPalette->colors[i].r;
+ }
+ lib.png_set_PLTE(png_ptr, info_ptr, palette, sdlPalette->ncolors);
+ }
+ else
+ { //not sure how to handle this
+// sig_bit.red = true_red_bit_depth;
+// sig_bit.green = true_green_bit_depth;
+// sig_bit.blue = true_blue_bit_depth;
+ /* if the image has an alpha channel then */
+// sig_bit.alpha = true_alpha_bit_depth;
+// png_set_sBIT(png_ptr, info_ptr, sig_bit);
+ }
+
+ /* Write the file header information. REQUIRED */
+ lib.png_write_info(png_ptr, info_ptr);
+
+ /* The easiest way to write the image (you may have a different memory
+ * layout, however, so choose what fits your needs best). You need to
+ * use the first method if you aren't handling interlacing yourself.
+ */
+
+ row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height);
+ if ( (row_pointers == NULL) ) {
+ error = "Out of memory";
+ goto done;
+ }
+ for (row = 0; row < (int)height; row++) {
+ row_pointers[row] = (png_bytep)
+ (Uint8 *)surface->pixels + row*surface->pitch;
+ }
+
+ if (height > PNG_UINT_32_MAX/sizeof(png_bytep))
+ {
+ error = "Image is too tall to process in memory";
+ goto done;
+ }
+
+ /* Read the entire image in one go */
+ lib.png_write_image(png_ptr, row_pointers);
+
+ /* It is REQUIRED to call this to finish writing the rest of the file */
+ lib.png_write_end(png_ptr, info_ptr);
+
+done: /* Clean up and return */
+ if ( png_ptr ) {
+ lib.png_destroy_write_struct(&png_ptr, &info_ptr);
+ }
+ if ( row_pointers ) {
+ free(row_pointers);
+ }
+ if (palette)
+ {
+ free(palette);
+ }
+ if ( error ) {
+ IMG_QuitPNG();
+ IMG_SetError(error);
+ return(-1);
+ } else {
+ IMG_QuitPNG();
+ }
+ return(0);
}
#endif /* LOAD_PNG */
Index: SDL_image.h
===================================================================
--- SDL_image.h (revision 4475)
+++ SDL_image.h (working copy)
## -107,6 +107,8 ##
extern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm);
+extern DECLSPEC int SDLCALL IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *src);
+
/* We'll use SDL for reporting errors */
#define IMG_SetError SDL_SetError
#define IMG_GetError SDL_GetError
I managed to get it working. I needed to call png_set_bgr() to fix the palette.
Saving SDL surfaces as PNG images is a problem that's been solved on the web repeatedly:
http://www.bishoujo.us/svn/renpy/trunk/module/
http://lists.libsdl.org/pipermail/sdl-libsdl.org/2006-May/055936.html
http://www.os4depot.net/index.php?function=showfile&file=development/example/sdlpngsavesurf.lha
http://encelo.netsons.org/programming/sdl
Rather than asking for help debugging a significant amount of code, comparing your code to those other implementations and seeing where they differ, or asking which of those other implementations is the best to use, would probably be more productive.
As an aside, patching the SDL_image library might be a less robust solution than writing separate dependent libraries to implement PNG saving. That way the next SDL upgrade won't break your code. If you were thinking of contributing the patch to SDL, all the other implementations mentioned go back a few years. I don't think that SDL_image doesn't include PNG saving for lack of anyone wanting or being able to code it.